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 org.hipparchus.util.FastMath;
20 import org.hipparchus.util.Precision;
21 import org.orekit.annotation.DefaultDataContext;
22 import org.orekit.data.DataContext;
23 import org.orekit.errors.OrekitException;
24 import org.orekit.errors.OrekitMessages;
25 import org.orekit.errors.OrekitParseException;
26 import org.orekit.time.AbsoluteDate;
27 import org.orekit.time.DateComponents;
28 import org.orekit.time.TimeScale;
29 import org.orekit.utils.Constants;
30
31 import java.io.BufferedReader;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.io.InputStreamReader;
35 import java.nio.charset.StandardCharsets;
36 import java.text.ParseException;
37 import java.util.regex.Matcher;
38 import java.util.regex.Pattern;
39
40
41
42
43
44
45
46
47
48
49
50 public class GRGSFormatReader extends PotentialCoefficientsReader {
51
52
53 private static final Pattern[] LINES;
54
55
56 private static final int EARTH = 0x1;
57
58
59 private static final int LIMITS = 0x2;
60
61
62 private static final int COEFFS = 0x4;
63
64
65 private AbsoluteDate referenceDate;
66
67
68 private Flattener dotFlattener;
69
70
71 private double[] cDot;
72
73
74 private double[] sDot;
75
76 static {
77
78
79 final String real = "[-+]?\\d?\\.\\d+[eEdD][-+]\\d\\d";
80 final String sep = ")\\s*(";
81
82
83 final String[] header = {
84 "^\\s*FIELD - .*$",
85 "^\\s+AE\\s+1/F\\s+GM\\s+OMEGA\\s*$",
86 "^\\s*(" + real + sep + real + sep + real + sep + real + ")\\s*$",
87 "^\\s*REFERENCE\\s+DATE\\s+:\\s+(\\d+)\\.0+\\s*$",
88 "^\\s*MAXIMAL\\s+DEGREE\\s+:\\s+(\\d+)\\s.*$",
89 "^\\s*L\\s+M\\s+DOT\\s+CBAR\\s+SBAR\\s+SIGMA C\\s+SIGMA S(\\s+LIB)?\\s*$"
90 };
91
92
93 final String data = "^([ 0-9]{3})([ 0-9]{3})( {3}|DOT)\\s*(" +
94 real + sep + real + sep + real + sep + real +
95 ")(\\s+[0-9]+)?\\s*$";
96
97
98 LINES = new Pattern[header.length + 1];
99 for (int i = 0; i < header.length; ++i) {
100 LINES[i] = Pattern.compile(header[i]);
101 }
102 LINES[LINES.length - 1] = Pattern.compile(data);
103
104 }
105
106
107
108
109
110
111
112
113
114 @DefaultDataContext
115 public GRGSFormatReader(final String supportedNames, final boolean missingCoefficientsAllowed) {
116 this(supportedNames, missingCoefficientsAllowed,
117 DataContext.getDefault().getTimeScales().getTT());
118 }
119
120
121
122
123
124
125
126
127
128
129 public GRGSFormatReader(final String supportedNames,
130 final boolean missingCoefficientsAllowed,
131 final TimeScale timeScale) {
132 super(supportedNames, missingCoefficientsAllowed, timeScale);
133 reset();
134 }
135
136
137 public void loadData(final InputStream input, final String name)
138 throws IOException, ParseException, OrekitException {
139
140
141 reset();
142
143
144
145
146
147
148
149
150
151
152
153
154
155 Flattener flattener = null;
156 int dotDegree = -1;
157 int dotOrder = -1;
158 int flags = 0;
159 int lineNumber = 0;
160 double[] c0 = null;
161 double[] s0 = null;
162 double[] c1 = null;
163 double[] s1 = null;
164 try (BufferedReader r = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {
165 for (String line = r.readLine(); line != null; line = r.readLine()) {
166
167 ++lineNumber;
168
169
170 final Matcher matcher = LINES[FastMath.min(LINES.length, lineNumber) - 1].matcher(line);
171 if (!matcher.matches()) {
172 throw new OrekitParseException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
173 lineNumber, name, line);
174 }
175
176 if (lineNumber == 3) {
177
178 setAe(parseDouble(matcher.group(1)));
179 setMu(parseDouble(matcher.group(3)));
180 flags |= EARTH;
181 } else if (lineNumber == 4) {
182
183 referenceDate = toDate(
184 new DateComponents(Integer.parseInt(matcher.group(1)), 1, 1));
185 } else if (lineNumber == 5) {
186
187 final int degree = FastMath.min(getMaxParseDegree(), Integer.parseInt(matcher.group(1)));
188 final int order = FastMath.min(getMaxParseOrder(), degree);
189 flattener = new Flattener(degree, order);
190 c0 = buildFlatArray(flattener, missingCoefficientsAllowed() ? 0.0 : Double.NaN);
191 s0 = buildFlatArray(flattener, missingCoefficientsAllowed() ? 0.0 : Double.NaN);
192 c1 = buildFlatArray(flattener, 0.0);
193 s1 = buildFlatArray(flattener, 0.0);
194 flags |= LIMITS;
195 } else if (lineNumber > 6) {
196
197 final int i = Integer.parseInt(matcher.group(1).trim());
198 final int j = Integer.parseInt(matcher.group(2).trim());
199 if (flattener.withinRange(i, j)) {
200 if ("DOT".equals(matcher.group(3).trim())) {
201
202
203 parseCoefficient(matcher.group(4), flattener, c1, i, j, "Cdot", name);
204 parseCoefficient(matcher.group(5), flattener, s1, i, j, "Sdot", name);
205 dotDegree = FastMath.max(dotDegree, i);
206 dotOrder = FastMath.max(dotOrder, j);
207
208 } else {
209
210
211 parseCoefficient(matcher.group(4), flattener, c0, i, j, "C", name);
212 parseCoefficient(matcher.group(5), flattener, s0, i, j, "S", name);
213
214 }
215 }
216 flags |= COEFFS;
217 }
218
219 }
220 }
221
222 if (flags != (EARTH | LIMITS | COEFFS)) {
223 String loaderName = getClass().getName();
224 loaderName = loaderName.substring(loaderName.lastIndexOf('.') + 1);
225 throw new OrekitException(OrekitMessages.UNEXPECTED_FILE_FORMAT_ERROR_FOR_LOADER,
226 name, loaderName);
227 }
228
229 if (missingCoefficientsAllowed()) {
230
231 if (Precision.equals(c0[flattener.index(0, 0)], 0.0, 0)) {
232 c0[flattener.index(0, 0)] = 1.0;
233 }
234 }
235
236
237 if (dotDegree >= 0) {
238 dotFlattener = new Flattener(dotDegree, dotOrder);
239 cDot = new double[dotFlattener.arraySize()];
240 sDot = new double[dotFlattener.arraySize()];
241 for (int n = 0; n <= dotDegree; ++n) {
242 for (int m = 0; m <= FastMath.min(n, dotOrder); ++m) {
243 cDot[dotFlattener.index(n, m)] = c1[flattener.index(n, m)];
244 sDot[dotFlattener.index(n, m)] = s1[flattener.index(n, m)];
245 }
246 }
247 }
248
249 setRawCoefficients(true, flattener, c0, s0, name);
250 setTideSystem(TideSystem.UNKNOWN);
251 setReadComplete(true);
252
253 }
254
255
256
257
258 private void reset() {
259 setReadComplete(false);
260 referenceDate = null;
261 dotFlattener = null;
262 cDot = null;
263 sDot = null;
264 }
265
266
267
268
269
270
271
272 public RawSphericalHarmonicsProvider getProvider(final boolean wantNormalized,
273 final int degree, final int order) {
274
275
276 RawSphericalHarmonicsProvider provider = getBaseProvider(wantNormalized, degree, order);
277
278 if (dotFlattener != null) {
279
280
281 final double scale = 1.0 / Constants.JULIAN_YEAR;
282 final Flattener rescaledFlattener = new Flattener(FastMath.min(degree, dotFlattener.getDegree()),
283 FastMath.min(order, dotFlattener.getOrder()));
284 provider = new SecularTrendSphericalHarmonics(provider, referenceDate, rescaledFlattener,
285 rescale(scale, wantNormalized, rescaledFlattener, dotFlattener, cDot),
286 rescale(scale, wantNormalized, rescaledFlattener, dotFlattener, sDot));
287
288 }
289
290 return provider;
291
292 }
293
294 }