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