changeset 7494:4de4b19b6be6

Fixed half broken interpolation code for lines to 'Dauerlinie'.
author Sascha L. Teichmann <teichmann@intevation.de>
date Fri, 01 Nov 2013 13:25:54 +0100
parents 8cdc86327149
children 607246315009
files artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesQFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesWFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQDay.java
diffstat 3 files changed, 94 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- 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);
         }
     }
 
--- 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);
         }
     }
 
--- 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<double []> FIRST_CMP = new Comparator<double []>() {
+        @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<double []> 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<double[]> dws = new ArrayList<double[]>(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<double[]> dqs = new ArrayList<double[]>(S);
+
+        for (int i = 0; i < S; ++i) {
+            dqs.add(new double[] { getDay(i), getQ(i) });
+        }
+
+        return interpolateX(dqs, q);
+    }
+
     @Override
     public void removeNaNs() {
 

http://dive4elements.wald.intevation.org