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