AggregatedPVCoordinatesProvider.java
- /* Copyright 2002-2025 Joseph Reed
- * 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.
- * Joseph Reed 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.utils;
- import java.util.Objects;
- import org.hipparchus.geometry.euclidean.threed.Vector3D;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitMessages;
- import org.orekit.frames.Frame;
- import org.orekit.time.AbsoluteDate;
- /** Aggregate multiple {@link PVCoordinatesProvider} instances together.
- * <p>
- * This can be used to describe an aircraft or surface vehicle.
- * </p>
- * @author Joe Reed
- * @since 11.3
- */
- public class AggregatedPVCoordinatesProvider implements PVCoordinatesProvider {
- /** Map of provider instances by transition time. */
- private final TimeSpanMap<PVCoordinatesProvider> pvProvMap;
- /** Earliest date at which {@link #getPVCoordinates(AbsoluteDate, Frame)} will return a valid result. */
- private final AbsoluteDate minDate;
- /** Latest date at which {@link #getPVCoordinates(AbsoluteDate, Frame)} will return a valid result. */
- private final AbsoluteDate maxDate;
- /** Class constructor.
- * <p>
- * Note the provided {@code map} is used directly. Modification of the
- * map after calling this constructor may result in undefined behavior.
- * </p>
- * @param map the map of {@link PVCoordinatesProvider} instances by time.
- */
- public AggregatedPVCoordinatesProvider(final TimeSpanMap<PVCoordinatesProvider> map) {
- this(map, null, null);
- }
- /** Class constructor.
- * <p>
- * Note the provided {@code map} is used directly. Modification of the
- * map after calling this constructor may result in undefined behavior.
- * </p>
- * @param map the map of {@link PVCoordinatesProvider} instances by time.
- * @param minDate the earliest valid date, {@code null} if always valid
- * @param maxDate the latest valid date, {@code null} if always valid
- */
- public AggregatedPVCoordinatesProvider(final TimeSpanMap<PVCoordinatesProvider> map,
- final AbsoluteDate minDate, final AbsoluteDate maxDate) {
- this.pvProvMap = Objects.requireNonNull(map, "PVCoordinatesProvider map must be non-null");
- this.minDate = minDate == null ? AbsoluteDate.PAST_INFINITY : minDate;
- this.maxDate = maxDate == null ? AbsoluteDate.FUTURE_INFINITY : maxDate;
- }
- /** Get the first date of the range.
- * @return the first date of the range
- */
- public AbsoluteDate getMinDate() {
- return minDate;
- }
- /** Get the last date of the range.
- * @return the last date of the range
- */
- public AbsoluteDate getMaxDate() {
- return maxDate;
- }
- @Override
- public Vector3D getPosition(final AbsoluteDate date, final Frame frame) {
- if (date.isBefore(minDate) || date.isAfter(maxDate)) {
- throw new OrekitException(OrekitMessages.OUT_OF_RANGE_DATE, date, minDate, maxDate);
- }
- return pvProvMap.get(date).getPosition(date, frame);
- }
- @Override
- public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
- if (date.isBefore(minDate) || date.isAfter(maxDate)) {
- throw new OrekitException(OrekitMessages.OUT_OF_RANGE_DATE, date, minDate, maxDate);
- }
- return pvProvMap.get(date).getPVCoordinates(date, frame);
- }
- /**
- * Builder class for {@link AggregatedPVCoordinatesProvider}.
- */
- public static class Builder {
- /** Time span map holding the incremental values. */
- private final TimeSpanMap<PVCoordinatesProvider> pvProvMap;
- /**
- * Create a builder using the {@link InvalidPVProvider} as the initial provider.
- */
- public Builder() {
- this(new InvalidPVProvider());
- }
- /**
- * Create a builder using the provided initial provider.
- *
- * @param initialProvider the inital provider
- */
- public Builder(final PVCoordinatesProvider initialProvider) {
- pvProvMap = new TimeSpanMap<>(initialProvider);
- }
- /** Add a {@link PVCoordinatesProvider} to the collection.
- * <p>
- * The provided date is the transition time, at which this provider will be used.
- * </p>
- * @param date the transition date
- * @param pvProv the provider
- * @param erasesLater if true, the entry erases all existing transitions that are later than {@code date}
- * @return this builder instance
- * @see TimeSpanMap#addValidAfter(Object, AbsoluteDate, boolean)
- */
- public Builder addPVProviderAfter(final AbsoluteDate date,
- final PVCoordinatesProvider pvProv,
- final boolean erasesLater) {
- pvProvMap.addValidAfter(pvProv, date, erasesLater);
- return this;
- }
- /** Add a {@link PVCoordinatesProvider} to the collection.
- * <p>
- * The provided date is the final transition time, before which this provider will be used.
- * </p>
- * @param date the transition date
- * @param pvProv the provider
- * @param erasesEarlier if true, the entry erases all existing transitions that are earlier than {@code date}
- * @return this builder instance
- * @see TimeSpanMap#addValidBefore(Object, AbsoluteDate, boolean)
- */
- public Builder addPVProviderBefore(final AbsoluteDate date, final PVCoordinatesProvider pvProv, final boolean erasesEarlier) {
- pvProvMap.addValidBefore(pvProv, date, erasesEarlier);
- return this;
- }
- /** Indicate the date before which the resulting PVCoordinatesProvider is invalid.
- *
- * @param firstValidDate first date at which the resuling provider should be valid
- * @return this instance
- */
- public Builder invalidBefore(final AbsoluteDate firstValidDate) {
- pvProvMap.addValidBefore(new InvalidPVProvider(), firstValidDate, true);
- return this;
- }
- /** Indicate the date after which the resulting PVCoordinatesProvider is invalid.
- *
- * @param lastValidDate last date at which the resuling provider should be valid
- * @return this instance
- */
- public Builder invalidAfter(final AbsoluteDate lastValidDate) {
- pvProvMap.addValidAfter(new InvalidPVProvider(), lastValidDate, true);
- return this;
- }
- /** Build the aggregated PVCoordinatesProvider.
- *
- * @return the new provider instance.
- */
- public AggregatedPVCoordinatesProvider build() {
- AbsoluteDate minDate = null;
- AbsoluteDate maxDate = null;
- // check the first span
- if (pvProvMap.getFirstTransition() != null) {
- if (pvProvMap.getFirstTransition().getBefore() instanceof InvalidPVProvider) {
- minDate = pvProvMap.getFirstTransition().getDate();
- }
- }
- if (pvProvMap.getLastTransition() != null) {
- if (pvProvMap.getLastTransition().getAfter() instanceof InvalidPVProvider) {
- maxDate = pvProvMap.getLastTransition().getDate();
- }
- }
- return new AggregatedPVCoordinatesProvider(pvProvMap, minDate, maxDate);
- }
- }
- /** Implementation of {@link PVCoordinatesProvider} that throws an {@link OrekitException} exception.
- *
- */
- public static class InvalidPVProvider implements PVCoordinatesProvider {
- /** Empty constructor.
- * <p>
- * This constructor is not strictly necessary, but it prevents spurious
- * javadoc warnings with JDK 18 and later.
- * </p>
- * @since 12.0
- */
- public InvalidPVProvider() {
- // nothing to do
- }
- @Override
- public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
- throw new OrekitException(OrekitMessages.OUT_OF_RANGE_DATE, date);
- }
- }
- }