1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.frames;
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.util.ArrayList;
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.SortedSet;
28 import java.util.function.Supplier;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31
32 import org.hipparchus.util.MathUtils;
33 import org.orekit.data.DataProvidersManager;
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.IERSConventions;
40 import org.orekit.utils.IERSConventions.NutationCorrectionConverter;
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 class RapidDataAndPredictionColumnsLoader extends AbstractEopLoader
67 implements EOPHistoryLoader {
68
69
70 private static final double ARC_SECONDS_TO_RADIANS = MathUtils.TWO_PI / 1296000;
71
72
73 private static final double MILLI_ARC_SECONDS_TO_RADIANS = ARC_SECONDS_TO_RADIANS / 1000;
74
75
76 private static final double MILLI_SECONDS_TO_SECONDS = 1.0e-3;
77
78
79 private static final String INTEGER2_FIELD = "((?:\\p{Blank}|\\p{Digit})\\p{Digit})";
80
81
82 private static final String MJD_FIELD = "\\p{Blank}+(\\p{Digit}+)(?:\\.00*)";
83
84
85 private static final String SEPARATOR = "\\p{Blank}*[IP]";
86
87
88 private static final String REAL_FIELD = "\\p{Blank}*(-?\\p{Digit}*\\.\\p{Digit}*)";
89
90
91 private static int DATE_START = 0;
92
93
94 private static int DATE_END = 15;
95
96
97 private static final Pattern DATE_PATTERN = Pattern.compile(INTEGER2_FIELD + INTEGER2_FIELD + INTEGER2_FIELD + MJD_FIELD);
98
99
100 private static int POLE_START = 16;
101
102
103 private static int POLE_END = 55;
104
105
106 private static final Pattern POLE_PATTERN = Pattern.compile(SEPARATOR + REAL_FIELD + REAL_FIELD + REAL_FIELD + REAL_FIELD);
107
108
109 private static int UT1_UTC_START = 57;
110
111
112 private static int UT1_UTC_END = 78;
113
114
115 private static final Pattern UT1_UTC_PATTERN = Pattern.compile(SEPARATOR + REAL_FIELD + REAL_FIELD);
116
117
118 private static int LOD_START = 79;
119
120
121 private static int LOD_END = 93;
122
123
124 private static final Pattern LOD_PATTERN = Pattern.compile(REAL_FIELD + REAL_FIELD);
125
126
127 private static int NUTATION_START = 95;
128
129
130 private static int NUTATION_END = 134;
131
132
133 private static final Pattern NUTATION_PATTERN = Pattern.compile(SEPARATOR + REAL_FIELD + REAL_FIELD + REAL_FIELD + REAL_FIELD);
134
135
136 private final boolean isNonRotatingOrigin;
137
138
139
140
141
142
143
144
145
146
147 RapidDataAndPredictionColumnsLoader(final boolean isNonRotatingOrigin,
148 final String supportedNames,
149 final DataProvidersManager manager,
150 final Supplier<TimeScale> utcSupplier) {
151 super(supportedNames, manager, utcSupplier);
152 this.isNonRotatingOrigin = isNonRotatingOrigin;
153 }
154
155
156 public void fillHistory(final IERSConventions.NutationCorrectionConverter converter,
157 final SortedSet<EOPEntry> history) {
158 final ItrfVersionProvider itrfVersionProvider = new ITRFVersionLoader(
159 ITRFVersionLoader.SUPPORTED_NAMES,
160 getDataProvidersManager());
161 final Parser parser =
162 new Parser(converter, itrfVersionProvider, getUtc(), isNonRotatingOrigin);
163 final EopParserLoaderopParserLoader">EopParserLoader loader = new EopParserLoader(parser);
164 this.feed(loader);
165 history.addAll(loader.getEop());
166 }
167
168
169 static class Parser extends AbstractEopParser {
170
171
172 private final boolean isNonRotatingOrigin;
173
174
175
176
177
178
179
180 Parser(final NutationCorrectionConverter converter,
181 final ItrfVersionProvider itrfVersionProvider,
182 final TimeScale utc,
183 final boolean isNonRotatingOrigin) {
184 super(converter, itrfVersionProvider, utc);
185 this.isNonRotatingOrigin = isNonRotatingOrigin;
186 }
187
188
189 @Override
190 public Collection<EOPEntry> parse(final InputStream input, final String name)
191 throws IOException {
192
193 final List<EOPEntry> history = new ArrayList<>();
194 ITRFVersionLoader.ITRFVersionConfiguration configuration = null;
195
196
197 int lineNumber = 0;
198
199
200 try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {
201
202 for (String line = reader.readLine(); line != null; line = reader.readLine()) {
203
204 lineNumber++;
205
206
207 final String datePart = (line.length() >= DATE_END) ? line.substring(DATE_START, DATE_END) : "";
208 final String polePart = (line.length() >= POLE_END) ? line.substring(POLE_START, POLE_END) : "";
209 final String ut1utcPart = (line.length() >= UT1_UTC_END ) ? line.substring(UT1_UTC_START, UT1_UTC_END) : "";
210 final String lodPart = (line.length() >= LOD_END) ? line.substring(LOD_START, LOD_END) : "";
211 final String nutationPart = (line.length() >= NUTATION_END) ? line.substring(NUTATION_START, NUTATION_END) : "";
212
213
214 final Matcher dateMatcher = DATE_PATTERN.matcher(datePart);
215 final int mjd;
216 if (dateMatcher.matches()) {
217 final int yy = Integer.parseInt(dateMatcher.group(1).trim());
218 final int mm = Integer.parseInt(dateMatcher.group(2).trim());
219 final int dd = Integer.parseInt(dateMatcher.group(3).trim());
220 mjd = Integer.parseInt(dateMatcher.group(4).trim());
221 final DateComponents">DateComponents reconstructedDate = new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, mjd);
222 if ((reconstructedDate.getYear() % 100) != yy ||
223 reconstructedDate.getMonth() != mm ||
224 reconstructedDate.getDay() != dd) {
225 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
226 lineNumber, name, line);
227 }
228 } else {
229 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
230 lineNumber, name, line);
231 }
232
233
234 final double x;
235 final double y;
236 if (polePart.trim().length() == 0) {
237
238 x = 0;
239 y = 0;
240 } else {
241 final Matcher poleMatcher = POLE_PATTERN.matcher(polePart);
242 if (poleMatcher.matches()) {
243 x = ARC_SECONDS_TO_RADIANS * Double.parseDouble(poleMatcher.group(1));
244 y = ARC_SECONDS_TO_RADIANS * Double.parseDouble(poleMatcher.group(3));
245 } else {
246 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
247 lineNumber, name, line);
248 }
249 }
250
251
252 final double dtu1;
253 if (ut1utcPart.trim().length() == 0) {
254
255 dtu1 = 0;
256 } else {
257 final Matcher ut1utcMatcher = UT1_UTC_PATTERN.matcher(ut1utcPart);
258 if (ut1utcMatcher.matches()) {
259 dtu1 = Double.parseDouble(ut1utcMatcher.group(1));
260 } else {
261 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
262 lineNumber, name, line);
263 }
264 }
265
266
267 final double lod;
268 if (lodPart.trim().length() == 0) {
269
270 lod = 0;
271 } else {
272 final Matcher lodMatcher = LOD_PATTERN.matcher(lodPart);
273 if (lodMatcher.matches()) {
274 lod = MILLI_SECONDS_TO_SECONDS * Double.parseDouble(lodMatcher.group(1));
275 } else {
276 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
277 lineNumber, name, line);
278 }
279 }
280
281
282 final double[] nro;
283 final double[] equinox;
284 final AbsoluteDate mjdDate =
285 new AbsoluteDate(new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, mjd),
286 getUtc());
287 if (nutationPart.trim().length() == 0) {
288
289 nro = new double[2];
290 equinox = new double[2];
291 } else {
292 final Matcher nutationMatcher = NUTATION_PATTERN.matcher(nutationPart);
293 if (nutationMatcher.matches()) {
294 if (isNonRotatingOrigin) {
295 nro = new double[] {
296 MILLI_ARC_SECONDS_TO_RADIANS * Double.parseDouble(nutationMatcher.group(1)),
297 MILLI_ARC_SECONDS_TO_RADIANS * Double.parseDouble(nutationMatcher.group(3))
298 };
299 equinox = getConverter().toEquinox(mjdDate, nro[0], nro[1]);
300 } else {
301 equinox = new double[] {
302 MILLI_ARC_SECONDS_TO_RADIANS * Double.parseDouble(nutationMatcher.group(1)),
303 MILLI_ARC_SECONDS_TO_RADIANS * Double.parseDouble(nutationMatcher.group(3))
304 };
305 nro = getConverter().toNonRotating(mjdDate, equinox[0], equinox[1]);
306 }
307 } else {
308 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
309 lineNumber, name, line);
310 }
311 }
312
313 if (configuration == null || !configuration.isValid(mjd)) {
314
315 configuration = getItrfVersionProvider().getConfiguration(name, mjd);
316 }
317 history.add(new EOPEntry(mjd, dtu1, lod, x, y, equinox[0], equinox[1], nro[0], nro[1],
318 configuration.getVersion(), mjdDate));
319
320 }
321
322 }
323
324 return history;
325 }
326
327 }
328
329 }