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 }