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