AbstractTimeScales.java
/* Contributed in the public domain.
* Licensed to CS GROUP (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.time;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.hipparchus.util.MathArrays;
import org.hipparchus.util.Pair;
import org.orekit.frames.EOPHistory;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
/**
* Abstract base class for {@link TimeScales} that implements some common functionality.
*
* @author Evan Ward
* @author Luc Maisonobe
* @since 10.1
*/
public abstract class AbstractTimeScales implements TimeScales {
/** GMST time scales. */
private final ConcurrentMap<Pair<IERSConventions, Boolean>, GMSTScale> gmstMap;
/** UT1 time scales. */
private final ConcurrentMap<Pair<IERSConventions, Boolean>, UT1Scale> ut1Map;
/** Simple constructor. */
public AbstractTimeScales() {
final int n = IERSConventions.values().length;
gmstMap = new ConcurrentHashMap<>(n * 2);
ut1Map = new ConcurrentHashMap<>(n * 2);
}
/**
* Get the Universal Time 1 scale.
* <p>
* As this method allow associating any history with the time scale, it may involve
* large data sets. So this method does <em>not</em> cache the resulting {@link
* UT1Scale UT1Scale} instance, a new instance will be returned each time. In order to
* avoid wasting memory, calling {@link #getUT1(IERSConventions, boolean)} with the
* single enumerate corresponding to the conventions may be a better solution. This
* method is made available only for expert use.
* </p>
*
* @param history EOP parameters providing dUT1 (may be null if no correction is
* desired)
* @return Universal Time 1 scale
* @see #getUT1(IERSConventions, boolean)
*/
protected UT1Scale getUT1(final EOPHistory history) {
return new UT1Scale(history, getUTC());
}
/**
* Get the EOP history for the given conventions.
*
* @param conventions to use in computing the EOP history.
* @param simpleEOP whether to ignore some small tidal effects.
* @return EOP history.
*/
protected abstract EOPHistory getEopHistory(IERSConventions conventions,
boolean simpleEOP);
@Override
public UT1Scale getUT1(final IERSConventions conventions, final boolean simpleEOP) {
final Pair<IERSConventions, Boolean> key = new Pair<>(conventions, simpleEOP);
synchronized (this) {
return ut1Map.computeIfAbsent(key, k -> getUT1(getEopHistory(conventions, simpleEOP)));
}
}
@Override
public GMSTScale getGMST(final IERSConventions conventions, final boolean simpleEOP) {
final Pair<IERSConventions, Boolean> key = new Pair<>(conventions, simpleEOP);
synchronized (this) {
return gmstMap.computeIfAbsent(key, k -> new GMSTScale(getUT1(conventions, simpleEOP)));
}
}
@Override
public AbsoluteDate getJulianEpoch() {
return new AbsoluteDate(DateComponents.JULIAN_EPOCH, TimeComponents.H12, this.getTT());
}
@Override
public AbsoluteDate getModifiedJulianEpoch() {
return new AbsoluteDate(DateComponents.MODIFIED_JULIAN_EPOCH, TimeComponents.H00, this.getTT());
}
@Override
public AbsoluteDate getFiftiesEpoch() {
return new AbsoluteDate(DateComponents.FIFTIES_EPOCH, TimeComponents.H00, this.getTT());
}
@Override
public AbsoluteDate getCcsdsEpoch() {
return new AbsoluteDate(DateComponents.CCSDS_EPOCH, TimeComponents.H00, this.getTAI());
}
@Override
public AbsoluteDate getGalileoEpoch() {
return new AbsoluteDate(DateComponents.GALILEO_EPOCH, TimeComponents.H00, this.getGST());
}
@Override
public AbsoluteDate getGpsEpoch() {
return new AbsoluteDate(DateComponents.GPS_EPOCH, TimeComponents.H00, this.getGPS());
}
@Override
public AbsoluteDate getQzssEpoch() {
return new AbsoluteDate(DateComponents.QZSS_EPOCH, TimeComponents.H00, this.getQZSS());
}
@Override
public AbsoluteDate getIrnssEpoch() {
return new AbsoluteDate(DateComponents.IRNSS_EPOCH, TimeComponents.H00, this.getIRNSS());
}
@Override
public AbsoluteDate getBeidouEpoch() {
return new AbsoluteDate(DateComponents.BEIDOU_EPOCH, TimeComponents.H00, this.getBDT());
}
@Override
public AbsoluteDate getGlonassEpoch() {
return new AbsoluteDate(DateComponents.GLONASS_EPOCH,
new TimeComponents(new TimeOffset(29L, 0L)), this.getTAI()).shiftedBy(new TimeOffset(-10800L, 0L));
}
@Override
public AbsoluteDate getJ2000Epoch() {
return new AbsoluteDate(DateComponents.J2000_EPOCH, TimeComponents.H12, this.getTT());
}
@Override
public AbsoluteDate getJavaEpoch() {
return new AbsoluteDate(DateComponents.JAVA_EPOCH, this.getTAI()).shiftedBy(new TimeOffset(8L, 82000000000000L));
}
@Override
public AbsoluteDate getPastInfinity() {
return getJavaEpoch().shiftedBy(Double.NEGATIVE_INFINITY);
}
@Override
public AbsoluteDate getFutureInfinity() {
return getJavaEpoch().shiftedBy(Double.POSITIVE_INFINITY);
}
@Override
public AbsoluteDate createJulianEpoch(final double julianEpoch) {
return new AbsoluteDate(getJ2000Epoch(),
Constants.JULIAN_YEAR * (julianEpoch - 2000.0));
}
@Override
public AbsoluteDate createBesselianEpoch(final double besselianEpoch) {
return new AbsoluteDate(getJ2000Epoch(),
MathArrays.linearCombination(
Constants.BESSELIAN_YEAR, besselianEpoch - 1900,
Constants.JULIAN_DAY, -36525,
Constants.JULIAN_DAY, 0.31352));
}
}