1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.events;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22
23 import org.hipparchus.CalculusFieldElement;
24 import org.hipparchus.Field;
25 import org.hipparchus.ode.events.Action;
26 import org.orekit.errors.OrekitIllegalArgumentException;
27 import org.orekit.errors.OrekitMessages;
28 import org.orekit.propagation.FieldSpacecraftState;
29 import org.orekit.propagation.events.handlers.FieldEventHandler;
30 import org.orekit.propagation.events.handlers.FieldStopOnEvent;
31 import org.orekit.propagation.events.intervals.DateDetectionAdaptableIntervalFactory;
32 import org.orekit.time.FieldAbsoluteDate;
33 import org.orekit.time.FieldTimeStamped;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class FieldDateDetector<T extends CalculusFieldElement<T>> extends FieldAbstractDetector<FieldDateDetector<T>, T>
52 implements FieldTimeStamped<T> {
53
54
55
56
57 public static final double DEFAULT_MAX_CHECK = DateDetector.DEFAULT_MAX_CHECK;
58
59
60
61
62 public static final double DEFAULT_MIN_GAP = DateDetector.DEFAULT_MIN_GAP;
63
64
65
66
67 public static final double DEFAULT_THRESHOLD = DateDetector.DEFAULT_THRESHOLD;
68
69
70
71
72 private final double minGap;
73
74
75 private FieldAbsoluteDate<T> gDate;
76
77
78 private final ArrayList<FieldEventDate<T>> eventDateList;
79
80
81 private int currentIndex;
82
83
84
85
86
87 public FieldDateDetector(final FieldAbsoluteDate<T> fieldAbsoluteDate) {
88 this(new FieldEventDetectionSettings<>(DEFAULT_MAX_CHECK, fieldAbsoluteDate.getField().getZero().newInstance(DEFAULT_THRESHOLD),
89 DEFAULT_MAX_ITER), new FieldStopOnEvent<>(), DEFAULT_MIN_GAP, fieldAbsoluteDate);
90 }
91
92
93
94
95
96
97
98
99
100 @SafeVarargs
101 public FieldDateDetector(final Field<T> field, final FieldTimeStamped<T>... dates) {
102 this(new FieldEventDetectionSettings<>(DateDetectionAdaptableIntervalFactory.getDatesDetectionFieldConstantInterval(dates),
103 field.getZero().newInstance(DEFAULT_THRESHOLD), DEFAULT_MAX_ITER), new FieldStopOnEvent<>(), DEFAULT_MIN_GAP, dates);
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117 @SafeVarargs
118 protected FieldDateDetector(final FieldEventDetectionSettings<T> detectionSettings,
119 final FieldEventHandler<T> handler, final double minGap,
120 final FieldTimeStamped<T>... dates) {
121 super(detectionSettings, handler);
122 this.currentIndex = -1;
123 this.gDate = null;
124 this.eventDateList = new ArrayList<>(dates.length);
125 for (final FieldTimeStamped<T> ts : dates) {
126 addEventDate(ts.getDate());
127 }
128 this.minGap = minGap;
129 }
130
131
132
133
134
135
136
137 public FieldDateDetector<T> withMinGap(final double newMinGap) {
138 @SuppressWarnings("unchecked")
139 final FieldTimeStamped<T>[] dates = eventDateList.toArray(new FieldEventDate[0]);
140 return new FieldDateDetector<>(getDetectionSettings(), getHandler(), newMinGap, dates);
141 }
142
143
144 @Override
145 protected FieldDateDetector<T> create(final FieldEventDetectionSettings<T> detectionSettings,
146 final FieldEventHandler<T> newHandler) {
147 @SuppressWarnings("unchecked")
148 final FieldTimeStamped<T>[] dates = eventDateList.toArray(new FieldEventDate[0]);
149 return new FieldDateDetector<>(detectionSettings, newHandler, minGap, dates);
150 }
151
152
153 @Override
154 public boolean dependsOnTimeOnly() {
155 return true;
156 }
157
158
159
160
161
162 public List<FieldTimeStamped<T>> getDates() {
163 return Collections.unmodifiableList(eventDateList);
164 }
165
166
167
168
169
170
171 public T g(final FieldSpacecraftState<T> s) {
172 gDate = s.getDate();
173 if (currentIndex < 0) {
174 return s.getMass().getField().getZero().newInstance(-1);
175 } else {
176 final FieldEventDate<T> event = getClosest(gDate);
177 return event.isgIncrease() ? gDate.durationFrom(event.getDate()) : event.getDate().durationFrom(gDate);
178 }
179 }
180
181
182
183
184 public FieldAbsoluteDate<T> getDate() {
185 return currentIndex < 0 ? null : eventDateList.get(currentIndex).getDate();
186 }
187
188
189
190
191
192
193
194
195
196
197
198 public void addEventDate(final FieldAbsoluteDate<T> target) throws IllegalArgumentException {
199 final boolean increasing;
200 if (currentIndex < 0) {
201 increasing = (gDate == null) ? true : target.durationFrom(gDate).getReal() > 0.0;
202 currentIndex = 0;
203 eventDateList.add(new FieldEventDate<>(target, increasing));
204 } else {
205 final int lastIndex = eventDateList.size() - 1;
206 final FieldAbsoluteDate<T> firstDate = eventDateList.get(0).getDate();
207 final FieldAbsoluteDate<T> lastDate = eventDateList.get(lastIndex).getDate();
208 if (firstDate.durationFrom(target).getReal() > minGap) {
209 increasing = !eventDateList.get(0).isgIncrease();
210 eventDateList.add(0, new FieldEventDate<>(target, increasing));
211 currentIndex++;
212 } else if (target.durationFrom(lastDate).getReal() > minGap) {
213 increasing = !eventDateList.get(lastIndex).isgIncrease();
214 eventDateList.add(new FieldEventDate<>(target, increasing));
215 } else {
216 throw new OrekitIllegalArgumentException(OrekitMessages.EVENT_DATE_TOO_CLOSE,
217 target.toAbsoluteDate(),
218 firstDate.toAbsoluteDate(),
219 lastDate.toAbsoluteDate(),
220 minGap,
221 firstDate.durationFrom(target).getReal(),
222 target.durationFrom(lastDate).getReal());
223 }
224 }
225 }
226
227
228
229
230
231 private FieldEventDate<T> getClosest(final FieldAbsoluteDate<T> target) {
232 final T dt = target.durationFrom(eventDateList.get(currentIndex).getDate());
233 if (dt.getReal() < 0.0 && currentIndex > 0) {
234 boolean found = false;
235 while (currentIndex > 0 && !found) {
236 if (target.durationFrom(eventDateList.get(currentIndex - 1).getDate()).getReal() < eventDateList.get(currentIndex).getDate().durationFrom(target).getReal()) {
237 currentIndex--;
238 } else {
239 found = true;
240 }
241 }
242 } else if (dt.getReal() > 0.0 && currentIndex < eventDateList.size() - 1) {
243 final int maxIndex = eventDateList.size() - 1;
244 boolean found = false;
245 while (currentIndex < maxIndex && !found) {
246 if (target.durationFrom(eventDateList.get(currentIndex + 1).getDate()).getReal() > eventDateList.get(currentIndex).getDate().durationFrom(target).getReal()) {
247 currentIndex++;
248 } else {
249 found = true;
250 }
251 }
252 }
253 return eventDateList.get(currentIndex);
254 }
255
256
257 private static class FieldEventDate<T extends CalculusFieldElement<T>> implements FieldTimeStamped<T> {
258
259
260 private final FieldAbsoluteDate<T> eventDate;
261
262
263 private final boolean gIncrease;
264
265
266
267
268
269 FieldEventDate(final FieldAbsoluteDate<T> date, final boolean increase) {
270 this.eventDate = date;
271 this.gIncrease = increase;
272 }
273
274
275
276
277 public FieldAbsoluteDate<T> getDate() {
278 return eventDate;
279 }
280
281
282
283
284 public boolean isgIncrease() {
285 return gIncrease;
286 }
287
288 }
289
290 }