1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.events.intervals;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.util.FastMath;
21 import org.orekit.time.AbsoluteDate;
22 import org.orekit.time.ChronologicalComparator;
23 import org.orekit.time.FieldTimeStamped;
24 import org.orekit.time.TimeStamped;
25
26 import java.util.Arrays;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.List;
30 import java.util.Optional;
31 import java.util.SortedSet;
32 import java.util.TreeSet;
33
34
35
36
37
38
39
40
41
42 public class DateDetectionAdaptableIntervalFactory {
43
44
45 public static final double DEFAULT_MAX_CHECK = 1.0e10;
46
47
48
49
50 private DateDetectionAdaptableIntervalFactory() {
51
52 }
53
54
55
56
57
58 public static AdaptableInterval getSingleDateDetectionAdaptableInterval() {
59 return AdaptableInterval.of(DEFAULT_MAX_CHECK);
60 }
61
62
63
64
65
66
67 public static AdaptableInterval getDatesDetectionConstantInterval(final TimeStamped... timeStampeds) {
68 if (timeStampeds == null || timeStampeds.length < 2) {
69 return getSingleDateDetectionAdaptableInterval();
70 }
71 return AdaptableInterval.of(getMinGap(timeStampeds) * 0.5);
72 }
73
74
75
76
77
78
79 public static AdaptableInterval getDatesDetectionInterval(final TimeStamped... timeStampeds) {
80 if (timeStampeds == null || timeStampeds.length < 2) {
81 return getSingleDateDetectionAdaptableInterval();
82 }
83 final double minGap = getMinGap(timeStampeds);
84 final SortedSet<TimeStamped> sortedSet = new TreeSet<>(new ChronologicalComparator());
85 sortedSet.addAll(Arrays.asList(timeStampeds));
86 return (state, isForward) -> {
87 final AbsoluteDate date = state.getDate();
88 double minDistance = Double.POSITIVE_INFINITY;
89 if (isForward) {
90 for (final TimeStamped ts : sortedSet) {
91 final AbsoluteDate nextDate = ts.getDate();
92 if (date.isBefore(nextDate)) {
93 minDistance = nextDate.durationFrom(date);
94 break;
95 }
96 }
97 } else {
98 final List<TimeStamped> inverted = new ArrayList<>(sortedSet);
99 Collections.reverse(inverted);
100 for (final TimeStamped ts : inverted) {
101 final AbsoluteDate nextDate = ts.getDate();
102 if (date.isAfter(nextDate)) {
103 minDistance = date.durationFrom(nextDate);
104 break;
105 }
106 }
107 }
108 return FastMath.abs(minDistance) + minGap / 2;
109 };
110 }
111
112
113
114
115
116
117 public static <T extends CalculusFieldElement<T>> FieldAdaptableInterval<T> getSingleDateDetectionFieldAdaptableInterval() {
118 return FieldAdaptableInterval.of(DEFAULT_MAX_CHECK);
119 }
120
121
122
123
124
125
126
127 @SafeVarargs
128 public static <T extends CalculusFieldElement<T>> FieldAdaptableInterval<T> getDatesDetectionFieldConstantInterval(final FieldTimeStamped<T>... timeStampeds) {
129 if (timeStampeds == null || timeStampeds.length < 2) {
130 return getSingleDateDetectionFieldAdaptableInterval();
131 }
132 final double minGap = getMinGap(Arrays.stream(timeStampeds).map(t -> (TimeStamped) t.getDate().toAbsoluteDate())
133 .toArray(TimeStamped[]::new));
134 return FieldAdaptableInterval.of(minGap * 0.5);
135 }
136
137
138
139
140
141
142
143 @SafeVarargs
144 public static <T extends CalculusFieldElement<T>> FieldAdaptableInterval<T> getDatesDetectionFieldInterval(final FieldTimeStamped<T>... timeStampeds) {
145 if (timeStampeds == null || timeStampeds.length < 2) {
146 return getSingleDateDetectionFieldAdaptableInterval();
147 }
148 return FieldAdaptableInterval.of(getDatesDetectionInterval(Arrays.stream(timeStampeds)
149 .map(t -> (TimeStamped) t.getDate().toAbsoluteDate()).toArray(TimeStamped[]::new)));
150 }
151
152
153
154
155
156
157 public static double getMinGap(final TimeStamped... timeStampeds) {
158 double minGap = DEFAULT_MAX_CHECK;
159 for (final TimeStamped timeStamped : timeStampeds) {
160 final Optional<Double> minDistance = Arrays.stream(timeStampeds)
161 .map(t -> (!t.getDate().isEqualTo(timeStamped.getDate())) ? FastMath.abs(t.durationFrom(timeStamped)) : Double.POSITIVE_INFINITY)
162 .min(Double::compareTo);
163 if (minDistance.isPresent()) {
164 minGap = FastMath.min(minGap, minDistance.get());
165 }
166 }
167 return minGap;
168 }
169 }