1   /* Copyright 2002-2026 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.bodies;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.hipparchus.CalculusFieldElement;
23  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24  import org.hipparchus.geometry.euclidean.threed.Vector3D;
25  import org.hipparchus.util.FastMath;
26  import org.hipparchus.util.FieldSinCos;
27  import org.hipparchus.util.SinCos;
28  import org.orekit.bodies.JPLEphemeridesLoader.EphemerisType;
29  import org.orekit.time.AbsoluteDate;
30  import org.orekit.time.FieldAbsoluteDate;
31  import org.orekit.time.TimeScales;
32  import org.orekit.utils.Constants;
33  
34  /** Enumerate for predefined IAU poles.
35   * <p>The pole models provided here come from the <a
36   * href="http://astropedia.astrogeology.usgs.gov/alfresco/d/d/workspace/SpacesStore/28fd9e81-1964-44d6-a58b-fbbf61e64e15/WGCCRE2009reprint.pdf">
37   * 2009 report</a> and the <a href="http://astropedia.astrogeology.usgs.gov/alfresco/d/d/workspace/SpacesStore/04d348b0-eb2b-46a2-abe9-6effacb37763/WGCCRE-Erratum-2011reprint.pdf">
38   * 2011 erratum</a> of the IAU/IAG Working Group on Cartographic Coordinates
39   * and Rotational Elements of the Planets and Satellites (WGCCRE). Note that these value
40   * differ from earliest reports (before 2005).
41   *</p>
42   * @author Luc Maisonobe
43   * @since 9.0
44   */
45  abstract class PredefinedIAUPoles implements IAUPole {
46  
47      /** Serializable UID. */
48      private static final long serialVersionUID = 20200130L;
49  
50      /** Time scales. */
51      private final TimeScales timeScales;
52      /**
53       * {@code true} iff this is GCRF aligned.
54       *
55       * @since 14.0
56       */
57      private final boolean isGcrf;
58  
59      /**
60       * Simple constructor.
61       *
62       * @param timeScales to use when computing the pole, including TDB and J2000.0.
63       */
64      PredefinedIAUPoles(final TimeScales timeScales) {
65          this(timeScales, false);
66      }
67  
68      /**
69       * Simple constructor.
70       *
71       * @param timeScales to use when computing the pole, including TDB and
72       *                   J2000.0.
73       * @param isGcrf     {@code true} iff this is GCRF aligned.
74       * @since 14.0
75       */
76      PredefinedIAUPoles(final TimeScales timeScales,
77                         final boolean isGcrf) {
78          this.timeScales = timeScales;
79          this.isGcrf = isGcrf;
80      }
81  
82      /** IAU pole and prime meridian model for Sun. */
83      private static class Sun extends PredefinedIAUPoles {
84  
85          /** Serializable UID. */
86          private static final long serialVersionUID = 20200130L;
87  
88          /** Constant term of the prime meridian. */
89          private static final double W0 = 84.176;
90  
91          /** Rate term of the prime meridian. */
92          private static final double W_DOT = 14.1844000;
93  
94          /** Fixed pole. */
95          private final Vector3D pole = new Vector3D(FastMath.toRadians(286.13),
96                                                     FastMath.toRadians(63.87));
97  
98          /**
99           * Simple constructor.
100          *
101          * @param timeScales to use when computing the pole, including TDB and J2000.0.
102          */
103         Sun(final TimeScales timeScales) {
104             super(timeScales);
105         }
106 
107         /** {@inheritDoc} */
108         public Vector3D getPole(final AbsoluteDate date) {
109             return pole;
110         }
111 
112         /** {@inheritDoc} */
113         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
114             return new FieldVector3D<>(date.getField(), pole);
115         }
116 
117         /** {@inheritDoc} */
118         public double getPrimeMeridianAngle(final AbsoluteDate date) {
119             return FastMath.toRadians(d(date) * W_DOT + W0);
120         }
121 
122         /** {@inheritDoc} */
123         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
124             return FastMath.toRadians(d(date).multiply(W_DOT).add(W0));
125         }
126 
127     }
128 
129     /** IAU pole and prime meridian model for Mercury. */
130     private static class Mercury extends PredefinedIAUPoles {
131 
132         /** Serializable UID. */
133         private static final long serialVersionUID = 20200130L;
134 
135         /** Constant term of the right ascension of the pole. */
136         private static final double ALPHA_0 = 281.0097;
137 
138         /** Rate term of the right ascension of the pole. */
139         private static final double ALPHA_DOT = -0.0328;
140 
141         /** Constant term of the declination of the pole. */
142         private static final double DELTA_0 = 61.4143;
143 
144         /** Rate term of the declination of the pole. */
145         private static final double DELTA_DOT = -0.0049;
146 
147         /** Constant term of the prime meridian. */
148         private static final double W_0 = 329.5469;
149 
150         /** Rate term of the prime meridian. */
151         private static final double W_DOT = 6.1385025;
152 
153         /** M1 coefficient of the prime meridian. */
154         private static final double M1_COEFF = 0.00993822;
155 
156         /** M2 coefficient of the prime meridian. */
157         private static final double M2_COEFF = -0.00104581;
158 
159         /** M3 coefficient of the prime meridian. */
160         private static final double M3_COEFF = -0.00010280;
161 
162         /** M4 coefficient of the prime meridian. */
163         private static final double M4_COEFF = -0.00002364;
164 
165         /** M5 coefficient of the prime meridian. */
166         private static final double M5_COEFF = -0.00000532;
167 
168         /** Constant term of the M1 angle. */
169         private static final double M1_0   = 174.791086;
170 
171         /** Rate term of the M1 angle. */
172         private static final double M1_DOT = 4.092335;
173 
174         /** Constant term of the M2 angle. */
175         private static final double M2_0   = 349.582171;
176 
177         /** Rate term of the M1 angle. */
178         private static final double M2_DOT = 8.184670;
179 
180         /** Constant term of the M3 angle. */
181         private static final double M3_0   = 164.373257;
182 
183         /** Rate term of the M1 angle. */
184         private static final double M3_DOT = 12.277005;
185 
186         /** Constant term of the M4 angle. */
187         private static final double M4_0   = 339.164343;
188 
189         /** Rate term of the M1 angle. */
190         private static final double M4_DOT = 16.369340;
191 
192         /** Constant term of the M5 angle. */
193         private static final double M5_0   = 153.955429;
194 
195         /** Rate term of the M1 angle. */
196         private static final double M5_DOT = 20.461675;
197 
198         /**
199          * Simple constructor.
200          *
201          * @param timeScales to use when computing the pole, including TDB and J2000.0.
202          */
203         Mercury(final TimeScales timeScales) {
204             super(timeScales);
205         }
206 
207         /** {@inheritDoc} */
208         public Vector3D getPole(final AbsoluteDate date) {
209             final double t = t(date);
210             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
211                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
212         }
213 
214         /** {@inheritDoc} */
215         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
216             final T t = t(date);
217             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
218                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
219         }
220 
221         /** {@inheritDoc} */
222         public double getPrimeMeridianAngle(final AbsoluteDate date) {
223             final double d = d(date);
224             return FastMath.toRadians(d(date) * W_DOT + W_0 +
225                                       FastMath.sin(FastMath.toRadians(d * M1_DOT + M1_0)) * M1_COEFF +
226                                       FastMath.sin(FastMath.toRadians(d * M2_DOT + M2_0)) * M2_COEFF +
227                                       FastMath.sin(FastMath.toRadians(d * M3_DOT + M3_0)) * M3_COEFF +
228                                       FastMath.sin(FastMath.toRadians(d * M4_DOT + M4_0)) * M4_COEFF +
229                                       FastMath.sin(FastMath.toRadians(d * M5_DOT + M5_0)) * M5_COEFF);
230         }
231 
232         /** {@inheritDoc} */
233         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
234             final T d = d(date);
235             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0).
236                              add(FastMath.toRadians(d.multiply(M1_DOT).add(M1_0)).sin().multiply(M1_COEFF)).
237                              add(FastMath.toRadians(d.multiply(M2_DOT).add(M2_0)).sin().multiply(M2_COEFF)).
238                              add(FastMath.toRadians(d.multiply(M3_DOT).add(M3_0)).sin().multiply(M3_COEFF)).
239                              add(FastMath.toRadians(d.multiply(M4_DOT).add(M4_0)).sin().multiply(M4_COEFF)).
240                              add(FastMath.toRadians(d.multiply(M5_DOT).add(M5_0)).sin().multiply(M5_COEFF)));
241         }
242 
243     }
244 
245     /** IAU pole and prime meridian model for Venus. */
246     private static class Venus extends PredefinedIAUPoles {
247 
248         /** Serializable UID. */
249         private static final long serialVersionUID = 20200130L;
250 
251         /** Constant term of the prime meridian. */
252         private static final double W_0 = 160.20;
253 
254         /** Rate term of the prime meridian. */
255         private static final double W_DOT = -1.4813688;
256 
257         /** Fixed pole. */
258         private final Vector3D pole = new Vector3D(FastMath.toRadians(272.76),
259                                                    FastMath.toRadians(67.16));
260 
261         /**
262          * Simple constructor.
263          *
264          * @param timeScales to use when computing the pole, including TDB and J2000.0.
265          */
266         Venus(final TimeScales timeScales) {
267             super(timeScales);
268         }
269 
270         /** {@inheritDoc} */
271         public Vector3D getPole(final AbsoluteDate date) {
272             return pole;
273         }
274 
275         /** {@inheritDoc} */
276         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
277             return new FieldVector3D<>(date.getField(), pole);
278         }
279 
280         /** {@inheritDoc} */
281         public double getPrimeMeridianAngle(final AbsoluteDate date) {
282             return FastMath.toRadians(d(date) * W_DOT + W_0);
283         }
284 
285         /** {@inheritDoc} */
286         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
287             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
288         }
289 
290     }
291 
292     /** IAU pole and prime meridian model for Earth. */
293     private static class Earth extends PredefinedIAUPoles {
294 
295         /** Serializable UID. */
296         private static final long serialVersionUID = 20200130L;
297 
298         /** Constant term of the right ascension of the pole. */
299         private static final double ALPHA_0 =  0.00;
300 
301         /** Rate term of the right ascension of the pole. */
302         private static final double ALPHA_DOT = -0.641;
303 
304         /** Constant term of the declination of the pole. */
305         private static final double DELTA_0 = 90.00;
306 
307         /** Rate term of the declination of the pole. */
308         private static final double DELTA_DOT = -0.557;
309 
310         /** Constant term of the prime meridian. */
311         private static final double W_0 = 190.147;
312 
313         /** Rate term of the prime meridian. */
314         private static final double W_DOT = 360.9856235;
315 
316         /**
317          * Simple constructor.
318          *
319          * @param timeScales to use when computing the pole, including TDB and J2000.0.
320          */
321         Earth(final TimeScales timeScales) {
322             super(timeScales);
323         }
324 
325         /** {@inheritDoc} */
326         public Vector3D getPole(final AbsoluteDate date) {
327             final double t = t(date);
328             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
329                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
330         }
331 
332         /** {@inheritDoc} */
333         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
334             final T t = t(date);
335             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
336                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
337         }
338 
339         /** {@inheritDoc} */
340         @Override
341         public Vector3D getNode(final AbsoluteDate date) {
342             final double t = t(date);
343             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0 + 90.0),
344                                 0.0);
345         }
346 
347         /** {@inheritDoc} */
348         @Override
349         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getNode(final FieldAbsoluteDate<T> date) {
350             final T t = t(date);
351             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0 + 90.0)),
352                                        date.getField().getZero());
353         }
354 
355         /** {@inheritDoc} */
356         public double getPrimeMeridianAngle(final AbsoluteDate date) {
357             return FastMath.toRadians(d(date) * W_DOT + W_0);
358         }
359 
360         /** {@inheritDoc} */
361         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
362             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
363         }
364 
365     }
366 
367     /** IAU pole and prime meridian model for the Moon. */
368     private static class Moon extends PredefinedIAUPoles {
369 
370         /** Serializable UID. */
371         private static final long serialVersionUID = 20200130L;
372 
373         /** Constant term of the right ascension of the pole. */
374         private static final double ALPHA_0 = 269.9949;
375 
376         /** Rate term of the right ascension of the pole. */
377         private static final double ALPHA_DOT = 0.0031;
378 
379         /** Constant term of the declination of the pole. */
380         private static final double DELTA_0 = 66.5392;
381 
382         /** Rate term of the declination of the pole. */
383         private static final double DELTA_DOT =  0.0130;
384 
385         /** Constant term of the prime meridian. */
386         private static final double W_0 = 38.3213;
387 
388         /** Rate term of the prime meridian. */
389         private static final double W_DOT = 13.17635815;
390 
391         /** Rate term of the prime meridian. */
392         private static final double W_DOT_DOT = -1.4e-12;
393 
394         /** Constant term of the E1 angle. */
395         private static final double E01_0    = 125.045;
396 
397         /** Rate term of the E1 angle. */
398         private static final double E01_DOT  =  -0.0529921;
399 
400         /** Sine coefficient of the E1 angle. */
401         private static final double E01_SIN  = -3.8787;
402 
403         /** Cosine coefficient of the E1 angle. */
404         private static final double E01_COS  =  1.5419;
405 
406         /** Sine coefficient of the E1 angle, for the prime meridian. */
407         private static final double E01_W_SIN =  3.5610;
408 
409         /** Constant term of the E2 angle. */
410         private static final double E02_0    = 250.089;
411 
412         /** Rate term of the E2 angle. */
413         private static final double E02_DOT  =  -0.1059842;
414 
415         /** Sine coefficient of the E2 angle. */
416         private static final double E02_SIN  = -0.1204;
417 
418         /** Cosine coefficient of the E2 angle. */
419         private static final double E02_COS  =  0.0239;
420 
421         /** Sine coefficient of the E2 angle, for the prime meridian. */
422         private static final double E02_W_SIN =  0.1208;
423 
424         /** Constant term of the E3 angle. */
425         private static final double E03_0    = 260.008;
426 
427         /** Rate term of the E3 angle. */
428         private static final double E03_DOT  =  13.0120009;
429 
430         /** Sine coefficient of the E3 angle. */
431         private static final double E03_SIN  =  0.0700;
432 
433         /** Cosine coefficient of the E3 angle. */
434         private static final double E03_COS  = -0.0278;
435 
436         /** Sine coefficient of the E3 angle, for the prime meridian. */
437         private static final double E03_W_SIN = -0.0642;
438 
439         /** Constant term of the E4 angle. */
440         private static final double E04_0    = 176.625;
441 
442         /** Rate term of the E4 angle. */
443         private static final double E04_DOT  =  13.3407154;
444 
445         /** Sine coefficient of the E4 angle. */
446         private static final double E04_SIN  = -0.0172;
447 
448         /** Cosine coefficient of the E4 angle. */
449         private static final double E04_COS  =  0.0068;
450 
451         /** Sine coefficient of the E4 angle, for the prime meridian. */
452         private static final double E04_W_SIN =  0.0158;
453 
454         /** Constant term of the E5 angle. */
455         private static final double E05_0    = 357.529;
456 
457         /** Rate term of the E5 angle. */
458         private static final double E05_DOT  =   0.9856003;
459 
460         /** Sine coefficient of the E5 angle, for the prime meridian. */
461         private static final double E05_W_SIN =  0.0252;
462 
463         /** Constant term of the E6 angle. */
464         private static final double E06_0    = 311.589;
465 
466         /** Rate term of the E6 angle. */
467         private static final double E06_DOT  =  26.4057084;
468 
469         /** Sine coefficient of the E6 angle. */
470         private static final double E06_SIN  = 0.0072;
471 
472         /** Cosine coefficient of the E6 angle. */
473         private static final double E06_COS  = -0.0029;
474 
475         /** Sine coefficient of the E6 angle, for the prime meridian. */
476         private static final double E06_W_SIN = -0.0066;
477 
478         /** Constant term of the E7 angle. */
479         private static final double E07_0    = 134.963;
480 
481         /** Rate term of the E7 angle. */
482         private static final double E07_DOT  =  13.0649930;
483 
484         /** Cosine coefficient of the E7 angle. */
485         private static final double E07_COS  =  0.0009;
486 
487         /** Sine coefficient of the E7 angle, for the prime meridian. */
488         private static final double E07_W_SIN = -0.0047;
489 
490         /** Constant term of the E8 angle. */
491         private static final double E08_0    = 276.617;
492 
493         /** Rate term of the E8 angle. */
494         private static final double E08_DOT  =   0.3287146;
495 
496         /** Sine coefficient of the E8 angle, for the prime meridian. */
497         private static final double E08_W_SIN = -0.0046;
498 
499         /** Constant term of the E9 angle. */
500         private static final double E09_0    =  34.226;
501 
502         /** Rate term of the E9 angle. */
503         private static final double E09_DOT  =   1.7484877;
504 
505         /** Sine coefficient of the E9 angle, for the prime meridian. */
506         private static final double E09_W_SIN =  0.0028;
507 
508         /** Constant term of the E10 angle. */
509         private static final double E10_0    =  15.134;
510 
511         /** Rate term of the E10 angle. */
512         private static final double E10_DOT  =  -0.1589763;
513 
514         /** Sine coefficient of the E10 angle. */
515         private static final double E10_SIN  = -0.0052;
516 
517         /** Cosine coefficient of the E10 angle. */
518         private static final double E10_COS  = 0.0008;
519 
520         /** Sine coefficient of the E10 angle, for the prime meridian. */
521         private static final double E10_W_SIN =  0.0052;
522 
523         /** Constant term of the E11 angle. */
524         private static final double E11_0    = 119.743;
525 
526         /** Rate term of the E11 angle. */
527         private static final double E11_DOT  =   0.0036096;
528 
529         /** Sine coefficient of the E11 angle, for the prime meridian. */
530         private static final double E11_W_SIN =  0.0040;
531 
532         /** Constant term of the E12 angle. */
533         private static final double E12_0    = 239.961;
534 
535         /** Rate term of the E12 angle. */
536         private static final double E12_DOT  =   0.1643573;
537 
538         /** Sine coefficient of the E12 angle, for the prime meridian. */
539         private static final double E12_W_SIN =  0.0019;
540 
541         /** Constant term of the E13 angle. */
542         private static final double E13_0    =  25.053;
543 
544         /** Rate term of the E13 angle. */
545         private static final double E13_DOT  =  12.9590088;
546 
547         /** Sine coefficient of the E13 angle. */
548         private static final double E13_SIN  = 0.0043;
549 
550         /** Cosine coefficient of the E13 angle. */
551         private static final double E13_COS  = -0.0009;
552 
553         /** Sine coefficient of the E13 angle, for the prime meridian. */
554         private static final double E13_W_SIN = -0.0044;
555 
556         /**
557          * Simple constructor.
558          *
559          * @param timeScales to use when computing the pole, including TDB and J2000.0.
560          */
561         Moon(final TimeScales timeScales) {
562             super(timeScales);
563         }
564 
565         /** {@inheritDoc} */
566         public Vector3D getPole(final AbsoluteDate date) {
567             final double d = d(date);
568             final double t = t(date);
569 
570             final SinCos scE01 = FastMath.sinCos(FastMath.toRadians(d * E01_DOT + E01_0));
571             final SinCos scE02 = FastMath.sinCos(FastMath.toRadians(d * E02_DOT + E02_0));
572             final SinCos scE03 = FastMath.sinCos(FastMath.toRadians(d * E03_DOT + E03_0));
573             final SinCos scE04 = FastMath.sinCos(FastMath.toRadians(d * E04_DOT + E04_0));
574             final SinCos scE06 = FastMath.sinCos(FastMath.toRadians(d * E06_DOT + E06_0));
575             final SinCos scE10 = FastMath.sinCos(FastMath.toRadians(d * E10_DOT + E10_0));
576             final SinCos scE13 = FastMath.sinCos(FastMath.toRadians(d * E13_DOT + E13_0));
577 
578             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0 +
579                                                    scE01.sin() * E01_SIN +
580                                                    scE02.sin() * E02_SIN +
581                                                    scE03.sin() * E03_SIN +
582                                                    scE04.sin() * E04_SIN +
583                                                    scE06.sin() * E06_SIN +
584                                                    scE10.sin() * E10_SIN +
585                                                    scE13.sin() * E13_SIN),
586                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0 +
587                                                    scE01.cos() * E01_COS +
588                                                    scE02.cos() * E02_COS +
589                                                    scE03.cos() * E03_COS +
590                                                    scE04.cos() * E04_COS +
591                                                    scE06.cos() * E06_COS +
592                                                    FastMath.cos(FastMath.toRadians(d * E07_DOT + E07_0)) * E07_COS +  // only the cosine is needed
593                                                    scE10.cos() * E10_COS +
594                                                    scE13.cos() * E13_COS));
595         }
596 
597         /** {@inheritDoc} */
598         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
599             final T d = d(date);
600             final T t = t(date);
601 
602             final FieldSinCos<T> scE01 = FastMath.sinCos(FastMath.toRadians(d.multiply(E01_DOT).add(E01_0)));
603             final FieldSinCos<T> scE02 = FastMath.sinCos(FastMath.toRadians(d.multiply(E02_DOT).add(E02_0)));
604             final FieldSinCos<T> scE03 = FastMath.sinCos(FastMath.toRadians(d.multiply(E03_DOT).add(E03_0)));
605             final FieldSinCos<T> scE04 = FastMath.sinCos(FastMath.toRadians(d.multiply(E04_DOT).add(E04_0)));
606             final FieldSinCos<T> scE06 = FastMath.sinCos(FastMath.toRadians(d.multiply(E06_DOT).add(E06_0)));
607             final FieldSinCos<T> scE10 = FastMath.sinCos(FastMath.toRadians(d.multiply(E10_DOT).add(E10_0)));
608             final FieldSinCos<T> scE13 = FastMath.sinCos(FastMath.toRadians(d.multiply(E13_DOT).add(E13_0)));
609 
610             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0).
611                                                  add(scE01.sin().multiply(E01_SIN)).
612                                                  add(scE02.sin().multiply(E02_SIN)).
613                                                  add(scE03.sin().multiply(E03_SIN)).
614                                                  add(scE04.sin().multiply(E04_SIN)).
615                                                  add(scE06.sin().multiply(E06_SIN)).
616                                                  add(scE10.sin().multiply(E10_SIN)).
617                                                  add(scE13.sin().multiply(E13_SIN))),
618                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0).
619                                                  add(scE01.cos().multiply(E01_COS)).
620                                                  add(scE02.cos().multiply(E02_COS)).
621                                                  add(scE03.cos().multiply(E03_COS)).
622                                                  add(scE04.cos().multiply(E04_COS)).
623                                                  add(scE06.cos().multiply(E06_COS)).
624                                                  add(FastMath.toRadians(d.multiply(E07_DOT).add(E07_0)).cos().multiply(E07_COS)).// only the cosine is needed
625                                                  add(scE10.cos().multiply(E10_COS)).
626                                                  add(scE13.cos().multiply(E13_COS))));
627         }
628 
629         /** {@inheritDoc} */
630         public double getPrimeMeridianAngle(final AbsoluteDate date) {
631             final double d = d(date);
632 
633             return FastMath.toRadians(d * (d * W_DOT_DOT + W_DOT) + W_0 +
634                                       FastMath.sin(FastMath.toRadians(d * E01_DOT + E01_0)) * E01_W_SIN +
635                                       FastMath.sin(FastMath.toRadians(d * E02_DOT + E02_0)) * E02_W_SIN +
636                                       FastMath.sin(FastMath.toRadians(d * E03_DOT + E03_0)) * E03_W_SIN +
637                                       FastMath.sin(FastMath.toRadians(d * E04_DOT + E04_0)) * E04_W_SIN +
638                                       FastMath.sin(FastMath.toRadians(d * E05_DOT + E05_0)) * E05_W_SIN +
639                                       FastMath.sin(FastMath.toRadians(d * E06_DOT + E06_0)) * E06_W_SIN +
640                                       FastMath.sin(FastMath.toRadians(d * E07_DOT + E07_0)) * E07_W_SIN +
641                                       FastMath.sin(FastMath.toRadians(d * E08_DOT + E08_0)) * E08_W_SIN +
642                                       FastMath.sin(FastMath.toRadians(d * E09_DOT + E09_0)) * E09_W_SIN +
643                                       FastMath.sin(FastMath.toRadians(d * E10_DOT + E10_0)) * E10_W_SIN +
644                                       FastMath.sin(FastMath.toRadians(d * E11_DOT + E11_0)) * E11_W_SIN +
645                                       FastMath.sin(FastMath.toRadians(d * E12_DOT + E12_0)) * E12_W_SIN +
646                                       FastMath.sin(FastMath.toRadians(d * E13_DOT + E13_0)) * E13_W_SIN);
647         }
648 
649         /** {@inheritDoc} */
650         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
651             final T d = d(date);
652             return FastMath.toRadians(d.multiply(d.multiply(W_DOT_DOT).add(W_DOT)).add(W_0).
653                                       add(FastMath.toRadians(d.multiply(E01_DOT).add(E01_0)).sin().multiply(E01_W_SIN)).
654                                       add(FastMath.toRadians(d.multiply(E02_DOT).add(E02_0)).sin().multiply(E02_W_SIN)).
655                                       add(FastMath.toRadians(d.multiply(E03_DOT).add(E03_0)).sin().multiply(E03_W_SIN)).
656                                       add(FastMath.toRadians(d.multiply(E04_DOT).add(E04_0)).sin().multiply(E04_W_SIN)).
657                                       add(FastMath.toRadians(d.multiply(E05_DOT).add(E05_0)).sin().multiply(E05_W_SIN)).
658                                       add(FastMath.toRadians(d.multiply(E06_DOT).add(E06_0)).sin().multiply(E06_W_SIN)).
659                                       add(FastMath.toRadians(d.multiply(E07_DOT).add(E07_0)).sin().multiply(E07_W_SIN)).
660                                       add(FastMath.toRadians(d.multiply(E08_DOT).add(E08_0)).sin().multiply(E08_W_SIN)).
661                                       add(FastMath.toRadians(d.multiply(E09_DOT).add(E09_0)).sin().multiply(E09_W_SIN)).
662                                       add(FastMath.toRadians(d.multiply(E10_DOT).add(E10_0)).sin().multiply(E10_W_SIN)).
663                                       add(FastMath.toRadians(d.multiply(E11_DOT).add(E11_0)).sin().multiply(E11_W_SIN)).
664                                       add(FastMath.toRadians(d.multiply(E12_DOT).add(E12_0)).sin().multiply(E12_W_SIN)).
665                                       add(FastMath.toRadians(d.multiply(E13_DOT).add(E13_0)).sin().multiply(E13_W_SIN)));
666         }
667 
668     }
669 
670     /** IAU pole and prime meridian model for Mars. */
671     private static class Mars extends PredefinedIAUPoles {
672 
673         /** Serializable UID. */
674         private static final long serialVersionUID = 20200130L;
675 
676         /** Constant term of the right ascension of the pole. */
677         private static final double ALPHA_0 = 317.68143;
678 
679         /** Rate term of the right ascension of the pole. */
680         private static final double ALPHA_DOT = -0.1061;
681 
682         /** Constant term of the declination of the pole. */
683         private static final double DELTA_0 =  52.88650;
684 
685         /** Rate term of the declination of the pole. */
686         private static final double DELTA_DOT = -0.0609;
687 
688         /** Constant term of the prime meridian. */
689         private static final double W_0 = 176.630;
690 
691         /** Rate term of the prime meridian. */
692         private static final double W_DOT = 350.89198226;
693 
694         /**
695          * Simple constructor.
696          *
697          * @param timeScales to use when computing the pole, including TDB and J2000.0.
698          */
699         Mars(final TimeScales timeScales) {
700             super(timeScales);
701         }
702 
703         /** {@inheritDoc} */
704         public Vector3D getPole(final AbsoluteDate date) {
705             final double t = t(date);
706             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
707                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
708         }
709 
710         /** {@inheritDoc} */
711         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
712             final T t = t(date);
713             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
714                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
715         }
716 
717         /** {@inheritDoc} */
718         public double getPrimeMeridianAngle(final AbsoluteDate date) {
719             return FastMath.toRadians(d(date) * W_DOT + W_0);
720         }
721 
722         /** {@inheritDoc} */
723         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
724             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
725         }
726 
727     }
728 
729     /** IAU pole and prime meridian model for Jupiter. */
730     private static class Jupiter extends PredefinedIAUPoles {
731 
732         /** Serializable UID. */
733         private static final long serialVersionUID = 20200130L;
734 
735         /** Constant term of the right ascension of the pole. */
736         private static final double ALPHA_0 = 268.056595;
737 
738         /** Rate term of the right ascension of the pole. */
739         private static final double ALPHA_DOT = -0.006499;
740 
741         /** Constant term of the declination of the pole. */
742         private static final double DELTA_0 = 64.495303;
743 
744         /** Rate term of the declination of the pole. */
745         private static final double DELTA_DOT = 0.002413;
746 
747         /** Constant term of the ja angle. */
748         private static final double JA_0 =  99.360714;
749 
750         /** Rate term of the ja angle. */
751         private static final double JA_DOT = 4850.4046;
752 
753         /** Sine coefficient of the ja angle. */
754         private static final double JA_SIN = 0.000117;
755 
756         /** Cosine coefficient of the ja angle. */
757         private static final double JA_COS = 0.000050;
758 
759         /** Constant term of the jb angle. */
760         private static final double JB_0 = 175.895369;
761 
762         /** Rate term of the jb angle. */
763         private static final double JB_DOT = 1191.9605;
764 
765         /** Sine coefficient of the jb angle. */
766         private static final double JB_SIN = 0.000938;
767 
768         /** Cosine coefficient of the jb angle. */
769         private static final double JB_COS = 0.000404;
770 
771         /** Constant term of the jc angle. */
772         private static final double JC_0 = 300.323162;
773 
774         /** Rate term of the jc angle. */
775         private static final double JC_DOT = 262.5475;
776 
777         /** Sine coefficient of the jc angle. */
778         private static final double JC_SIN = 0.001432;
779 
780         /** Cosine coefficient of the jc angle. */
781         private static final double JC_COS = 0.000617;
782 
783         /** Constant term of the jd angle. */
784         private static final double JD_0 = 114.012305;
785 
786         /** Rate term of the jd angle. */
787         private static final double JD_DOT = 6070.2476;
788 
789         /** Sine coefficient of the jd angle. */
790         private static final double JD_SIN = 0.000030;
791 
792         /** Cosine coefficient of the jd angle. */
793         private static final double JD_COS = -0.000013;
794 
795         /** Constant term of the je angle. */
796         private static final double JE_0 = 49.511251;
797 
798         /** Rate term of the je angle. */
799         private static final double JE_DOT = 64.3000;
800 
801         /** Sine coefficient of the je angle. */
802         private static final double JE_SIN = 0.002150;
803 
804         /** Cosine coefficient of the je angle. */
805         private static final double JE_COS = 0.000926;
806 
807         /** Constant term of the prime meridian. */
808         private static final double W_0 = 284.95;
809 
810         /** Rate term of the prime meridian. */
811         private static final double W_DOT = 870.5360000;
812 
813         /**
814          * Simple constructor.
815          *
816          * @param timeScales to use when computing the pole, including TDB and J2000.0.
817          */
818         Jupiter(final TimeScales timeScales) {
819             super(timeScales);
820         }
821 
822         /** {@inheritDoc} */
823         public Vector3D getPole(final AbsoluteDate date) {
824 
825             final double t = t(date);
826             final double ja = FastMath.toRadians(t * JA_DOT + JA_0);
827             final double jb = FastMath.toRadians(t * JB_DOT + JB_0);
828             final double jc = FastMath.toRadians(t * JC_DOT + JC_0);
829             final double jd = FastMath.toRadians(t * JD_DOT + JD_0);
830             final double je = FastMath.toRadians(t * JE_DOT + JE_0);
831 
832             final SinCos scJa = FastMath.sinCos(ja);
833             final SinCos scJb = FastMath.sinCos(jb);
834             final SinCos scJc = FastMath.sinCos(jc);
835             final SinCos scJd = FastMath.sinCos(jd);
836             final SinCos scJe = FastMath.sinCos(je);
837 
838             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0 +
839                                                    scJa.sin() * JA_SIN +
840                                                    scJb.sin() * JB_SIN +
841                                                    scJc.sin() * JC_SIN +
842                                                    scJd.sin() * JD_SIN +
843                                                    scJe.sin() * JE_SIN),
844                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0 +
845                                                    scJa.cos() * JA_COS +
846                                                    scJb.cos() * JB_COS +
847                                                    scJc.cos() * JC_COS +
848                                                    scJd.cos() * JD_COS +
849                                                    scJe.cos() * JE_COS));
850         }
851 
852         /** {@inheritDoc} */
853         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
854 
855             final T t = t(date);
856             final T ja = FastMath.toRadians(t.multiply(JA_DOT).add(JA_0));
857             final T jb = FastMath.toRadians(t.multiply(JB_DOT).add(JB_0));
858             final T jc = FastMath.toRadians(t.multiply(JC_DOT).add(JC_0));
859             final T jd = FastMath.toRadians(t.multiply(JD_DOT).add(JD_0));
860             final T je = FastMath.toRadians(t.multiply(JE_DOT).add(JE_0));
861 
862             final FieldSinCos<T> scJa = FastMath.sinCos(ja);
863             final FieldSinCos<T> scJb = FastMath.sinCos(jb);
864             final FieldSinCos<T> scJc = FastMath.sinCos(jc);
865             final FieldSinCos<T> scJd = FastMath.sinCos(jd);
866             final FieldSinCos<T> scJe = FastMath.sinCos(je);
867 
868             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0).
869                                                  add(scJa.sin().multiply(JA_SIN)).
870                                                  add(scJb.sin().multiply(JB_SIN)).
871                                                  add(scJc.sin().multiply(JC_SIN)).
872                                                  add(scJd.sin().multiply(JD_SIN)).
873                                                  add(scJe.sin().multiply(JE_SIN))),
874                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0).
875                                                  add(scJa.cos().multiply(JA_COS)).
876                                                  add(scJb.cos().multiply(JB_COS)).
877                                                  add(scJc.cos().multiply(JC_COS)).
878                                                  add(scJd.cos().multiply(JD_COS)).
879                                                  add(scJe.cos().multiply(JE_COS))));
880 
881         }
882 
883         /** {@inheritDoc} */
884         public double getPrimeMeridianAngle(final AbsoluteDate date) {
885             return FastMath.toRadians(d(date) * W_DOT + W_0);
886         }
887 
888         /** {@inheritDoc} */
889         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
890             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
891         }
892 
893     }
894 
895     /** IAU pole and prime meridian model for Saturn. */
896     private static class Saturn extends PredefinedIAUPoles {
897 
898         /** Serializable UID. */
899         private static final long serialVersionUID = 20200130L;
900 
901         /** Constant term of the right ascension of the pole. */
902         private static final double ALPHA_0 = 40.589;
903 
904         /** Rate term of the right ascension of the pole. */
905         private static final double ALPHA_DOT = -0.036;
906 
907         /** Constant term of the declination of the pole. */
908         private static final double DELTA_0 = 83.537;
909 
910         /** Rate term of the declination of the pole. */
911         private static final double DELTA_DOT = -0.004;
912 
913         /** Constant term of the prime meridian. */
914         private static final double W_0 = 38.90;
915 
916         /** Rate term of the prime meridian. */
917         private static final double W_DOT = 810.7939024;
918 
919         /**
920          * Simple constructor.
921          *
922          * @param timeScales to use when computing the pole, including TDB and J2000.0.
923          */
924         Saturn(final TimeScales timeScales) {
925             super(timeScales);
926         }
927 
928         /** {@inheritDoc} */
929         public Vector3D getPole(final AbsoluteDate date) {
930             final double t = t(date);
931             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
932                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
933         }
934 
935         /** {@inheritDoc} */
936         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
937             final T t = t(date);
938             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
939                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
940         }
941 
942         /** {@inheritDoc} */
943         public double getPrimeMeridianAngle(final AbsoluteDate date) {
944             return FastMath.toRadians(d(date) * W_DOT + W_0);
945         }
946 
947         /** {@inheritDoc} */
948         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
949             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
950         }
951 
952     }
953 
954     /** IAU pole and prime meridian model for Uranus. */
955     private static class Uranus extends PredefinedIAUPoles {
956 
957         /** Serializable UID. */
958         private static final long serialVersionUID = 20200130L;
959 
960         /** Constant term of the prime meridian. */
961         private static final double W_0 = 203.81;
962 
963         /** Rate term of the prime meridian. */
964         private static final double W_DOT = -501.1600928;
965 
966         /** Fixed pole. */
967         private final Vector3D pole = new Vector3D(FastMath.toRadians(257.311),
968                                                    FastMath.toRadians(-15.175));
969 
970         /**
971          * Simple constructor.
972          *
973          * @param timeScales to use when computing the pole, including TDB and J2000.0.
974          */
975         Uranus(final TimeScales timeScales) {
976             super(timeScales);
977         }
978 
979         /** {@inheritDoc} */
980         public Vector3D getPole(final AbsoluteDate date) {
981             return pole;
982         }
983 
984         /** {@inheritDoc} */
985         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
986             return new FieldVector3D<>(date.getField(), pole);
987         }
988 
989         /** {@inheritDoc} */
990         public double getPrimeMeridianAngle(final AbsoluteDate date) {
991             return FastMath.toRadians(d(date) * W_DOT + W_0);
992         }
993 
994         /** {@inheritDoc} */
995         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
996             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
997         }
998 
999     }
1000 
1001     /** IAU pole and prime meridian model for Neptune. */
1002     private static class Neptune extends PredefinedIAUPoles {
1003 
1004         /** Serializable UID. */
1005         private static final long serialVersionUID = 20200130L;
1006 
1007         /** Constant term of the right ascension of the pole. */
1008         private static final double ALPHA_0 = 299.36;
1009 
1010         /** Sine term of the right ascension of the pole. */
1011         private static final double ALPHA_SIN = 0.70;
1012 
1013         /** Constant term of the declination of the pole. */
1014         private static final double DELTA_0 = 43.46;
1015 
1016         /** Cosine term of the declination of the pole. */
1017         private static final double DELTA_COS = -0.51;
1018 
1019         /** Constant term of the prime meridian. */
1020         private static final double W_0 = 253.18;
1021 
1022         /** Rate term of the prime meridian. */
1023         private static final double W_DOT = 536.3128492;
1024 
1025         /** Sine term of the prime meridian. */
1026         private static final double W_SIN = -0.48;
1027 
1028         /** Constant term of the N angle. */
1029         private static final double N_0   = 357.85;
1030 
1031         /** Rate term of the M1 angle. */
1032         private static final double N_DOT = 52.316;
1033 
1034         /**
1035          * Simple constructor.
1036          *
1037          * @param timeScales to use when computing the pole, including TDB and J2000.0.
1038          */
1039         Neptune(final TimeScales timeScales) {
1040             super(timeScales);
1041         }
1042 
1043         /** {@inheritDoc} */
1044         public Vector3D getPole(final AbsoluteDate date) {
1045             final double n  = FastMath.toRadians(t(date) * N_DOT + N_0);
1046             final SinCos sc = FastMath.sinCos(n);
1047             return new Vector3D(FastMath.toRadians(sc.sin() * ALPHA_SIN + ALPHA_0),
1048                                 FastMath.toRadians(sc.cos() * DELTA_COS + DELTA_0));
1049         }
1050 
1051         /** {@inheritDoc} */
1052         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
1053             final T n = FastMath.toRadians(t(date).multiply(N_DOT).add(N_0));
1054             final FieldSinCos<T> sc = FastMath.sinCos(n);
1055             return new FieldVector3D<>(FastMath.toRadians(sc.sin().multiply(ALPHA_SIN).add(ALPHA_0)),
1056                                        FastMath.toRadians(sc.cos().multiply(DELTA_COS).add(DELTA_0)));
1057         }
1058 
1059         /** {@inheritDoc} */
1060         public double getPrimeMeridianAngle(final AbsoluteDate date) {
1061             final double n = FastMath.toRadians(t(date) * N_DOT + N_0);
1062             return FastMath.toRadians(d(date) * W_DOT + FastMath.sin(n) * W_SIN + W_0);
1063         }
1064 
1065         /** {@inheritDoc} */
1066         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
1067             final T n = FastMath.toRadians(t(date).multiply(N_DOT).add(N_0));
1068             return FastMath.toRadians(d(date).multiply(W_DOT).add(n.sin().multiply(W_SIN)).add(W_0));
1069         }
1070 
1071     }
1072 
1073     /** IAU pole and prime meridian model for Pluto. */
1074     private static class Pluto extends PredefinedIAUPoles {
1075 
1076         /** Serializable UID. */
1077         private static final long serialVersionUID = 20200130L;
1078 
1079         /** Constant term of the prime meridian. */
1080         private static final double W_0 = 302.695;
1081 
1082         /** Rate term of the prime meridian. */
1083         private static final double W_DOT = 56.3625225;
1084 
1085         /** Fixed pole. */
1086         private final Vector3D pole = new Vector3D(FastMath.toRadians(132.993),
1087                                                    FastMath.toRadians(-6.163));
1088 
1089         /**
1090          * Simple constructor.
1091          *
1092          * @param timeScales to use when computing the pole, including TDB and J2000.0.
1093          */
1094         Pluto(final TimeScales timeScales) {
1095             super(timeScales);
1096         }
1097 
1098         /** {@inheritDoc} */
1099         public Vector3D getPole(final AbsoluteDate date) {
1100             return pole;
1101         }
1102 
1103         /** {@inheritDoc} */
1104         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
1105             return new FieldVector3D<>(date.getField(), pole);
1106         }
1107 
1108         /** {@inheritDoc} */
1109         public double getPrimeMeridianAngle(final AbsoluteDate date) {
1110             return FastMath.toRadians(d(date) * W_DOT + W_0);
1111         }
1112 
1113         /** {@inheritDoc} */
1114         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
1115             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
1116         }
1117 
1118     }
1119 
1120     /** Default IAUPole implementation for barycenters.
1121      * <p>
1122      * This implementation defines directions such that the inertially oriented and body
1123      * oriented frames are identical and aligned with GCRF. It is used for example
1124      * to define the ICRF.
1125      * </p>
1126      */
1127     private static class GcrfAligned extends PredefinedIAUPoles {
1128 
1129         /** Serializable UID. */
1130         private static final long serialVersionUID = 20200130L;
1131 
1132         /**
1133          * Simple constructor.
1134          *
1135          * @param timeScales to use when computing the pole, including TDB and J2000.0.
1136          */
1137         GcrfAligned(final TimeScales timeScales) {
1138             super(timeScales, true);
1139         }
1140 
1141         /** {@inheritDoc} */
1142         public Vector3D getPole(final AbsoluteDate date) {
1143             return Vector3D.PLUS_K;
1144         }
1145 
1146         /** {@inheritDoc} */
1147         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
1148             return FieldVector3D.getPlusK(date.getField());
1149         }
1150 
1151         /** {@inheritDoc} */
1152         @Override
1153         public Vector3D getNode(final AbsoluteDate date) {
1154             return Vector3D.PLUS_I;
1155         }
1156 
1157         /** {@inheritDoc} */
1158         @Override
1159         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getNode(final FieldAbsoluteDate<T> date) {
1160             return FieldVector3D.getPlusI(date.getField());
1161         }
1162 
1163         /** {@inheritDoc} */
1164         public double getPrimeMeridianAngle(final AbsoluteDate date) {
1165             return 0;
1166         }
1167 
1168         /** {@inheritDoc} */
1169         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
1170             return date.getField().getZero();
1171         }
1172 
1173     }
1174 
1175 
1176     /** Get a predefined IAU pole.
1177      * @param body body identifier
1178      * @param timeScales to use when computing the pole, including TDB and J2000.0.
1179      * @return predefined IAU pole
1180      */
1181     public static PredefinedIAUPoles getIAUPole(final EphemerisType body,
1182                                                 final TimeScales timeScales) {
1183 
1184         switch (body) {
1185             case SUN :
1186                 return new Sun(timeScales);
1187             case MERCURY :
1188                 return new Mercury(timeScales);
1189             case VENUS :
1190                 return new Venus(timeScales);
1191             case EARTH :
1192                 return new Earth(timeScales);
1193             case MOON :
1194                 return new Moon(timeScales);
1195             case MARS :
1196                 return new Mars(timeScales);
1197             case JUPITER :
1198                 return new Jupiter(timeScales);
1199             case SATURN :
1200                 return new Saturn(timeScales);
1201             case URANUS :
1202                 return new Uranus(timeScales);
1203             case NEPTUNE :
1204                 return new Neptune(timeScales);
1205             case PLUTO :
1206                 return new Pluto(timeScales);
1207             default :
1208                 // Solar system & Earth Moon barycenter
1209                 return new GcrfAligned(timeScales);
1210         }
1211     }
1212 
1213     /**
1214      * List of predefined IAU poles.
1215      *
1216      * @param timeScales to use when computing the pole, including TDB and J2000.0.
1217      * @return the poles.
1218      */
1219     static List<PredefinedIAUPoles> values(final TimeScales timeScales) {
1220         final List<PredefinedIAUPoles> values = new ArrayList<>(12);
1221         values.add(new Sun(timeScales));
1222         values.add(new Mercury(timeScales));
1223         values.add(new Venus(timeScales));
1224         values.add(new Earth(timeScales));
1225         values.add(new Moon(timeScales));
1226         values.add(new Mars(timeScales));
1227         values.add(new Jupiter(timeScales));
1228         values.add(new Saturn(timeScales));
1229         values.add(new Uranus(timeScales));
1230         values.add(new Neptune(timeScales));
1231         values.add(new Pluto(timeScales));
1232         values.add(new GcrfAligned(timeScales));
1233         return values;
1234     }
1235 
1236     /** Compute the interval in julian centuries from standard epoch.
1237      * @param date date
1238      * @return interval between date and standard epoch in julian centuries
1239      */
1240     protected double t(final AbsoluteDate date) {
1241         return date.offsetFrom(timeScales.getJ2000Epoch(), timeScales.getTDB()) /
1242                 Constants.JULIAN_CENTURY;
1243     }
1244 
1245     /** Compute the interval in julian centuries from standard epoch.
1246      * @param date date
1247      * @param <T> type of the filed elements
1248      * @return interval between date and standard epoch in julian centuries
1249      */
1250     protected <T extends CalculusFieldElement<T>> T t(final FieldAbsoluteDate<T> date) {
1251         final FieldAbsoluteDate<T> j2000Epoch =
1252                 new FieldAbsoluteDate<>(date.getField(), timeScales.getJ2000Epoch());
1253         return date.offsetFrom(j2000Epoch, timeScales.getTDB()).divide(Constants.JULIAN_CENTURY);
1254     }
1255 
1256     /** Compute the interval in julian days from standard epoch.
1257      * @param date date
1258      * @return interval between date and standard epoch in julian days
1259      */
1260     protected double d(final AbsoluteDate date) {
1261         return date.offsetFrom(timeScales.getJ2000Epoch(), timeScales.getTDB()) /
1262                 Constants.JULIAN_DAY;
1263     }
1264 
1265     /** Compute the interval in julian days from standard epoch.
1266      * @param date date
1267      * @param <T> type of the filed elements
1268      * @return interval between date and standard epoch in julian days
1269      */
1270     protected <T extends CalculusFieldElement<T>> T d(final FieldAbsoluteDate<T> date) {
1271         final FieldAbsoluteDate<T> j2000Epoch =
1272                 new FieldAbsoluteDate<>(date.getField(), timeScales.getJ2000Epoch());
1273         return date.offsetFrom(j2000Epoch, timeScales.getTDB()).divide(Constants.JULIAN_DAY);
1274     }
1275 
1276     @Override
1277     public boolean isGcrfAligned() {
1278         return isGcrf;
1279     }
1280 
1281 }