Commit 9b699c0f authored by Luc Maisonobe's avatar Luc Maisonobe

Allow dates selectors to be used backward.

parent 8ccd498e
......@@ -26,7 +26,7 @@ import org.hipparchus.util.FastMath;
* <p>
* The dates can be aligned to whole steps in some time scale. So for example
* if a rest period of 3600s is used and the alignment time scale is set to
* {@link org.orekit.time.TimeScalesFactory#getUTC() UTC}, the first date of
* {@link org.orekit.time.TimeScalesFactory#getUTC() UTC}, the earliest date of
* each burst will occur at whole hours in UTC time.
* </p>
* <p>
......@@ -57,8 +57,8 @@ public class BurstSelector implements DatesSelector {
/** Last selected date. */
private AbsoluteDate last;
/** Number of selected dates in last burst. */
private int lastSize;
/** Index of last selected date in current burst. */
private int index;
/** Simple constructor.
* <p>
......@@ -87,62 +87,73 @@ public class BurstSelector implements DatesSelector {
this.alignmentTimeScale = alignmentTimeScale;
this.last = null;
this.first = null;
this.lastSize = 0;
this.index = 0;
}
/** {@inheritDoc} */
@Override
public List<AbsoluteDate> selectDates(final AbsoluteDate start, final AbsoluteDate end) {
final int increment = end.durationFrom(start) > 0 ? +1 : -1;
final int firstIndex = increment > 0 ? 0 : maxBurstSize - 1;
final int lastIndex = maxBurstSize - 1 - firstIndex;
final double signedHighRateStep = FastMath.copySign(highRateStep, increment);
final double signedBurstPeriod = FastMath.copySign(burstPeriod, increment);
final List<AbsoluteDate> selected = new ArrayList<>();
final boolean reset = first == null || start.durationFrom(first) > burstPeriod;
final boolean reset = first == null || increment * start.durationFrom(first) > burstPeriod;
if (reset) {
first = null;
lastSize = 0;
first = null;
index = firstIndex;
}
for (AbsoluteDate next = reset ? start : last.shiftedBy(highRateStep);
next.compareTo(end) <= 0;
next = last.shiftedBy(highRateStep)) {
for (AbsoluteDate next = reset ? start : last.shiftedBy(signedHighRateStep);
increment * next.durationFrom(end) <= 0;
next = last.shiftedBy(signedHighRateStep)) {
if (lastSize == maxBurstSize) {
if (index == lastIndex + increment) {
// we have exceeded burst size, jump to next burst
next = first.shiftedBy(burstPeriod);
first = null;
lastSize = 0;
if (next.compareTo(end) > 0) {
next = first.shiftedBy(signedBurstPeriod);
first = null;
index = firstIndex;
if (increment * next.durationFrom(end) > 0) {
// next burst is out of current interval
break;
}
}
if (first == null && alignmentTimeScale != null) {
// align date to time scale
final double t = next.getComponents(alignmentTimeScale).getTime().getSecondsInLocalDay();
final double dt = burstPeriod * FastMath.round(t / burstPeriod) - t;
// align earliest burst date to time scale
final double offset = firstIndex * highRateStep;
final double t = next.getComponents(alignmentTimeScale).getTime().getSecondsInLocalDay() - offset;
final double dt = burstPeriod * FastMath.round(t / burstPeriod) - t;
next = next.shiftedBy(dt);
if (next.compareTo(start) < 0) {
// alignment shifted date before interval
next = next.shiftedBy(burstPeriod);
while (index != lastIndex && increment * next.durationFrom(start) < 0) {
next = next.shiftedBy(signedHighRateStep);
index += increment;
}
if (increment * next.durationFrom(start) < 0) {
// alignment shifted date out of interval
next = next.shiftedBy(signedBurstPeriod - (maxBurstSize - 1) * signedHighRateStep);
index = firstIndex;
}
}
if (next.compareTo(start) >= 0) {
if (next.compareTo(end) <= 0) {
if (increment * next.durationFrom(start) >= 0) {
if (increment * next.durationFrom(end) <= 0) {
// the date is within range, select it
if (first == null) {
first = next;
lastSize = 0;
first = next.shiftedBy(-signedHighRateStep * index);
}
selected.add(next);
++lastSize;
} else {
// we have exceeded date range
break;
}
}
last = next;
last = next;
index += increment;
}
......
......@@ -33,6 +33,17 @@ import java.util.List;
public interface DatesSelector {
/** Select dates within an interval.
* <p>
* The {@code start} and {@code end} date may be either in direct or reverse
* chronological order. The list is produced in the same order as {@code start}
* and {@code end}, i.e. direct chronological order if {@code start} is earlier
* than {@code end} or reverse chronological order if {@code start} is later
* than {@code end}.
* </p>
* <p>
* The ordering (direct or reverse chronological order) should not be changed
* between calls, otherwise unpredictable results may occur.
* </p>
* @param start interval start
* @param end interval end
* @return selected dates within this interval
......
......@@ -62,26 +62,23 @@ public class FixedStepSelector implements DatesSelector {
@Override
public List<AbsoluteDate> selectDates(final AbsoluteDate start, final AbsoluteDate end) {
final double sign = FastMath.copySign(1, end.durationFrom(start));
final List<AbsoluteDate> selected = new ArrayList<>();
final boolean reset = last == null || start.durationFrom(last) > step;
for (AbsoluteDate next = reset ? start : last.shiftedBy(step);
next.compareTo(end) <= 0;
next = last.shiftedBy(step)) {
final boolean reset = last == null || sign * start.durationFrom(last) > step;
for (AbsoluteDate next = reset ? start : last.shiftedBy(sign * step);
sign * next.durationFrom(end) <= 0;
next = last.shiftedBy(sign * step)) {
if (alignmentTimeScale != null) {
// align date to time scale
final double t = next.getComponents(alignmentTimeScale).getTime().getSecondsInLocalDay();
final double dt = step * FastMath.round(t / step) - t;
next = next.shiftedBy(dt);
if (next.compareTo(start) < 0) {
// alignment shifted date before interval
next = next.shiftedBy(step);
}
}
if (next.compareTo(start) >= 0) {
if (next.compareTo(end) <= 0) {
if (sign * next.durationFrom(start) >= 0) {
if (sign * next.durationFrom(end) <= 0) {
// the date is within range, select it
selected.add(next);
} else {
......
......@@ -43,7 +43,7 @@ public class BurstSelectorStepTest {
}
@Test
public void testAlignUTCBefore() {
public void testAlignUTCBeforeForward() {
final TimeScale utc = TimeScalesFactory.getUTC();
final DatesSelector selector = new BurstSelector(2, 10.0, 30.0, utc);
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:27.0", utc);
......@@ -57,7 +57,21 @@ public class BurstSelectorStepTest {
}
@Test
public void testAlignUTCAfter() {
public void testAlignUTCBeforeBackward() {
final TimeScale utc = TimeScalesFactory.getUTC();
final DatesSelector selector = new BurstSelector(2, 10.0, 30.0, utc);
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:27.0", utc);
final AbsoluteDate t1 = t0.shiftedBy(62);
final List<AbsoluteDate> list = selector.selectDates(t1, t0);
Assert.assertEquals(4, list.size());
Assert.assertEquals( 70.0, list.get(0).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 60.0, list.get(1).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 40.0, list.get(2).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 30.0, list.get(3).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
}
@Test
public void testAlignUTCAfterForward() {
final TimeScale utc = TimeScalesFactory.getUTC();
final DatesSelector selector = new BurstSelector(3, 10.0, 60.0, utc);
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:27.0", utc);
......@@ -73,6 +87,23 @@ public class BurstSelectorStepTest {
Assert.assertEquals(120.0, list2.get(3).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
}
@Test
public void testAlignUTCAfterBackward() {
final TimeScale utc = TimeScalesFactory.getUTC();
final DatesSelector selector = new BurstSelector(3, 10.0, 60.0, utc);
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:27.0", utc);
final AbsoluteDate t1 = t0.shiftedBy(2);
final AbsoluteDate t2 = t1.shiftedBy(98);
final List<AbsoluteDate> list1 = selector.selectDates(t2, t1);
Assert.assertEquals(4, list1.size());
Assert.assertEquals(120.0, list1.get(0).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 80.0, list1.get(1).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 70.0, list1.get(2).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 60.0, list1.get(3).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
final List<AbsoluteDate> list2 = selector.selectDates(t1, t0);
Assert.assertEquals(0, list2.size());
}
@Test
public void testInterruptedStream() {
final TimeScale utc = TimeScalesFactory.getUTC();
......@@ -94,12 +125,12 @@ public class BurstSelectorStepTest {
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:27.0", utc);
final AbsoluteDate t1 = t0.shiftedBy(71);
final AbsoluteDate t2 = t1.shiftedBy(30);
final AbsoluteDate t3 = t2.shiftedBy(15);
final AbsoluteDate t3 = t2.shiftedBy(19);
final List<AbsoluteDate> list1 = selector.selectDates(t0, t1);
Assert.assertEquals(5, list1.size());
final List<AbsoluteDate> list2 = selector.selectDates(t2, t3);
Assert.assertEquals(1, list2.size());
Assert.assertEquals(40.0, list2.get(0).durationFrom(list1.get(list1.size() - 1)), 1.0e-15);
Assert.assertEquals(50.0, list2.get(0).durationFrom(list1.get(list1.size() - 1)), 1.0e-15);
}
@Test
......@@ -131,6 +162,38 @@ public class BurstSelectorStepTest {
Assert.assertEquals(0, list2.size());
}
@Test
public void testStartMidBurstForward() {
final TimeScale utc = TimeScalesFactory.getUTC();
final DatesSelector selector = new BurstSelector(3, 10.0, 60.0, utc);
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:17.0", utc);
final AbsoluteDate t1 = t0.shiftedBy(118);
final List<AbsoluteDate> list1 = selector.selectDates(t0, t1);
Assert.assertEquals(6, list1.size());
Assert.assertEquals( 20.0, list1.get(0).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 60.0, list1.get(1).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 70.0, list1.get(2).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 80.0, list1.get(3).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals(120.0, list1.get(4).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals(130.0, list1.get(5).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
}
@Test
public void testStartMidBurstBackward() {
final TimeScale utc = TimeScalesFactory.getUTC();
final DatesSelector selector = new BurstSelector(3, 10.0, 60.0, utc);
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:17.0", utc);
final AbsoluteDate t1 = t0.shiftedBy(118);
final List<AbsoluteDate> list1 = selector.selectDates(t1, t0);
Assert.assertEquals(6, list1.size());
Assert.assertEquals(130.0, list1.get(0).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals(120.0, list1.get(1).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 80.0, list1.get(2).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 70.0, list1.get(3).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 60.0, list1.get(4).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 20.0, list1.get(5).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
}
@Before
public void setUp() {
Utils.setDataRoot("regular-data");
......
......@@ -48,7 +48,7 @@ public class FixedStepSelectorTest {
}
@Test
public void testAlignUTCBefore() {
public void testAlignUTCBeforeForward() {
final TimeScale utc = TimeScalesFactory.getUTC();
final DatesSelector selector = new FixedStepSelector(5.0, utc);
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:27.0", utc);
......@@ -61,7 +61,20 @@ public class FixedStepSelectorTest {
}
@Test
public void testAlignUTCAfter() {
public void testAlignUTCBeforeBackward() {
final TimeScale utc = TimeScalesFactory.getUTC();
final DatesSelector selector = new FixedStepSelector(5.0, utc);
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:27.0", utc);
final AbsoluteDate t1 = t0.shiftedBy(17);
final List<AbsoluteDate> list = selector.selectDates(t1, t0);
Assert.assertEquals(3, list.size());
Assert.assertEquals( 40.0, list.get(0).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 35.0, list.get(1).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 30.0, list.get(2).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
}
@Test
public void testAlignUTCAfterForward() {
final TimeScale utc = TimeScalesFactory.getUTC();
final DatesSelector selector = new FixedStepSelector(10.0, utc);
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:27.0", utc);
......@@ -82,6 +95,28 @@ public class FixedStepSelectorTest {
Assert.assertEquals(110.0, list2.get(8).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
}
@Test
public void testAlignUTCAfterBackward() {
final TimeScale utc = TimeScalesFactory.getUTC();
final DatesSelector selector = new FixedStepSelector(10.0, utc);
final AbsoluteDate t0 = new AbsoluteDate("2003-02-25T00:00:27.0", utc);
final AbsoluteDate t1 = t0.shiftedBy(2);
final AbsoluteDate t2 = t1.shiftedBy(89);
final List<AbsoluteDate> list1 = selector.selectDates(t2, t1);
Assert.assertEquals(9, list1.size());
Assert.assertEquals(110.0, list1.get(0).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals(100.0, list1.get(1).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 90.0, list1.get(2).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 80.0, list1.get(3).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 70.0, list1.get(4).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 60.0, list1.get(5).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 50.0, list1.get(6).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 40.0, list1.get(7).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
Assert.assertEquals( 30.0, list1.get(8).getComponents(utc).getTime().getSecondsInLocalDay(), 1.0e-15);
final List<AbsoluteDate> list2 = selector.selectDates(t1, t0);
Assert.assertEquals(0, list2.size());
}
@Test
public void testInterruptedStream() {
final TimeScale utc = TimeScalesFactory.getUTC();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment