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.text.ParseException;
25 import java.util.LinkedList;
26 import java.util.List;
27
28 import org.orekit.data.DataLoader;
29 import org.orekit.errors.OrekitException;
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 * @exception OrekitException if some data is missing or unexpected
89 * data is encountered
90 */
91 public void loadData(final InputStream input, final String name)
92 throws IOException, ParseException, OrekitException {
93
94 final List<Double> xValues = new LinkedList<Double>();
95 final List<Double> yValues = new LinkedList<Double>();
96 final LinkedList<List<Double>> cellValues = new LinkedList<List<Double>>();
97
98 final StreamTokenizer tokenizer =
99 new StreamTokenizer(new BufferedReader(new InputStreamReader(input, "UTF-8")));
100
101 // ignore comments starting with a #
102 tokenizer.commentChar('#');
103 tokenizer.eolIsSignificant(true);
104
105 int tokenCount = 0;
106 boolean headerRow = false;
107 boolean done = false;
108
109 do {
110 switch (tokenizer.nextToken()) {
111
112 case StreamTokenizer.TT_EOF:
113 done = true;
114 break;
115
116 case StreamTokenizer.TT_EOL:
117 // end of header row
118 if (yValues.size() > 0) {
119 headerRow = false;
120 }
121 tokenCount = 0;
122 break;
123
124 case StreamTokenizer.TT_NUMBER:
125 if (headerRow) {
126 yValues.add(tokenizer.nval);
127 } else {
128 if (tokenCount == 0) {
129 xValues.add(tokenizer.nval);
130 cellValues.add(new LinkedList<Double>());
131 } else {
132 cellValues.getLast().add(tokenizer.nval);
133 }
134 }
135 tokenCount++;
136 break;
137
138 case StreamTokenizer.TT_WORD:
139 // we are in the header row now
140 if (tokenizer.sval.startsWith("Table")) {
141 headerRow = true;
142 }
143 break;
144
145 default:
146 break;
147 }
148
149 } while (!done);
150
151 xArr = toPrimitiveArray(xValues);
152 yArr = toPrimitiveArray(yValues);
153 fArr = new double[cellValues.size()][];
154 int idx = 0;
155
156 for (List<Double> row : cellValues) {
157 fArr[idx++] = toPrimitiveArray(row);
158 }
159
160 }
161
162 /** Converts a list of {@link Double} objects into an array of double primitives.
163 * @param list the list of {@link Double} objects
164 * @return the double array containing the list elements
165 */
166 private double[] toPrimitiveArray(final List<Double> list) {
167 final double[] result = new double[list.size()];
168 int idx = 0;
169 for (Double element : list) {
170 result[idx++] = element;
171 }
172 return result;
173 }
174 }