changeset 436:6642ab6c583c

Added vectorizer rings callback which generates polygon datasets suitable for polygon plots. gnv-artifacts/trunk@484 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sat, 26 Dec 2009 15:32:08 +0000
parents 67091b17462d
children b624879d2902
files gnv-artifacts/ChangeLog gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonDataset.java gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonSeries.java gnv-artifacts/src/main/java/de/intevation/gnv/raster/PolygonDatasetProducer.java gnv-artifacts/src/main/java/de/intevation/gnv/raster/Vectorizer.java
diffstat 5 files changed, 176 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/gnv-artifacts/ChangeLog	Fri Dec 25 12:00:14 2009 +0000
+++ b/gnv-artifacts/ChangeLog	Sat Dec 26 15:32:08 2009 +0000
@@ -1,3 +1,25 @@
+2009-12-26	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
+
+	* src/main/java/de/intevation/gnv/raster/PolygonDatasetProducer.java:
+	  New. Vectorizer rings callback which produces PolygonDatasets suitable
+	  to be fed into PolygonPlot.
+
+	* src/main/java/de/intevation/gnv/raster/Vectorizer.java: 
+	  Forward height to rings callback.
+	  Made simplification of chains an option (default: true).
+	  This should be turn off if generating iso lines.
+	  Made edges hashable (handy to find neighbored edges in
+	  iso line scanning).
+
+	* src/main/java/de/intevation/gnv/jfreechart/PolygonSeries.java:
+	  Added default constructor. Generate unique comparable long id
+	  in thos constructor.
+	  Added method to add a single ring.
+
+	* src/main/java/de/intevation/gnv/jfreechart/PolygonDataset.java:
+	  Added constructor to construct with a collection of polygon
+	  series.
+
 2009-12-25	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
 
 	* src/main/java/de/intevation/gnv/raster/Palette.java: Added
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonDataset.java	Fri Dec 25 12:00:14 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonDataset.java	Sat Dec 26 15:32:08 2009 +0000
@@ -1,6 +1,7 @@
 package de.intevation.gnv.jfreechart;
 
 import java.util.List;
+import java.util.Collection;
 import java.util.ArrayList;
 
 import org.jfree.data.Range;
@@ -17,12 +18,15 @@
 
 
     public PolygonDataset() {
-        this(null);
+        data = new ArrayList();
     }
 
+    public PolygonDataset(Collection series) {
+        data = new ArrayList(series);
+    }
 
     public PolygonDataset(PolygonSeries series) {
-        data = new ArrayList();
+        this();
 
         if (series != null) {
             data.add(series);
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonSeries.java	Fri Dec 25 12:00:14 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonSeries.java	Sat Dec 26 15:32:08 2009 +0000
@@ -16,6 +16,15 @@
     protected CompactXYItems []  rings;
     protected Map                attributes;
 
+    private static long uniqueKey;
+
+    protected synchronized static Long createUniqueKey() {
+        return new Long(uniqueKey++);
+    }
+
+    public PolygonSeries() {
+        this(createUniqueKey(), null);
+    }
 
     public PolygonSeries(Comparable key, CompactXYItems [] rings) {
         this(key, null, rings, new HashMap());
@@ -49,6 +58,18 @@
         return rings;
     }
 
+    public void addRing(CompactXYItems newRing) {
+        if (rings == null) {
+            rings = new CompactXYItems [] { newRing };
+        }
+        else {
+            CompactXYItems [] nRings = new CompactXYItems[rings.length + 1];
+            System.arraycopy(rings, 0, nRings, 0, rings.length);
+            nRings[rings.length] = newRing;
+            rings = nRings;
+        }
+    }
+
     public void addRings(CompactXYItems [] newRings) {
         if (newRings == null || newRings.length == 0) {
             return;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/raster/PolygonDatasetProducer.java	Sat Dec 26 15:32:08 2009 +0000
@@ -0,0 +1,97 @@
+package de.intevation.gnv.raster;
+
+import java.util.List;
+import java.util.HashMap;
+
+import gnu.trove.TDoubleArrayList;
+
+import de.intevation.gnv.raster.Vectorizer.RingsHandler;
+import de.intevation.gnv.raster.Vectorizer.Edge;
+
+import de.intevation.gnv.jfreechart.PolygonSeries;
+import de.intevation.gnv.jfreechart.PolygonDataset;
+import de.intevation.gnv.jfreechart.CompactXYItems;
+
+public class PolygonDatasetProducer
+implements   RingsHandler
+{
+    protected double minX;
+    protected double minY;
+
+    protected double maxX;
+    protected double maxY;
+
+    protected HashMap<Integer, PolygonSeries> polygonSeries;
+
+    protected PolygonDatasetProducer() {
+    }
+
+    public PolygonDatasetProducer(
+        double minX, double minY,
+        double maxX, double maxY
+
+    ) {
+        this.minX = minX;
+        this.minY = minY;
+        this.maxX = maxX;
+        this.maxY = maxY;
+
+        polygonSeries = new HashMap<Integer, PolygonSeries>();
+    }
+
+    public void handleRings(
+        List<Edge> rings, 
+        int        value, 
+        int        width,
+        int        height
+    ) {
+        if (value == -1) {
+            return;
+        }
+
+        Integer v = Integer.valueOf(value);
+
+        PolygonSeries ps = (PolygonSeries)polygonSeries.get(v);
+
+        if (ps == null) {
+            polygonSeries.put(v, ps = new PolygonSeries());
+            ps.setAttribute("fill", v);
+        }
+
+        TDoubleArrayList vertices = new TDoubleArrayList();
+
+        /* minX = 0*m1 + b1 <=> b1 = minX
+         * maxX = (width-1)*m1 + b1
+         * m1 = (maxX - minX)/(width-1)
+         */
+
+         double b1 = minX;
+         double m1 = width != 1
+            ? (maxX - minX)/(width-1)
+            : 0d;
+
+         double b2 = minY;
+         double m2 = height != 1
+            ? (maxY - minY)/(height-1)
+            : 0d;
+
+        for (Edge head: rings) {
+            Edge current = head;
+            do {
+                double x = m1*(current.a % width) + b1;
+                double y = m2*(current.a / width) + b2;
+                vertices.add(x);
+                vertices.add(y);
+                current = current.next;
+            }
+            while (current != head);
+            ps.addRing(new CompactXYItems(vertices.toNativeArray()));
+            vertices.clear();
+        }
+    }
+
+    public PolygonDataset getPolygonDataset() {
+        return new PolygonDataset(polygonSeries.values());
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/raster/Vectorizer.java	Fri Dec 25 12:00:14 2009 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/raster/Vectorizer.java	Sat Dec 26 15:32:08 2009 +0000
@@ -14,7 +14,11 @@
 {
     public interface RingsHandler {
 
-        void handleRings(List rings, int value, int width);
+        void handleRings(
+            List<Edge> rings,
+            int        value, 
+            int        width,
+            int        height);
 
     } // interface RingsHandler
 
@@ -69,6 +73,15 @@
             do { ++length; } while ((current = current.next) != this);
             return length;
         }
+
+        public int hashCode() {
+            return (a << 16) | b;
+        }
+
+        public boolean equals(Object other) {
+            Edge e = (Edge)other;
+            return a == e.a && b == e.b;
+        }
     } // class Edge
 
     protected static Edge simplify(Edge edge, int width) {
@@ -113,11 +126,17 @@
     protected int []            raster;
     protected int               width;
     protected TIntObjectHashMap openEdges;
-    protected ArrayList         rings;
+    protected List<Edge>        rings;
+    protected boolean           simplify;
 
     public Vectorizer() {
-        openEdges = new TIntObjectHashMap();
-        rings     = new ArrayList();
+        this(true);
+    }
+
+    public Vectorizer(boolean simplify) {
+        openEdges     = new TIntObjectHashMap();
+        rings         = new ArrayList<Edge>();
+        this.simplify = simplify;
     }
 
     public Vectorizer(int [] raster, int width) {
@@ -163,7 +182,7 @@
         }
 
         if (edge.isComplete()) {
-            rings.add(simplify(edge, width + 1));
+            rings.add(simplify ? simplify(edge, width + 1) : edge);
         }
         else {
             if (otherA == null) {
@@ -183,6 +202,7 @@
 
         int regions = 0;
 
+        int height = raster.length / width;
 
         for (int i = 0; i < raster.length; ++i) {
             if (visited.get(i)) {
@@ -278,7 +298,11 @@
                 current = stack.pop();
             }
 
-            handler.handleRings(rings, currentValue, width + 1);
+            handler.handleRings(
+                rings, 
+                currentValue, 
+                width + 1,
+                height + 1);
 
             resetRegion();
         }

http://dive4elements.wald.intevation.org