1   /* Copyright 2002-2025 CS GROUP
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 org.orekit.errors.OrekitException;
20  import org.orekit.errors.OrekitMessages;
21  import org.orekit.propagation.SpacecraftState;
22  import org.orekit.propagation.events.handlers.EventHandler;
23  import org.orekit.propagation.events.intervals.AdaptableInterval;
24  import org.orekit.time.AbsoluteDate;
25  
26  /** Common parts shared by several orbital events finders.
27   * @param <T> type of the detector
28   * @see org.orekit.propagation.Propagator#addEventDetector(EventDetector)
29   * @author Luc Maisonobe
30   */
31  public abstract class AbstractDetector<T extends AbstractDetector<T>> implements EventDetector {
32  
33      /** Default maximum checking interval (s). */
34      public static final double DEFAULT_MAX_CHECK = EventDetectionSettings.DEFAULT_MAX_CHECK;
35  
36      /** Default convergence threshold (s). */
37      public static final double DEFAULT_THRESHOLD = EventDetectionSettings.DEFAULT_THRESHOLD;
38  
39      /** Default maximum number of iterations in the event time search. */
40      public static final int DEFAULT_MAX_ITER = EventDetectionSettings.DEFAULT_MAX_ITER;
41  
42      /** Detection settings. */
43      private final EventDetectionSettings eventDetectionSettings;
44  
45      /** Default handler for event overrides. */
46      private final EventHandler handler;
47  
48      /** Propagation direction. */
49      private boolean forward;
50  
51      /** Build a new instance.
52       * @param maxCheck maximum checking interval, must be strictly positive (s)
53       * @param threshold convergence threshold (s)
54       * @param maxIter maximum number of iterations in the event time search
55       * @param handler event handler to call at event occurrences
56       */
57      protected AbstractDetector(final double maxCheck, final double threshold, final int maxIter,
58                                 final EventHandler handler) {
59          this(new EventDetectionSettings(maxCheck, threshold, maxIter), handler);
60      }
61  
62      /** Build a new instance.
63       * @param detectionSettings event detection settings
64       * @param handler event handler to call at event occurrences
65       * @since 12.2
66       */
67      protected AbstractDetector(final EventDetectionSettings detectionSettings, final EventHandler handler) {
68          checkStrictlyPositive(detectionSettings.getThreshold());
69          this.eventDetectionSettings = detectionSettings;
70          this.handler   = handler;
71          this.forward   = true;
72      }
73  
74      /**
75       * Check if propagation is forward or not.
76       * @param state initial state
77       * @param targetDate target propagation date
78       * @return forward flag
79       * @since 13.0
80       */
81      public static boolean checkIfForward(final SpacecraftState state, final AbsoluteDate targetDate) {
82          return targetDate.durationFrom(state.getDate()) >= 0.0;
83      }
84  
85      /** Check value is strictly positive.
86       * @param value value to check
87       * @exception OrekitException if value is not strictly positive
88       * @since 11.2
89       */
90      private void checkStrictlyPositive(final double value) throws OrekitException {
91          if (value <= 0.0) {
92              throw new OrekitException(OrekitMessages.NOT_STRICTLY_POSITIVE, value);
93          }
94      }
95  
96      /**
97       * {@inheritDoc}
98       *
99       * <p> This implementation sets the direction of propagation and initializes the event
100      * handler. If a subclass overrides this method it should call {@code
101      * super.init(s0, t)}.
102      */
103     @Override
104     public void init(final SpacecraftState s0,
105                      final AbsoluteDate t) {
106         EventDetector.super.init(s0, t);
107         forward = checkIfForward(s0, t);
108     }
109 
110     /** {@inheritDoc} */
111     @Override
112     public EventDetectionSettings getDetectionSettings() {
113         return eventDetectionSettings;
114     }
115 
116     /**
117      * Set up the maximum checking interval.
118      * <p>
119      * This will override a maximum checking interval if it has been configured previously.
120      * </p>
121      * @param newMaxCheck maximum checking interval (s)
122      * @return a new detector with updated configuration (the instance is not changed)
123      * @since 6.1
124      */
125     public T withMaxCheck(final double newMaxCheck) {
126         return withMaxCheck(AdaptableInterval.of(newMaxCheck));
127     }
128 
129     /**
130      * Set up the maximum checking interval.
131      * <p>
132      * This will override a maximum checking interval if it has been configured previously.
133      * </p>
134      * @param newMaxCheck maximum checking interval (s)
135      * @return a new detector with updated configuration (the instance is not changed)
136      * @since 12.0
137      */
138     public T withMaxCheck(final AdaptableInterval newMaxCheck) {
139         return withDetectionSettings(new EventDetectionSettings(newMaxCheck, getThreshold(), getMaxIterationCount()));
140     }
141 
142     /**
143      * Set up the maximum number of iterations in the event time search.
144      * <p>
145      * This will override a number of iterations if it has been configured previously.
146      * </p>
147      * @param newMaxIter maximum number of iterations in the event time search
148      * @return a new detector with updated configuration (the instance is not changed)
149      * @since 6.1
150      */
151     public T withMaxIter(final int newMaxIter) {
152         return withDetectionSettings(new EventDetectionSettings(getMaxCheckInterval(), getThreshold(), newMaxIter));
153     }
154 
155     /**
156      * Set up the convergence threshold.
157      * <p>
158      * This will override a convergence threshold if it has been configured previously.
159      * </p>
160      * @param newThreshold convergence threshold (s)
161      * @return a new detector with updated configuration (the instance is not changed)
162      * @since 6.1
163      */
164     public T withThreshold(final double newThreshold) {
165         return withDetectionSettings(new EventDetectionSettings(getMaxCheckInterval(), newThreshold, getMaxIterationCount()));
166     }
167 
168     /**
169      * Set up the event detection settings.
170      * <p>
171      * This will override settings previously configured.
172      * </p>
173      * @param newSettings new event detection settings
174      * @return a new detector with updated configuration (the instance is not changed)
175      * @since 12.2
176      */
177     public T withDetectionSettings(final EventDetectionSettings newSettings) {
178         return create(new EventDetectionSettings(newSettings.getMaxCheckInterval(), newSettings.getThreshold(), newSettings.getMaxIterationCount()),
179                 getHandler());
180     }
181 
182     /**
183      * Set up the event handler to call at event occurrences.
184      * <p>
185      * This will override a handler if it has been configured previously.
186      * </p>
187      * @param newHandler event handler to call at event occurrences
188      * @return a new detector with updated configuration (the instance is not changed)
189      * @since 6.1
190      */
191     public T withHandler(final EventHandler newHandler) {
192         return create(getDetectionSettings(), newHandler);
193     }
194 
195     /** {@inheritDoc} */
196     @Override
197     public EventHandler getHandler() {
198         return handler;
199     }
200 
201     /** Build a new instance.
202      * @param detectionSettings detection settings
203      * @param newHandler event handler to call at event occurrences
204      * @return a new instance of the appropriate sub-type
205      * @since 12.2
206      */
207     protected abstract T create(EventDetectionSettings detectionSettings, EventHandler newHandler);
208 
209     /** Check if the current propagation is forward or backward.
210      * @return true if the current propagation is forward
211      * @since 7.2
212      */
213     public boolean isForward() {
214         return forward;
215     }
216 
217 }