LazyLoadedGeoMagneticFields.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.models.earth;
- import java.util.Collection;
- import java.util.NavigableMap;
- import java.util.SortedMap;
- import java.util.TreeMap;
- import org.hipparchus.util.FastMath;
- import org.orekit.data.DataProvidersManager;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitMessages;
- import org.orekit.models.earth.GeoMagneticFieldFactory.FieldModel;
- /**
- * Loads magnetic fields on request and can be configured after creation. Designed to
- * match the behavior of {@link GeoMagneticFieldFactory} in Orekit 10.0
- *
- * @author Evan Ward
- * @author Thomas Neidhart
- * @since 10.1
- */
- public class LazyLoadedGeoMagneticFields implements GeoMagneticFields {
- /** Loaded IGRF models. */
- private NavigableMap<Integer, GeoMagneticField> igrfModels = null;
- /** Loaded WMM models. */
- private NavigableMap<Integer, GeoMagneticField> wmmModels = null;
- /** Provides access to auxiliary data files. */
- private final DataProvidersManager dataProvidersManager;
- /**
- * Create a factory for magnetic fields that uses the given data manager to load
- * magnetic field files.
- *
- * @param dataProvidersManager provides access to auxiliary data files.
- */
- public LazyLoadedGeoMagneticFields(final DataProvidersManager dataProvidersManager) {
- this.dataProvidersManager = dataProvidersManager;
- }
- @Override
- public GeoMagneticField getField(final FieldModel type, final double year) {
- switch (type) {
- case WMM:
- return getWMM(year);
- case IGRF:
- return getIGRF(year);
- default:
- throw new OrekitException(OrekitMessages.NON_EXISTENT_GEOMAGNETIC_MODEL, type.name(), year);
- }
- }
- @Override
- public GeoMagneticField getIGRF(final double year) {
- synchronized (this) {
- if (igrfModels == null) {
- igrfModels = loadModels("^IGRF\\.COF$");
- }
- return getModel(FieldModel.IGRF, igrfModels, year);
- }
- }
- @Override
- public GeoMagneticField getWMM(final double year) {
- synchronized (this) {
- if (wmmModels == null) {
- wmmModels = loadModels("^WMM\\.COF$");
- }
- return getModel(FieldModel.WMM, wmmModels, year);
- }
- }
- /** Loads the geomagnetic model files from the given filename. The loaded
- * models are inserted in a {@link NavigableMap} with their epoch as key in order
- * to retrieve them in a sorted manner.
- * @param supportedNames a regular expression for valid filenames
- * @return a {@link NavigableMap} of all loaded models
- */
- private NavigableMap<Integer, GeoMagneticField> loadModels(final String supportedNames) {
- NavigableMap<Integer, GeoMagneticField> loadedModels = null;
- final GeoMagneticModelLoader loader = new GeoMagneticModelLoader();
- dataProvidersManager.feed(supportedNames, loader);
- if (!loader.stillAcceptsData()) {
- final Collection<GeoMagneticField> models = loader.getModels();
- if (models != null) {
- loadedModels = new TreeMap<>();
- for (GeoMagneticField model : models) {
- // round to a precision of two digits after the comma
- final int epoch = (int) FastMath.round(model.getEpoch() * 100d);
- loadedModels.put(epoch, model);
- }
- }
- }
- // if no models could be loaded -> throw exception
- if (loadedModels == null || loadedModels.size() == 0) {
- throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_RESOURCE, supportedNames);
- }
- return loadedModels;
- }
- /** Gets a geomagnetic field model for the given year. In case the specified
- * year does not match an existing model epoch, the resulting field is
- * generated by either time-transforming an existing model using its secular
- * variation coefficients, or by linear interpolating two existing models.
- * @param type the type of the field (e.g. WMM or IGRF)
- * @param models all loaded field models, sorted by their epoch
- * @param year the epoch of the resulting field model
- * @return a {@link GeoMagneticField} model for the given year
- */
- private static GeoMagneticField getModel(final FieldModel type,
- final NavigableMap<Integer, GeoMagneticField> models,
- final double year) {
- final int epochKey = (int) (year * 100d);
- final SortedMap<Integer, GeoMagneticField> head = models.headMap(epochKey, true);
- if (head.isEmpty()) {
- throw new OrekitException(OrekitMessages.NON_EXISTENT_GEOMAGNETIC_MODEL, type.name(), year);
- }
- GeoMagneticField model = models.get(head.lastKey());
- if (model.getEpoch() < year) {
- if (model.supportsTimeTransform()) {
- model = model.transformModel(year);
- } else {
- final SortedMap<Integer, GeoMagneticField> tail = models.tailMap(epochKey, false);
- if (tail.isEmpty()) {
- throw new OrekitException(OrekitMessages.NON_EXISTENT_GEOMAGNETIC_MODEL, type.name(), year);
- }
- final GeoMagneticField secondModel = models.get(tail.firstKey());
- if (secondModel != model) {
- model = model.transformModel(secondModel, year);
- }
- }
- }
- return model;
- }
- }