use of org.locationtech.jts.geom.Polygon in project OpenTripPlanner by opentripplanner.
the class WalkableAreaBuilder method toJTSPolygon.
private Polygon toJTSPolygon(VLPolygon visibilityPolygon) {
if (visibilityPolygon.vertices.isEmpty()) {
return null;
}
// incomprehensibly, visilibity's routines for figuring out point-polygon containment are
// too broken
// to use here, so we have to fall back to JTS.
Coordinate[] coordinates = new Coordinate[visibilityPolygon.n() + 1];
for (int p = 0; p < coordinates.length; ++p) {
VLPoint vlPoint = visibilityPolygon.get(p);
coordinates[p] = new Coordinate(vlPoint.x, vlPoint.y);
}
LinearRing shell = GeometryUtils.getGeometryFactory().createLinearRing(coordinates);
Polygon poly = GeometryUtils.getGeometryFactory().createPolygon(shell, new LinearRing[0]);
return poly;
}
use of org.locationtech.jts.geom.Polygon in project OpenTripPlanner by opentripplanner.
the class DelaunayIsolineBuilder method punchHoles.
@SuppressWarnings("unchecked")
private final List<Polygon> punchHoles(List<LinearRing> rings) {
List<Polygon> shells = new ArrayList<Polygon>(rings.size());
List<LinearRing> holes = new ArrayList<LinearRing>(rings.size() / 2);
// 1. Split the polygon list in two: shells and holes (CCW and CW)
for (LinearRing ring : rings) {
if (CGAlgorithms.signedArea(ring.getCoordinateSequence()) > 0.0)
holes.add(ring);
else
shells.add(geometryFactory.createPolygon(ring));
}
// 2. Sort the shells based on number of points to optimize step 3.
Collections.sort(shells, new Comparator<Polygon>() {
@Override
public int compare(Polygon o1, Polygon o2) {
return o2.getNumPoints() - o1.getNumPoints();
}
});
for (Polygon shell : shells) {
shell.setUserData(new ArrayList<LinearRing>());
}
// 3. For each hole, determine which shell it fits in.
int nHolesFailed = 0;
for (LinearRing hole : holes) {
outer: {
// Probably most of the time, the first shell will be the one
for (Polygon shell : shells) {
if (shell.contains(hole)) {
((List<LinearRing>) shell.getUserData()).add(hole);
break outer;
}
}
// This should not happen, but do not break bad here
// as loosing a hole is not critical, we still have
// sensible data to return.
nHolesFailed += 1;
}
}
if (nHolesFailed > 0) {
LOG.error("Could not find a shell for {} holes.", nHolesFailed);
}
// 4. Build the list of punched polygons
List<Polygon> punched = new ArrayList<Polygon>(shells.size());
for (Polygon shell : shells) {
List<LinearRing> shellHoles = ((List<LinearRing>) shell.getUserData());
punched.add(geometryFactory.createPolygon((LinearRing) (shell.getExteriorRing()), shellHoles.toArray(new LinearRing[shellHoles.size()])));
}
return punched;
}
use of org.locationtech.jts.geom.Polygon in project OpenTripPlanner by opentripplanner.
the class DelaunayIsolineBuilder method computeIsoline.
@Override
public Geometry computeIsoline(TZ z0) {
Queue<DelaunayEdge<TZ>> processQ = new ArrayDeque<DelaunayEdge<TZ>>(triangulation.edgesCount());
for (DelaunayEdge<TZ> e : triangulation.edges()) {
e.setProcessed(false);
processQ.add(e);
}
if (debug)
generateDebugGeometry(z0);
List<LinearRing> rings = new ArrayList<LinearRing>();
while (!processQ.isEmpty()) {
DelaunayEdge<TZ> e = processQ.remove();
if (e.isProcessed())
continue;
e.setProcessed(true);
int cut = zMetric.cut(e.getA().getZ(), e.getB().getZ(), z0);
if (cut == 0) {
// While, next edge
continue;
}
List<Coordinate> polyPoints = new ArrayList<Coordinate>();
boolean ccw = cut > 0;
while (true) {
// Add a point to polyline
Coordinate cA = e.getA().getCoordinates();
Coordinate cB = e.getB().getCoordinates();
double k = zMetric.interpolate(e.getA().getZ(), e.getB().getZ(), z0);
Coordinate cC = new Coordinate(cA.x * (1.0 - k) + cB.x * k, cA.y * (1.0 - k) + cB.y * k);
polyPoints.add(cC);
e.setProcessed(true);
DelaunayEdge<TZ> E1 = e.getEdge1(ccw);
DelaunayEdge<TZ> E2 = e.getEdge2(ccw);
int cut1 = E1 == null ? 0 : zMetric.cut(E1.getA().getZ(), E1.getB().getZ(), z0);
int cut2 = E2 == null ? 0 : zMetric.cut(E2.getA().getZ(), E2.getB().getZ(), z0);
boolean ok1 = cut1 != 0 && !E1.isProcessed();
boolean ok2 = cut2 != 0 && !E2.isProcessed();
if (ok1) {
e = E1;
ccw = cut1 > 0;
} else if (ok2) {
e = E2;
ccw = cut2 > 0;
} else {
// This must be the end of the polyline...
break;
}
}
// Close the polyline
polyPoints.add(polyPoints.get(0));
if (polyPoints.size() > 5) {
// If the ring is smaller than 4 points do not add it,
// that will remove too small islands or holes.
LinearRing ring = geometryFactory.createLinearRing(polyPoints.toArray(new Coordinate[polyPoints.size()]));
rings.add(ring);
}
}
List<Polygon> retval = punchHoles(rings);
return geometryFactory.createGeometryCollection(retval.toArray(new Geometry[retval.size()]));
}
use of org.locationtech.jts.geom.Polygon in project OpenTripPlanner by opentripplanner.
the class GeometryUtils method convertGeoJsonToJtsGeometry.
/**
* Convert a org.geojson.Xxxx geometry to a JTS geometry.
* Only support Point, Polygon and MultiPolygon for now.
* @param geoJsonGeom
* @return The equivalent JTS geometry.
* @throws UnsupportedGeometryException
*/
public static Geometry convertGeoJsonToJtsGeometry(GeoJsonObject geoJsonGeom) throws UnsupportedGeometryException {
if (geoJsonGeom instanceof org.geojson.Point) {
org.geojson.Point geoJsonPoint = (org.geojson.Point) geoJsonGeom;
return gf.createPoint(new Coordinate(geoJsonPoint.getCoordinates().getLongitude(), geoJsonPoint.getCoordinates().getLatitude()));
} else if (geoJsonGeom instanceof org.geojson.Polygon) {
org.geojson.Polygon geoJsonPolygon = (org.geojson.Polygon) geoJsonGeom;
LinearRing shell = gf.createLinearRing(convertPath(geoJsonPolygon.getExteriorRing()));
LinearRing[] holes = new LinearRing[geoJsonPolygon.getInteriorRings().size()];
int i = 0;
for (List<LngLatAlt> hole : geoJsonPolygon.getInteriorRings()) {
holes[i++] = gf.createLinearRing(convertPath(hole));
}
return gf.createPolygon(shell, holes);
} else if (geoJsonGeom instanceof org.geojson.MultiPolygon) {
org.geojson.MultiPolygon geoJsonMultiPolygon = (org.geojson.MultiPolygon) geoJsonGeom;
Polygon[] jtsPolygons = new Polygon[geoJsonMultiPolygon.getCoordinates().size()];
int i = 0;
for (List<List<LngLatAlt>> geoJsonRings : geoJsonMultiPolygon.getCoordinates()) {
org.geojson.Polygon geoJsonPoly = new org.geojson.Polygon();
for (List<LngLatAlt> geoJsonRing : geoJsonRings) geoJsonPoly.add(geoJsonRing);
jtsPolygons[i++] = (Polygon) convertGeoJsonToJtsGeometry(geoJsonPoly);
}
return gf.createMultiPolygon(jtsPolygons);
} else if (geoJsonGeom instanceof org.geojson.LineString) {
org.geojson.LineString geoJsonLineString = (org.geojson.LineString) geoJsonGeom;
return gf.createLineString(convertPath(geoJsonLineString.getCoordinates()));
} else if (geoJsonGeom instanceof org.geojson.MultiLineString) {
org.geojson.MultiLineString geoJsonMultiLineString = (org.geojson.MultiLineString) geoJsonGeom;
LineString[] jtsLineStrings = new LineString[geoJsonMultiLineString.getCoordinates().size()];
int i = 0;
for (List<LngLatAlt> geoJsonPath : geoJsonMultiLineString.getCoordinates()) {
org.geojson.LineString geoJsonLineString = new org.geojson.LineString(geoJsonPath.toArray(new LngLatAlt[geoJsonPath.size()]));
jtsLineStrings[i++] = (LineString) convertGeoJsonToJtsGeometry(geoJsonLineString);
}
return gf.createMultiLineString(jtsLineStrings);
}
throw new UnsupportedGeometryException(geoJsonGeom.getClass().toString());
}
use of org.locationtech.jts.geom.Polygon in project OpenTripPlanner by opentripplanner.
the class RecursiveGridIsolineBuilder method punchHoles.
@SuppressWarnings("unchecked")
private final List<Polygon> punchHoles(GeometryFactory geomFactory, List<LinearRing> rings) {
List<Polygon> shells = new ArrayList<Polygon>(rings.size());
List<LinearRing> holes = new ArrayList<LinearRing>(rings.size() / 2);
// 1. Split the polygon list in two: shells and holes (CCW and CW)
for (LinearRing ring : rings) {
if (CGAlgorithms.signedArea(ring.getCoordinateSequence()) > 0.0)
holes.add(ring);
else
shells.add(geomFactory.createPolygon(ring));
}
// 2. Sort the shells based on number of points to optimize step 3.
Collections.sort(shells, new Comparator<Polygon>() {
@Override
public int compare(Polygon o1, Polygon o2) {
return o2.getNumPoints() - o1.getNumPoints();
}
});
for (Polygon shell : shells) {
shell.setUserData(new ArrayList<LinearRing>());
}
// 3. For each hole, determine which shell it fits in.
for (LinearRing hole : holes) {
outer: {
// Probably most of the time, the first shell will be the one
for (Polygon shell : shells) {
if (shell.contains(hole)) {
((List<LinearRing>) shell.getUserData()).add(hole);
break outer;
}
}
// This should not happen, but do not break bad here
// as loosing a hole is not critical, we still have
// sensible data to return.
LOG.error("Cannot find fitting shell for a hole!");
}
}
// 4. Build the list of punched polygons
List<Polygon> punched = new ArrayList<Polygon>(shells.size());
for (Polygon shell : shells) {
List<LinearRing> shellHoles = ((List<LinearRing>) shell.getUserData());
punched.add(geomFactory.createPolygon((LinearRing) (shell.getExteriorRing()), shellHoles.toArray(new LinearRing[shellHoles.size()])));
}
return punched;
}
Aggregations