1   /* Contributed in the public domain.
2    * Licensed to CS GROUP (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.propagation.events;
18  
19  import java.util.function.ToDoubleFunction;
20  
21  import org.orekit.propagation.SpacecraftState;
22  import org.orekit.propagation.events.handlers.ContinueOnEvent;
23  import org.orekit.propagation.events.handlers.EventHandler;
24  
25  /**
26   * A detector that implements the {@link #g(SpacecraftState)} function using a lambda that
27   * can be set using {@link #withFunction(ToDoubleFunction)}.
28   *
29   * <p>For example, to create a simple date detector use:
30   *
31   * <pre>
32   * FunctionalDetector d = new FunctionalDetector()
33   *     .withGFunction((s) -&gt; s.getDate().durationFrom(triggerDate))
34   *     .withMaxCheck(1e10);
35   * </pre>
36   *
37   * @author Evan Ward
38   * @since 9.2
39   */
40  public class FunctionalDetector extends AbstractDetector<FunctionalDetector> {
41  
42      /** The g function. */
43      private final ToDoubleFunction<SpacecraftState> function;
44  
45      /**
46       * Create an event detector with the default values. These are {@link
47       * #DEFAULT_MAXCHECK}, {@link #DEFAULT_THRESHOLD}, {@link #DEFAULT_MAX_ITER}, {@link
48       * ContinueOnEvent}, and a g function that is identically unity.
49       */
50      public FunctionalDetector() {
51          this(AdaptableInterval.of(DEFAULT_MAXCHECK), DEFAULT_THRESHOLD, DEFAULT_MAX_ITER,
52               new ContinueOnEvent(),
53               (ToDoubleFunction<SpacecraftState>) value -> 1.0);
54      }
55  
56      /**
57       * Private constructor.
58       *
59       * @param maxCheck  maximum checking interval
60       * @param threshold convergence threshold (s)
61       * @param maxIter   maximum number of iterations in the event time search
62       * @param handler   event handler to call at event occurrences
63       * @param function  the switching function.
64       */
65      protected FunctionalDetector(final AdaptableInterval maxCheck,
66                                   final double threshold,
67                                   final int maxIter,
68                                   final EventHandler handler,
69                                   final ToDoubleFunction<SpacecraftState> function) {
70          super(maxCheck, threshold, maxIter, handler);
71          this.function = function;
72      }
73  
74  
75      @Override
76      public double g(final SpacecraftState s) {
77          return function.applyAsDouble(s);
78      }
79  
80      @Override
81      protected FunctionalDetector create(
82              final AdaptableInterval newMaxCheck,
83              final double newThreshold,
84              final int newMaxIter,
85              final EventHandler newHandler) {
86  
87          return new FunctionalDetector(newMaxCheck, newThreshold, newMaxIter, newHandler,
88                                        function);
89      }
90  
91      /**
92       * Create a new event detector with a new g function, keeping all other attributes the
93       * same. It is recommended to use {@link #withMaxCheck(AdaptableInterval)} and {@link
94       * #withThreshold(double)} to set appropriate values for this g function.
95       *
96       * @param newGFunction the new g function.
97       * @return a new detector with the new g function.
98       */
99      public FunctionalDetector withFunction(
100             final ToDoubleFunction<SpacecraftState> newGFunction) {
101         return new FunctionalDetector(getMaxCheckInterval(), getThreshold(),
102                                       getMaxIterationCount(), getHandler(), newGFunction);
103     }
104 
105     /**
106      * Get the switching function.
107      *
108      * @return the function used in {@link #g(SpacecraftState)}.
109      */
110     public ToDoubleFunction<SpacecraftState> getFunction() {
111         return function;
112     }
113 
114 }