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.nio.charset.StandardCharsets;
24 import java.text.ParseException;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.regex.Pattern;
29
30 import org.hipparchus.util.FastMath;
31 import org.hipparchus.util.Precision;
32 import org.orekit.annotation.DefaultDataContext;
33 import org.orekit.data.DataContext;
34 import org.orekit.errors.OrekitException;
35 import org.orekit.errors.OrekitMessages;
36 import org.orekit.time.AbsoluteDate;
37 import org.orekit.time.DateComponents;
38 import org.orekit.time.TimeScale;
39 import org.orekit.utils.Constants;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class SHMFormatReader extends PotentialCoefficientsReader {
56
57
58 private static final Pattern SEPARATOR = Pattern.compile("\\s+");
59
60
61 private static final String GRCOEF = "GRCOEF";
62
63
64 private static final String GRCOF2 = "GRCOF2";
65
66
67 private static final String GRDOTA = "GRDOTA";
68
69
70 private AbsoluteDate referenceDate;
71
72
73 private final List<List<Double>> cDot;
74
75
76 private final List<List<Double>> sDot;
77
78
79
80
81
82
83
84
85
86 @DefaultDataContext
87 public SHMFormatReader(final String supportedNames, final boolean missingCoefficientsAllowed) {
88 this(supportedNames, missingCoefficientsAllowed,
89 DataContext.getDefault().getTimeScales().getTT());
90 }
91
92
93
94
95
96
97
98 public SHMFormatReader(final String supportedNames,
99 final boolean missingCoefficientsAllowed,
100 final TimeScale timeScale) {
101 super(supportedNames, missingCoefficientsAllowed, timeScale);
102 referenceDate = null;
103 cDot = new ArrayList<>();
104 sDot = new ArrayList<>();
105 }
106
107
108 public void loadData(final InputStream input, final String name)
109 throws IOException, ParseException, OrekitException {
110
111
112 setReadComplete(false);
113 referenceDate = null;
114 cDot.clear();
115 sDot.clear();
116
117 boolean normalized = false;
118 TideSystem tideSystem = TideSystem.UNKNOWN;
119
120 boolean okEarth = false;
121 boolean okSHM = false;
122 boolean okCoeffs = false;
123 double[][] c = null;
124 double[][] s = null;
125 String line = null;
126 int lineNumber = 1;
127 try (BufferedReader r = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {
128 line = r.readLine();
129 if ((line != null) &&
130 "FIRST ".equals(line.substring(0, 6)) &&
131 "SHM ".equals(line.substring(49, 56))) {
132 for (line = r.readLine(); line != null; line = r.readLine()) {
133 lineNumber++;
134 if (line.length() >= 6) {
135 final String[] tab = SEPARATOR.split(line);
136
137
138 if ("EARTH".equals(tab[0])) {
139 setMu(parseDouble(tab[1]));
140 setAe(parseDouble(tab[2]));
141 okEarth = true;
142 }
143
144
145 if ("SHM".equals(tab[0])) {
146
147 final int degree = FastMath.min(getMaxParseDegree(), Integer.parseInt(tab[1]));
148 final int order = FastMath.min(getMaxParseOrder(), degree);
149 c = buildTriangularArray(degree, order, missingCoefficientsAllowed() ? 0.0 : Double.NaN);
150 s = buildTriangularArray(degree, order, missingCoefficientsAllowed() ? 0.0 : Double.NaN);
151 final String lowerCaseLine = line.toLowerCase(Locale.US);
152 normalized = lowerCaseLine.contains("fully normalized");
153 if (lowerCaseLine.contains("exclusive permanent tide")) {
154 tideSystem = TideSystem.TIDE_FREE;
155 } else {
156 tideSystem = TideSystem.UNKNOWN;
157 }
158 okSHM = true;
159 }
160
161
162 if (GRCOEF.equals(line.substring(0, 6)) || GRCOF2.equals(tab[0]) || GRDOTA.equals(tab[0])) {
163 final int i = Integer.parseInt(tab[1]);
164 final int j = Integer.parseInt(tab[2]);
165 if (i < c.length && j < c[i].length) {
166 if (GRDOTA.equals(tab[0])) {
167
168
169 extendListOfLists(cDot, i, j, 0.0);
170 extendListOfLists(sDot, i, j, 0.0);
171 parseCoefficient(tab[3], cDot, i, j, "Cdot", name);
172 parseCoefficient(tab[4], sDot, i, j, "Sdot", name);
173
174
175 final DateComponents#DateComponents">DateComponents localRef = new DateComponents(Integer.parseInt(tab[7].substring(0, 4)),
176 Integer.parseInt(tab[7].substring(4, 6)),
177 Integer.parseInt(tab[7].substring(6, 8)));
178 if (referenceDate == null) {
179
180 referenceDate = toDate(localRef);
181 } else if (!referenceDate.equals(toDate(localRef))) {
182 throw new OrekitException(OrekitMessages.SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD,
183 referenceDate, toDate(localRef), name);
184 }
185
186 } else {
187
188
189 parseCoefficient(tab[3], c, i, j, "C", name);
190 parseCoefficient(tab[4], s, i, j, "S", name);
191 okCoeffs = true;
192
193 }
194 }
195 }
196
197 }
198 }
199 }
200 } catch (NumberFormatException nfe) {
201 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
202 lineNumber, name, line);
203 }
204
205 if (missingCoefficientsAllowed() && c.length > 0 && c[0].length > 0) {
206
207 if (Precision.equals(c[0][0], 0.0, 0)) {
208 c[0][0] = 1.0;
209 }
210 }
211
212 if (!(okEarth && okSHM && okCoeffs)) {
213 String loaderName = getClass().getName();
214 loaderName = loaderName.substring(loaderName.lastIndexOf('.') + 1);
215 throw new OrekitException(OrekitMessages.UNEXPECTED_FILE_FORMAT_ERROR_FOR_LOADER,
216 name, loaderName);
217 }
218
219 setRawCoefficients(normalized, c, s, name);
220 setTideSystem(tideSystem);
221 setReadComplete(true);
222
223 }
224
225
226
227
228
229
230
231
232
233
234
235
236
237 public RawSphericalHarmonicsProvider getProvider(final boolean wantNormalized,
238 final int degree, final int order) {
239
240
241 RawSphericalHarmonicsProvider provider = getConstantProvider(wantNormalized, degree, order);
242
243 if (!cDot.isEmpty()) {
244
245
246 final double[][] cArray = toArray(cDot);
247 final double[][] sArray = toArray(sDot);
248 rescale(1.0 / Constants.JULIAN_YEAR, true, cArray, sArray, wantNormalized, cArray, sArray);
249 provider = new SecularTrendSphericalHarmonics(provider, referenceDate, cArray, sArray);
250
251 }
252
253 return provider;
254
255 }
256
257 }