# HG changeset patch # User Sascha L. Teichmann # Date 1383308754 -3600 # Node ID 4de4b19b6be66fa934b3cc5a1fd4cbf95c439515 # Parent 8cdc863271499c1b3624c560cd0f915f591efefb Fixed half broken interpolation code for lines to 'Dauerlinie'. diff -r 8cdc86327149 -r 4de4b19b6be6 artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesQFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesQFacet.java Fri Nov 01 12:12:24 2013 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesQFacet.java Fri Nov 01 13:25:54 2013 +0100 @@ -20,7 +20,6 @@ import org.dive4elements.artifactdatabase.state.DefaultFacet; import org.dive4elements.river.artifacts.MainValuesArtifact; -import org.dive4elements.river.artifacts.math.Linear; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StickyAxisAnnotation; @@ -51,7 +50,6 @@ this.isAtGauge = atGauge; } - /** * Set the hit-point in Q where a line drawn from the axis would hit the * curve in WQDay (if hit). @@ -59,34 +57,14 @@ */ protected static void setHitPoint(WQDay wqday, StickyAxisAnnotation annotation) { - if (wqday.size() == 0) { - return; - } + float q = annotation.getPos(); + Double day = wqday.interpolateDayByQ(q); - int idx = 0; - float q = annotation.getPos(); - boolean qIncreases = wqday.getQ(0) < wqday.getQ(wqday.size()-1); - if (qIncreases) { - while (idx < wqday.size() && wqday.getQ(idx) < q) { - idx++; - } + if (day != null) { + annotation.setHitPoint(day.floatValue()); } - else { - idx = wqday.size() -1; - while (idx > 0 && wqday.getQ(idx) > q) { - idx--; - } - } - - double day = 0d; - int mod = (qIncreases) ? -1 : +1; - if (idx != 0 && idx <= wqday.size()-1) { - day = Linear.linear(q, wqday.getQ(idx +mod), wqday.getQ(idx), - wqday.getDay(idx+mod), wqday.getDay(idx)); - annotation.setHitPoint((float)day); - } - else { - logger.debug("StickyAnnotation does not hit wqday curve"); + else if (logger.isDebugEnabled()) { + logger.debug("StickyAnnotation does not hit wqday curve: " + q); } } diff -r 8cdc86327149 -r 4de4b19b6be6 artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesWFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesWFacet.java Fri Nov 01 12:12:24 2013 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesWFacet.java Fri Nov 01 13:25:54 2013 +0100 @@ -20,7 +20,6 @@ import org.dive4elements.artifactdatabase.state.DefaultFacet; import org.dive4elements.river.artifacts.MainValuesArtifact; -import org.dive4elements.river.artifacts.math.Linear; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StickyAxisAnnotation; import org.dive4elements.river.exports.fixings.FixChartGenerator; @@ -54,35 +53,15 @@ * Employ linear interpolation. */ protected static void setHitPoint(WQDay wqday, StickyAxisAnnotation annotation) { - - if (wqday.size() == 0) { - return; - } + float w = annotation.getPos(); - int idx = 0; - float w = annotation.getPos(); - boolean wIncreases = wqday.getW(0) < wqday.getW(wqday.size()-1); - if (wIncreases) { - while (idx < wqday.size() && wqday.getW(idx) < w) { - idx++; - } + Double day = wqday.interpolateDayByW(w); + + if (day != null) { + annotation.setHitPoint(day.floatValue()); } - else { - idx = wqday.size() -1; - while (idx > 0 && wqday.getW(idx) > w) { - idx--; - } - } - - double day = 0d; - int mod = (wIncreases) ? -1 : +1; - if (idx != 0 && idx < wqday.size()-1-mod) { - day = Linear.linear(w, wqday.getW(idx +mod), wqday.getW(idx), - wqday.getDay(idx+mod), wqday.getDay(idx)); - annotation.setHitPoint((float)day); - } - else { - logger.debug("StickyAnnotation does not hit wqday curve"); + else if (logger.isDebugEnabled()) { + logger.debug("StickyAnnotation does not hit wqday curve: " + w); } } diff -r 8cdc86327149 -r 4de4b19b6be6 artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQDay.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQDay.java Fri Nov 01 12:12:24 2013 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQDay.java Fri Nov 01 13:25:54 2013 +0100 @@ -8,6 +8,12 @@ package org.dive4elements.river.artifacts.model; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import org.dive4elements.river.artifacts.math.Linear; + import gnu.trove.TIntArrayList; /** @@ -19,6 +25,19 @@ public class WQDay extends WQ { + public static final Comparator FIRST_CMP = new Comparator() { + @Override + public int compare(double [] a, double [] b) { + double diff = a[0] - b[0]; + if (diff < 0d) return -1; + if (diff > 0d) return +1; + return 0; + } + }; + + public static final double EPSILON = 1e-4; + + protected TIntArrayList days; public WQDay() { @@ -52,6 +71,68 @@ return days.getQuick(idx); } + private static final Double interpolateX(ArrayList dxs, double x) { + + Collections.sort(dxs, FIRST_CMP); + + if (Math.abs(x - dxs.get(0)[1]) < EPSILON) { + return dxs.get(0)[0]; + } + + for (int i = 1, S = dxs.size(); i < S; ++i) { + double [] curr = dxs.get(i); + if (Math.abs(x - curr[1]) < EPSILON) { + return curr[0]; + } + + double [] prev = dxs.get(i-1); + double x1 = Math.min(prev[1], curr[1]); + double x2 = Math.max(prev[1], curr[1]); + if (x > x1 && x < x2) { + return Linear.linear( + x, + prev[1], curr[1], + prev[0], curr[0]); + } + } + + return null; + } + + public Double interpolateDayByW(double w) { + + int S = days.size(); + + if (S == 0) { + return null; + } + + ArrayList dws = new ArrayList(S); + + for (int i = 0; i < S; ++i) { + dws.add(new double[] { getDay(i), getW(i) }); + } + + return interpolateX(dws, w); + } + + public Double interpolateDayByQ(double q) { + + int S = days.size(); + + if (S == 0) { + return null; + } + + ArrayList dqs = new ArrayList(S); + + for (int i = 0; i < S; ++i) { + dqs.add(new double[] { getDay(i), getQ(i) }); + } + + return interpolateX(dqs, q); + } + @Override public void removeNaNs() {