1 /* Copyright 2002-2024 CS GROUP
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.data;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.InputStreamReader;
23 import java.io.Serializable;
24 import java.nio.charset.StandardCharsets;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32
33 import org.hipparchus.CalculusFieldElement;
34 import org.hipparchus.exception.DummyLocalizable;
35 import org.hipparchus.util.FastMath;
36 import org.orekit.annotation.DefaultDataContext;
37 import org.orekit.errors.OrekitException;
38 import org.orekit.errors.OrekitInternalError;
39 import org.orekit.errors.OrekitMessages;
40 import org.orekit.time.AbsoluteDate;
41 import org.orekit.time.FieldAbsoluteDate;
42 import org.orekit.time.TimeScalarFunction;
43 import org.orekit.time.TimeScale;
44 import org.orekit.time.TimeScales;
45 import org.orekit.utils.Constants;
46 import org.orekit.utils.IERSConventions;
47
48 /**
49 * Class computing the fundamental arguments for nutation and tides.
50 * <p>
51 * The fundamental arguments are split in two sets:
52 * </p>
53 * <ul>
54 * <li>the Delaunay arguments for Moon and Sun effects</li>
55 * <li>the planetary arguments for other planets</li>
56 * </ul>
57 *
58 * @author Luc Maisonobe
59 * @see SeriesTerm
60 * @see PoissonSeries
61 * @see BodiesElements
62 */
63 public class FundamentalNutationArguments implements Serializable {
64
65 /** Serializable UID. */
66 private static final long serialVersionUID = 20131209L;
67
68 /** IERS conventions to use. */
69 private final IERSConventions conventions;
70
71 /** Time scale for GMST computation. */
72 private final TimeScale timeScale;
73
74 /** Function computing Greenwich Mean Sidereal Time. */
75 private final transient TimeScalarFunction gmstFunction;
76
77 /** Function computing Greenwich Mean Sidereal Time rate. */
78 private final transient TimeScalarFunction gmstRateFunction;
79
80 // luni-solar Delaunay arguments
81
82 /** Coefficients for mean anomaly of the Moon. */
83 private final double[] lCoefficients;
84
85 /** Coefficients for mean anomaly of the Sun. */
86 private final double[] lPrimeCoefficients;
87
88 /** Coefficients for L - Ω where L is the mean longitude of the Moon. */
89 private final double[] fCoefficients;
90
91 /** Coefficients for mean elongation of the Moon from the Sun. */
92 private final double[] dCoefficients;
93
94 /** Coefficients for mean longitude of the ascending node of the Moon. */
95 private final double[] omegaCoefficients;
96
97 // planetary nutation arguments
98
99 /** Coefficients for mean Mercury longitude. */
100 private final double[] lMeCoefficients;
101
102 /** Coefficients for mean Venus longitude. */
103 private final double[] lVeCoefficients;
104
105 /** Coefficients for mean Earth longitude. */
106 private final double[] lECoefficients;
107
108 /** Coefficients for mean Mars longitude. */
109 private final double[] lMaCoefficients;
110
111 /** Coefficients for mean Jupiter longitude. */
112 private final double[] lJCoefficients;
113
114 /** Coefficients for mean Saturn longitude. */
115 private final double[] lSaCoefficients;
116
117 /** Coefficients for mean Uranus longitude. */
118 private final double[] lUCoefficients;
119
120 /** Coefficients for mean Neptune longitude. */
121 private final double[] lNeCoefficients;
122
123 /** Coefficients for general accumulated precession. */
124 private final double[] paCoefficients;
125
126 /** Set of time scales to use in computations. */
127 private final transient TimeScales timeScales;
128
129 /** Build a model of fundamental arguments from an IERS table file.
130 *
131 * <p>This method uses the {@link DataContext#getDefault() default data context}.
132 *
133 * @param conventions IERS conventions to use
134 * @param timeScale time scale for GMST computation
135 * (may be null if tide parameter γ = GMST + π is not needed)
136 * @param stream stream containing the IERS table
137 * @param name name of the resource file (for error messages only)
138 * @see #FundamentalNutationArguments(IERSConventions, TimeScale, List, TimeScales)
139 * @see #FundamentalNutationArguments(IERSConventions, TimeScale, InputStream, String, TimeScales)
140 */
141 @DefaultDataContext
142 public FundamentalNutationArguments(final IERSConventions conventions,
143 final TimeScale timeScale,
144 final InputStream stream, final String name) {
145 this(conventions, timeScale, stream, name,
146 DataContext.getDefault().getTimeScales());
147 }
148
149 /**
150 * Build a model of fundamental arguments from an IERS table file.
151 *
152 * @param conventions IERS conventions to use
153 * @param timeScale time scale for GMST computation (may be null if tide parameter γ
154 * = GMST + π is not needed)
155 * @param stream stream containing the IERS table
156 * @param name name of the resource file (for error messages only)
157 * @param timeScales TAI time scale
158 * @see #FundamentalNutationArguments(IERSConventions, TimeScale, List, TimeScales)
159 * @since 10.1
160 */
161 public FundamentalNutationArguments(final IERSConventions conventions,
162 final TimeScale timeScale,
163 final InputStream stream,
164 final String name,
165 final TimeScales timeScales) {
166 this(conventions, timeScale, parseCoefficients(stream, name), timeScales);
167 }
168
169 /** Build a model of fundamental arguments from an IERS table file.
170 *
171 * <p>This method uses the {@link DataContext#getDefault() default data context}.
172 *
173 * @param conventions IERS conventions to use
174 * @param timeScale time scale for GMST computation
175 * (may be null if tide parameter γ = GMST + π is not needed)
176 * @param coefficients list of coefficients arrays (all 14 arrays must be provided,
177 * the 5 Delaunay first and the 9 planetary afterwards)
178 * @since 6.1
179 * @see #FundamentalNutationArguments(IERSConventions, TimeScale, List, TimeScales)
180 */
181 @DefaultDataContext
182 public FundamentalNutationArguments(final IERSConventions conventions, final TimeScale timeScale,
183 final List<double[]> coefficients) {
184 this(conventions, timeScale, coefficients,
185 DataContext.getDefault().getTimeScales());
186 }
187
188 /** Build a model of fundamental arguments from an IERS table file.
189 * @param conventions IERS conventions to use
190 * @param timeScale time scale for GMST computation
191 * (may be null if tide parameter γ = GMST + π is not needed)
192 * @param coefficients list of coefficients arrays (all 14 arrays must be provided,
193 * the 5 Delaunay first and the 9 planetary afterwards)
194 * @param timeScales used in the computation.
195 * @since 10.1
196 */
197 public FundamentalNutationArguments(final IERSConventions conventions,
198 final TimeScale timeScale,
199 final List<double[]> coefficients,
200 final TimeScales timeScales) {
201 this.conventions = conventions;
202 this.timeScale = timeScale;
203 this.timeScales = timeScales;
204 this.gmstFunction = (timeScale == null) ? null :
205 conventions.getGMSTFunction(timeScale, timeScales);
206 this.gmstRateFunction = (timeScale == null) ? null :
207 conventions.getGMSTRateFunction(timeScale, timeScales);
208 this.lCoefficients = coefficients.get( 0);
209 this.lPrimeCoefficients = coefficients.get( 1);
210 this.fCoefficients = coefficients.get( 2);
211 this.dCoefficients = coefficients.get( 3);
212 this.omegaCoefficients = coefficients.get( 4);
213 this.lMeCoefficients = coefficients.get( 5);
214 this.lVeCoefficients = coefficients.get( 6);
215 this.lECoefficients = coefficients.get( 7);
216 this.lMaCoefficients = coefficients.get( 8);
217 this.lJCoefficients = coefficients.get( 9);
218 this.lSaCoefficients = coefficients.get(10);
219 this.lUCoefficients = coefficients.get(11);
220 this.lNeCoefficients = coefficients.get(12);
221 this.paCoefficients = coefficients.get(13);
222 }
223
224 /** Parse coefficients.
225 * @param stream stream containing the IERS table
226 * @param name name of the resource file (for error messages only)
227 * @return list of coefficients arrays
228 */
229 private static List<double[]> parseCoefficients(final InputStream stream, final String name) {
230
231 if (stream == null) {
232 throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, name);
233 }
234
235 // setup the reader
236 try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
237
238 final DefinitionParser definitionParser = new DefinitionParser();
239
240 int lineNumber = 0;
241
242 // look for the reference date and the 14 polynomials
243 final int n = FundamentalName.values().length;
244 final Map<FundamentalName, double[]> polynomials = new HashMap<FundamentalName, double[]>(n);
245 for (String line = reader.readLine(); line != null; line = reader.readLine()) {
246 lineNumber++;
247 if (definitionParser.parseDefinition(line, lineNumber, name)) {
248 polynomials.put(definitionParser.getParsedName(),
249 definitionParser.getParsedPolynomial());
250 }
251 }
252
253 final List<double[]> coefficients = new ArrayList<double[]>(n);
254 coefficients.add(getCoefficients(FundamentalName.L, polynomials, name));
255 coefficients.add(getCoefficients(FundamentalName.L_PRIME, polynomials, name));
256 coefficients.add(getCoefficients(FundamentalName.F, polynomials, name));
257 coefficients.add(getCoefficients(FundamentalName.D, polynomials, name));
258 coefficients.add(getCoefficients(FundamentalName.OMEGA, polynomials, name));
259 if (polynomials.containsKey(FundamentalName.L_ME)) {
260 // IERS conventions 2003 and later provide planetary nutation arguments
261 coefficients.add(getCoefficients(FundamentalName.L_ME, polynomials, name));
262 coefficients.add(getCoefficients(FundamentalName.L_VE, polynomials, name));
263 coefficients.add(getCoefficients(FundamentalName.L_E, polynomials, name));
264 coefficients.add(getCoefficients(FundamentalName.L_MA, polynomials, name));
265 coefficients.add(getCoefficients(FundamentalName.L_J, polynomials, name));
266 coefficients.add(getCoefficients(FundamentalName.L_SA, polynomials, name));
267 coefficients.add(getCoefficients(FundamentalName.L_U, polynomials, name));
268 coefficients.add(getCoefficients(FundamentalName.L_NE, polynomials, name));
269 coefficients.add(getCoefficients(FundamentalName.PA, polynomials, name));
270 } else {
271 // IERS conventions 1996 and earlier don't provide planetary nutation arguments
272 final double[] zero = new double[] {
273 0.0
274 };
275 while (coefficients.size() < n) {
276 coefficients.add(zero);
277 }
278 }
279
280 return coefficients;
281
282 } catch (IOException ioe) {
283 throw new OrekitException(ioe, new DummyLocalizable(ioe.getMessage()));
284 }
285
286 }
287
288 /** Get the coefficients for a fundamental argument.
289 * @param argument fundamental argument
290 * @param polynomials map of the polynomials
291 * @param fileName name of the file from which the coefficients have been read
292 * @return polynomials coefficients (ordered from high degrees to low degrees)
293 */
294 private static double[] getCoefficients(final FundamentalName argument,
295 final Map<FundamentalName, double[]> polynomials,
296 final String fileName) {
297 if (!polynomials.containsKey(argument)) {
298 throw new OrekitException(OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE, fileName);
299 }
300 return polynomials.get(argument);
301 }
302
303 /** Evaluate a polynomial.
304 * @param tc offset in Julian centuries
305 * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
306 * @return value of the polynomial
307 */
308 private double value(final double tc, final double[] coefficients) {
309 double value = 0;
310 for (int i = coefficients.length - 1; i >= 0; --i) {
311 value = coefficients[i] + tc * value;
312 }
313 return value;
314 }
315
316 /** Evaluate a polynomial time derivative.
317 * @param tc offset in Julian centuries
318 * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
319 * @return time derivative of the polynomial
320 */
321 private double derivative(final double tc, final double[] coefficients) {
322 double derivative = 0;
323 for (int i = coefficients.length - 1; i > 0; --i) {
324 derivative = i * coefficients[i] + tc * derivative;
325 }
326 return derivative / Constants.JULIAN_CENTURY;
327 }
328
329 /** Evaluate a polynomial.
330 * @param tc offset in Julian centuries
331 * @param <T> type of the field elements
332 * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
333 * @return value of the polynomial
334 */
335 private <T extends CalculusFieldElement<T>> T value(final T tc, final double[] coefficients) {
336 T value = tc.getField().getZero();
337 for (int i = coefficients.length - 1; i >= 0; --i) {
338 value = tc.multiply(value).add(coefficients[i]);
339 }
340 return value;
341 }
342
343 /** Evaluate a polynomial time derivative.
344 * @param tc offset in Julian centuries
345 * @param <T> type of the field elements
346 * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
347 * @return time derivative of the polynomial
348 */
349 private <T extends CalculusFieldElement<T>> T derivative(final T tc, final double[] coefficients) {
350 T derivative = tc.getField().getZero();
351 for (int i = coefficients.length - 1; i > 0; --i) {
352 derivative = tc.multiply(derivative).add(i * coefficients[i]);
353 }
354 return derivative.divide(Constants.JULIAN_CENTURY);
355 }
356
357 /** Evaluate all fundamental arguments for the current date (Delaunay plus planetary).
358 * @param date current date
359 * @return all fundamental arguments for the current date (Delaunay plus planetary)
360 */
361 public BodiesElements evaluateAll(final AbsoluteDate date) {
362
363 final double tc = conventions.evaluateTC(date, timeScales);
364 final double gamma = gmstFunction == null ?
365 Double.NaN : gmstFunction.value(date) + FastMath.PI;
366 final double gammaDot = gmstRateFunction == null ?
367 Double.NaN : gmstRateFunction.value(date);
368
369 return new BodiesElements(date, tc, gamma, gammaDot,
370 value(tc, lCoefficients), // mean anomaly of the Moon
371 derivative(tc, lCoefficients), // mean anomaly of the Moon time derivative
372 value(tc, lPrimeCoefficients), // mean anomaly of the Sun
373 derivative(tc, lPrimeCoefficients), // mean anomaly of the Sun time derivative
374 value(tc, fCoefficients), // L - Ω where L is the mean longitude of the Moon
375 derivative(tc, fCoefficients), // L - Ω where L is the mean longitude of the Moon time derivative
376 value(tc, dCoefficients), // mean elongation of the Moon from the Sun
377 derivative(tc, dCoefficients), // mean elongation of the Moon from the Sun time derivative
378 value(tc, omegaCoefficients), // mean longitude of the ascending node of the Moon
379 derivative(tc, omegaCoefficients), // mean longitude of the ascending node of the Moon time derivative
380 value(tc, lMeCoefficients), // mean Mercury longitude
381 derivative(tc, lMeCoefficients), // mean Mercury longitude time derivative
382 value(tc, lVeCoefficients), // mean Venus longitude
383 derivative(tc, lVeCoefficients), // mean Venus longitude time derivative
384 value(tc, lECoefficients), // mean Earth longitude
385 derivative(tc, lECoefficients), // mean Earth longitude time derivative
386 value(tc, lMaCoefficients), // mean Mars longitude
387 derivative(tc, lMaCoefficients), // mean Mars longitude time derivative
388 value(tc, lJCoefficients), // mean Jupiter longitude
389 derivative(tc, lJCoefficients), // mean Jupiter longitude time derivative
390 value(tc, lSaCoefficients), // mean Saturn longitude
391 derivative(tc, lSaCoefficients), // mean Saturn longitude time derivative
392 value(tc, lUCoefficients), // mean Uranus longitude
393 derivative(tc, lUCoefficients), // mean Uranus longitude time derivative
394 value(tc, lNeCoefficients), // mean Neptune longitude
395 derivative(tc, lNeCoefficients), // mean Neptune longitude time derivative
396 value(tc, paCoefficients), // general accumulated precession in longitude
397 derivative(tc, paCoefficients)); // general accumulated precession in longitude time derivative
398
399 }
400
401 /** Evaluate all fundamental arguments for the current date (Delaunay plus planetary).
402 * @param date current date
403 * @param <T> type of the field elements
404 * @return all fundamental arguments for the current date (Delaunay plus planetary)
405 */
406 public <T extends CalculusFieldElement<T>> FieldBodiesElements<T> evaluateAll(final FieldAbsoluteDate<T> date) {
407
408 final T tc = conventions.evaluateTC(date, timeScales);
409 final T gamma = gmstFunction == null ?
410 tc.getField().getZero().add(Double.NaN) : gmstFunction.value(date).add(tc.getPi());
411 final T gammaDot = gmstRateFunction == null ?
412 tc.getField().getZero().add(Double.NaN) : gmstRateFunction.value(date);
413
414 return new FieldBodiesElements<>(date, tc, gamma, gammaDot,
415 value(tc, lCoefficients), // mean anomaly of the Moon
416 derivative(tc, lCoefficients), // mean anomaly of the Moon time derivative
417 value(tc, lPrimeCoefficients), // mean anomaly of the Sun
418 derivative(tc, lPrimeCoefficients), // mean anomaly of the Sun time derivative
419 value(tc, fCoefficients), // L - Ω where L is the mean longitude of the Moon
420 derivative(tc, fCoefficients), // L - Ω where L is the mean longitude of the Moon time derivative
421 value(tc, dCoefficients), // mean elongation of the Moon from the Sun
422 derivative(tc, dCoefficients), // mean elongation of the Moon from the Sun time derivative
423 value(tc, omegaCoefficients), // mean longitude of the ascending node of the Moon
424 derivative(tc, omegaCoefficients), // mean longitude of the ascending node of the Moon time derivative
425 value(tc, lMeCoefficients), // mean Mercury longitude
426 derivative(tc, lMeCoefficients), // mean Mercury longitude time derivative
427 value(tc, lVeCoefficients), // mean Venus longitude
428 derivative(tc, lVeCoefficients), // mean Venus longitude time derivative
429 value(tc, lECoefficients), // mean Earth longitude
430 derivative(tc, lECoefficients), // mean Earth longitude time derivative
431 value(tc, lMaCoefficients), // mean Mars longitude
432 derivative(tc, lMaCoefficients), // mean Mars longitude time derivative
433 value(tc, lJCoefficients), // mean Jupiter longitude
434 derivative(tc, lJCoefficients), // mean Jupiter longitude time derivative
435 value(tc, lSaCoefficients), // mean Saturn longitude
436 derivative(tc, lSaCoefficients), // mean Saturn longitude time derivative
437 value(tc, lUCoefficients), // mean Uranus longitude
438 derivative(tc, lUCoefficients), // mean Uranus longitude time derivative
439 value(tc, lNeCoefficients), // mean Neptune longitude
440 derivative(tc, lNeCoefficients), // mean Neptune longitude time derivative
441 value(tc, paCoefficients), // general accumulated precession in longitude
442 derivative(tc, paCoefficients)); // general accumulated precession in longitude time derivative
443
444 }
445
446 /** Replace the instance with a data transfer object for serialization.
447 * <p>
448 * This intermediate class serializes only the frame key.
449 * </p>
450 * @return data transfer object that will be serialized
451 */
452 @DefaultDataContext
453 private Object writeReplace() {
454 return new DataTransferObject(conventions, timeScale,
455 Arrays.asList(lCoefficients, lPrimeCoefficients, fCoefficients,
456 dCoefficients, omegaCoefficients,
457 lMeCoefficients, lVeCoefficients, lECoefficients,
458 lMaCoefficients, lJCoefficients, lSaCoefficients,
459 lUCoefficients, lNeCoefficients, paCoefficients));
460 }
461
462 /** Internal class used only for serialization. */
463 @DefaultDataContext
464 private static class DataTransferObject implements Serializable {
465
466 /** Serializable UID. */
467 private static final long serialVersionUID = 20131209L;
468
469 /** IERS conventions to use. */
470 private final IERSConventions conventions;
471
472 /** Time scale for GMST computation. */
473 private final TimeScale timeScale;
474
475 /** All coefficients. */
476 private final List<double[]> coefficients;
477
478 /** Simple constructor.
479 * @param conventions IERS conventions to use
480 * @param timeScale time scale for GMST computation
481 * @param coefficients all coefficients
482 */
483 DataTransferObject(final IERSConventions conventions, final TimeScale timeScale,
484 final List<double[]> coefficients) {
485 this.conventions = conventions;
486 this.timeScale = timeScale;
487 this.coefficients = coefficients;
488 }
489
490 /** Replace the deserialized data transfer object with a {@link TIRFProvider}.
491 * @return replacement {@link TIRFProvider}
492 */
493 private Object readResolve() {
494 try {
495 // retrieve a managed frame
496 return new FundamentalNutationArguments(conventions, timeScale, coefficients);
497 } catch (OrekitException oe) {
498 throw new OrekitInternalError(oe);
499 }
500 }
501
502 }
503
504 /** Enumerate for the fundamental names. */
505 private enum FundamentalName {
506
507 /** Constant for Mean anomaly of the Moon. */
508 L() {
509 /** {@inheritDoc} */
510 public String getArgumentName() {
511 return "l";
512 }
513 },
514
515 /** Constant for Mean anomaly of the Sun. */
516 L_PRIME() {
517 /** {@inheritDoc} */
518 public String getArgumentName() {
519 return "l'";
520 }
521 },
522
523 /** Constant for L - Ω where L is the mean longitude of the Moon. */
524 F() {
525 /** {@inheritDoc} */
526 public String getArgumentName() {
527 return "F";
528 }
529 },
530
531 /** Constant for mean elongation of the Moon from the Sun. */
532 D() {
533 /** {@inheritDoc} */
534 public String getArgumentName() {
535 return "D";
536 }
537 },
538
539 /** Constant for longitude of the ascending node of the Moon. */
540 OMEGA() {
541 /** {@inheritDoc} */
542 public String getArgumentName() {
543 return "\u03a9";
544 }
545 },
546
547 /** Constant for mean Mercury longitude. */
548 L_ME() {
549 /** {@inheritDoc} */
550 public String getArgumentName() {
551 return "LMe";
552 }
553 },
554
555 /** Constant for mean Venus longitude. */
556 L_VE() {
557 /** {@inheritDoc} */
558 public String getArgumentName() {
559 return "LVe";
560 }
561 },
562
563 /** Constant for mean Earth longitude. */
564 L_E() {
565 /** {@inheritDoc} */
566 public String getArgumentName() {
567 return "LE";
568 }
569 },
570
571 /** Constant for mean Mars longitude. */
572 L_MA() {
573 /** {@inheritDoc} */
574 public String getArgumentName() {
575 return "LMa";
576 }
577 },
578
579 /** Constant for mean Jupiter longitude. */
580 L_J() {
581 /** {@inheritDoc} */
582 public String getArgumentName() {
583 return "LJ";
584 }
585 },
586
587 /** Constant for mean Saturn longitude. */
588 L_SA() {
589 /** {@inheritDoc} */
590 public String getArgumentName() {
591 return "LSa";
592 }
593 },
594
595 /** Constant for mean Uranus longitude. */
596 L_U() {
597 /** {@inheritDoc} */
598 public String getArgumentName() {
599 return "LU";
600 }
601 },
602
603 /** Constant for mean Neptune longitude. */
604 L_NE() {
605 /** {@inheritDoc} */
606 public String getArgumentName() {
607 return "LNe";
608 }
609 },
610
611 /** Constant for general accumulated precession in longitude. */
612 PA() {
613 /** {@inheritDoc} */
614 public String getArgumentName() {
615 return "pA";
616 }
617 };
618
619 /** Get the fundamental name.
620 * @return fundamental name
621 */
622 public abstract String getArgumentName();
623
624 }
625
626 /** Local parser for argument definition lines. */
627 private static class DefinitionParser {
628
629 /** Regular expression pattern for definitions. */
630 private final Pattern pattern;
631
632 /** Parser for polynomials. */
633 private PolynomialParser polynomialParser;
634
635 /** Last parsed fundamental name. */
636 private FundamentalName parsedName;
637
638 /** Last parsed polynomial. */
639 private double[] parsedPolynomial;
640
641 /** Simple constructor. */
642 DefinitionParser() {
643
644 // the luni-solar Delaunay arguments polynomial parts should read something like:
645 // F5 ≡ Ω = 125.04455501° − 6962890.5431″t + 7.4722″t² + 0.007702″t³ − 0.00005939″t⁴
646 // whereas the planetary arguments polynomial parts should read something like:
647 // F14 ≡ pA = 0.02438175 × t + 0.00000538691 × t²
648 final String unicodeIdenticalTo = "\u2261";
649
650 // pattern for the global line
651 final StringBuilder builder = new StringBuilder();
652 for (final FundamentalName fn : FundamentalName.values()) {
653 if (builder.length() > 0) {
654 builder.append('|');
655 }
656 builder.append(fn.getArgumentName());
657 }
658 final String fundamentalName = "\\p{Space}*((?:" + builder.toString() + ")+)";
659 pattern = Pattern.compile("\\p{Space}*F\\p{Digit}+\\p{Space}*" + unicodeIdenticalTo +
660 fundamentalName + "\\p{Space}*=\\p{Space}*(.*)");
661
662 polynomialParser = new PolynomialParser('t', PolynomialParser.Unit.NO_UNITS);
663
664 }
665
666 /** Parse a definition line.
667 * @param line line to parse
668 * @param lineNumber line number
669 * @param fileName name of the file
670 * @return true if a definition has been parsed
671 */
672 public boolean parseDefinition(final String line, final int lineNumber, final String fileName) {
673
674 parsedName = null;
675 parsedPolynomial = null;
676
677 final Matcher matcher = pattern.matcher(line);
678 if (matcher.matches()) {
679 for (FundamentalName fn : FundamentalName.values()) {
680 if (fn.getArgumentName().equals(matcher.group(1))) {
681 parsedName = fn;
682 }
683 }
684
685 // parse the polynomial
686 parsedPolynomial = polynomialParser.parse(matcher.group(2));
687
688 return true;
689
690 } else {
691 return false;
692 }
693
694 }
695
696 /** Get the last parsed fundamental name.
697 * @return last parsed fundamental name
698 */
699 public FundamentalName getParsedName() {
700 return parsedName;
701 }
702
703 /** Get the last parsed polynomial.
704 * @return last parsed polynomial
705 */
706 public double[] getParsedPolynomial() {
707 return parsedPolynomial.clone();
708 }
709
710 }
711
712 }