FramesFactory.java

  1. /* Copyright 2002-2013 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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.ArrayList;
  19. import java.util.HashMap;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.SortedSet;
  23. import java.util.TreeSet;

  24. import org.orekit.bodies.CelestialBodyFactory;
  25. import org.orekit.errors.OrekitException;
  26. import org.orekit.time.AbsoluteDate;
  27. import org.orekit.time.ChronologicalComparator;
  28. import org.orekit.utils.Constants;
  29. import org.orekit.utils.IERSConventions;
  30. import org.orekit.utils.OrekitConfiguration;


  31. /** Factory for predefined reference frames.
  32.  *
  33.  * <h5> FramesFactory Presentation </h5>
  34.  * <p>
  35.  * Several predefined reference {@link Frame frames} are implemented in OREKIT.
  36.  * They are linked together in a tree with the <i>Geocentric
  37.  * Celestial Reference Frame</i> (GCRF) as the root of the tree.
  38.  * This factory is designed to:
  39.  * </p>
  40.  * <ul>
  41.  *   <li>build the frames tree consistently,</li>
  42.  *   <li>avoid rebuilding some frames that may be costly to recreate all the time,</li>
  43.  *   <li>set up interpolation/caching features for some frames that may induce costly computation</li>
  44.  *   <li>streamline the {@link EOPHistory Earth Orientation Parameters} history loading.</li>
  45.  * </ul>
  46.  * <h5> Reference Frames </h5>
  47.  * <p>
  48.  * The user can retrieve those reference frames using various static methods, the most
  49.  * important ones being: {@link #getFrame(Predefined)}, {@link #getGCRF()},
  50.  * {@link #getCIRF(IERSConventions, boolean)} {@link #getTIRF(IERSConventions, boolean)},
  51.  * {@link #getITRF(IERSConventions, boolean)}, {@link #getEME2000()},
  52.  * {@link #getMOD(IERSConventions)}, {@link #getTOD(IERSConventions)},
  53.  * {@link #getGTOD(IERSConventions)}, {@link #getITRFEquinox(IERSConventions, boolean)},
  54.  * {@link #getTEME()} and {@link #getVeis1950()}.
  55.  * </p>
  56.  * <h5> International Terrestrial Reference Frame</h5>
  57.  * <p>
  58.  * This frame is the current (as of 2013) reference realization of
  59.  * the International Terrestrial Reference System produced by IERS.
  60.  * It is described in <a href="ftp://tai.bipm.org/iers/conv2010/tn36.pdf">
  61.  * IERS conventions (2010)</a>. It replaces the Earth Centered Earth Fixed
  62.  * frame which is the reference frame for GPS satellites.
  63.  * </p>
  64.  * <p>
  65.  * This frame is used to define position on solid Earth. It rotates with
  66.  * the Earth and includes the pole motion with respect to Earth crust as
  67.  * provided by {@link org.orekit.data.DataProvidersManager IERS data}.
  68.  * Its pole axis is the IERS Reference Pole (IRP).
  69.  * </p>
  70.  * <p>
  71.  * Previous realizations of the ITRS are available and linked together using
  72.  * {@link HelmertTransformation Helmert transformations}. Parameters for all
  73.  * ITRS realizations since 1988 are available from the ITRF site <a
  74.  * href="ftp://itrf.ensg.ign.fr/pub/itrf/ITRF.TP"> ftp://itrf.ensg.ign.fr/pub/itrf/ITRF.TP</a>).
  75.  * Orekit provides a {@link HelmertTransformation.Predefined#createTransformedITRF(Frame,
  76.  * String) utility} method to build simply several of them and link them together.
  77.  * </p>
  78.  * <p>
  79.  * ITRF can be built using the new non-rotating origin paradigm
  80.  * mandated by IAU 2000 resolution B1.8 and any supported {@link IERSConventions
  81.  * IERS conventions} (even IERS 1996 can be used with non-rotating origin paradigm,
  82.  * despite the resolution was not yet adopted at conventions publication time.
  83.  * </p>
  84.  * <p>
  85.  * ITRF can also be built using the classical equinox paradigm used prior to IAU 2000
  86.  * resolution B1.8 and any supported {@link IERSConventions IERS conventions} (even
  87.  * IERS 2003 and 2010 can be used with equinox paradigm, despite the resolution is
  88.  * in effect now). The choice of paradigm (non-rotating origin or equinox) and the
  89.  * choice of IERS conventions (i.e. the choice of precession/nutation models) can
  90.  * be made independently by user, Orekit provides all alternatives.
  91.  * </p>
  92.  * <h5>Intermediate frames</h5>
  93.  * <p>
  94.  * Orekit also provides all the intermediate frames that are needed to transform
  95.  * between GCRF and ITRF, along the two paths: ITRF/TIRF/CIRF/GCRF for the
  96.  * non-rotating origin paradigm and ITRF/GTOD/TOD/MOD/EME2000/GCRF for the equinox
  97.  * paradigm.
  98.  * </p>
  99.  * <h5> Earth Orientation Parameters </h5>
  100.  * <p>
  101.  * This factory also handles loading of Earth Orientation Parameters (EOP) needed
  102.  * for accurate transformations between inertial and Earth fixed frames, using
  103.  * {@link org.orekit.data.DataProvidersManager} features. EOP are IERS conventions
  104.  * dependent, because they correspond to correction to the precession/nutation
  105.  * models. When EOP should be applied, but EOP data are not available, then a null
  106.  * (0.0) correction is used. This can occur when no EOP data is loaded, or when the
  107.  * requested date is beyond the time span of the loaded EOP data. Using a null
  108.  * correction can result in coarse accuracy. To check the time span covered by EOP data use
  109.  * {@link #getEOPHistory(IERSConventions, boolean)}, {@link EOPHistory#getStartDate()},
  110.  * and {@link EOPHistory#getEndDate()}.
  111.  * <p>
  112.  * For more on configuring the EOP data Orekit uses see
  113.  * <a href="https://www.orekit.org/forge/projects/orekit/wiki/Configuration">
  114.  * https://www.orekit.org/forge/projects/orekit/wiki/Configuration</a>.
  115.  * <p>
  116.  * Here is a schematic representation of the predefined reference frames tree:
  117.  * </p>
  118.  * <pre>
  119.  *                                                                  GCRF
  120.  *                                                                    |
  121.  *                                                 |-----------------------------------------------
  122.  *                                                 |                         |     Frame bias     |
  123.  *                                                 |                         |                 EME2000
  124.  *                                                 |                         |                    |
  125.  *                                                 |                         | Precession effects |
  126.  *                                                 |                         |                    |
  127.  *           Bias, Precession and Nutation effects |                        MOD                  MOD  (Mean Equator Of Date)
  128.  *                                                 |                         |             w/o EOP corrections
  129.  *                                                 |                         |  Nutation effects  |
  130.  *    (Celestial Intermediate Reference Frame)   CIRF                        |                    |
  131.  *                                                 |                        TOD                  TOD  (True Equator Of Date)
  132.  *                          Earth natural rotation |                         |             w/o EOP corrections
  133.  *                                                 |-------------            |    Sidereal Time   |
  134.  *                                                 |            |            |                    |
  135.  *  (Terrestrial Intermediate Reference Frame)   TIRF         TIRF         GTOD                 GTOD  (Greenwich True Of Date)
  136.  *                                                 |    w/o tidal effects                  w/o EOP corrections
  137.  *                                     Pole motion |            |                                 |
  138.  *                                                 |            |                                 |-------------
  139.  *                                                 |            |                                 |            |
  140.  * (International Terrestrial Reference Frame)   ITRF         ITRF                              ITRF        VEIS1950
  141.  *                                                 |    w/o tidal effects                   equinox-based
  142.  *                                                 |            |
  143.  *                                           other ITRF     other ITRF
  144.  *                                                      w/o tidal effects
  145.  * </pre>
  146.  * <p>
  147.  * This is a utility class, so its constructor is private.
  148.  * </p>
  149.  * @author Guylaine Prat
  150.  * @author Luc Maisonobe
  151.  * @author Pascal Parraud
  152.  */
  153. public class FramesFactory {

  154.     /** Default regular expression for the Rapid Data and Prediction EOP columns files (IAU1980 compatibles). */
  155.     public static final String RAPID_DATA_PREDICTION_COLUMNS_1980_FILENAME = "^finals\\.[^.]*$";

  156.     /** Default regular expression for the Rapid Data and Prediction EOP XML files (IAU1980 compatibles). */
  157.     public static final String RAPID_DATA_PREDICTION_XML_1980_FILENAME = "^finals\\..*\\.xml$";

  158.     /** Default regular expression for the EOPC04 files (IAU1980 compatibles). */
  159.     public static final String EOPC04_1980_FILENAME = "^eopc04_08\\.(\\d\\d)$";

  160.     /** Default regular expression for the BulletinB files (IAU1980 compatibles). */
  161.     public static final String BULLETINB_1980_FILENAME = "^bulletinb((-\\d\\d\\d\\.txt)|(\\.\\d\\d\\d))$";

  162.     /** Default regular expression for the Rapid Data and Prediction EOP columns files (IAU2000 compatibles). */
  163.     public static final String RAPID_DATA_PREDICITON_COLUMNS_2000_FILENAME = "^finals2000A\\.[^.]*$";

  164.     /** Default regular expression for the Rapid Data and Prediction EOP XML files (IAU2000 compatibles). */
  165.     public static final String RAPID_DATA_PREDICITON_XML_2000_FILENAME = "^finals2000A\\..*\\.xml$";

  166.     /** Default regular expression for the EOPC04 files (IAU2000 compatibles). */
  167.     public static final String EOPC04_2000_FILENAME = "^eopc04_08_IAU2000\\.(\\d\\d)$";

  168.     /** Default regular expression for the BulletinB files (IAU2000 compatibles). */
  169.     public static final String BULLETINB_2000_FILENAME = "^bulletinb_IAU2000((-\\d\\d\\d\\.txt)|(\\.\\d\\d\\d))$";

  170.     /** Predefined frames. */
  171.     private static transient Map<Predefined, FactoryManagedFrame> FRAMES =
  172.         new HashMap<Predefined, FactoryManagedFrame>();

  173.     /** Loaders for Earth Orientation parameters. */
  174.     private static final Map<IERSConventions, List<EOPHistoryLoader>> EOP_HISTORY_LOADERS =
  175.         new HashMap<IERSConventions, List<EOPHistoryLoader>>();

  176.     /** Private constructor.
  177.      * <p>This class is a utility class, it should neither have a public
  178.      * nor a default constructor. This private constructor prevents
  179.      * the compiler from generating one automatically.</p>
  180.      */
  181.     private FramesFactory() {
  182.     }

  183.     /** Add the default loaders EOP history (IAU 1980 precession/nutation).
  184.      * <p>
  185.      * The default loaders look for IERS EOP 08 C04 and bulletins B files. They
  186.      * correspond to {@link IERSConventions#IERS_1996 IERS 1996} conventions.
  187.      * </p>
  188.      * @param rapidDataColumnsSupportedNames regular expression for supported
  189.      * rapid data columns EOP files names
  190.      * (may be null if the default IERS file names are used)
  191.      * @param rapidDataXMLSupportedNames regular expression for supported
  192.      * rapid data XML EOP files names
  193.      * (may be null if the default IERS file names are used)
  194.      * @param eopC04SupportedNames regular expression for supported EOP 08 C04 files names
  195.      * (may be null if the default IERS file names are used)
  196.      * @param bulletinBSupportedNames regular expression for supported bulletin B files names
  197.      * (may be null if the default IERS file names are used)
  198.      * @see <a href="http://hpiers.obspm.fr/eoppc/eop/eopc04/">IERS EOP 08 C04 files</a>
  199.      * @see #addEOPHistoryLoader(IERSConventions, EOPHistoryLoader)
  200.      * @see #clearEOPHistoryLoaders()
  201.      * @see #addDefaultEOP2000HistoryLoaders(String, String, String, String)
  202.      */
  203.     public static void addDefaultEOP1980HistoryLoaders(final String rapidDataColumnsSupportedNames,
  204.                                                        final String rapidDataXMLSupportedNames,
  205.                                                        final String eopC04SupportedNames,
  206.                                                        final String bulletinBSupportedNames) {
  207.         final String rapidColNames =
  208.                 (rapidDataColumnsSupportedNames == null) ?
  209.                 RAPID_DATA_PREDICTION_COLUMNS_1980_FILENAME : rapidDataColumnsSupportedNames;
  210.         addEOPHistoryLoader(IERSConventions.IERS_1996,
  211.                             new RapidDataAndPredictionColumnsLoader(false, rapidColNames));
  212.         final String rapidXmlNames =
  213.                 (rapidDataXMLSupportedNames == null) ?
  214.                 RAPID_DATA_PREDICTION_XML_1980_FILENAME : rapidDataXMLSupportedNames;
  215.         addEOPHistoryLoader(IERSConventions.IERS_1996,
  216.                             new RapidDataAndPredictionXMLLoader(rapidXmlNames));
  217.         final String eopcNames =
  218.                 (eopC04SupportedNames == null) ? EOPC04_1980_FILENAME : eopC04SupportedNames;
  219.         addEOPHistoryLoader(IERSConventions.IERS_1996,
  220.                             new EOP08C04FilesLoader(eopcNames));
  221.         final String bulBNames =
  222.             (bulletinBSupportedNames == null) ? BULLETINB_1980_FILENAME : bulletinBSupportedNames;
  223.         addEOPHistoryLoader(IERSConventions.IERS_1996,
  224.                             new BulletinBFilesLoader(bulBNames));
  225.     }

  226.     /** Add the default loaders for EOP history (IAU 2000/2006 precession/nutation).
  227.      * <p>
  228.      * The default loaders look for IERS EOP 08 C04 and bulletins B files. They
  229.      * correspond to both {@link IERSConventions#IERS_2003 IERS 2003} and {@link
  230.      * IERSConventions#IERS_2010 IERS 2010} conventions.
  231.      * </p>
  232.      * @param rapidDataColumnsSupportedNames regular expression for supported
  233.      * rapid data columns EOP files names
  234.      * (may be null if the default IERS file names are used)
  235.      * @param rapidDataXMLSupportedNames regular expression for supported
  236.      * rapid data XML EOP files names
  237.      * (may be null if the default IERS file names are used)
  238.      * @param eopC04SupportedNames regular expression for supported EOP 08 C04 files names
  239.      * (may be null if the default IERS file names are used)
  240.      * @param bulletinBSupportedNames regular expression for supported bulletin B files names
  241.      * (may be null if the default IERS file names are used)
  242.      * @see <a href="http://hpiers.obspm.fr/eoppc/eop/eopc04/">IERS EOP 08 C04 files</a>
  243.      * @see #addEOPHistoryLoader(IERSConventions, EOPHistoryLoader)
  244.      * @see #clearEOPHistoryLoaders()
  245.      * @see #addDefaultEOP1980HistoryLoaders(String, String, String, String)
  246.      */
  247.     public static void addDefaultEOP2000HistoryLoaders(final String rapidDataColumnsSupportedNames,
  248.                                                        final String rapidDataXMLSupportedNames,
  249.                                                        final String eopC04SupportedNames,
  250.                                                        final String bulletinBSupportedNames) {
  251.         final String rapidColNames =
  252.                 (rapidDataColumnsSupportedNames == null) ?
  253.                 RAPID_DATA_PREDICITON_COLUMNS_2000_FILENAME : rapidDataColumnsSupportedNames;
  254.         addEOPHistoryLoader(IERSConventions.IERS_2003,
  255.                             new RapidDataAndPredictionColumnsLoader(true, rapidColNames));
  256.         addEOPHistoryLoader(IERSConventions.IERS_2010,
  257.                             new RapidDataAndPredictionColumnsLoader(true, rapidColNames));
  258.         final String rapidXmlNames =
  259.             (rapidDataXMLSupportedNames == null) ?
  260.             RAPID_DATA_PREDICITON_XML_2000_FILENAME : rapidDataXMLSupportedNames;
  261.         addEOPHistoryLoader(IERSConventions.IERS_2003,
  262.                             new RapidDataAndPredictionXMLLoader(rapidXmlNames));
  263.         addEOPHistoryLoader(IERSConventions.IERS_2010,
  264.                             new RapidDataAndPredictionXMLLoader(rapidXmlNames));
  265.         final String eopcNames =
  266.             (eopC04SupportedNames == null) ? EOPC04_2000_FILENAME : eopC04SupportedNames;
  267.         addEOPHistoryLoader(IERSConventions.IERS_2003,
  268.                             new EOP08C04FilesLoader(eopcNames));
  269.         addEOPHistoryLoader(IERSConventions.IERS_2010,
  270.                             new EOP08C04FilesLoader(eopcNames));
  271.         final String bulBNames =
  272.             (bulletinBSupportedNames == null) ? BULLETINB_2000_FILENAME : bulletinBSupportedNames;
  273.         addEOPHistoryLoader(IERSConventions.IERS_2003,
  274.                             new BulletinBFilesLoader(bulBNames));
  275.         addEOPHistoryLoader(IERSConventions.IERS_2010,
  276.                             new BulletinBFilesLoader(bulBNames));
  277.     }

  278.     /** Add a loader for Earth Orientation Parameters history.
  279.      * @param conventions IERS conventions to which EOP history applies
  280.      * @param loader custom loader to add for the EOP history
  281.      * @see #addDefaultEOP1980HistoryLoaders(String, String, String, String)
  282.      * @see #clearEOPHistoryLoaders()
  283.      */
  284.     public static void addEOPHistoryLoader(final IERSConventions conventions, final EOPHistoryLoader loader) {
  285.         synchronized (EOP_HISTORY_LOADERS) {
  286.             if (!EOP_HISTORY_LOADERS.containsKey(conventions)) {
  287.                 EOP_HISTORY_LOADERS.put(conventions, new ArrayList<EOPHistoryLoader>());
  288.             }
  289.             EOP_HISTORY_LOADERS.get(conventions).add(loader);
  290.         }
  291.     }

  292.     /** Clear loaders for Earth Orientation Parameters history.
  293.      * @see #addEOPHistoryLoader(IERSConventions, EOPHistoryLoader)
  294.      * @see #addDefaultEOP1980HistoryLoaders(String, String, String, String)
  295.      */
  296.     public static void clearEOPHistoryLoaders() {
  297.         synchronized (EOP_HISTORY_LOADERS) {
  298.             EOP_HISTORY_LOADERS.clear();
  299.         }
  300.     }

  301.     /** Get Earth Orientation Parameters history.
  302.      * <p>
  303.      * If no {@link EOPHistoryLoader} has been added by calling {@link
  304.      * #addEOPHistoryLoader(IERSConventions, EOPHistoryLoader) addEOPHistoryLoader}
  305.      * or if {@link #clearEOPHistoryLoaders() clearEOPHistoryLoaders} has been
  306.      * called afterwards, the {@link #addDefaultEOP1980HistoryLoaders(String, String,
  307.      * String, String)} and {@link #addDefaultEOP2000HistoryLoaders(String, String,
  308.      * String, String)} methods will be called automatically with supported file names
  309.      * parameters all set to null, in order to get the default loaders configuration.
  310.      * </p>
  311.      * @param conventions conventions for which EOP history is requested
  312.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  313.      * @return Earth Orientation Parameters history
  314.      * @exception OrekitException if the data cannot be loaded
  315.      */
  316.     public static EOPHistory getEOPHistory(final IERSConventions conventions, final boolean simpleEOP)
  317.         throws OrekitException {

  318.         synchronized (EOP_HISTORY_LOADERS) {

  319.             //TimeStamped based set needed to remove duplicates
  320.             if (EOP_HISTORY_LOADERS.isEmpty()) {
  321.                 addDefaultEOP2000HistoryLoaders(null, null, null, null);
  322.                 addDefaultEOP1980HistoryLoaders(null, null, null, null);
  323.             }

  324.             OrekitException pendingException = null;
  325.             final SortedSet<EOPEntry> data = new TreeSet<EOPEntry>(new ChronologicalComparator());

  326.             // try to load canonical data if available
  327.             if (EOP_HISTORY_LOADERS.containsKey(conventions)) {
  328.                 for (final EOPHistoryLoader loader : EOP_HISTORY_LOADERS.get(conventions)) {
  329.                     try {
  330.                         loader.fillHistory(conventions.getNutationCorrectionConverter(), data);
  331.                     } catch (OrekitException oe) {
  332.                         pendingException = oe;
  333.                     }
  334.                 }
  335.             }

  336.             if (data.isEmpty() && pendingException != null) {
  337.                 throw pendingException;
  338.             }

  339.             final EOPHistory history = new EOPHistory(conventions, data, simpleEOP);
  340.             history.checkEOPContinuity(5 * Constants.JULIAN_DAY);
  341.             return history;

  342.         }

  343.     }

  344.     /** Get one of the predefined frames.
  345.      * @param factoryKey key of the frame within the factory
  346.      * @return the predefined frame
  347.      * @exception OrekitException if frame cannot be built due to missing data
  348.      */
  349.     @SuppressWarnings("deprecation")
  350.     public static Frame getFrame(final Predefined factoryKey)
  351.         throws OrekitException {
  352.         switch (factoryKey) {
  353.         case GCRF :
  354.             return getGCRF();
  355.         case ICRF :
  356.             return getICRF();
  357.         case EME2000 :
  358.             return getEME2000();
  359.         case ITRF_2008_WITHOUT_TIDAL_EFFECTS :
  360.         case ITRF_CIO_CONV_2010_SIMPLE_EOP :
  361.             return getITRF(IERSConventions.IERS_2010, true);
  362.         case ITRF_2008_WITH_TIDAL_EFFECTS :
  363.         case ITRF_CIO_CONV_2010_ACCURATE_EOP :
  364.             return getITRF(IERSConventions.IERS_2010, false);
  365.         case ITRF_CIO_CONV_2003_SIMPLE_EOP :
  366.             return getITRF(IERSConventions.IERS_2003, true);
  367.         case ITRF_CIO_CONV_2003_ACCURATE_EOP :
  368.             return getITRF(IERSConventions.IERS_2003, false);
  369.         case ITRF_CIO_CONV_1996_SIMPLE_EOP :
  370.             return getITRF(IERSConventions.IERS_1996, true);
  371.         case ITRF_CIO_CONV_1996_ACCURATE_EOP :
  372.             return getITRF(IERSConventions.IERS_1996, false);
  373.         case ITRF_2005_WITHOUT_TIDAL_EFFECTS :
  374.             return getITRF2005(true);
  375.         case ITRF_2005_WITH_TIDAL_EFFECTS :
  376.             return getITRF2005(false);
  377.         case ITRF_2000_WITHOUT_TIDAL_EFFECTS :
  378.             return getITRF2000(true);
  379.         case ITRF_2000_WITH_TIDAL_EFFECTS :
  380.             return getITRF2000(false);
  381.         case ITRF_97_WITHOUT_TIDAL_EFFECTS :
  382.             return getITRF97(true);
  383.         case ITRF_97_WITH_TIDAL_EFFECTS :
  384.             return getITRF97(false);
  385.         case ITRF_93_WITHOUT_TIDAL_EFFECTS :
  386.             return getITRF93(true);
  387.         case ITRF_93_WITH_TIDAL_EFFECTS :
  388.             return getITRF93(false);
  389.         case ITRF_EQUINOX_CONV_2010_SIMPLE_EOP :
  390.             return getITRFEquinox(IERSConventions.IERS_2010, true);
  391.         case ITRF_EQUINOX_CONV_2010_ACCURATE_EOP :
  392.             return getITRFEquinox(IERSConventions.IERS_2010, false);
  393.         case ITRF_EQUINOX_CONV_2003_SIMPLE_EOP :
  394.             return getITRFEquinox(IERSConventions.IERS_2003, true);
  395.         case ITRF_EQUINOX_CONV_2003_ACCURATE_EOP :
  396.             return getITRFEquinox(IERSConventions.IERS_2003, false);
  397.         case ITRF_EQUINOX :
  398.         case ITRF_EQUINOX_CONV_1996_SIMPLE_EOP :
  399.             return getITRFEquinox(IERSConventions.IERS_1996, true);
  400.         case ITRF_EQUINOX_CONV_1996_ACCURATE_EOP :
  401.             return getITRFEquinox(IERSConventions.IERS_1996, false);
  402.         case TIRF_2000_CONV_2010_WITHOUT_TIDAL_EFFECTS :
  403.         case TIRF_CONVENTIONS_2010_SIMPLE_EOP :
  404.             return getTIRF(IERSConventions.IERS_2010, true);
  405.         case TIRF_2000_CONV_2010_WITH_TIDAL_EFFECTS :
  406.         case TIRF_CONVENTIONS_2010_ACCURATE_EOP :
  407.             return getTIRF(IERSConventions.IERS_2010, false);
  408.         case TIRF_2000_CONV_2003_WITHOUT_TIDAL_EFFECTS :
  409.         case TIRF_CONVENTIONS_2003_SIMPLE_EOP :
  410.             return getTIRF(IERSConventions.IERS_2003, true);
  411.         case TIRF_2000_CONV_2003_WITH_TIDAL_EFFECTS :
  412.         case TIRF_CONVENTIONS_2003_ACCURATE_EOP :
  413.             return getTIRF(IERSConventions.IERS_2003, false);
  414.         case TIRF_CONVENTIONS_1996_SIMPLE_EOP :
  415.             return getTIRF(IERSConventions.IERS_1996, true);
  416.         case TIRF_CONVENTIONS_1996_ACCURATE_EOP :
  417.             return getTIRF(IERSConventions.IERS_1996, false);
  418.         case CIRF_2000_CONV_2010 :
  419.         case CIRF_CONVENTIONS_2010_ACCURATE_EOP :
  420.             return getCIRF(IERSConventions.IERS_2010, false);
  421.         case CIRF_CONVENTIONS_2010_SIMPLE_EOP :
  422.             return getCIRF(IERSConventions.IERS_2010, true);
  423.         case CIRF_2000_CONV_2003 :
  424.         case CIRF_CONVENTIONS_2003_ACCURATE_EOP :
  425.             return getCIRF(IERSConventions.IERS_2003, false);
  426.         case CIRF_CONVENTIONS_2003_SIMPLE_EOP :
  427.             return getCIRF(IERSConventions.IERS_2003, true);
  428.         case CIRF_CONVENTIONS_1996_ACCURATE_EOP :
  429.             return getCIRF(IERSConventions.IERS_1996, false);
  430.         case CIRF_CONVENTIONS_1996_SIMPLE_EOP :
  431.             return getCIRF(IERSConventions.IERS_1996, true);
  432.         case VEIS_1950 :
  433.             return getVeis1950();
  434.         case GTOD_WITHOUT_EOP_CORRECTIONS :
  435.             return getGTOD(IERSConventions.IERS_1996, false, true);
  436.         case GTOD_CONVENTIONS_2010_ACCURATE_EOP :
  437.             return getGTOD(IERSConventions.IERS_2010, true, false);
  438.         case GTOD_CONVENTIONS_2010_SIMPLE_EOP :
  439.             return getGTOD(IERSConventions.IERS_2010, true, true);
  440.         case GTOD_CONVENTIONS_2003_ACCURATE_EOP :
  441.             return getGTOD(IERSConventions.IERS_2003, true, false);
  442.         case GTOD_CONVENTIONS_2003_SIMPLE_EOP :
  443.             return getGTOD(IERSConventions.IERS_2003, true, true);
  444.         case GTOD_WITH_EOP_CORRECTIONS :
  445.         case GTOD_CONVENTIONS_1996_ACCURATE_EOP :
  446.             return getGTOD(IERSConventions.IERS_1996, true, false);
  447.         case GTOD_CONVENTIONS_1996_SIMPLE_EOP :
  448.             return getGTOD(IERSConventions.IERS_1996, true, true);
  449.         case TOD_WITHOUT_EOP_CORRECTIONS :
  450.             return getTOD(IERSConventions.IERS_1996, false, true);
  451.         case TOD_CONVENTIONS_2010_ACCURATE_EOP :
  452.             return getTOD(IERSConventions.IERS_2010, true, false);
  453.         case TOD_CONVENTIONS_2010_SIMPLE_EOP :
  454.             return getTOD(IERSConventions.IERS_2010, true, true);
  455.         case TOD_CONVENTIONS_2003_ACCURATE_EOP :
  456.             return getTOD(IERSConventions.IERS_2003, true, false);
  457.         case TOD_CONVENTIONS_2003_SIMPLE_EOP :
  458.             return getTOD(IERSConventions.IERS_2003, true, true);
  459.         case TOD_WITH_EOP_CORRECTIONS :
  460.         case TOD_CONVENTIONS_1996_ACCURATE_EOP :
  461.             return getTOD(IERSConventions.IERS_1996, true, false);
  462.         case TOD_CONVENTIONS_1996_SIMPLE_EOP :
  463.             return getTOD(IERSConventions.IERS_1996, true, true);
  464.         case MOD_WITHOUT_EOP_CORRECTIONS :
  465.             return getMOD(IERSConventions.IERS_1996, false);
  466.         case MOD_CONVENTIONS_2010 :
  467.             return getMOD(IERSConventions.IERS_2010, true);
  468.         case MOD_CONVENTIONS_2003 :
  469.             return getMOD(IERSConventions.IERS_2003, true);
  470.         case MOD_WITH_EOP_CORRECTIONS :
  471.         case MOD_CONVENTIONS_1996 :
  472.             return getMOD(IERSConventions.IERS_1996, true);
  473.         case TEME :
  474.             return getTEME();
  475.         default :
  476.             throw OrekitException.createInternalError(null);
  477.         }
  478.     }

  479.     /** Get the unique GCRF frame.
  480.      * <p>The GCRF frame is the root frame in the frame tree.</p>
  481.      * @return the unique instance of the GCRF frame
  482.      */
  483.     public static Frame getGCRF() {
  484.         return Frame.getRoot();
  485.     }

  486.     /** Get the unique ICRF frame.
  487.      * <p>The ICRF frame is centered at solar system barycenter and aligned
  488.      * with EME2000.</p>
  489.      * @return the unique instance of the ICRF frame
  490.      * @exception OrekitException if solar system ephemerides cannot be loaded
  491.      */
  492.     public static Frame getICRF() throws OrekitException {
  493.         return CelestialBodyFactory.getSolarSystemBarycenter().getInertiallyOrientedFrame();
  494.     }

  495.     /** Get the unique EME2000 frame.
  496.      * <p>The EME2000 frame is also called the J2000 frame.
  497.      * The former denomination is preferred in Orekit.</p>
  498.      * @return the unique instance of the EME2000 frame
  499.      */
  500.     public static FactoryManagedFrame getEME2000() {
  501.         synchronized (FramesFactory.class) {

  502.             // try to find an already built frame
  503.             FactoryManagedFrame frame = FRAMES.get(Predefined.EME2000);

  504.             if (frame == null) {
  505.                 // it's the first time we need this frame, build it and store it
  506.                 frame = new FactoryManagedFrame(getGCRF(), new EME2000Provider(), true, Predefined.EME2000);
  507.                 FRAMES.put(Predefined.EME2000, frame);
  508.             }

  509.             return frame;

  510.         }
  511.     }

  512.     /** Get the ITRF2008 reference frame, using IERS 2010 conventions.
  513.      * @param conventions IERS conventions to apply
  514.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  515.      * @return the selected reference frame singleton.
  516.      * @exception OrekitException if data embedded in the library cannot be read
  517.      * @since 6.1
  518.      */
  519.     public static FactoryManagedFrame getITRF(final IERSConventions conventions,
  520.                                               final boolean simpleEOP)
  521.         throws OrekitException {
  522.         synchronized (FramesFactory.class) {

  523.             // try to find an already built frame
  524.             final Predefined factoryKey;
  525.             switch (conventions) {
  526.             case IERS_1996 :
  527.                 factoryKey = simpleEOP ?
  528.                              Predefined.ITRF_CIO_CONV_1996_SIMPLE_EOP :
  529.                              Predefined.ITRF_CIO_CONV_1996_ACCURATE_EOP;
  530.                 break;
  531.             case IERS_2003 :
  532.                 factoryKey = simpleEOP ?
  533.                              Predefined.ITRF_CIO_CONV_2003_SIMPLE_EOP :
  534.                              Predefined.ITRF_CIO_CONV_2003_ACCURATE_EOP;
  535.                 break;
  536.             case IERS_2010 :
  537.                 factoryKey = simpleEOP ?
  538.                              Predefined.ITRF_CIO_CONV_2010_SIMPLE_EOP :
  539.                              Predefined.ITRF_CIO_CONV_2010_ACCURATE_EOP;
  540.                 break;
  541.             default :
  542.                 // this should never happen
  543.                 throw OrekitException.createInternalError(null);
  544.             }
  545.             FactoryManagedFrame frame = FRAMES.get(factoryKey);

  546.             if (frame == null) {
  547.                 // it's the first time we need this frame, build it and store it
  548.                 final Frame tirfFrame = getTIRF(conventions, simpleEOP);
  549.                 final TIRFProvider tirfProvider = (TIRFProvider) tirfFrame.getTransformProvider();
  550.                 frame = new FactoryManagedFrame(tirfFrame,
  551.                                                 new ITRFProvider(tirfProvider.getEOPHistory()),
  552.                                                 false, factoryKey);
  553.                 FRAMES.put(factoryKey, frame);
  554.             }

  555.             return frame;

  556.         }
  557.     }

  558.     /** Get the ITRF2008 reference frame, using IERS 2010 conventions and ignoring tidal effects.
  559.      * @return the selected reference frame singleton.
  560.      * @exception OrekitException if the precession-nutation model data embedded in the
  561.      * library cannot be read.
  562.      * @deprecated as of 6.1, replaced with {@link #getITRF(IERSConventions, boolean)}
  563.      */
  564.     @Deprecated
  565.     public static FactoryManagedFrame getITRF2008() throws OrekitException {
  566.         return getITRF2008(true);
  567.     }

  568.     /** Get the ITRF2008 reference frame, using IERS 2010 conventions.
  569.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  570.      * @return the selected reference frame singleton.
  571.      * @exception OrekitException if the precession-nutation model data embedded in the
  572.      * library cannot be read.
  573.      * @deprecated as of 6.1, replaced with {@link #getITRF(IERSConventions, boolean)}
  574.      */
  575.     @Deprecated
  576.     public static FactoryManagedFrame getITRF2008(final boolean simpleEOP) throws OrekitException {
  577.         return getITRF(IERSConventions.IERS_2010, simpleEOP);
  578.     }

  579.     /** Get the ITRF2005 reference frame, using IERS 2010 conventions and ignoring tidal effects.
  580.      * @return the selected reference frame singleton.
  581.      * @exception OrekitException if the precession-nutation model data embedded in the
  582.      * library cannot be read.
  583.      * @deprecated as of 6.1, replaced by {@link #getITRF(IERSConventions, boolean)} and
  584.      * {@link HelmertTransformation.Predefined#ITRF_2008_TO_ITRF_2005}
  585.      */
  586.     @Deprecated
  587.     public static FactoryManagedFrame getITRF2005() throws OrekitException {
  588.         return getITRF2005(true);
  589.     }

  590.     /** Get the ITRF2005 reference frame, using IERS 2010 conventions.
  591.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  592.      * @return the selected reference frame singleton.
  593.      * @exception OrekitException if the precession-nutation model data embedded in the
  594.      * library cannot be read.
  595.      * @deprecated as of 6.1, replaced by {@link #getITRF(IERSConventions, boolean)} and
  596.      * {@link HelmertTransformation.Predefined#ITRF_2008_TO_ITRF_2005}
  597.      */
  598.     @Deprecated
  599.     public static FactoryManagedFrame getITRF2005(final boolean simpleEOP) throws OrekitException {

  600.         final Predefined factoryKey = simpleEOP ?
  601.                                       Predefined.ITRF_2005_WITHOUT_TIDAL_EFFECTS :
  602.                                       Predefined.ITRF_2005_WITH_TIDAL_EFFECTS;

  603.         return getITRSRealization(factoryKey, getITRF2008(simpleEOP),
  604.                                   HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_2005);

  605.     }

  606.     /** Get the ITRF2000 reference frame, ignoring tidal effects.
  607.      * @return the selected reference frame singleton.
  608.      * @exception OrekitException if the precession-nutation model data embedded in the
  609.      * library cannot be read.
  610.      * @deprecated as of 6.1, replaced by {@link #getITRF(IERSConventions, boolean)} and
  611.      * {@link HelmertTransformation.Predefined#ITRF_2008_TO_ITRF_2000}
  612.      */
  613.     @Deprecated
  614.     public static FactoryManagedFrame getITRF2000() throws OrekitException {
  615.         return getITRF2000(true);
  616.     }

  617.     /** Get the ITRF2000 reference frame.
  618.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  619.      * @return the selected reference frame singleton.
  620.      * @exception OrekitException if the precession-nutation model data embedded in the
  621.      * library cannot be read.
  622.      * @deprecated as of 6.1, replaced by {@link #getITRF(IERSConventions, boolean)} and
  623.      * {@link HelmertTransformation.Predefined#ITRF_2008_TO_ITRF_2000}
  624.      */
  625.     @Deprecated
  626.     public static FactoryManagedFrame getITRF2000(final boolean simpleEOP) throws OrekitException {

  627.         final Predefined factoryKey = simpleEOP ?
  628.                                       Predefined.ITRF_2000_WITHOUT_TIDAL_EFFECTS :
  629.                                       Predefined.ITRF_2000_WITH_TIDAL_EFFECTS;

  630.         return getITRSRealization(factoryKey, getITRF2008(simpleEOP),
  631.                                   HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_2000);

  632.     }

  633.     /** Get the ITRF97 reference frame, ignoring tidal effects.
  634.      * @return the selected reference frame singleton.
  635.      * @exception OrekitException if the precession-nutation model data embedded in the
  636.      * library cannot be read.
  637.      * @deprecated as of 6.1, replaced by {@link #getITRF(IERSConventions, boolean)} and
  638.      * {@link HelmertTransformation.Predefined#ITRF_2008_TO_ITRF_97}
  639.      */
  640.     @Deprecated
  641.     public static FactoryManagedFrame getITRF97() throws OrekitException {
  642.         return getITRF97(true);
  643.     }

  644.     /** Get the ITRF97 reference frame.
  645.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  646.      * @return the selected reference frame singleton.
  647.      * @exception OrekitException if the precession-nutation model data embedded in the
  648.      * library cannot be read.
  649.      * @deprecated as of 6.1, replaced by {@link #getITRF(IERSConventions, boolean)} and
  650.      * {@link HelmertTransformation.Predefined#ITRF_2008_TO_ITRF_97}
  651.      */
  652.     @Deprecated
  653.     public static FactoryManagedFrame getITRF97(final boolean simpleEOP) throws OrekitException {

  654.         final Predefined factoryKey = simpleEOP ?
  655.                                       Predefined.ITRF_97_WITHOUT_TIDAL_EFFECTS :
  656.                                       Predefined.ITRF_97_WITH_TIDAL_EFFECTS;

  657.         return getITRSRealization(factoryKey, getITRF2008(simpleEOP),
  658.                                   HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_97);

  659.     }

  660.     /** Get the ITRF93 reference frame, ignoring tidal effects.
  661.      * @return the selected reference frame singleton.
  662.      * @exception OrekitException if the precession-nutation model data embedded in the
  663.      * library cannot be read.
  664.      * @deprecated as of 6.1, replaced by {@link #getITRF(IERSConventions, boolean)} and
  665.      * {@link HelmertTransformation.Predefined#ITRF_2008_TO_ITRF_93}
  666.      */
  667.     @Deprecated
  668.     public static FactoryManagedFrame getITRF93() throws OrekitException {
  669.         return getITRF93(true);
  670.     }

  671.     /** Get the ITRF93 reference frame.
  672.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  673.      * @return the selected reference frame singleton.
  674.      * @exception OrekitException if the precession-nutation model data embedded in the
  675.      * library cannot be read.
  676.      * @deprecated as of 6.1, replaced by {@link #getITRF(IERSConventions, boolean)} and
  677.      * {@link HelmertTransformation.Predefined#ITRF_2008_TO_ITRF_93}
  678.      */
  679.     @Deprecated
  680.     public static FactoryManagedFrame getITRF93(final boolean simpleEOP) throws OrekitException {

  681.         final Predefined factoryKey = simpleEOP ?
  682.                                       Predefined.ITRF_93_WITHOUT_TIDAL_EFFECTS :
  683.                                       Predefined.ITRF_93_WITH_TIDAL_EFFECTS;

  684.         return getITRSRealization(factoryKey, getITRF2008(simpleEOP),
  685.                                   HelmertTransformation.Predefined.ITRF_2008_TO_ITRF_93);

  686.     }

  687.     /** Get an ITRS realization reference frame.
  688.      * @param factoryKey key of the frame within the factory
  689.      * @param parent parent frame to which the Helmert transformation should be applied
  690.      * to define the desired realization
  691.      * @param predefined predefined transformation between parent frame and created frame
  692.      * @return the selected reference frame singleton.
  693.      * @exception OrekitException if the precession-nutation model data embedded in the
  694.      * library cannot be read.
  695.      */
  696.     private static FactoryManagedFrame getITRSRealization(final Predefined factoryKey, final Frame parent,
  697.                                                           final HelmertTransformation.Predefined predefined)
  698.         throws OrekitException {
  699.         synchronized (FramesFactory.class) {

  700.             // try to find an already built frame
  701.             FactoryManagedFrame frame = FRAMES.get(factoryKey);

  702.             if (frame == null) {
  703.                 // it's the first time we need this frame, build it and store it
  704.                 final Frame nonFactoryManaged = predefined.createTransformedITRF(parent, factoryKey.getName());
  705.                 final TransformProvider provider = nonFactoryManaged.getTransformProvider();
  706.                 frame = new FactoryManagedFrame(parent, provider, false, factoryKey);
  707.                 FRAMES.put(factoryKey, frame);

  708.             }

  709.             return frame;

  710.         }
  711.     }

  712.     /** Get the TIRF reference frame, ignoring tidal effects.
  713.      * @param conventions IERS conventions to apply
  714.      * @return the selected reference frame singleton.
  715.      * @exception OrekitException if the precession-nutation model data embedded in the
  716.      * library cannot be read.
  717.      * @deprecated since 6.1 replaced with {@link #getTIRF(IERSConventions)}
  718.      */
  719.     @Deprecated
  720.     public static FactoryManagedFrame getTIRF2000(final IERSConventions conventions) throws OrekitException {
  721.         return getTIRF(conventions);
  722.     }

  723.     /** Get the TIRF reference frame, ignoring tidal effects.
  724.      * @param conventions IERS conventions to apply
  725.      * @return the selected reference frame singleton.
  726.      * @exception OrekitException if the precession-nutation model data embedded in the
  727.      * library cannot be read.
  728.      */
  729.     public static FactoryManagedFrame getTIRF(final IERSConventions conventions) throws OrekitException {
  730.         return getTIRF(conventions, true);
  731.     }

  732.     /** Get the TIRF reference frame.
  733.      * @param conventions IERS conventions to apply
  734.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  735.      * @return the selected reference frame singleton.
  736.      * @exception OrekitException if the precession-nutation model data embedded in the
  737.      * library cannot be read.
  738.      * @deprecated since 6.1 replaced with {@link #getTIRF(IERSConventions, boolean)}
  739.      */
  740.     @Deprecated
  741.     public static FactoryManagedFrame getTIRF2000(final IERSConventions conventions,
  742.                                                   final boolean simpleEOP) throws OrekitException {
  743.         return getTIRF(conventions, simpleEOP);
  744.     }

  745.     /** Get the TIRF reference frame.
  746.      * @param conventions IERS conventions to apply
  747.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  748.      * @return the selected reference frame singleton.
  749.      * @exception OrekitException if the precession-nutation model data embedded in the
  750.      * library cannot be read.
  751.      * @since 6.1
  752.      */
  753.     public static FactoryManagedFrame getTIRF(final IERSConventions conventions,
  754.                                               final boolean simpleEOP)
  755.         throws OrekitException {
  756.         synchronized (FramesFactory.class) {

  757.             // try to find an already built frame
  758.             final Predefined factoryKey;
  759.             switch (conventions) {
  760.             case IERS_1996 :
  761.                 factoryKey = simpleEOP ?
  762.                              Predefined.TIRF_CONVENTIONS_1996_SIMPLE_EOP :
  763.                              Predefined.TIRF_CONVENTIONS_1996_ACCURATE_EOP;
  764.                 break;
  765.             case IERS_2003 :
  766.                 factoryKey = simpleEOP ?
  767.                              Predefined.TIRF_CONVENTIONS_2003_SIMPLE_EOP :
  768.                              Predefined.TIRF_CONVENTIONS_2003_ACCURATE_EOP;
  769.                 break;
  770.             case IERS_2010 :
  771.                 factoryKey = simpleEOP ?
  772.                              Predefined.TIRF_CONVENTIONS_2010_SIMPLE_EOP :
  773.                              Predefined.TIRF_CONVENTIONS_2010_ACCURATE_EOP;
  774.                 break;
  775.             default :
  776.                 // this should never happen
  777.                 throw OrekitException.createInternalError(null);
  778.             }
  779.             FactoryManagedFrame frame = FRAMES.get(factoryKey);

  780.             if (frame == null) {
  781.                 // it's the first time we need this frame, build it and store it
  782.                 final Frame cirf = getCIRF(conventions, simpleEOP);
  783.                 final InterpolatingTransformProvider cirfInterpolating =
  784.                         (InterpolatingTransformProvider) cirf.getTransformProvider();
  785.                 final CIRFProvider cirfRaw = (CIRFProvider) cirfInterpolating.getRawProvider();
  786.                 final EOPHistory eopHistory = cirfRaw.getEOPHistory();
  787.                 frame = new FactoryManagedFrame(cirf, new TIRFProvider(eopHistory), false, factoryKey);
  788.                 FRAMES.put(factoryKey, frame);
  789.             }

  790.             return frame;

  791.         }
  792.     }

  793.     /** Get the CIRF2000 reference frame.
  794.      * @param conventions IERS conventions to apply
  795.      * @return the selected reference frame singleton.
  796.      * @exception OrekitException if the precession-nutation model data embedded in the
  797.      * library cannot be read.
  798.      * @deprecated since 6.1 repaced with {@link #getCIRF(IERSConventions, boolean)}
  799.      */
  800.     @Deprecated
  801.     public static FactoryManagedFrame getCIRF2000(final IERSConventions conventions) throws OrekitException {
  802.         return getCIRF(conventions, false);
  803.     }

  804.     /** Get the CIRF2000 reference frame.
  805.      * @param conventions IERS conventions to apply
  806.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  807.      * @return the selected reference frame singleton.
  808.      * @exception OrekitException if the precession-nutation model data embedded in the
  809.      * library cannot be read.
  810.      */
  811.     public static FactoryManagedFrame getCIRF(final IERSConventions conventions,
  812.                                               final boolean simpleEOP)
  813.         throws OrekitException {
  814.         synchronized (FramesFactory.class) {

  815.             // try to find an already built frame
  816.             final Predefined factoryKey;
  817.             switch (conventions) {
  818.             case IERS_1996 :
  819.                 factoryKey = simpleEOP ?
  820.                              Predefined.CIRF_CONVENTIONS_1996_SIMPLE_EOP :
  821.                              Predefined.CIRF_CONVENTIONS_1996_ACCURATE_EOP;
  822.                 break;
  823.             case IERS_2003 :
  824.                 factoryKey = simpleEOP ?
  825.                              Predefined.CIRF_CONVENTIONS_2003_SIMPLE_EOP :
  826.                              Predefined.CIRF_CONVENTIONS_2003_ACCURATE_EOP;
  827.                 break;
  828.             case IERS_2010 :
  829.                 factoryKey = simpleEOP ?
  830.                              Predefined.CIRF_CONVENTIONS_2010_SIMPLE_EOP :
  831.                              Predefined.CIRF_CONVENTIONS_2010_ACCURATE_EOP;
  832.                 break;
  833.             default :
  834.                 // this should never happen
  835.                 throw OrekitException.createInternalError(null);
  836.             }
  837.             FactoryManagedFrame frame = FRAMES.get(factoryKey);

  838.             if (frame == null) {
  839.                 // it's the first time we need this frame, build it and store it
  840.                 final EOPHistory eopHistory = FramesFactory.getEOPHistory(conventions, simpleEOP);
  841.                 final TransformProvider interpolating =
  842.                         new InterpolatingTransformProvider(new CIRFProvider(eopHistory), true, false,
  843.                                                            AbsoluteDate.PAST_INFINITY, AbsoluteDate.FUTURE_INFINITY,
  844.                                                            6, Constants.JULIAN_DAY / 24,
  845.                                                            OrekitConfiguration.getCacheSlotsNumber(),
  846.                                                            Constants.JULIAN_YEAR, 30 * Constants.JULIAN_DAY);
  847.                 frame = new FactoryManagedFrame(getGCRF(), interpolating, true, factoryKey);
  848.                 FRAMES.put(factoryKey, frame);
  849.             }

  850.             return frame;

  851.         }
  852.     }

  853.     /** Get the VEIS 1950 reference frame.
  854.      * <p>Its parent frame is the GTOD frame with IERS 1996 conventions without EOP corrections.<p>
  855.      * @return the selected reference frame singleton.
  856.      * @exception OrekitException if data embedded in the library cannot be read
  857.      */
  858.     public static FactoryManagedFrame getVeis1950() throws OrekitException {
  859.         synchronized (FramesFactory.class) {

  860.             // try to find an already built frame
  861.             final Predefined factoryKey = Predefined.VEIS_1950;
  862.             FactoryManagedFrame frame = FRAMES.get(factoryKey);

  863.             if (frame == null) {
  864.                 // it's the first time we need this frame, build it and store it
  865.                 frame = new FactoryManagedFrame(FramesFactory.getGTOD(IERSConventions.IERS_1996, false, true),
  866.                                                 new VEISProvider(), true, factoryKey);
  867.                 FRAMES.put(factoryKey, frame);
  868.             }

  869.             return frame;

  870.         }
  871.     }

  872.     /** Get the equinox-based ITRF reference frame.
  873.      * @return the selected reference frame singleton.
  874.      * @exception OrekitException if data embedded in the library cannot be read
  875.      * @deprecated since 6.1 replaced with {@link #getITRFEquinox(IERSConventions, boolean)}
  876.      */
  877.     @Deprecated
  878.     public static FactoryManagedFrame getITRFEquinox() throws OrekitException {
  879.         return getITRFEquinox(IERSConventions.IERS_1996, true);
  880.     }

  881.     /** Get the equinox-based ITRF reference frame.
  882.      * @param conventions IERS conventions to apply
  883.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  884.      * @return the selected reference frame singleton.
  885.      * @exception OrekitException if data embedded in the library cannot be read
  886.      * @since 6.1
  887.      */
  888.     public static FactoryManagedFrame getITRFEquinox(final IERSConventions conventions,
  889.                                                      final boolean simpleEOP)
  890.         throws OrekitException {
  891.         synchronized (FramesFactory.class) {

  892.             // try to find an already built frame
  893.             final Predefined factoryKey;
  894.             switch (conventions) {
  895.             case IERS_1996 :
  896.                 factoryKey = simpleEOP ?
  897.                              Predefined.ITRF_EQUINOX_CONV_1996_SIMPLE_EOP :
  898.                              Predefined.ITRF_EQUINOX_CONV_1996_ACCURATE_EOP;
  899.                 break;
  900.             case IERS_2003 :
  901.                 factoryKey = simpleEOP ?
  902.                              Predefined.ITRF_EQUINOX_CONV_2003_SIMPLE_EOP :
  903.                              Predefined.ITRF_EQUINOX_CONV_2003_ACCURATE_EOP;
  904.                 break;
  905.             case IERS_2010 :
  906.                 factoryKey = simpleEOP ?
  907.                              Predefined.ITRF_EQUINOX_CONV_2010_SIMPLE_EOP :
  908.                              Predefined.ITRF_EQUINOX_CONV_2010_ACCURATE_EOP;
  909.                 break;
  910.             default :
  911.                 // this should never happen
  912.                 throw OrekitException.createInternalError(null);
  913.             }
  914.             FactoryManagedFrame frame = FRAMES.get(factoryKey);

  915.             if (frame == null) {
  916.                 // it's the first time we need this frame, build it and store it
  917.                 final Frame gtod = getGTOD(conventions, true, simpleEOP);
  918.                 final InterpolatingTransformProvider gtodInterpolating =
  919.                         (InterpolatingTransformProvider) gtod.getTransformProvider();
  920.                 final GTODProvider gtodRaw    = (GTODProvider) gtodInterpolating.getRawProvider();
  921.                 final EOPHistory   eopHistory = gtodRaw.getEOPHistory();
  922.                 frame = new FactoryManagedFrame(gtod, new ITRFProvider(eopHistory), false, factoryKey);
  923.                 FRAMES.put(factoryKey, frame);
  924.             }

  925.             return frame;

  926.         }
  927.     }

  928.     /** Get the GTOD reference frame.
  929.      * <p>
  930.      * The applyEOPCorr parameter is available mainly for testing purposes or for
  931.      * consistency with legacy software that don't handle EOP correction parameters.
  932.      * Beware that setting this parameter to {@code false} leads to crude accuracy
  933.      * (order of magnitudes for errors might be above 250m in LEO and 1400m in GEO).
  934.      * For this reason, setting this parameter to false is restricted to {@link
  935.      * IERSConventions#IERS_1996 IERS 1996} conventions, and hence the {@link
  936.      * IERSConventions IERS conventions} cannot be freely chosen here.
  937.      * </p>
  938.      * @param applyEOPCorr if true, EOP corrections are applied (here, dut1 and lod)
  939.      * @return the selected reference frame singleton.
  940.      * @exception OrekitException if data embedded in the library cannot be read
  941.      */
  942.     public static FactoryManagedFrame getGTOD(final boolean applyEOPCorr) throws OrekitException {
  943.         return getGTOD(IERSConventions.IERS_1996, applyEOPCorr, true);
  944.     }

  945.     /** Get the GTOD reference frame.
  946.      * @param conventions IERS conventions to apply
  947.      * @return the selected reference frame singleton.
  948.      * @exception OrekitException if data embedded in the library cannot be read
  949.      * @deprecated as of 6.1, replaced with {@link #getGTOD(IERSConventions, boolean)}
  950.      */
  951.     @Deprecated
  952.     public static FactoryManagedFrame getGTOD(final IERSConventions conventions)
  953.         throws OrekitException {
  954.         return getGTOD(conventions, true, true);
  955.     }

  956.     /** Get the GTOD reference frame.
  957.      * @param conventions IERS conventions to apply
  958.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  959.      * @return the selected reference frame singleton.
  960.      * @exception OrekitException if data embedded in the library cannot be read
  961.      */
  962.     public static FactoryManagedFrame getGTOD(final IERSConventions conventions,
  963.                                               final boolean simpleEOP)
  964.         throws OrekitException {
  965.         return getGTOD(conventions, true, simpleEOP);
  966.     }

  967.     /** Get the GTOD reference frame.
  968.      * <p>
  969.      * The applyEOPCorr parameter is available mainly for testing purposes or for
  970.      * consistency with legacy software that don't handle EOP correction parameters.
  971.      * Beware that setting this parameter to {@code false} leads to crude accuracy
  972.      * (order of magnitudes for errors might be above 250m in LEO and 1400m in GEO).
  973.      * For this reason, setting this parameter to false is restricted to {@link
  974.      * IERSConventions#IERS_1996 IERS 1996} conventions, and hence this method is private.
  975.      * </p>
  976.      * @param conventions IERS conventions to apply
  977.      * @param applyEOPCorr if true, EOP corrections are applied (here, dut1 and lod)
  978.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  979.      * @return the selected reference frame singleton.
  980.      * @exception OrekitException if data embedded in the library cannot be read
  981.      */
  982.     private static FactoryManagedFrame getGTOD(final IERSConventions conventions,
  983.                                                final boolean applyEOPCorr,
  984.                                                final boolean simpleEOP)
  985.         throws OrekitException {

  986.         if (conventions != IERSConventions.IERS_1996 && !applyEOPCorr) {
  987.             // this should never happen as this method is private and called
  988.             // only above with controlled input
  989.             throw OrekitException.createInternalError(null);
  990.         }

  991.         synchronized (FramesFactory.class) {

  992.             // try to find an already built frame
  993.             final Predefined factoryKey;
  994.             switch (conventions) {
  995.             case IERS_1996 :
  996.                 factoryKey = applyEOPCorr ?
  997.                              (simpleEOP ? Predefined.GTOD_CONVENTIONS_1996_SIMPLE_EOP : Predefined.GTOD_CONVENTIONS_1996_ACCURATE_EOP) :
  998.                              Predefined.GTOD_WITHOUT_EOP_CORRECTIONS;
  999.                 break;
  1000.             case IERS_2003 :
  1001.                 factoryKey = simpleEOP ?
  1002.                              Predefined.GTOD_CONVENTIONS_2003_SIMPLE_EOP :
  1003.                              Predefined.GTOD_CONVENTIONS_2003_ACCURATE_EOP;
  1004.                 break;
  1005.             case IERS_2010 :
  1006.                 factoryKey = simpleEOP ?
  1007.                              Predefined.GTOD_CONVENTIONS_2010_SIMPLE_EOP :
  1008.                              Predefined.GTOD_CONVENTIONS_2010_ACCURATE_EOP;
  1009.                 break;
  1010.             default :
  1011.                 // this should never happen
  1012.                 throw OrekitException.createInternalError(null);
  1013.             }
  1014.             FactoryManagedFrame frame = FRAMES.get(factoryKey);

  1015.             if (frame == null) {
  1016.                 // it's the first time we need this frame, build it and store it
  1017.                 final Frame tod = getTOD(conventions, applyEOPCorr, simpleEOP);
  1018.                 final InterpolatingTransformProvider todInterpolating =
  1019.                         (InterpolatingTransformProvider) tod.getTransformProvider();
  1020.                 final TODProvider       todRaw     = (TODProvider) todInterpolating.getRawProvider();
  1021.                 final EOPHistory        eopHistory = todRaw.getEOPHistory();
  1022.                 final GTODProvider      gtodRaw    = new GTODProvider(conventions, eopHistory);
  1023.                 final TransformProvider gtodInterpolating =
  1024.                         new InterpolatingTransformProvider(gtodRaw, true, false,
  1025.                                                            AbsoluteDate.PAST_INFINITY, AbsoluteDate.FUTURE_INFINITY,
  1026.                                                            todInterpolating.getGridPoints(), todInterpolating.getStep(),
  1027.                                                            OrekitConfiguration.getCacheSlotsNumber(),
  1028.                                                            Constants.JULIAN_YEAR, 30 * Constants.JULIAN_DAY);
  1029.                 frame = new FactoryManagedFrame(tod, gtodInterpolating, false, factoryKey);
  1030.                 FRAMES.put(factoryKey, frame);
  1031.             }

  1032.             return frame;

  1033.         }
  1034.     }

  1035.     /** Get the GTOD reference frame.
  1036.      * <p>
  1037.      * The applyEOPCorr parameter is available mainly for testing purposes or for
  1038.      * consistency with legacy software that don't handle EOP correction parameters.
  1039.      * Beware that setting this parameter to {@code false} leads to crude accuracy
  1040.      * (order of magnitudes for errors might be above 250m in LEO and 1400m in GEO).
  1041.      * </p>
  1042.      * @param applyEOPCorr if true, EOP corrections are applied (here, lod)
  1043.      * @return the selected reference frame singleton.
  1044.      * @exception OrekitException if data embedded in the library cannot be read
  1045.      * @deprecated as of 6.0, replaced by {@link #getGTOD(IERSConventions, boolean)}
  1046.      */
  1047.     @Deprecated
  1048.     public static FactoryManagedFrame getPEF(final boolean applyEOPCorr) throws OrekitException {
  1049.         return getGTOD(applyEOPCorr);
  1050.     }

  1051.     /** Get the TOD reference frame.
  1052.      * <p>
  1053.      * The applyEOPCorr parameter is available mainly for testing purposes or for
  1054.      * consistency with legacy software that don't handle EOP correction parameters.
  1055.      * Beware that setting this parameter to {@code false} leads to crude accuracy
  1056.      * (order of magnitudes for errors might be above 1m in LEO and 10m in GEO).
  1057.      * For this reason, setting this parameter to false is restricted to {@link
  1058.      * IERSConventions#IERS_1996 IERS 1996} conventions, and hence the {@link
  1059.      * IERSConventions IERS conventions} cannot be freely chosen here.
  1060.      * </p>
  1061.      * @param applyEOPCorr if true, EOP corrections are applied (here, nutation)
  1062.      * @return the selected reference frame singleton.
  1063.      * @exception OrekitException if data embedded in the library cannot be read
  1064.      */
  1065.     public static FactoryManagedFrame getTOD(final boolean applyEOPCorr)
  1066.         throws OrekitException {
  1067.         return getTOD(IERSConventions.IERS_1996, applyEOPCorr, false);
  1068.     }

  1069.     /** Get the TOD reference frame.
  1070.      * @param conventions IERS conventions to apply
  1071.      * @return the selected reference frame singleton.
  1072.      * @exception OrekitException if data embedded in the library cannot be read
  1073.      * @deprecated as of 6.1, replaced with {@link #getTOD(IERSConventions, boolean)}
  1074.      */
  1075.     public static FactoryManagedFrame getTOD(final IERSConventions conventions)
  1076.         throws OrekitException {
  1077.         return getTOD(conventions, true, true);
  1078.     }

  1079.     /** Get the TOD reference frame.
  1080.      * @param conventions IERS conventions to apply
  1081.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  1082.      * @return the selected reference frame singleton.
  1083.      * @exception OrekitException if data embedded in the library cannot be read
  1084.      */
  1085.     public static FactoryManagedFrame getTOD(final IERSConventions conventions,
  1086.                                              final boolean simpleEOP)
  1087.         throws OrekitException {
  1088.         return getTOD(conventions, true, simpleEOP);
  1089.     }

  1090.     /** Get the TOD reference frame.
  1091.      * <p>
  1092.      * The applyEOPCorr parameter is available mainly for testing purposes or for
  1093.      * consistency with legacy software that don't handle EOP correction parameters.
  1094.      * Beware that setting this parameter to {@code false} leads to crude accuracy
  1095.      * (order of magnitudes for errors might be above 1m in LEO and 10m in GEO).
  1096.      * For this reason, setting this parameter to false is restricted to {@link
  1097.      * IERSConventions#IERS_1996 IERS 1996} conventions, and hence this method is private.
  1098.      * </p>
  1099.      * @param conventions IERS conventions to apply
  1100.      * @param applyEOPCorr if true, EOP corrections are applied (here, nutation)
  1101.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  1102.      * @return the selected reference frame singleton.
  1103.      * @exception OrekitException if data embedded in the library cannot be read
  1104.      */
  1105.     private static FactoryManagedFrame getTOD(final IERSConventions conventions,
  1106.                                               final boolean applyEOPCorr,
  1107.                                               final boolean simpleEOP)
  1108.         throws OrekitException {

  1109.         if (conventions != IERSConventions.IERS_1996 && !applyEOPCorr) {
  1110.             // this should never happen as this method is private and called
  1111.             // only above with controlled input
  1112.             throw OrekitException.createInternalError(null);
  1113.         }

  1114.         synchronized (FramesFactory.class) {

  1115.             // try to find an already built frame
  1116.             final Predefined factoryKey;
  1117.             switch (conventions) {
  1118.             case IERS_1996 :
  1119.                 factoryKey = applyEOPCorr ?
  1120.                              (simpleEOP ? Predefined.TOD_CONVENTIONS_1996_SIMPLE_EOP : Predefined.TOD_CONVENTIONS_1996_ACCURATE_EOP) :
  1121.                              Predefined.TOD_WITHOUT_EOP_CORRECTIONS;
  1122.                 break;
  1123.             case IERS_2003 :
  1124.                 factoryKey = simpleEOP ?
  1125.                              Predefined.TOD_CONVENTIONS_2003_SIMPLE_EOP :
  1126.                              Predefined.TOD_CONVENTIONS_2003_ACCURATE_EOP;
  1127.                 break;
  1128.             case IERS_2010 :
  1129.                 factoryKey = simpleEOP ?
  1130.                              Predefined.TOD_CONVENTIONS_2010_SIMPLE_EOP :
  1131.                              Predefined.TOD_CONVENTIONS_2010_ACCURATE_EOP;
  1132.                 break;
  1133.             default :
  1134.                 // this should never happen
  1135.                 throw OrekitException.createInternalError(null);
  1136.             }
  1137.             final int interpolationPoints;
  1138.             final int pointsPerDay;
  1139.             if (applyEOPCorr) {
  1140.                 interpolationPoints = 6;
  1141.                 pointsPerDay        = 24;
  1142.             } else {
  1143.                 interpolationPoints = 6;
  1144.                 pointsPerDay        = 8;
  1145.             }
  1146.             FactoryManagedFrame frame = FRAMES.get(factoryKey);

  1147.             if (frame == null) {
  1148.                 // it's the first time we need this frame, build it and store it
  1149.                 final EOPHistory eopHistory = applyEOPCorr ? getEOPHistory(conventions, simpleEOP) : null;
  1150.                 final TransformProvider interpolating =
  1151.                         new InterpolatingTransformProvider(new TODProvider(conventions, eopHistory),
  1152.                                                            true, false,
  1153.                                                            AbsoluteDate.PAST_INFINITY, AbsoluteDate.FUTURE_INFINITY,
  1154.                                                            interpolationPoints, Constants.JULIAN_DAY / pointsPerDay,
  1155.                                                            OrekitConfiguration.getCacheSlotsNumber(),
  1156.                                                            Constants.JULIAN_YEAR, 30 * Constants.JULIAN_DAY);
  1157.                 frame = new FactoryManagedFrame(getMOD(conventions, applyEOPCorr), interpolating, true, factoryKey);
  1158.                 FRAMES.put(factoryKey, frame);
  1159.             }

  1160.             return frame;

  1161.         }
  1162.     }

  1163.     /** Get the MOD reference frame.
  1164.      * <p>
  1165.      * The applyEOPCorr parameter is available mainly for testing purposes or for
  1166.      * consistency with legacy software that don't handle EOP correction parameters.
  1167.      * Beware that setting this parameter to {@code false} leads to crude accuracy
  1168.      * (order of magnitudes for errors might be above 1m in LEO and 10m in GEO).
  1169.      * For this reason, setting this parameter to false is restricted to {@link
  1170.      * IERSConventions#IERS_1996 IERS 1996} conventions, and hence the {@link
  1171.      * IERSConventions IERS conventions} cannot be freely chosen here.
  1172.      * </p>
  1173.      * @param applyEOPCorr if true, EOP corrections are applied (EME2000/GCRF bias compensation)
  1174.      * @return the selected reference frame singleton.
  1175.      * @exception OrekitException if data embedded in the library cannot be read
  1176.      */
  1177.     public static FactoryManagedFrame getMOD(final boolean applyEOPCorr)
  1178.         throws OrekitException {
  1179.         return getMOD(IERSConventions.IERS_1996, applyEOPCorr);
  1180.     }

  1181.     /** Get the MOD reference frame.
  1182.      * @param conventions IERS conventions to apply
  1183.      * @return the selected reference frame singleton.
  1184.      * @exception OrekitException if data embedded in the library cannot be read
  1185.      */
  1186.     public static FactoryManagedFrame getMOD(final IERSConventions conventions)
  1187.         throws OrekitException {
  1188.         return getMOD(conventions, true);
  1189.     }

  1190.     /** Get the MOD reference frame.
  1191.      * <p>
  1192.      * The applyEOPCorr parameter is available mainly for testing purposes or for
  1193.      * consistency with legacy software that don't handle EOP correction parameters.
  1194.      * Beware that setting this parameter to {@code false} leads to crude accuracy
  1195.      * (order of magnitudes for errors might be above 1m in LEO and 10m in GEO).
  1196.      * For this reason, setting this parameter to false is restricted to {@link
  1197.      * IERSConventions#IERS_1996 IERS 1996} conventions, and hence this method is private.
  1198.      * </p>
  1199.      * @param conventions IERS conventions to apply
  1200.      * @param applyEOPCorr if true, EOP corrections are applied (EME2000/GCRF bias compensation)
  1201.      * @return the selected reference frame singleton.
  1202.      * @exception OrekitException if data embedded in the library cannot be read
  1203.      */
  1204.     private static FactoryManagedFrame getMOD(final IERSConventions conventions, final boolean applyEOPCorr)
  1205.         throws OrekitException {

  1206.         if (conventions != IERSConventions.IERS_1996 && !applyEOPCorr) {
  1207.             // this should never happen as this method is private and called
  1208.             // only above with controlled input
  1209.             throw OrekitException.createInternalError(null);
  1210.         }

  1211.         synchronized (FramesFactory.class) {

  1212.             final Predefined factoryKey;
  1213.             final Frame parent;
  1214.             switch (conventions) {
  1215.             case IERS_1996 :
  1216.                 factoryKey = applyEOPCorr ? Predefined.MOD_CONVENTIONS_1996 : Predefined.MOD_WITHOUT_EOP_CORRECTIONS;
  1217.                 parent     = applyEOPCorr ? FramesFactory.getGCRF() : FramesFactory.getEME2000();
  1218.                 break;
  1219.             case IERS_2003 :
  1220.                 factoryKey = Predefined.MOD_CONVENTIONS_2003;
  1221.                 // in IERS conventions 2003, the precession angles zetaA, thetaA and zA
  1222.                 // from equation 33 are computed from EME2000, not from GCRF
  1223.                 parent     = FramesFactory.getEME2000();
  1224.                 break;
  1225.             case IERS_2010 :
  1226.                 factoryKey = Predefined.MOD_CONVENTIONS_2010;
  1227.                 // precession angles epsilon0, psiA, omegaA and chiA
  1228.                 // from equations 5.39 and 5.40 are computed from EME2000
  1229.                 parent     = FramesFactory.getEME2000();
  1230.                 break;
  1231.             default :
  1232.                 // this should never happen
  1233.                 throw OrekitException.createInternalError(null);
  1234.             }

  1235.             // try to find an already built frame
  1236.             FactoryManagedFrame frame = FRAMES.get(factoryKey);

  1237.             if (frame == null) {
  1238.                 // it's the first time we need this frame, build it and store it
  1239.                 frame = new FactoryManagedFrame(parent, new MODProvider(conventions), true, factoryKey);
  1240.                 FRAMES.put(factoryKey, frame);
  1241.             }

  1242.             return frame;

  1243.         }
  1244.     }

  1245.     /** Get the MOD reference frame.
  1246.      * <p>
  1247.      * The applyEOPCorr parameter is available mainly for testing purposes or for
  1248.      * consistency with legacy software that don't handle EOP correction parameters.
  1249.      * Beware that setting this parameter to {@code false} leads to crude accuracy
  1250.      * (order of magnitudes for errors might be above 1m in LEO and 10m in GEO).
  1251.      * </p>
  1252.      * @param applyEOPCorr if true, EOP corrections are applied (EME2000/GCRF bias compensation)
  1253.      * @return the selected reference frame singleton.
  1254.      * @exception OrekitException if data embedded in the library cannot be read
  1255.      * @deprecated as of 6.0, replaced by {@link #getMOD(IERSConventions)}
  1256.      */
  1257.     @Deprecated
  1258.     public static FactoryManagedFrame getMEME(final boolean applyEOPCorr) throws OrekitException {
  1259.         return getMOD(IERSConventions.IERS_1996, applyEOPCorr);
  1260.     }

  1261.     /** Get the TEME reference frame.
  1262.      * <p>
  1263.      * The TEME frame is used for the SGP4 model in TLE propagation. This frame has <em>no</em>
  1264.      * official definition and there are some ambiguities about whether it should be used
  1265.      * as "of date" or "of epoch". This frame should therefore be used <em>only</em> for
  1266.      * TLE propagation and not for anything else, as recommended by the CCSDS Orbit Data Message
  1267.      * blue book.
  1268.      * </p>
  1269.      * @return the selected reference frame singleton.
  1270.      * @exception OrekitException if data embedded in the library cannot be read
  1271.      */
  1272.     public static FactoryManagedFrame getTEME() throws OrekitException {
  1273.         synchronized (FramesFactory.class) {

  1274.             // try to find an already built frame
  1275.             final Predefined factoryKey = Predefined.TEME;
  1276.             FactoryManagedFrame frame = FRAMES.get(factoryKey);

  1277.             if (frame == null) {
  1278.                 // it's the first time we need this frame, build it and store it
  1279.                 final Frame tod = getTOD(IERSConventions.IERS_1996, false, true);
  1280.                 final InterpolatingTransformProvider todInterpolating =
  1281.                         (InterpolatingTransformProvider) tod.getTransformProvider();
  1282.                 final TEMEProvider temeRaw = new TEMEProvider(IERSConventions.IERS_1996, null);
  1283.                 final TransformProvider temeInterpolating =
  1284.                         new InterpolatingTransformProvider(temeRaw, true, false,
  1285.                                                            AbsoluteDate.PAST_INFINITY, AbsoluteDate.FUTURE_INFINITY,
  1286.                                                            todInterpolating.getGridPoints(), todInterpolating.getStep(),
  1287.                                                            OrekitConfiguration.getCacheSlotsNumber(),
  1288.                                                            Constants.JULIAN_YEAR, 30 * Constants.JULIAN_DAY);

  1289.                 frame = new FactoryManagedFrame(tod, temeInterpolating, true, factoryKey);
  1290.                 FRAMES.put(factoryKey, frame);
  1291.             }

  1292.             return frame;

  1293.         }
  1294.     }

  1295.     /** Get the transform between two frames, suppressing all interpolation.
  1296.      * <p>
  1297.      * This method is similar to {@link Frame#getTransformTo(Frame, AbsoluteDate)}
  1298.      * except it removes the performance enhancing interpolation features that are
  1299.      * added by the {@link FramesFactory factory} to some frames, in order to focus
  1300.      * on accuracy. The interpolation features are intended to save processing time
  1301.      * by avoiding doing some lengthy computation like nutation evaluation at each
  1302.      * time step and caching some results. This method can be used to avoid this,
  1303.      * when very high accuracy is desired, or for testing purposes. It should be
  1304.      * used with care, as doing the full computation is <em>really</em> costly for
  1305.      * some frames.
  1306.      * </p>
  1307.      * @param from frame from which transformation starts
  1308.      * @param to frame to which transformation ends
  1309.      * @param date date of the transform
  1310.      * @return transform between the two frames, avoiding interpolation
  1311.      * @throws OrekitException if transform cannot be computed at this date
  1312.      */
  1313.     public static Transform getNonInterpolatingTransform(final Frame from, final Frame to,
  1314.                                                          final AbsoluteDate date)
  1315.         throws OrekitException {

  1316.         // common ancestor to both frames in the frames tree
  1317.         Frame currentF = from.getDepth() > to.getDepth() ? from.getAncestor(from.getDepth() - to.getDepth()) : from;
  1318.         Frame currentT = from.getDepth() > to.getDepth() ? to : to.getAncestor(to.getDepth() - from.getDepth());
  1319.         while (currentF != currentT) {
  1320.             currentF = currentF.getParent();
  1321.             currentT = currentT.getParent();
  1322.         }
  1323.         final Frame common = currentF;

  1324.         // transform from common to instance
  1325.         Transform commonToInstance = Transform.IDENTITY;
  1326.         for (Frame frame = from; frame != common; frame = frame.getParent()) {
  1327.             TransformProvider provider = frame.getTransformProvider();
  1328.             while (provider instanceof InterpolatingTransformProvider) {
  1329.                 provider = ((InterpolatingTransformProvider) provider).getRawProvider();
  1330.             }
  1331.             commonToInstance =
  1332.                     new Transform(date, provider.getTransform(date), commonToInstance);
  1333.         }

  1334.         // transform from destination up to common
  1335.         Transform commonToDestination = Transform.IDENTITY;
  1336.         for (Frame frame = to; frame != common; frame = frame.getParent()) {
  1337.             commonToDestination =
  1338.                     new Transform(date, frame.getTransformProvider().getTransform(date), commonToDestination);
  1339.         }

  1340.         // transform from instance to destination via common
  1341.         return new Transform(date, commonToInstance.getInverse(), commonToDestination);

  1342.     }

  1343. }