1 /* Copyright 2011-2012 Space Applications Services
2 * Licensed to CS Communication & Systèmes (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.utils;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.InputStreamReader;
23 import java.io.StreamTokenizer;
24 import java.nio.charset.StandardCharsets;
25 import java.text.ParseException;
26 import java.util.LinkedList;
27 import java.util.List;
28
29 import org.orekit.data.DataLoader;
30
31 /** Used to read an interpolation table from a data file.
32 * @author Thomas Neidhart
33 */
34 public class InterpolationTableLoader implements DataLoader {
35
36 /** Abscissa grid for the bi-variate interpolation function read from the file. */
37 private double[] xArr;
38
39 /** Ordinate grid for the bi-variate interpolation function read from the file. */
40 private double[] yArr;
41
42 /** Values samples for the bi-variate interpolation function read from the file. */
43 private double[][] fArr;
44
45 /** Returns a copy of the abscissa grid for the interpolation function.
46 * @return the abscissa grid for the interpolation function,
47 * or <code>null</code> if the file could not be read
48 */
49 public double[] getAbscissaGrid() {
50 return xArr.clone();
51 }
52
53 /** Returns a copy of the ordinate grid for the interpolation function.
54 * @return the ordinate grid for the interpolation function,
55 * or <code>null</code> if the file could not be read
56 */
57 public double[] getOrdinateGrid() {
58 return yArr.clone();
59 }
60
61 /** Returns a copy of the values samples for the interpolation function.
62 * @return the values samples for the interpolation function,
63 * or <code>null</code> if the file could not be read
64 */
65 public double[][] getValuesSamples() {
66 return fArr.clone();
67 }
68
69 /** {@inheritDoc} */
70 public boolean stillAcceptsData() {
71 return xArr == null;
72 }
73
74 /** Loads an bi-variate interpolation table from the given {@link InputStream}.
75 * The format of the table is as follows (number of rows/columns can be extended):
76 * <pre>
77 * Table: tableName
78 *
79 * | 0.0 | 60.0 | 66.0
80 * -------------------------
81 * 0 | 0.0 | 0.003 | 0.006
82 * 500 | 0.0 | 0.003 | 0.006
83 * </pre>
84 * @param input the input stream to read data from
85 * @param name the name of the input file
86 * @exception IOException if data can't be read
87 * @exception ParseException if data can't be parsed
88 */
89 public void loadData(final InputStream input, final String name)
90 throws IOException, ParseException {
91
92 final List<Double> xValues = new LinkedList<Double>();
93 final List<Double> yValues = new LinkedList<Double>();
94 final LinkedList<List<Double>> cellValues = new LinkedList<List<Double>>();
95
96 final StreamTokenizer tokenizer =
97 new StreamTokenizer(new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)));
98
99 // ignore comments starting with a #
100 tokenizer.commentChar('#');
101 tokenizer.eolIsSignificant(true);
102
103 int tokenCount = 0;
104 boolean headerRow = false;
105 boolean done = false;
106
107 do {
108 switch (tokenizer.nextToken()) {
109
110 case StreamTokenizer.TT_EOF:
111 done = true;
112 break;
113
114 case StreamTokenizer.TT_EOL:
115 // end of header row
116 if (yValues.size() > 0) {
117 headerRow = false;
118 }
119 tokenCount = 0;
120 break;
121
122 case StreamTokenizer.TT_NUMBER:
123 if (headerRow) {
124 yValues.add(tokenizer.nval);
125 } else {
126 if (tokenCount == 0) {
127 xValues.add(tokenizer.nval);
128 cellValues.add(new LinkedList<Double>());
129 } else {
130 cellValues.getLast().add(tokenizer.nval);
131 }
132 }
133 tokenCount++;
134 break;
135
136 case StreamTokenizer.TT_WORD:
137 // we are in the header row now
138 if (tokenizer.sval.startsWith("Table")) {
139 headerRow = true;
140 }
141 break;
142
143 default:
144 break;
145 }
146
147 } while (!done);
148
149 xArr = toPrimitiveArray(xValues);
150 yArr = toPrimitiveArray(yValues);
151 fArr = new double[cellValues.size()][];
152 int idx = 0;
153
154 for (List<Double> row : cellValues) {
155 fArr[idx++] = toPrimitiveArray(row);
156 }
157
158 }
159
160 /** Converts a list of {@link Double} objects into an array of double primitives.
161 * @param list the list of {@link Double} objects
162 * @return the double array containing the list elements
163 */
164 private double[] toPrimitiveArray(final List<Double> list) {
165 final double[] result = new double[list.size()];
166 int idx = 0;
167 for (Double element : list) {
168 result[idx++] = element;
169 }
170 return result;
171 }
172 }