1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.gravity.potential;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.InputStreamReader;
23 import java.text.ParseException;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29 import org.hipparchus.util.FastMath;
30 import org.hipparchus.util.Precision;
31 import org.orekit.errors.OrekitException;
32 import org.orekit.errors.OrekitMessages;
33 import org.orekit.errors.OrekitParseException;
34 import org.orekit.time.DateComponents;
35 import org.orekit.utils.Constants;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 public class ICGEMFormatReader extends PotentialCoefficientsReader {
86
87
88 private static final String PRODUCT_TYPE = "product_type";
89
90
91 private static final String GRAVITY_FIELD = "gravity_field";
92
93
94 private static final String GRAVITY_CONSTANT = "gravity_constant";
95
96
97 private static final String REFERENCE_RADIUS = "radius";
98
99
100 private static final String MAX_DEGREE = "max_degree";
101
102
103 private static final String TIDE_SYSTEM_INDICATOR = "tide_system";
104
105
106 private static final String ZERO_TIDE = "zero_tide";
107
108
109 private static final String TIDE_FREE = "tide_free";
110
111
112 private static final String TIDE_UNKNOWN = "unknown";
113
114
115 private static final String NORMALIZATION_INDICATOR = "norm";
116
117
118 private static final String NORMALIZED = "fully_normalized";
119
120
121 private static final String UNNORMALIZED = "unnormalized";
122
123
124 private static final String END_OF_HEADER = "end_of_head";
125
126
127 private static final String GFC = "gfc";
128
129
130 private static final String GFCT = "gfct";
131
132
133 private static final String DOT = "dot";
134
135
136 private static final String TRND = "trnd";
137
138
139 private static final String ASIN = "asin";
140
141
142 private static final String ACOS = "acos";
143
144
145 private TideSystem tideSystem;
146
147
148 private boolean normalized;
149
150
151 private DateComponents referenceDate;
152
153
154 private final List<List<Double>> cTrend;
155
156
157 private final List<List<Double>> sTrend;
158
159
160 private final Map<Double, List<List<Double>>> cCos;
161
162
163 private final Map<Double, List<List<Double>>> cSin;
164
165
166 private final Map<Double, List<List<Double>>> sCos;
167
168
169 private final Map<Double, List<List<Double>>> sSin;
170
171
172
173
174
175 public ICGEMFormatReader(final String supportedNames, final boolean missingCoefficientsAllowed) {
176 super(supportedNames, missingCoefficientsAllowed);
177 referenceDate = null;
178 cTrend = new ArrayList<List<Double>>();
179 sTrend = new ArrayList<List<Double>>();
180 cCos = new HashMap<Double, List<List<Double>>>();
181 cSin = new HashMap<Double, List<List<Double>>>();
182 sCos = new HashMap<Double, List<List<Double>>>();
183 sSin = new HashMap<Double, List<List<Double>>>();
184 }
185
186
187 public void loadData(final InputStream input, final String name)
188 throws IOException, ParseException, OrekitException {
189
190
191 setReadComplete(false);
192 referenceDate = null;
193 cTrend.clear();
194 sTrend.clear();
195 cCos.clear();
196 cSin.clear();
197 sCos.clear();
198 sSin.clear();
199
200
201
202 normalized = true;
203 tideSystem = TideSystem.UNKNOWN;
204
205 final BufferedReader r = new BufferedReader(new InputStreamReader(input, "UTF-8"));
206 boolean inHeader = true;
207 double[][] c = null;
208 double[][] s = null;
209 boolean okCoeffs = false;
210 int lineNumber = 0;
211 for (String line = r.readLine(); line != null; line = r.readLine()) {
212 try {
213 ++lineNumber;
214 if (line.trim().length() == 0) {
215 continue;
216 }
217 final String[] tab = line.split("\\s+");
218 if (inHeader) {
219 if ((tab.length == 2) && PRODUCT_TYPE.equals(tab[0])) {
220 if (!GRAVITY_FIELD.equals(tab[1])) {
221 throw new OrekitParseException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
222 lineNumber, name, line);
223 }
224 } else if ((tab.length == 2) && tab[0].endsWith(GRAVITY_CONSTANT)) {
225 setMu(parseDouble(tab[1]));
226 } else if ((tab.length == 2) && REFERENCE_RADIUS.equals(tab[0])) {
227 setAe(parseDouble(tab[1]));
228 } else if ((tab.length == 2) && MAX_DEGREE.equals(tab[0])) {
229
230 final int degree = FastMath.min(getMaxParseDegree(), Integer.parseInt(tab[1]));
231 final int order = FastMath.min(getMaxParseOrder(), degree);
232 c = buildTriangularArray(degree, order, missingCoefficientsAllowed() ? 0.0 : Double.NaN);
233 s = buildTriangularArray(degree, order, missingCoefficientsAllowed() ? 0.0 : Double.NaN);
234
235 } else if ((tab.length == 2) && TIDE_SYSTEM_INDICATOR.equals(tab[0])) {
236 if (ZERO_TIDE.equals(tab[1])) {
237 tideSystem = TideSystem.ZERO_TIDE;
238 } else if (TIDE_FREE.equals(tab[1])) {
239 tideSystem = TideSystem.TIDE_FREE;
240 } else if (TIDE_UNKNOWN.equals(tab[1])) {
241 tideSystem = TideSystem.UNKNOWN;
242 } else {
243 throw new OrekitParseException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
244 lineNumber, name, line);
245 }
246 } else if ((tab.length == 2) && NORMALIZATION_INDICATOR.equals(tab[0])) {
247 if (NORMALIZED.equals(tab[1])) {
248 normalized = true;
249 } else if (UNNORMALIZED.equals(tab[1])) {
250 normalized = false;
251 } else {
252 throw new OrekitParseException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
253 lineNumber, name, line);
254 }
255 } else if ((tab.length == 2) && END_OF_HEADER.equals(tab[0])) {
256 inHeader = false;
257 }
258 } else {
259 if ((tab.length == 7 && GFC.equals(tab[0])) || (tab.length == 8 && GFCT.equals(tab[0]))) {
260
261 final int i = Integer.parseInt(tab[1]);
262 final int j = Integer.parseInt(tab[2]);
263 if (i < c.length && j < c[i].length) {
264
265 parseCoefficient(tab[3], c, i, j, "C", name);
266 parseCoefficient(tab[4], s, i, j, "S", name);
267 okCoeffs = true;
268
269 if (tab.length == 8) {
270
271 final DateComponents#DateComponents">DateComponents localRef = new DateComponents(Integer.parseInt(tab[7].substring(0, 4)),
272 Integer.parseInt(tab[7].substring(4, 6)),
273 Integer.parseInt(tab[7].substring(6, 8)));
274 if (referenceDate == null) {
275
276 referenceDate = localRef;
277 } else if (!referenceDate.equals(localRef)) {
278 throw new OrekitException(OrekitMessages.SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD,
279 referenceDate, localRef, name);
280 }
281 }
282
283 }
284 } else if (tab.length == 7 && (DOT.equals(tab[0]) || TRND.equals(tab[0]))) {
285
286 final int i = Integer.parseInt(tab[1]);
287 final int j = Integer.parseInt(tab[2]);
288 if (i < c.length && j < c[i].length) {
289
290
291 extendListOfLists(cTrend, i, j, 0.0);
292 extendListOfLists(sTrend, i, j, 0.0);
293 parseCoefficient(tab[3], cTrend, i, j, "Ctrend", name);
294 parseCoefficient(tab[4], sTrend, i, j, "Strend", name);
295
296 }
297
298 } else if (tab.length == 8 && (ASIN.equals(tab[0]) || ACOS.equals(tab[0]))) {
299
300 final int i = Integer.parseInt(tab[1]);
301 final int j = Integer.parseInt(tab[2]);
302 if (i < c.length && j < c[i].length) {
303
304
305 final Double period = Double.valueOf(tab[7]);
306 if (!cCos.containsKey(period)) {
307 cCos.put(period, new ArrayList<List<Double>>());
308 cSin.put(period, new ArrayList<List<Double>>());
309 sCos.put(period, new ArrayList<List<Double>>());
310 sSin.put(period, new ArrayList<List<Double>>());
311 }
312 final List<List<Double>> cCosPeriod = cCos.get(period);
313 final List<List<Double>> cSinPeriod = cSin.get(period);
314 final List<List<Double>> sCosPeriod = sCos.get(period);
315 final List<List<Double>> sSinPeriod = sSin.get(period);
316
317
318 extendListOfLists(cCosPeriod, i, j, 0.0);
319 extendListOfLists(cSinPeriod, i, j, 0.0);
320 extendListOfLists(sCosPeriod, i, j, 0.0);
321 extendListOfLists(sSinPeriod, i, j, 0.0);
322 if (ACOS.equals(tab[0])) {
323 parseCoefficient(tab[3], cCosPeriod, i, j, "Ccos", name);
324 parseCoefficient(tab[4], sCosPeriod, i, j, "SCos", name);
325 } else {
326 parseCoefficient(tab[3], cSinPeriod, i, j, "Csin", name);
327 parseCoefficient(tab[4], sSinPeriod, i, j, "Ssin", name);
328 }
329
330 }
331
332 } else {
333 throw new OrekitParseException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
334 lineNumber, name, line);
335 }
336 }
337 } catch (NumberFormatException nfe) {
338 final OrekitParseExceptionion.html#OrekitParseException">OrekitParseException pe = new OrekitParseException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
339 lineNumber, name, line);
340 pe.initCause(nfe);
341 throw pe;
342 }
343 }
344
345 if (missingCoefficientsAllowed() && c.length > 0 && c[0].length > 0) {
346
347 if (Precision.equals(c[0][0], 0.0, 0)) {
348 c[0][0] = 1.0;
349 }
350 }
351
352 if (Double.isNaN(getAe()) || Double.isNaN(getMu()) || !okCoeffs) {
353 String loaderName = getClass().getName();
354 loaderName = loaderName.substring(loaderName.lastIndexOf('.') + 1);
355 throw new OrekitException(OrekitMessages.UNEXPECTED_FILE_FORMAT_ERROR_FOR_LOADER,
356 name, loaderName);
357 }
358
359 setRawCoefficients(normalized, c, s, name);
360 setTideSystem(tideSystem);
361 setReadComplete(true);
362
363 }
364
365
366
367
368
369
370
371
372
373
374
375
376
377 public RawSphericalHarmonicsProvider getProvider(final boolean wantNormalized,
378 final int degree, final int order) {
379
380 RawSphericalHarmonicsProvider provider = getConstantProvider(wantNormalized, degree, order);
381 if (cTrend.isEmpty() && cCos.isEmpty()) {
382
383 return provider;
384 }
385
386 if (!cTrend.isEmpty()) {
387
388
389 final double[][] cArrayTrend = toArray(cTrend);
390 final double[][] sArrayTrend = toArray(sTrend);
391 rescale(1.0 / Constants.JULIAN_YEAR, normalized, cArrayTrend, sArrayTrend, wantNormalized, cArrayTrend, sArrayTrend);
392 provider = new SecularTrendSphericalHarmonics(provider, referenceDate, cArrayTrend, sArrayTrend);
393
394 }
395
396 for (final Map.Entry<Double, List<List<Double>>> entry : cCos.entrySet()) {
397
398 final double period = entry.getKey();
399
400
401 final double[][] cArrayCos = toArray(cCos.get(period));
402 final double[][] sArrayCos = toArray(sCos.get(period));
403 final double[][] cArraySin = toArray(cSin.get(period));
404 final double[][] sArraySin = toArray(sSin.get(period));
405 rescale(1.0, normalized, cArrayCos, sArrayCos, wantNormalized, cArrayCos, sArrayCos);
406 rescale(1.0, normalized, cArraySin, sArraySin, wantNormalized, cArraySin, sArraySin);
407 provider = new PulsatingSphericalHarmonics(provider, period * Constants.JULIAN_YEAR,
408 cArrayCos, cArraySin, sArrayCos, sArraySin);
409
410 }
411
412 return provider;
413
414 }
415
416 }