FilterType.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF 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.propagation.events;

import org.orekit.errors.OrekitInternalError;
import org.orekit.propagation.events.handlers.EventHandler;

/** Enumerate for {@link EventSlopeFilter filtering events}.
 * <p>This class is heavily based on the class with the same name from the
 * Hipparchus library. The changes performed consist in package
 * name and error handling.</p>
 * @since 6.0
 */

public enum FilterType {

    /** Constant for triggering only decreasing events.
     * <p>When this filter is used, the wrapped {@link EventHandler
     * event handler} {@link
     * EventHandler#eventOccurred(org.orekit.propagation.SpacecraftState,
     * EventDetector, boolean) eventOccurred} method will be called
     * <em>only</em> with its {@code increasing} argument set to false.</p>
     */
    TRIGGER_ONLY_DECREASING_EVENTS {

        /**  {@inheritDoc} */
        protected boolean getTriggeredIncreasing() {
            return false;
        }

        /** {@inheritDoc}
         * <p>
         * states scheduling for computing h(t, y) as an altered version of g(t, y)
         * <ul>
         * <li>0 are triggered events for which a zero is produced (here decreasing events)</li>
         * <li>X are ignored events for which zero is masked (here increasing events)</li>
         * </ul>
         * </p>
         * <p>
         * Several expressions are used to compute h, depending on the current state:
         * <ul>
         *   <li>h = max(+s, -g, +g)</li>
         *   <li>h = +g</li>
         *   <li>h = min(-s, -g, +g)</li>
         *   <li>h = -g</li>
         * </ul>
         * where s is a tiny positive value: {@link org.hipparchus.util.Precision#SAFE_MIN}.
         * </p>
         */
        protected  Transformer selectTransformer(final Transformer previous,
                                                 final double g, final boolean forward) {
            if (forward) {
                switch (previous) {
                    case UNINITIALIZED :
                        // we are initializing the first point
                        if (g > 0) {
                            // initialize as if previous root (i.e. backward one) was an ignored increasing event
                            return Transformer.MAX;
                        } else if (g < 0) {
                            // initialize as if previous root (i.e. backward one) was a triggered decreasing event
                            return Transformer.PLUS;
                        } else {
                            // we are exactly at a root, we don't know if it is an increasing
                            // or a decreasing event, we remain in uninitialized state
                            return Transformer.UNINITIALIZED;
                        }
                    case PLUS  :
                        if (g >= 0) {
                            // we have crossed the zero line on an ignored increasing event,
                            // we must change the transformer
                            return Transformer.MIN;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MINUS :
                        if (g >= 0) {
                            // we have crossed the zero line on an ignored increasing event,
                            // we must change the transformer
                            return Transformer.MAX;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MIN   :
                        if (g <= 0) {
                            // we have crossed the zero line on a triggered decreasing event,
                            // we must change the transformer
                            return Transformer.MINUS;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MAX   :
                        if (g <= 0) {
                            // we have crossed the zero line on a triggered decreasing event,
                            // we must change the transformer
                            return Transformer.PLUS;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    default    :
                        // this should never happen
                        throw new OrekitInternalError(null);
                }
            } else {
                switch (previous) {
                    case UNINITIALIZED :
                        // we are initializing the first point
                        if (g > 0) {
                            // initialize as if previous root (i.e. forward one) was a triggered decreasing event
                            return Transformer.MINUS;
                        } else if (g < 0) {
                            // initialize as if previous root (i.e. forward one) was an ignored increasing event
                            return Transformer.MIN;
                        } else {
                            // we are exactly at a root, we don't know if it is an increasing
                            // or a decreasing event, we remain in uninitialized state
                            return Transformer.UNINITIALIZED;
                        }
                    case PLUS  :
                        if (g <= 0) {
                            // we have crossed the zero line on an ignored increasing event,
                            // we must change the transformer
                            return Transformer.MAX;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MINUS :
                        if (g <= 0) {
                            // we have crossed the zero line on an ignored increasing event,
                            // we must change the transformer
                            return Transformer.MIN;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MIN   :
                        if (g >= 0) {
                            // we have crossed the zero line on a triggered decreasing event,
                            // we must change the transformer
                            return Transformer.PLUS;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MAX   :
                        if (g >= 0) {
                            // we have crossed the zero line on a triggered decreasing event,
                            // we must change the transformer
                            return Transformer.MINUS;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    default    :
                        // this should never happen
                        throw new OrekitInternalError(null);
                }
            }
        }

    },

    /** Constant for triggering only increasing events.
     * <p>When this filter is used, the wrapped {@link EventHandler
     * event handler} {@link EventHandler#eventOccurred(org.orekit.propagation.SpacecraftState,
     * EventDetector, boolean) eventOccurred} method will be called <em>only</em> with
     * its {@code increasing} argument set to true.</p>
     */
    TRIGGER_ONLY_INCREASING_EVENTS {

        /**  {@inheritDoc} */
        protected boolean getTriggeredIncreasing() {
            return true;
        }

        /** {@inheritDoc}
         * <p>
         * states scheduling for computing h(t, y) as an altered version of g(t, y)
         * <ul>
         * <li>0 are triggered events for which a zero is produced (here increasing events)</li>
         * <li>X are ignored events for which zero is masked (here decreasing events)</li>
         * </ul>
         * </p>
         * <p>
         * Several expressions are used to compute h, depending on the current state:
         * <ul>
         *   <li>h = max(+s, -g, +g)</li>
         *   <li>h = +g</li>
         *   <li>h = min(-s, -g, +g)</li>
         *   <li>h = -g</li>
         * </ul>
         * where s is a tiny positive value: {@link org.hipparchus.util.Precision#SAFE_MIN}.
         * </p>
         */
        protected  Transformer selectTransformer(final Transformer previous,
                                                 final double g, final boolean forward) {
            if (forward) {
                switch (previous) {
                    case UNINITIALIZED :
                        // we are initializing the first point
                        if (g > 0) {
                            // initialize as if previous root (i.e. backward one) was a triggered increasing event
                            return Transformer.PLUS;
                        } else if (g < 0) {
                            // initialize as if previous root (i.e. backward one) was an ignored decreasing event
                            return Transformer.MIN;
                        } else {
                            // we are exactly at a root, we don't know if it is an increasing
                            // or a decreasing event, we remain in uninitialized state
                            return Transformer.UNINITIALIZED;
                        }
                    case PLUS  :
                        if (g <= 0) {
                            // we have crossed the zero line on an ignored decreasing event,
                            // we must change the transformer
                            return Transformer.MAX;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MINUS :
                        if (g <= 0) {
                            // we have crossed the zero line on an ignored decreasing event,
                            // we must change the transformer
                            return Transformer.MIN;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MIN   :
                        if (g >= 0) {
                            // we have crossed the zero line on a triggered increasing event,
                            // we must change the transformer
                            return Transformer.PLUS;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MAX   :
                        if (g >= 0) {
                            // we have crossed the zero line on a triggered increasing event,
                            // we must change the transformer
                            return Transformer.MINUS;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    default    :
                        // this should never happen
                        throw new OrekitInternalError(null);
                }
            } else {
                switch (previous) {
                    case UNINITIALIZED :
                        // we are initializing the first point
                        if (g > 0) {
                            // initialize as if previous root (i.e. forward one) was an ignored decreasing event
                            return Transformer.MAX;
                        } else if (g < 0) {
                            // initialize as if previous root (i.e. forward one) was a triggered increasing event
                            return Transformer.MINUS;
                        } else {
                            // we are exactly at a root, we don't know if it is an increasing
                            // or a decreasing event, we remain in uninitialized state
                            return Transformer.UNINITIALIZED;
                        }
                    case PLUS  :
                        if (g >= 0) {
                            // we have crossed the zero line on an ignored decreasing event,
                            // we must change the transformer
                            return Transformer.MIN;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MINUS :
                        if (g >= 0) {
                            // we have crossed the zero line on an ignored decreasing event,
                            // we must change the transformer
                            return Transformer.MAX;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MIN   :
                        if (g <= 0) {
                            // we have crossed the zero line on a triggered increasing event,
                            // we must change the transformer
                            return Transformer.MINUS;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    case MAX   :
                        if (g <= 0) {
                            // we have crossed the zero line on a triggered increasing event,
                            // we must change the transformer
                            return Transformer.PLUS;
                        } else {
                            // we are still in the same status
                            return previous;
                        }
                    default    :
                        // this should never happen
                        throw new OrekitInternalError(null);
                }
            }
        }

    };

    /** Get the increasing status of triggered events.
     * @return true if triggered events are increasing events
     */
    protected abstract boolean getTriggeredIncreasing();

    /** Get next function transformer in the specified direction.
     * @param previous transformer active on the previous point with respect
     * to integration direction (may be null if no previous point is known)
     * @param g current value of the g function
     * @param forward true if integration goes forward
     * @return next transformer transformer
     */
    protected abstract Transformer selectTransformer(Transformer previous,
                                                     double g, boolean forward);

}