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