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