diff options
Diffstat (limited to 'altoslib/AltosTimeSeries.java')
-rw-r--r-- | altoslib/AltosTimeSeries.java | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/altoslib/AltosTimeSeries.java b/altoslib/AltosTimeSeries.java index 1d3d9a6c..30b24d82 100644 --- a/altoslib/AltosTimeSeries.java +++ b/altoslib/AltosTimeSeries.java @@ -17,9 +17,9 @@ package org.altusmetrum.altoslib_11; import java.util.*; public class AltosTimeSeries implements Iterable<AltosTimeValue> { - public String label; - public AltosUnits units; - List<AltosTimeValue> values; + public String label; + public AltosUnits units; + ArrayList<AltosTimeValue> values; public void add(AltosTimeValue tv) { values.add(tv); @@ -33,6 +33,58 @@ public class AltosTimeSeries implements Iterable<AltosTimeValue> { return values.get(i); } + private double lerp(AltosTimeValue v0, AltosTimeValue v1, double t) { + /* degenerate case */ + if (v0.time == v1.time) + return (v0.value + v1.value) / 2; + + return (v0.value * (v1.time - t) + v1.value * (t - v0.time)) / v1.time - v0.time; + } + + private int after_index(double time) { + int lo = 0; + int hi = values.size() - 1; + + while (lo <= hi) { + int mid = (lo + hi) / 2; + + if (values.get(mid).time < time) + lo = mid + 1; + else + hi = mid - 1; + } + return lo; + } + + /* Compute a value for an arbitrary time */ + public double value(double time) { + int after = after_index(time); + if (after == 0) + return values.get(0).value; + if (after == values.size()) + return values.get(after - 1).value; + + return lerp(values.get(after-1), values.get(after), time); + } + + /* Find the value just before an arbitrary time */ + public double value_before(double time) { + int after = after_index(time); + + if (after == 0) + return values.get(0).value; + return values.get(after-1).value; + } + + /* Find the value just after an arbitrary time */ + public double value_after(double time) { + int after = after_index(time); + + if (after == values.size()) + return values.get(after-1).value; + return values.get(after).value; + } + public int size() { return values.size(); } @@ -144,11 +196,16 @@ public class AltosTimeSeries implements Iterable<AltosTimeValue> { int left = find_left(i, half_width); int right = find_right(i, half_width); + for (int j = left; j <= right; j++) { double j_time = values.get(j).time; if (left_time <= j_time && j_time <= right_time) { - double coeff = filter_coeff(j_time - center_time, width); + double j_left = j == left ? left_time : values.get(j-1).time; + double j_right = j == right ? right_time : values.get(j+1).time; + double interval = (j_right - j_left) / 2.0; + double coeff = filter_coeff(j_time - center_time, width) * interval; + total_coeff += coeff; total_value += coeff * values.get(j).value; } |