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.time;
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.hipparchus.util.FastMath;
23
24 /** Selector generating a continuous stream of dates separated by a constant step.
25 * <p>
26 * The dates can be aligned to whole steps in some time scale. So for example
27 * if a step of 60s is used and the alignment time scale is set to
28 * {@link org.orekit.time.TimeScales#getUTC() UTC}, dates will be selected
29 * at whole minutes in UTC time.
30 * </p>
31 * <p>
32 * BEWARE! This class stores internally the last selected dates, so it is <em>neither</em>
33 * reusable across several {@link org.orekit.estimation.measurements.generation.EventBasedScheduler
34 * fixed step} or {@link org.orekit.estimation.measurements.generation.ContinuousScheduler
35 * continuous} schedulers, <em>nor</em> thread-safe. A separate selector should be used for each
36 * scheduler and for each thread in multi-threading context.
37 * </p>
38 * @author Luc Maisonobe
39 * @since 9.3
40 */
41 public class FixedStepSelector implements DatesSelector {
42
43 /** Step between two consecutive dates. */
44 private final double step;
45
46 /** Alignment time scale (null is alignment is not needed). */
47 private final TimeScale alignmentTimeScale;
48
49 /** Last selected date. */
50 private AbsoluteDate last;
51
52 /** Simple constructor.
53 * @param step step between two consecutive dates (s)
54 * @param alignmentTimeScale alignment time scale (null is alignment is not needed)
55 */
56 public FixedStepSelector(final double step, final TimeScale alignmentTimeScale) {
57 this.step = step;
58 this.alignmentTimeScale = alignmentTimeScale;
59 this.last = null;
60 }
61
62 /** {@inheritDoc} */
63 @Override
64 public List<AbsoluteDate> selectDates(final AbsoluteDate start, final AbsoluteDate end) {
65
66 final double sign = FastMath.copySign(1, end.durationFrom(start));
67 final List<AbsoluteDate> selected = new ArrayList<>();
68
69 final boolean reset = last == null || sign * start.durationFrom(last) > step;
70 for (AbsoluteDate next = reset ? start : last.shiftedBy(sign * step);
71 sign * next.durationFrom(end) <= 0;
72 next = last.shiftedBy(sign * step)) {
73
74 if (alignmentTimeScale != null) {
75 // align date to time scale
76 final double t = next.getComponents(alignmentTimeScale).getTime().getSecondsInLocalDay();
77 final double dt = step * FastMath.round(t / step) - t;
78 next = next.shiftedBy(dt);
79 }
80
81 if (sign * next.durationFrom(start) >= 0) {
82 if (sign * next.durationFrom(end) <= 0) {
83 // the date is within range, select it
84 selected.add(next);
85 } else {
86 // we have exceeded date range
87 break;
88 }
89 }
90 last = next;
91
92 }
93
94 return selected;
95
96 }
97
98 }