changeset 360:ee760729f6b8

Added mapping from linear diagram space to 2D map coordinates. gnv-artifacts/trunk@434 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 15 Dec 2009 15:58:58 +0000
parents 59ad8f37a590
children aec85d00d82c
files gnv-artifacts/ChangeLog gnv-artifacts/src/main/java/de/intevation/gnv/math/LinearMetrics.java gnv-artifacts/src/main/java/de/intevation/gnv/math/LinearToMap.java
diffstat 3 files changed, 269 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/gnv-artifacts/ChangeLog	Tue Dec 15 15:50:39 2009 +0000
+++ b/gnv-artifacts/ChangeLog	Tue Dec 15 15:58:58 2009 +0000
@@ -1,6 +1,16 @@
+2009-12-15	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
+
+	* src/main/java/de/intevation/gnv/math/LinearToMap.java: Map linear
+	  coordinates (from, to) to world coordinates (x, y) along a line string
+	  given by a set of java.awt.geom.Point2D points.
+
+	* src/main/java/de/intevation/gnv/math/LinearMetrics.java: Implements
+	  Euclidean metric used by LinearToMap.	TODO: Do same for WGS84 to
+	  be more precise.
+
 2009-12-15  Tim Englich  <tim.englich@intevation.de>
 
-    * src/main/java/de/intevation/gnv/statistics/TimeseriesStatistics.java (calculateStatistics): 
+	* src/main/java/de/intevation/gnv/statistics/TimeseriesStatistics.java (calculateStatistics): 
 	  Issue96 Resloved big that one entry is missiing in the Statitic.
 	  The last row of the ResultSet was never used.
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/math/LinearMetrics.java	Tue Dec 15 15:58:58 2009 +0000
@@ -0,0 +1,63 @@
+package de.intevation.gnv.math;
+
+import java.awt.geom.Point2D;
+
+import de.intevation.gnv.math.LinearToMap.Metrics;
+import de.intevation.gnv.math.LinearToMap.Interpolator;
+
+/**
+ *  @author Sascha L. Teichmann
+ */
+public final class LinearMetrics
+implements         Metrics
+{
+    public static final Metrics INSTANCE =
+        new LinearMetrics();
+
+    public static final class LinearInterpolator
+    implements                Interpolator
+    {
+        private double mx;
+        private double bx;
+        private double my;
+        private double by;
+
+        public LinearInterpolator(Point2D p1, Point2D p2) {
+
+            /*
+             I) p1.x = 0*m + bx
+            II) p2.x = 1*m + bx
+
+            bx = p1.x
+
+            p2.x = m + p1.x
+
+            mx = p2.x - p1.x
+            */
+
+            bx = p1.getX();
+            mx = p2.getX() - bx;
+
+            by = p1.getY();
+            my = p2.getY() - by;
+        }
+
+        public void interpolate(double t, Point2D v) {
+            double x = t*mx + bx;
+            double y = t*my + by;
+            v.setLocation(x, y);
+        }
+    } // class LinearInterpolator
+
+    private LinearMetrics() {
+    }
+
+    public double distance(Point2D p1, Point2D p2) {
+        return p1.distance(p2);
+    }
+
+    public Interpolator getInterpolator(Point2D p1, Point2D p2) {
+        return new LinearInterpolator(p1, p2);
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/math/LinearToMap.java	Tue Dec 15 15:58:58 2009 +0000
@@ -0,0 +1,195 @@
+package de.intevation.gnv.math;
+
+import java.awt.geom.Point2D;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ *  @author Sascha L. Teichmann
+ */
+public class LinearToMap
+{
+    public interface Interpolator {
+
+        void interpolate(double t, Point2D v);
+
+    } // interface Interpolator
+
+    public interface Metrics {
+
+        double distance(Point2D p1, Point2D p2);
+
+        Interpolator getInterpolator(Point2D p1, Point2D p2);
+
+    } // interface Metrics
+
+    public static final class Range {
+        private Range next;
+
+        private double from;
+        private double to;
+        private double b;
+
+        private Point2D p1;
+        private Point2D p2;
+
+        private Interpolator interpolator;
+
+        public Range() {
+        }
+
+        public Range(
+            double       from, 
+            double       to,
+            Interpolator interpolator,
+            Point2D      p1,
+            Point2D      p2
+        ) {
+            this.from         = from;
+            this.to           = to;
+            this.interpolator = interpolator;
+            this.p1           = p1;
+            this.p2           = p2;
+
+            b = from == to
+                ? 0d
+                : 1.0d/(to - from);
+        }
+
+        public void eval(double x, Point2D v) {
+            interpolator.interpolate((x - from)*b, v);
+        }
+
+        public boolean inside(double x) {
+            return x >= from && x <= to;
+        }
+
+        public Point2D startPoint() {
+            return p1;
+        }
+
+        public Point2D endPoint() {
+            return p2;
+        }
+    } // class Range
+
+    protected Range head;
+    protected Range last;
+
+    public LinearToMap() {
+    }
+
+    public LinearToMap(
+        List    path, 
+        double  from, 
+        double  to,
+        Metrics metrics
+    ) {
+        double diagramLength = Math.abs(to - from);
+
+        double worldLength = length(path, metrics);
+
+        double rangeStart = from;
+
+        Range last = null;
+
+        for (int i = 1, N = path.size(); i < N; ++i) {
+            Point2D p1 = (Point2D)path.get(i-1);
+            Point2D p2 = (Point2D)path.get(i);
+            double segmentLength = metrics.distance(p1, p2);
+
+            double relativeLength = segmentLength / worldLength;
+
+            double rangeLength = diagramLength * relativeLength;
+
+            double rangeEnd = rangeStart + rangeLength;
+
+            Range range = new Range(
+                rangeStart, rangeEnd,
+                metrics.getInterpolator(p1, p2),
+                p1, p2);
+
+            if (last == null) {
+                last = head = range;
+            }
+            else {
+                last.next = range;
+                last = range;
+            }
+            rangeStart = rangeEnd;
+        }
+    }
+
+    protected Range locateRange(double diagramX) {
+
+        if (last != null && last.inside(diagramX)) {
+            return last;
+        }
+
+        Range current = head;
+        while (current != null) {
+            if (current.inside(diagramX)) {
+                return last = current;
+            }
+            current = current.next;
+        }
+
+        return null;
+    }
+
+    public boolean locate(double diagramX, Point2D v) {
+        Range range = locateRange(diagramX);
+        if (range == null) {
+            return false;
+        }
+        range.eval(diagramX, v);
+        return true;
+    }
+
+    public static double length(List path, Metrics metrics) {
+        double sum = 0d;
+        for (int i = path.size()-1; i >= 1; --i) {
+            Point2D p1 = (Point2D)path.get(i);
+            Point2D p2 = (Point2D)path.get(i-1);
+            sum += metrics.distance(p1, p2);
+        }
+        return sum;
+    }
+
+    public int numRanges() {
+        int count = 0;
+        Range current = head;
+        while (current != null) {
+            ++count;
+            current = current.next;
+        }
+        return count;
+    }
+
+    public Iterator ranges() {
+        return new Iterator() {
+
+            Range current = head;
+
+            public boolean hasNext() {
+                return current != null;
+            }
+
+            public Object next() {
+                if (!hasNext()) {
+                    throw new NoSuchElementException();
+                }
+                Range x = current;
+                current = current.next;
+                return x;
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:

http://dive4elements.wald.intevation.org