sascha@465: package de.intevation.gnv.raster; sascha@465: sascha@465: import java.util.Map; sascha@465: import java.util.List; sascha@465: import java.util.HashMap; sascha@465: import java.util.TreeMap; sascha@465: import java.util.ArrayList; sascha@465: sascha@465: import com.vividsolutions.jts.geom.GeometryFactory; sascha@465: import com.vividsolutions.jts.geom.MultiPolygon; sascha@465: import com.vividsolutions.jts.geom.Polygon; sascha@465: import com.vividsolutions.jts.geom.Coordinate; sascha@465: import com.vividsolutions.jts.geom.LinearRing; sascha@465: import com.vividsolutions.jts.geom.PrecisionModel; sascha@465: sascha@465: import com.vividsolutions.jts.algorithm.CGAlgorithms; sascha@465: sascha@465: import com.vividsolutions.jts.geom.impl.PackedCoordinateSequenceFactory; sascha@465: sascha@465: import org.apache.log4j.Logger; sascha@465: sascha@465: import de.intevation.gnv.raster.Vectorizer.Edge; sascha@465: sascha@465: /** sascha@465: * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) sascha@465: */ sascha@465: public class JTSMultiPolygonProducer sascha@465: extends AbstractProducer sascha@465: { sascha@465: private static Logger log = Logger.getLogger( sascha@465: JTSMultiPolygonProducer.class); sascha@465: sascha@465: public static final int SRID_WGS84 = 4326; sascha@465: sascha@465: public interface ValueConverter { sascha@465: sascha@465: Integer convert(Integer value); sascha@465: sascha@465: } // interface ValueConverter sascha@465: sascha@465: protected GeometryFactory geometryFactory; sascha@465: sascha@465: protected HashMap> valueToPolygons; sascha@465: sascha@465: public JTSMultiPolygonProducer() { sascha@465: } sascha@465: sascha@465: public JTSMultiPolygonProducer( sascha@465: double minX, double minY, sascha@465: double maxX, double maxY sascha@465: ) { sascha@465: this( sascha@465: createDefaultGeometryFactory(), sascha@465: minX, minY, sascha@465: maxX, maxY); sascha@465: } sascha@465: sascha@465: public JTSMultiPolygonProducer( sascha@465: GeometryFactory geometryFactory, sascha@465: double minX, double minY, sascha@465: double maxX, double maxY sascha@465: ) { sascha@465: super(minX, minY, maxX, maxY); sascha@465: this.geometryFactory = geometryFactory; sascha@465: valueToPolygons = new HashMap>(); sascha@465: } sascha@465: sascha@465: public static GeometryFactory createDefaultGeometryFactory() { sascha@498: return createDefaultGeometryFactory(2); sascha@498: } sascha@498: sascha@498: public static GeometryFactory createDefaultGeometryFactory(int dim) { sascha@465: return new GeometryFactory( sascha@465: new PrecisionModel( sascha@465: PrecisionModel.FLOATING), sascha@465: SRID_WGS84, sascha@465: new PackedCoordinateSequenceFactory( sascha@465: PackedCoordinateSequenceFactory.DOUBLE, sascha@498: dim)); sascha@465: } sascha@465: sascha@465: public void handleRings( sascha@465: List rings, sascha@465: int value, sascha@465: int width, sascha@465: int height sascha@465: ) { sascha@465: if (value == -1) { sascha@465: return; sascha@465: } sascha@465: sascha@465: Integer v = Integer.valueOf(value); sascha@465: sascha@465: ArrayList polygons = valueToPolygons.get(v); sascha@465: sascha@465: if (polygons == null) { sascha@465: valueToPolygons.put(v, polygons = new ArrayList()); sascha@465: } sascha@465: sascha@465: double b1 = minX; sascha@465: double m1 = width != 1 sascha@465: ? (maxX - minX)/(width-1) sascha@465: : 0d; sascha@465: sascha@465: double b2 = minY; sascha@465: double m2 = height != 1 sascha@465: ? (maxY - minY)/(height-1) sascha@465: : 0d; sascha@465: sascha@465: ArrayList vertices = new ArrayList(); sascha@465: sascha@465: LinearRing shell = null; sascha@465: ArrayList holes = new ArrayList(); sascha@465: sascha@465: for (Edge head: rings) { sascha@465: Edge current = head; sascha@465: do { sascha@465: vertices.add(new Coordinate( sascha@465: m1*(current.a % width) + b1, sascha@465: m2*(current.a / width) + b2)); sascha@465: } sascha@495: while ((current = current.prev) != head); sascha@465: vertices.add(new Coordinate( sascha@465: m1*(head.a % width) + b1, sascha@465: m2*(head.a / width) + b2)); sascha@465: sascha@465: Coordinate [] coordinates = sascha@465: vertices.toArray(new Coordinate[vertices.size()]); sascha@465: sascha@465: vertices.clear(); sascha@465: sascha@465: LinearRing ring = geometryFactory.createLinearRing( sascha@465: coordinates); sascha@465: sascha@465: if (CGAlgorithms.isCCW(coordinates)) { sascha@465: shell = ring; sascha@465: } sascha@465: else { sascha@465: holes.add(ring); sascha@465: } sascha@465: } sascha@465: sascha@465: if (shell == null) { sascha@465: log.error("polygon has no shell"); sascha@465: return; sascha@465: } sascha@465: sascha@465: Polygon polygon = geometryFactory.createPolygon( sascha@465: shell, sascha@465: holes.toArray(new LinearRing[holes.size()])); sascha@465: sascha@465: polygons.add(polygon); sascha@465: } sascha@465: sascha@465: public Map getMultiPolygons() { sascha@465: return getMultiPolygons(null); sascha@465: } sascha@465: sascha@465: public Map getMultiPolygons( sascha@465: ValueConverter valueConverter sascha@465: ) { sascha@465: TreeMap multiPolygons = sascha@465: new TreeMap(); sascha@465: sascha@465: for (Map.Entry> entry: sascha@465: valueToPolygons.entrySet() sascha@465: ) { sascha@465: ArrayList polygons = entry.getValue(); sascha@465: sascha@465: Integer value = valueConverter != null sascha@465: ? valueConverter.convert(entry.getKey()) sascha@465: : entry.getKey(); sascha@465: sascha@465: multiPolygons.put( sascha@465: value, sascha@465: geometryFactory.createMultiPolygon( sascha@465: polygons.toArray(new Polygon[polygons.size()]))); sascha@465: } sascha@465: sascha@465: return multiPolygons; sascha@465: } sascha@465: sascha@465: public void clear() { sascha@465: valueToPolygons.clear(); sascha@465: } sascha@465: } sascha@465: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :