package org.osm2world.core.math;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
/**
* converts between own and JTS geometry representations.
*
* When handling three-dimensional coordinates, the y and z information will
* be swapped when converting from or to JTS. JTS uses x and y as 2D
* plane, z as elevation info.
*/
public class JTSConversionUtil {
public static final GeometryFactory GF = new GeometryFactory();
public static final Coordinate vectorXZToJTSCoordinate(VectorXZ v) {
return new Coordinate(v.x, v.z);
}
public static final Coordinate vectorXYZToJTSCoordinate(VectorXYZ v) {
return new Coordinate(v.x, v.z, v.y);
}
public static final VectorXZ vectorXZFromJTSCoordinate(Coordinate c) {
return new VectorXZ(c.x, c.y);
}
public static final VectorXYZ vectorXYZFromJTSCoordinate(Coordinate c) {
return new VectorXYZ(c.x, c.z, c.y);
}
public static LineString lineSegmentXZToJTSLineString(LineSegmentXZ segment) {
Coordinate[] points = {
vectorXZToJTSCoordinate(segment.p1),
vectorXZToJTSCoordinate(segment.p2)
};
return new LineString(new CoordinateArraySequence(points), GF);
}
public static final Polygon polygonXZToJTSPolygon(SimplePolygonXZ polygon) {
List<VectorXZ> vertices = polygon.getVertexLoop();
Coordinate[] array = new Coordinate[vertices.size()];
for (int i = 0; i < array.length; i++) {
VectorXZ vertex = vertices.get(i);
array[i] = vectorXZToJTSCoordinate(vertex);
}
return new Polygon(
new LinearRing(new CoordinateArraySequence(array), GF),
null, GF);
}
public static final PolygonWithHolesXZ
polygonXZFromJTSPolygon(Polygon polygon)
throws InvalidGeometryException {
/* create outer polygon */
SimplePolygonXZ outerPolygon =
polygonXZFromLineString(polygon.getExteriorRing());
/* create holes */
List<SimplePolygonXZ> holes = Collections.emptyList();
if (polygon.getNumInteriorRing() > 0) {
holes = new ArrayList<SimplePolygonXZ>();
for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
holes.add(polygonXZFromLineString(
polygon.getInteriorRingN(i)));
}
}
return new PolygonWithHolesXZ(outerPolygon, holes);
}
private static final SimplePolygonXZ polygonXZFromLineString(LineString lineString) {
List<VectorXZ> vertexLoop = new ArrayList<VectorXZ>(lineString.getNumPoints());
for (Coordinate coordinate : lineString.getCoordinates()) {
vertexLoop.add(vectorXZFromJTSCoordinate(coordinate));
}
return new SimplePolygonXZ(vertexLoop);
}
public static final Collection<PolygonWithHolesXZ>
polygonsXZFromJTSGeometry(Geometry geometry) {
Collection<PolygonWithHolesXZ> result =
new ArrayList<PolygonWithHolesXZ>(1);
if (geometry instanceof Polygon) {
if (geometry.getNumPoints() > 2) {
try {
result.add(polygonXZFromJTSPolygon((Polygon)geometry));
} catch (InvalidGeometryException e) {
//don't add the broken polygon
}
}
} else if (geometry instanceof GeometryCollection) {
GeometryCollection collection = (GeometryCollection)geometry;
for (int i = 0; i < collection.getNumGeometries(); i++) {
result.addAll(polygonsXZFromJTSGeometry(collection.getGeometryN(i)));
}
} else {
System.err.println("unhandled geometry type: " + geometry.getClass());
}
return result;
}
}