Mercurial > dive4elements > gnv-client
diff gnv-artifacts/src/main/java/de/intevation/gnv/raster/JTSMultiLineStringProducer.java @ 875:5e9efdda6894
merged gnv-artifacts/1.0
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:13:56 +0200 |
parents | feae2f9d6c6f |
children | f953c9a559d8 |
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/JTSMultiLineStringProducer.java Fri Sep 28 12:13:56 2012 +0200 @@ -0,0 +1,239 @@ +package de.intevation.gnv.raster; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.LineString; +import com.vividsolutions.jts.geom.MultiLineString; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.geom.TopologyException; + +import de.intevation.gnv.math.IJKey; + +import de.intevation.gnv.raster.Vectorizer.Edge; + +import de.intevation.gnv.utils.Pair; + +import gnu.trove.TIntObjectHashMap; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + +/** + * Vectorizer backend to generated iso lines in form of + * JTS multi linestrings. + * + * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> + */ +public class JTSMultiLineStringProducer +extends IsoProducer +{ + private static Logger log = Logger.getLogger( + JTSMultiLineStringProducer.class); + + /** + * The JTS geometry factory of this producer. + */ + protected GeometryFactory geometryFactory; + + /** + * The polygon used to clip the produced multe line strings. + */ + protected Polygon clip; + + /** + * Constructor to create a JTSMultiLineStringProducer with + * a given clipping polygon and a world bounding box. + * @param clip The clipping polygon. + * @param minX Min x coord of the world. + * @param minY Min y coord of the world. + * @param maxX Max x coord of the world. + * @param maxY Max y coord of the world. + */ + public JTSMultiLineStringProducer( + Polygon clip, + double minX, double minY, + double maxX, double maxY + ) { + this( + clip, + // XXX: Geotools crashes if only using a 2d packed data format! + JTSMultiPolygonProducer.createDefaultGeometryFactory(3), + minX, minY, + maxX, maxY); + } + + /** + * Constructor to create a JTSMultiLineStringProducer with + * a given clipping polygon, a geometry factory + * and a world bounding box. + * @param clip The clipping polygon. + * @param geometryFactory The geometry factory. + * @param minX Min x coord of the world. + * @param minY Min y coord of the world. + * @param maxX Max x coord of the world. + * @param maxY Max y coord of the world. + */ + public JTSMultiLineStringProducer( + Polygon clip, + GeometryFactory geometryFactory, + double minX, double minY, + double maxX, double maxY + ) { + super(minX, minY, maxX, maxY); + this.clip = clip; + this.geometryFactory = geometryFactory; + } + + /** + * Clips a given line string against the clippin polygon. The + * result is stored in the given list of line strings. + * @param lineString The line string to be clipped. + * @param lineStrings The result line string list. + */ + protected void clipLineString( + LineString lineString, + ArrayList<LineString> lineStrings + ) { + if (clip == null) { + lineStrings.add(lineString); + return; + } + + if (!lineString.intersects(clip)) { + return; + } + + try { + Geometry result = lineString.intersection(clip); + + if (result instanceof LineString) { + lineStrings.add((LineString)result); + } + else if (result instanceof MultiLineString) { + MultiLineString mls = (MultiLineString)result; + for (int i = 0, N = mls.getNumGeometries(); i < N; ++i) { + Geometry g = mls.getGeometryN(i); + if (g instanceof LineString) { + lineStrings.add((LineString)g); + } + else { + log.warn("cannot handle geometry " + g.getClass()); + } + } + } + else { + log.warn("cannot handle " + result.getClass()); + } + } + catch (TopologyException te) { + log.error(te.getLocalizedMessage(), te); + lineStrings.add(lineString); + } + } + + /** + * Returns a list of pairs attribute -> multi line string. + * All line strings produced are grouped by there attribute + * which is generated with the given attribute generator. + * @param attributeGenerator The attribute generator. + * @return The list of attribute/multi line strings. + */ + public List<Pair<Object, MultiLineString>> getMultiLineStrings( + AttributeGenerator attributeGenerator + ) { + ArrayList<Pair<Object, MultiLineString>> multiLineStrings = + new ArrayList<Pair<Object, MultiLineString>>(); + + 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> coordinates = new ArrayList<Coordinate>(); + + for (IJKey key: joinPairs()) { + ArrayList<LineString> lineStrings = new ArrayList<LineString>(); + + // process complete + ArrayList<Edge> completeList = complete.get(key); + if (completeList != null) { + for (Edge head: completeList) { + Edge current = head; + do { + coordinates.add(new Coordinate( + m1*(current.a % width) + b1, + m2*(current.a / width) + b2)); + } + while ((current = current.next) != head); + // add head again to close shape + coordinates.add(new Coordinate( + m1*(head.a % width) + b1, + m2*(head.a / width) + b2)); + + clipLineString( + geometryFactory.createLineString( + coordinates.toArray( + new Coordinate[coordinates.size()])), + lineStrings); + + coordinates.clear(); + } + } + + // process open + TIntObjectHashMap map = commonOpen.get(key); + + if (map != null) { + for (Edge head: headList(map)) { + + head = Vectorizer.simplify(head, width); + Edge current = head, last = head; + do { + coordinates.add(new Coordinate( + m1*(current.a % width) + b1, + m2*(current.a / width) + b2)); + last = current; + } + while ((current = current.next) != null); + // add b from tail + coordinates.add(new Coordinate( + m1*(last.b % width) + b1, + m2*(last.b / width) + b2)); + + clipLineString( + geometryFactory.createLineString( + coordinates.toArray( + new Coordinate[coordinates.size()])), + lineStrings); + + coordinates.clear(); + } // for all in common open + } // if map defined for key + + if (!lineStrings.isEmpty()) { + MultiLineString multiLineString = + geometryFactory.createMultiLineString( + lineStrings.toArray( + new LineString[lineStrings.size()])); + lineStrings.clear(); + Object attribute = attributeGenerator != null + ? attributeGenerator.generateAttribute(key.i, key.j) + : key; + multiLineStrings.add(new Pair<Object, MultiLineString>( + attribute, + multiLineString)); + } + } // for all pairs + + return multiLineStrings; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :