diff gnv-artifacts/src/main/java/de/intevation/gnv/raster/JTSMultiPolygonProducer.java @ 465:f7038820df2e

Added support to trace rasters to JTS multi polygons and multi line strings. Write them to shape files with GeoTools. gnv-artifacts/trunk@526 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 11 Jan 2010 00:29:45 +0000
parents
children 6e8364e766fa
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/raster/JTSMultiPolygonProducer.java	Mon Jan 11 00:29:45 2010 +0000
@@ -0,0 +1,183 @@
+package de.intevation.gnv.raster;
+
+import java.util.Map;
+import java.util.List;
+import java.util.HashMap;
+import java.util.TreeMap;
+import java.util.ArrayList;
+
+import com.vividsolutions.jts.geom.GeometryFactory;
+import com.vividsolutions.jts.geom.MultiPolygon;
+import com.vividsolutions.jts.geom.Polygon;
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.LinearRing;
+import com.vividsolutions.jts.geom.PrecisionModel;
+
+import com.vividsolutions.jts.algorithm.CGAlgorithms;
+
+import com.vividsolutions.jts.geom.impl.PackedCoordinateSequenceFactory;
+
+import org.apache.log4j.Logger;
+
+import de.intevation.gnv.raster.Vectorizer.Edge;
+
+/**
+ * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
+ */
+public class JTSMultiPolygonProducer
+extends      AbstractProducer
+{
+    private static Logger log = Logger.getLogger(
+        JTSMultiPolygonProducer.class);
+
+    public static final int SRID_WGS84 = 4326;
+
+    public interface ValueConverter {
+
+        Integer convert(Integer value);
+
+    } // interface ValueConverter
+
+    protected GeometryFactory geometryFactory;
+
+    protected HashMap<Integer, ArrayList<Polygon>> valueToPolygons;
+
+    public JTSMultiPolygonProducer() {
+    }
+
+    public JTSMultiPolygonProducer(
+        double minX, double minY,
+        double maxX, double maxY
+    ) {
+        this(
+            createDefaultGeometryFactory(),
+            minX, minY,
+            maxX, maxY);
+    }
+
+    public JTSMultiPolygonProducer(
+        GeometryFactory geometryFactory,
+        double minX, double minY,
+        double maxX, double maxY
+    ) {
+        super(minX, minY, maxX, maxY);
+        this.geometryFactory = geometryFactory;
+        valueToPolygons = new HashMap<Integer, ArrayList<Polygon>>();
+    }
+
+    public static GeometryFactory createDefaultGeometryFactory() {
+        return new GeometryFactory(
+            new PrecisionModel(
+                PrecisionModel.FLOATING),
+            SRID_WGS84,
+            new PackedCoordinateSequenceFactory(
+                PackedCoordinateSequenceFactory.DOUBLE,
+                2));
+    }
+
+    public void handleRings(
+        List<Edge> rings, 
+        int        value, 
+        int        width,
+        int        height
+    ) {
+        if (value == -1) {
+            return;
+        }
+
+        Integer v = Integer.valueOf(value);
+
+        ArrayList<Polygon> polygons = valueToPolygons.get(v);
+
+        if (polygons == null) {
+            valueToPolygons.put(v, polygons = new ArrayList<Polygon>());
+        }
+
+        double b1 = minX;
+        double m1 = width != 1
+           ? (maxX - minX)/(width-1)
+           : 0d;
+
+        double b2 = minY;
+        double m2 = height != 1
+           ? (maxY - minY)/(height-1)
+           : 0d;
+
+        ArrayList<Coordinate> vertices = new ArrayList<Coordinate>();
+
+        LinearRing shell = null;
+        ArrayList<LinearRing> holes = new ArrayList<LinearRing>();
+
+        for (Edge head: rings) {
+            Edge current = head;
+            do {
+                vertices.add(new Coordinate(
+                    m1*(current.a % width) + b1,
+                    m2*(current.a / width) + b2));
+            }
+            while ((current = current.next) != head);
+            vertices.add(new Coordinate(
+                m1*(head.a % width) + b1,
+                m2*(head.a / width) + b2));
+
+            Coordinate [] coordinates =
+                vertices.toArray(new Coordinate[vertices.size()]);
+
+            vertices.clear();
+
+            LinearRing ring = geometryFactory.createLinearRing(
+                coordinates);
+
+            if (CGAlgorithms.isCCW(coordinates)) {
+                shell = ring;
+            }
+            else {
+                holes.add(ring);
+            }
+        }
+
+        if (shell == null) {
+            log.error("polygon has no shell");
+            return;
+        }
+
+        Polygon polygon = geometryFactory.createPolygon(
+            shell,
+            holes.toArray(new LinearRing[holes.size()]));
+
+        polygons.add(polygon);
+    }
+
+    public Map<Integer, MultiPolygon> getMultiPolygons() {
+        return getMultiPolygons(null);
+    }
+
+    public Map<Integer, MultiPolygon> getMultiPolygons(
+        ValueConverter valueConverter
+    ) {
+        TreeMap<Integer, MultiPolygon> multiPolygons =
+            new TreeMap<Integer, MultiPolygon>();
+
+        for (Map.Entry<Integer, ArrayList<Polygon>> entry:
+            valueToPolygons.entrySet()
+        ) {
+            ArrayList<Polygon> polygons = entry.getValue();
+
+            Integer value = valueConverter != null
+                ? valueConverter.convert(entry.getKey())
+                : entry.getKey();
+
+            multiPolygons.put(
+                value,
+                geometryFactory.createMultiPolygon(
+                    polygons.toArray(new Polygon[polygons.size()])));
+        }
+
+        return multiPolygons;
+    }
+
+    public void clear() {
+        valueToPolygons.clear();
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org