1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.time;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.util.FastMath;
22 import org.orekit.errors.OrekitIllegalArgumentException;
23 import org.orekit.errors.OrekitInternalError;
24 import org.orekit.errors.OrekitMessages;
25 import org.orekit.utils.ImmutableFieldTimeStampedCache;
26
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.List;
31 import java.util.Optional;
32 import java.util.stream.Collectors;
33 import java.util.stream.Stream;
34
35
36
37
38
39
40
41
42
43 public abstract class AbstractFieldTimeInterpolator<T extends FieldTimeStamped<KK>, KK extends CalculusFieldElement<KK>>
44 implements FieldTimeInterpolator<T, KK> {
45
46
47 public static final double DEFAULT_EXTRAPOLATION_THRESHOLD_SEC = 1e-3;
48
49
50 public static final int DEFAULT_INTERPOLATION_POINTS = 2;
51
52
53 private final double extrapolationThreshold;
54
55
56 private final int interpolationPoints;
57
58
59
60
61
62
63
64 public AbstractFieldTimeInterpolator(final int interpolationPoints, final double extrapolationThreshold) {
65 this.interpolationPoints = interpolationPoints;
66 this.extrapolationThreshold = extrapolationThreshold;
67 }
68
69
70
71
72
73
74
75
76 public static <T extends CalculusFieldElement<T>> void checkInterpolatorCompatibilityWithSampleSize(
77 final FieldTimeInterpolator<? extends FieldTimeStamped<T>, T> interpolator,
78 final int sampleSize) {
79
80
81 final List<FieldTimeInterpolator<? extends FieldTimeStamped<T>, T>> subInterpolators =
82 interpolator.getSubInterpolators();
83 for (final FieldTimeInterpolator<? extends FieldTimeStamped<T>, T> subInterpolator : subInterpolators) {
84 if (sampleSize < subInterpolator.getNbInterpolationPoints()) {
85 throw new OrekitIllegalArgumentException(OrekitMessages.NOT_ENOUGH_DATA, sampleSize);
86 }
87 }
88 }
89
90
91 @Override
92 public T interpolate(final FieldAbsoluteDate<KK> interpolationDate, final Stream<T> sample) {
93 return interpolate(interpolationDate, sample.collect(Collectors.toList()));
94 }
95
96
97 @Override
98 public T interpolate(final FieldAbsoluteDate<KK> interpolationDate, final Collection<T> sample) {
99 final InterpolationData interpolationData = new InterpolationData(interpolationDate, sample);
100 return interpolate(interpolationData);
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115 public static <T extends FieldTimeStamped<KK>, KK extends CalculusFieldElement<KK>> FieldAbsoluteDate<KK> getCentralDate(
116 final FieldAbsoluteDate<KK> date,
117 final ImmutableFieldTimeStampedCache<T, KK> cachedSamples,
118 final double threshold) {
119 return getCentralDate(
120 date,
121 cachedSamples.getEarliest().getDate(),
122 cachedSamples.getLatest().getDate(),
123 threshold);
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138 public static <KK extends CalculusFieldElement<KK>> FieldAbsoluteDate<KK> getCentralDate(
139 final FieldAbsoluteDate<KK> date,
140 final FieldAbsoluteDate<KK> minDate,
141 final FieldAbsoluteDate<KK> maxDate,
142 final double threshold) {
143 final FieldAbsoluteDate<KK> central;
144
145 if (date.compareTo(minDate) < 0 && FastMath.abs(date.durationFrom(minDate)).getReal() <= threshold) {
146
147 central = minDate;
148 } else if (date.compareTo(maxDate) > 0 && FastMath.abs(date.durationFrom(maxDate)).getReal() <= threshold) {
149
150 central = maxDate;
151 } else {
152 central = date;
153 }
154
155 return central;
156 }
157
158
159 public List<FieldTimeInterpolator<? extends FieldTimeStamped<KK>, KK>> getSubInterpolators() {
160 return Collections.singletonList(this);
161 }
162
163
164 public int getNbInterpolationPoints() {
165 final List<FieldTimeInterpolator<? extends FieldTimeStamped<KK>, KK>> subInterpolators = getSubInterpolators();
166
167 if (subInterpolators.size() == 1) {
168 return interpolationPoints;
169 }
170
171 else {
172 final Optional<Integer> optionalMaxNbInterpolationPoints =
173 subInterpolators.stream().map(FieldTimeInterpolator::getNbInterpolationPoints).max(Integer::compareTo);
174 if (optionalMaxNbInterpolationPoints.isPresent()) {
175 return optionalMaxNbInterpolationPoints.get();
176 } else {
177
178 throw new OrekitInternalError(null);
179 }
180 }
181 }
182
183
184 public double getExtrapolationThreshold() {
185 return extrapolationThreshold;
186 }
187
188
189
190
191
192
193
194
195 protected <S extends CalculusFieldElement<S>> void addOptionalSubInterpolatorIfDefined(
196 final FieldTimeInterpolator<? extends FieldTimeStamped<S>, S> subInterpolator,
197 final List<FieldTimeInterpolator<? extends FieldTimeStamped<S>, S>> subInterpolators) {
198
199 if (subInterpolator != null) {
200 subInterpolators.addAll(subInterpolator.getSubInterpolators());
201 }
202 }
203
204
205
206
207
208
209
210
211 protected abstract T interpolate(InterpolationData interpolationData);
212
213
214
215
216
217
218
219
220
221
222
223 protected KK getTimeParameter(final FieldAbsoluteDate<KK> interpolatingTime,
224 final FieldAbsoluteDate<KK> previousDate,
225 final FieldAbsoluteDate<KK> nextDate) {
226
227 return interpolatingTime.durationFrom(previousDate).divide(nextDate.getDate().durationFrom(previousDate));
228 }
229
230
231
232
233
234
235 public class InterpolationData {
236
237
238 private final FieldAbsoluteDate<KK> interpolationDate;
239
240
241 private final List<T> neighborList;
242
243
244 private final Field<KK> field;
245
246
247 private final KK zero;
248
249
250 private final KK one;
251
252
253
254
255
256
257
258 protected InterpolationData(final FieldAbsoluteDate<KK> interpolationDate, final Collection<T> sample) {
259
260 if (sample.isEmpty()) {
261 throw new OrekitIllegalArgumentException(OrekitMessages.NOT_ENOUGH_DATA, 0);
262 }
263
264
265 if (sample.size() == interpolationPoints) {
266
267
268 this.neighborList = Collections.unmodifiableList(new ArrayList<>(sample));
269 } else {
270
271
272
273 final ImmutableFieldTimeStampedCache<T, KK> cachedSamples =
274 new ImmutableFieldTimeStampedCache<>(interpolationPoints, sample);
275
276
277 final FieldAbsoluteDate<KK> central =
278 AbstractFieldTimeInterpolator.getCentralDate(
279 interpolationDate,
280 cachedSamples,
281 extrapolationThreshold);
282 final Stream<T> neighborsStream = cachedSamples.getNeighbors(central);
283
284
285 neighborList = Collections.unmodifiableList(neighborsStream.collect(Collectors.toList()));
286 }
287
288
289 this.field = interpolationDate.getField();
290 this.zero = field.getZero();
291 this.one = field.getOne();
292
293
294 this.interpolationDate = interpolationDate;
295 }
296
297
298
299
300 public FieldAbsoluteDate<KK> getInterpolationDate() {
301 return interpolationDate;
302 }
303
304
305
306
307 public List<T> getNeighborList() {
308 return neighborList;
309 }
310
311
312
313
314 public Field<KK> getField() {
315 return field;
316 }
317
318
319
320
321 public KK getZero() {
322 return zero;
323 }
324
325
326
327
328 public KK getOne() {
329 return one;
330 }
331 }
332 }