ITRFVersion.java

  1. /* Copyright 2002-2025 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. import java.util.regex.Matcher;
  19. import java.util.regex.Pattern;

  20. import org.hipparchus.CalculusFieldElement;
  21. import org.orekit.annotation.DefaultDataContext;
  22. import org.orekit.data.DataContext;
  23. import org.orekit.errors.OrekitException;
  24. import org.orekit.errors.OrekitMessages;
  25. import org.orekit.time.AbsoluteDate;
  26. import org.orekit.time.FieldAbsoluteDate;
  27. import org.orekit.time.TimeScale;

  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.     /** Constant for ITRF 2020. */
  36.     ITRF_2020(2020),

  37.     /** Constant for ITRF 2014. */
  38.     ITRF_2014(2014),

  39.     /** Constant for ITRF 2008. */
  40.     ITRF_2008(2008),

  41.     /** Constant for ITRF 2005. */
  42.     ITRF_2005(2005),

  43.     /** Constant for ITRF 2000. */
  44.     ITRF_2000(2000),

  45.     /** Constant for ITRF 1997. */
  46.     ITRF_1997(1997),

  47.     /** Constant for ITRF 1996. */
  48.     ITRF_1996(1996),

  49.     /** Constant for ITRF 1994. */
  50.     ITRF_1994(1994),

  51.     /** Constant for ITRF 1993. */
  52.     ITRF_1993(1993),

  53.     /** Constant for ITRF 1992. */
  54.     ITRF_1992(1992),

  55.     /** Constant for ITRF 1991. */
  56.     ITRF_1991(1991),

  57.     /** Constant for ITRF 1990. */
  58.     ITRF_1990(1990),

  59.     /** Constant for ITRF 89. */
  60.     ITRF_1989(1989),

  61.     /** Constant for ITRF 88. */
  62.     ITRF_1988(1988);

  63.     /** Regular expression for ITRF names, using several variations. */
  64.     private static final Pattern PATTERN = Pattern.compile("[Ii][Tt][Rr][Ff][-_ ]?([0-9]{2,4})");

  65.     /** Reference year of the frame version. */
  66.     private final int year;

  67.     /** Name. */
  68.     private final String name;

  69.     /** Simple constructor.
  70.      * @param year reference year of the frame version
  71.      */
  72.     ITRFVersion(final int year) {
  73.         this.year = year;
  74.         this.name = "ITRF-" + year;
  75.     }

  76.     /** Get the reference year of the frame version.
  77.      * @return reference year of the frame version
  78.      */
  79.     public int getYear() {
  80.         return year;
  81.     }

  82.     /** Get the name the frame version.
  83.      * @return name of the frame version
  84.      */
  85.     public String getName() {
  86.         return name;
  87.     }

  88.     /** Find an ITRF version from its reference year.
  89.      * @param year reference year of the frame version
  90.      * @return ITRF version for specified year
  91.      */
  92.     public static ITRFVersion getITRFVersion(final int year) {

  93.         final int fixedYear = (year < 100) ? (year + (year > 87 ? 1900 : 2000)) : year;

  94.         // loop over all predefined frames versions
  95.         for (final ITRFVersion version : values()) {
  96.             if (version.getYear() == fixedYear) {
  97.                 return version;
  98.             }
  99.         }

  100.         // we don't have the required frame
  101.         throw new OrekitException(OrekitMessages.NO_SUCH_ITRF_FRAME, year);

  102.     }

  103.     /** Find an ITRF version from its name.
  104.      * @param name name of the frame version (case is ignored)
  105.      * @return ITRF version
  106.      */
  107.     public static ITRFVersion getITRFVersion(final String name) {

  108.         // extract year from name
  109.         final Matcher matcher = PATTERN.matcher(name);
  110.         if (matcher.matches()) {
  111.             try {
  112.                 return getITRFVersion(Integer.parseInt(matcher.group(1)));
  113.             } catch (OrekitException oe) {
  114.                 throw new OrekitException(OrekitMessages.NO_SUCH_ITRF_FRAME, name);
  115.             }
  116.         }

  117.         // we don't have the required frame
  118.         throw new OrekitException(OrekitMessages.NO_SUCH_ITRF_FRAME, name);

  119.     }

  120.     /** Get last supported ITRF version.
  121.      * @return last supported ITRF version
  122.      * @since 11.2
  123.      */
  124.     public static ITRFVersion getLast() {
  125.         ITRFVersion last = ITRFVersion.ITRF_1988;
  126.         for (final ITRFVersion iv : ITRFVersion.values()) {
  127.             if (iv.getYear() > last.getYear()) {
  128.                 last = iv;
  129.             }
  130.         }
  131.         return last;
  132.     }

  133.     /** Find a converter between specified ITRF frames.
  134.      *
  135.      * <p>This method uses the {@link DataContext#getDefault() default data context}.
  136.      *
  137.      * @param origin origin ITRF
  138.      * @param destination destination ITRF
  139.      * @return transform from {@code origin} to {@code destination}
  140.      * @see #getConverter(ITRFVersion, ITRFVersion, TimeScale)
  141.      */
  142.     @DefaultDataContext
  143.     public static Converter getConverter(final ITRFVersion origin, final ITRFVersion destination) {
  144.         return getConverter(origin, destination,
  145.                 DataContext.getDefault().getTimeScales().getTT());
  146.     }

  147.     /** Find a converter between specified ITRF frames.
  148.      * @param origin origin ITRF
  149.      * @param destination destination ITRF
  150.      * @param tt TT time scale.
  151.      * @return transform from {@code origin} to {@code destination}
  152.      * @since 10.1
  153.      */
  154.     public static Converter getConverter(final ITRFVersion origin,
  155.                                          final ITRFVersion destination,
  156.                                          final TimeScale tt) {

  157.         TransformProvider provider = null;

  158.         // special case for no transform
  159.         if (origin == destination) {
  160.             provider = TransformProviderUtils.IDENTITY_PROVIDER;
  161.         }

  162.         if (provider == null) {
  163.             // try to find a direct provider
  164.             provider = getDirectTransformProvider(origin, destination, tt);
  165.         }

  166.         if (provider == null) {
  167.             // no direct provider found, use last supported ITRF as a pivot frame
  168.             final ITRFVersion last = getLast();
  169.             provider = TransformProviderUtils.getCombinedProvider(getDirectTransformProvider(origin, last, tt),
  170.                                                                   getDirectTransformProvider(last, destination, tt));
  171.         }

  172.         // build the converter, to keep the origin and destination information
  173.         return new Converter(origin, destination, provider);

  174.     }

  175.     /** Find a direct transform provider between specified ITRF frames.
  176.      * @param origin origin ITRF
  177.      * @param destination destination ITRF
  178.      * @param tt TT time scale.
  179.      * @return transform from {@code origin} to {@code destination}, or null if no direct transform is found
  180.      */
  181.     private static TransformProvider getDirectTransformProvider(
  182.             final ITRFVersion origin,
  183.             final ITRFVersion destination,
  184.             final TimeScale tt) {

  185.         // loop over all predefined transforms
  186.         for (final HelmertTransformation.Predefined predefined : HelmertTransformation.Predefined.values()) {
  187.             if (predefined.getOrigin() == origin && predefined.getDestination() == destination) {
  188.                 // we have an Helmert transformation in the specified direction
  189.                 return predefined.getTransformation(tt);
  190.             } else if (predefined.getOrigin() == destination && predefined.getDestination() == origin) {
  191.                 // we have an Helmert transformation in the opposite direction
  192.                 return TransformProviderUtils.getReversedProvider(predefined.getTransformation(tt));
  193.             }
  194.         }

  195.         // we don't have the required transform
  196.         return null;

  197.     }

  198.     /** Specialized transform provider between ITRF frames. */
  199.     public static class Converter implements TransformProvider {

  200.         /** Origin ITRF. */
  201.         private final ITRFVersion origin;

  202.         /** Destination ITRF. */
  203.         private final ITRFVersion destination;

  204.         /** Underlying provider. */
  205.         private final TransformProvider provider;

  206.         /** Simple constructor.
  207.          * @param origin origin ITRF
  208.          * @param destination destination ITRF
  209.          * @param provider underlying provider
  210.          */
  211.         Converter(final ITRFVersion origin, final ITRFVersion destination, final TransformProvider provider) {
  212.             this.origin      = origin;
  213.             this.destination = destination;
  214.             this.provider    = provider;
  215.         }

  216.         /** Get the origin ITRF.
  217.          * @return origin ITRF
  218.          */
  219.         public ITRFVersion getOrigin() {
  220.             return origin;
  221.         }

  222.         /** Get the destination ITRF.
  223.          * @return destination ITRF
  224.          */
  225.         public ITRFVersion getDestination() {
  226.             return destination;
  227.         }

  228.         /** {@inheritDoc} */
  229.         @Override
  230.         public Transform getTransform(final AbsoluteDate date) {
  231.             return provider.getTransform(date);
  232.         }

  233.         /** {@inheritDoc} */
  234.         @Override
  235.         public KinematicTransform getKinematicTransform(final AbsoluteDate date) {
  236.             return provider.getKinematicTransform(date);
  237.         }

  238.         /** {@inheritDoc} */
  239.         @Override
  240.         public StaticTransform getStaticTransform(final AbsoluteDate date) {
  241.             return provider.getStaticTransform(date);
  242.         }

  243.         /** {@inheritDoc} */
  244.         @Override
  245.         public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
  246.             return provider.getTransform(date);
  247.         }

  248.         /** {@inheritDoc} */
  249.         @Override
  250.         public <T extends CalculusFieldElement<T>> FieldKinematicTransform<T> getKinematicTransform(final FieldAbsoluteDate<T> date) {
  251.             return provider.getKinematicTransform(date);
  252.         }

  253.         /** {@inheritDoc} */
  254.         @Override
  255.         public <T extends CalculusFieldElement<T>> FieldStaticTransform<T> getStaticTransform(final FieldAbsoluteDate<T> date) {
  256.             return provider.getStaticTransform(date);
  257.         }

  258.     }

  259. }