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.frames;
18  
19  import org.hipparchus.RealFieldElement;
20  import org.orekit.annotation.DefaultDataContext;
21  import org.orekit.data.DataContext;
22  import org.orekit.errors.OrekitException;
23  import org.orekit.errors.OrekitMessages;
24  import org.orekit.time.AbsoluteDate;
25  import org.orekit.time.FieldAbsoluteDate;
26  import org.orekit.time.TimeScale;
27  
28  /** Enumerate for ITRF versions.
29   * @see EOPEntry
30   * @see HelmertTransformation
31   * @author Luc Maisonobe
32   * @since 9.2
33   */
34  public enum ITRFVersion {
35  
36      /** Constant for ITRF 2014. */
37      ITRF_2014(2014),
38  
39      /** Constant for ITRF 2008. */
40      ITRF_2008(2008),
41  
42      /** Constant for ITRF 2005. */
43      ITRF_2005(2005),
44  
45      /** Constant for ITRF 2000. */
46      ITRF_2000(2000),
47  
48      /** Constant for ITRF 97. */
49      ITRF_97(1997),
50  
51      /** Constant for ITRF 96. */
52      ITRF_96(1996),
53  
54      /** Constant for ITRF 94. */
55      ITRF_94(1994),
56  
57      /** Constant for ITRF 93. */
58      ITRF_93(1993),
59  
60      /** Constant for ITRF 92. */
61      ITRF_92(1992),
62  
63      /** Constant for ITRF 91. */
64      ITRF_91(1991),
65  
66      /** Constant for ITRF 90. */
67      ITRF_90(1990),
68  
69      /** Constant for ITRF 89. */
70      ITRF_89(1989),
71  
72      /** Constant for ITRF 88. */
73      ITRF_88(1988);
74  
75      /** Reference year of the frame version. */
76      private final int year;
77  
78      /** Name. */
79      private final String name;
80  
81      /** Simple constructor.
82       * @param year reference year of the frame version
83       */
84      ITRFVersion(final int year) {
85          this.year = year;
86          this.name = "ITRF-" + ((year >= 2000) ? year : (year - 1900));
87      }
88  
89      /** Get the reference year of the frame version.
90       * @return reference year of the frame version
91       */
92      public int getYear() {
93          return year;
94      }
95  
96      /** Get the name the frame version.
97       * @return name of the frame version
98       */
99      public String getName() {
100         return name;
101     }
102 
103     /** Find an ITRF version from its reference year.
104      * @param year reference year of the frame version
105      * @return ITRF version for specified year
106      */
107     public static ITRFVersion getITRFVersion(final int year) {
108 
109         // loop over all predefined frames versions
110         for (final ITRFVersion version : values()) {
111             if (version.getYear() == year) {
112                 return version;
113             }
114         }
115 
116         // we don't have the required frame
117         throw new OrekitException(OrekitMessages.NO_SUCH_ITRF_FRAME, year);
118 
119     }
120 
121     /** Find an ITRF version from its name.
122      * @param name name of the frame version (case is ignored)
123      * @return ITRF version
124      */
125     public static ITRFVersion getITRFVersion(final String name) {
126 
127         // loop over all predefined frames versions
128         for (final ITRFVersion version : values()) {
129             if (version.getName().equalsIgnoreCase(name)) {
130                 return version;
131             }
132         }
133 
134         // we don't have the required frame
135         throw new OrekitException(OrekitMessages.NO_SUCH_ITRF_FRAME, name);
136 
137     }
138 
139     /** Find a converter between specified ITRF frames.
140      *
141      * <p>This method uses the {@link DataContext#getDefault() default data context}.
142      *
143      * @param origin origin ITRF
144      * @param destination destination ITRF
145      * @return transform from {@code origin} to {@code destination}
146      * @see #getConverter(ITRFVersion, ITRFVersion, TimeScale)
147      */
148     @DefaultDataContext
149     public static Converter getConverter(final ITRFVersionRFVersion">ITRFVersion origin, final ITRFVersion destination) {
150         return getConverter(origin, destination,
151                 DataContext.getDefault().getTimeScales().getTT());
152     }
153 
154     /** Find a converter between specified ITRF frames.
155      * @param origin origin ITRF
156      * @param destination destination ITRF
157      * @param tt TT time scale.
158      * @return transform from {@code origin} to {@code destination}
159      * @since 10.1
160      */
161     public static Converter getConverter(final ITRFVersion origin,
162                                          final ITRFVersion destination,
163                                          final TimeScale tt) {
164 
165         TransformProvider provider = null;
166 
167         // special case for no transform
168         if (origin == destination) {
169             provider = TransformProviderUtils.IDENTITY_PROVIDER;
170         }
171 
172         if (provider == null) {
173             // try to find a direct provider
174             provider = getDirectTransformProvider(origin, destination, tt);
175         }
176 
177         if (provider == null) {
178             // no direct provider found, use ITRF 2014 as a pivot frame
179             provider = TransformProviderUtils.getCombinedProvider(getDirectTransformProvider(origin, ITRF_2014, tt),
180                                                                   getDirectTransformProvider(ITRF_2014, destination, tt));
181         }
182 
183         // build the converter, to keep the origin and destination information
184         return new Converter(origin, destination, provider);
185 
186     }
187 
188     /** Find a direct transform provider between specified ITRF frames.
189      * @param origin origin ITRF
190      * @param destination destination ITRF
191      * @param tt TT time scale.
192      * @return transform from {@code origin} to {@code destination}, or null if no direct transform is found
193      */
194     private static TransformProvider getDirectTransformProvider(
195             final ITRFVersion origin,
196             final ITRFVersion destination,
197             final TimeScale tt) {
198 
199         // loop over all predefined transforms
200         for (final HelmertTransformation.Predefined predefined : HelmertTransformation.Predefined.values()) {
201             if (predefined.getOrigin() == origin && predefined.getDestination() == destination) {
202                 // we have an Helmert transformation in the specified direction
203                 return predefined.getTransformation(tt);
204             } else if (predefined.getOrigin() == destination && predefined.getDestination() == origin) {
205                 // we have an Helmert transformation in the opposite direction
206                 return TransformProviderUtils.getReversedProvider(predefined.getTransformation(tt));
207             }
208         }
209 
210         // we don't have the required transform
211         return null;
212 
213     }
214 
215     /** Specialized transform provider between ITRF frames. */
216     public static class Converter implements TransformProvider {
217 
218         /** Serializable UID. */
219         private static final long serialVersionUID = 20180330L;
220 
221         /** Origin ITRF. */
222         private final ITRFVersion origin;
223 
224         /** Destination ITRF. */
225         private final ITRFVersion destination;
226 
227         /** Underlying provider. */
228         private final TransformProvider provider;
229 
230         /** Simple constructor.
231          * @param origin origin ITRF
232          * @param destination destination ITRF
233          * @param provider underlying provider
234          */
235         Converter(final ITRFVersionRFVersion">ITRFVersion origin, final ITRFVersion destination, final TransformProvider provider) {
236             this.origin      = origin;
237             this.destination = destination;
238             this.provider    = provider;
239         }
240 
241         /** Get the origin ITRF.
242          * @return origin ITRF
243          */
244         public ITRFVersion getOrigin() {
245             return origin;
246         }
247 
248         /** Get the destination ITRF.
249          * @return destination ITRF
250          */
251         public ITRFVersion getDestination() {
252             return destination;
253         }
254 
255         /** {@inheritDoc} */
256         @Override
257         public Transform getTransform(final AbsoluteDate date) {
258             return provider.getTransform(date);
259         }
260 
261         /** {@inheritDoc} */
262         @Override
263         public <T extends RealFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
264             return provider.getTransform(date);
265         }
266 
267     }
268 
269 }