/** * Buffer polygons by buffering the individual boundary segments and either unioning or * differencing them. * * @param g * @param distance * @return the buffer geometry */ public static Geometry bufferBySegments(Geometry g, double distance) { Geometry segs = LineHandlingFunctions.extractSegments(g); double posDist = Math.abs(distance); Geometry segBuf = bufferByComponents(segs, posDist); if (distance < 0.0) return g.difference(segBuf); return g.union(segBuf); }
private GeometryCollection editGeometryCollection( GeometryCollection collection, GeometryEditorOperation operation) { // first edit the entire collection // MD - not sure why this is done - could just check original collection? GeometryCollection collectionForType = (GeometryCollection) operation.edit(collection, factory); // edit the component geometries ArrayList geometries = new ArrayList(); for (int i = 0; i < collectionForType.getNumGeometries(); i++) { Geometry geometry = edit(collectionForType.getGeometryN(i), operation); if (geometry == null || geometry.isEmpty()) { continue; } geometries.add(geometry); } if (collectionForType.getClass() == MultiPoint.class) { return factory.createMultiPoint((Point[]) geometries.toArray(new Point[] {})); } if (collectionForType.getClass() == MultiLineString.class) { return factory.createMultiLineString((LineString[]) geometries.toArray(new LineString[] {})); } if (collectionForType.getClass() == MultiPolygon.class) { return factory.createMultiPolygon((Polygon[]) geometries.toArray(new Polygon[] {})); } return factory.createGeometryCollection((Geometry[]) geometries.toArray(new Geometry[] {})); }
static double area(Collection geoms) { double area = 0.0; for (Iterator i = geoms.iterator(); i.hasNext(); ) { Geometry geom = (Geometry) i.next(); area += geom.getArea(); } return area; }
private static Polygon findPolygonContaining(Geometry geom, Coordinate pt) { PointLocator locator = new PointLocator(); for (int i = 0; i < geom.getNumGeometries(); i++) { Polygon poly = (Polygon) geom.getGeometryN(i); int loc = locator.locate(pt, poly); if (loc == Location.INTERIOR) return poly; } return null; }
/** * Gets a {@link LineString} which is a minimum diameter * * @return a {@link LineString} which is a minimum diameter */ public LineString getDiameter() { computeMinimumDiameter(); // return empty linestring if no minimum width calculated if (minWidthPt == null) return inputGeom.getFactory().createLineString((Coordinate[]) null); Coordinate basePt = minBaseSeg.project(minWidthPt); return inputGeom.getFactory().createLineString(new Coordinate[] {basePt, minWidthPt}); }
/** * Edit the input {@link Geometry} with the given edit operation. Clients can create subclasses of * {@link GeometryEditorOperation} or {@link CoordinateOperation} to perform required * modifications. * * @param geometry the Geometry to edit * @param operation the edit operation to carry out * @return a new {@link Geometry} which is the result of the editing (which may be empty) */ public Geometry edit(Geometry geometry, GeometryEditorOperation operation) { // nothing to do if (geometry == null) return null; Geometry result = editInternal(geometry, operation); if (isUserDataCopied) { result.setUserData(geometry.getUserData()); } return result; }
public static Geometry componentBuffers(Geometry g, double distance) { List bufs = new ArrayList(); for (Iterator it = new GeometryCollectionIterator(g); it.hasNext(); ) { Geometry comp = (Geometry) it.next(); if (comp instanceof GeometryCollection) continue; bufs.add(comp.buffer(distance)); } return FunctionsUtil.getFactoryOrDefault(g) .createGeometryCollection(GeometryFactory.toGeometryArray(bufs)); }
public static Geometry bufferByChains(Geometry g, double distance, int maxChainSize) { if (maxChainSize <= 0) throw new IllegalArgumentException( "Maximum Chain Size must be specified as an input parameter"); Geometry segs = LineHandlingFunctions.extractChains(g, maxChainSize); double posDist = Math.abs(distance); Geometry segBuf = bufferByComponents(segs, posDist); if (distance < 0.0) return g.difference(segBuf); return g.union(segBuf); }
static List findIntersecting(Collection targetGeoms, Geometry queryGeom) { List result = new ArrayList(); for (Iterator it = targetGeoms.iterator(); it.hasNext(); ) { Geometry test = (Geometry) it.next(); if (test.intersects(queryGeom)) { result.add(test); } } return result; }
public static List extractElements(Geometry geom, boolean skipEmpty) { List elem = new ArrayList(); if (geom == null) return elem; for (int i = 0; i < geom.getNumGeometries(); i++) { Geometry elemGeom = geom.getGeometryN(i); if (skipEmpty && elemGeom.isEmpty()) continue; elem.add(elemGeom); } return elem; }
/** * Gets the minimum rectangular {@link Polygon} which encloses the input geometry. The rectangle * has width equal to the minimum diameter, and a longer length. If the convex hull of the input * is degenerate (a line or point) a {@link LineString} or {@link Point} is returned. * * <p>The minimum rectangle can be used as an extremely generalized representation for the given * geometry. * * @return the minimum rectangle enclosing the input (or a line or point if degenerate) */ public Geometry getMinimumRectangle() { computeMinimumDiameter(); // check if minimum rectangle is degenerate (a point or line segment) if (minWidth == 0.0) { if (minBaseSeg.p0.equals2D(minBaseSeg.p1)) { return inputGeom.getFactory().createPoint(minBaseSeg.p0); } return minBaseSeg.toGeometry(inputGeom.getFactory()); } // deltas for the base segment of the minimum diameter double dx = minBaseSeg.p1.x - minBaseSeg.p0.x; double dy = minBaseSeg.p1.y - minBaseSeg.p0.y; /* double c0 = computeC(dx, dy, minBaseSeg.p0); double c1 = computeC(dx, dy, minBaseSeg.p1); */ double minPara = Double.MAX_VALUE; double maxPara = -Double.MAX_VALUE; double minPerp = Double.MAX_VALUE; double maxPerp = -Double.MAX_VALUE; // compute maxima and minima of lines parallel and perpendicular to base segment for (int i = 0; i < convexHullPts.length; i++) { double paraC = computeC(dx, dy, convexHullPts[i]); if (paraC > maxPara) maxPara = paraC; if (paraC < minPara) minPara = paraC; double perpC = computeC(-dy, dx, convexHullPts[i]); if (perpC > maxPerp) maxPerp = perpC; if (perpC < minPerp) minPerp = perpC; } // compute lines along edges of minimum rectangle LineSegment maxPerpLine = computeSegmentForLine(-dx, -dy, maxPerp); LineSegment minPerpLine = computeSegmentForLine(-dx, -dy, minPerp); LineSegment maxParaLine = computeSegmentForLine(-dy, dx, maxPara); LineSegment minParaLine = computeSegmentForLine(-dy, dx, minPara); // compute vertices of rectangle (where the para/perp max & min lines intersect) Coordinate p0 = maxParaLine.lineIntersection(maxPerpLine); Coordinate p1 = minParaLine.lineIntersection(maxPerpLine); Coordinate p2 = minParaLine.lineIntersection(minPerpLine); Coordinate p3 = maxParaLine.lineIntersection(minPerpLine); LinearRing shell = inputGeom.getFactory().createLinearRing(new Coordinate[] {p0, p1, p2, p3, p0}); return inputGeom.getFactory().createPolygon(shell, null); }
private void checkExpectedEmpty() { // can't check areal features if (input.getDimension() >= 2) return; // can't check positive distances if (distance > 0.0) return; // at this point can expect an empty result if (!result.isEmpty()) { isValid = false; errorMsg = "Result is non-empty"; errorIndicator = result; } report("ExpectedEmpty"); }
private void checkArea() { double inputArea = input.getArea(); double resultArea = result.getArea(); if (distance > 0.0 && inputArea > resultArea) { isValid = false; errorMsg = "Area of positive buffer is smaller than input"; errorIndicator = result; } if (distance < 0.0 && inputArea < resultArea) { isValid = false; errorMsg = "Area of negative buffer is larger than input"; errorIndicator = result; } report("Area"); }
public final Geometry edit(Geometry geometry, GeometryFactory factory) { if (geometry instanceof LinearRing) { return factory.createLinearRing(edit(geometry.getCoordinates(), geometry)); } if (geometry instanceof LineString) { return factory.createLineString(edit(geometry.getCoordinates(), geometry)); } if (geometry instanceof Point) { Coordinate[] newCoordinates = edit(geometry.getCoordinates(), geometry); return factory.createPoint((newCoordinates.length > 0) ? newCoordinates[0] : null); } return geometry; }
private void checkEnvelope() { if (distance < 0.0) return; double padding = distance * MAX_ENV_DIFF_FRAC; if (padding == 0.0) padding = 0.001; Envelope expectedEnv = new Envelope(input.getEnvelopeInternal()); expectedEnv.expandBy(distance); Envelope bufEnv = new Envelope(result.getEnvelopeInternal()); bufEnv.expandBy(padding); if (!bufEnv.contains(expectedEnv)) { isValid = false; errorMsg = "Buffer envelope is incorrect"; errorIndicator = input.getFactory().toGeometry(bufEnv); } report("Envelope"); }
public Geometry combine(Geometry orig, Geometry geom) { List origList = extractElements(orig, true); List geomList = extractElements(geom, true); origList.addAll(geomList); if (origList.size() == 0) { // return a clone of the orig geometry return (Geometry) orig.clone(); } // return the "simplest possible" geometry return geomFactory.buildGeometry(origList); }
private Geometry editInternal(Geometry geometry, GeometryEditorOperation operation) { // if client did not supply a GeometryFactory, use the one from the input Geometry if (factory == null) factory = geometry.getFactory(); if (geometry instanceof GeometryCollection) { return editGeometryCollection((GeometryCollection) geometry, operation); } if (geometry instanceof Polygon) { return editPolygon((Polygon) geometry, operation); } if (geometry instanceof Point) { return operation.edit(geometry, factory); } if (geometry instanceof LineString) { return operation.edit(geometry, factory); } Assert.shouldNeverReachHere("Unsupported Geometry class: " + geometry.getClass().getName()); return null; }
public static void computeDistance(Geometry geom, Coordinate pt, PointPairDistance ptDist) { if (geom instanceof LineString) { computeDistance((LineString) geom, pt, ptDist); } else if (geom instanceof Polygon) { computeDistance((Polygon) geom, pt, ptDist); } else if (geom instanceof GeometryCollection) { GeometryCollection gc = (GeometryCollection) geom; for (int i = 0; i < gc.getNumGeometries(); i++) { Geometry g = gc.getGeometryN(i); computeDistance(g, pt, ptDist); } } else { // assume geom is Point ptDist.setMinimum(geom.getCoordinate(), pt); } }
private void computeWidthConvex(Geometry convexGeom) { // System.out.println("Input = " + geom); if (convexGeom instanceof Polygon) convexHullPts = ((Polygon) convexGeom).getExteriorRing().getCoordinates(); else convexHullPts = convexGeom.getCoordinates(); // special cases for lines or points or degenerate rings if (convexHullPts.length == 0) { minWidth = 0.0; minWidthPt = null; minBaseSeg = null; } else if (convexHullPts.length == 1) { minWidth = 0.0; minWidthPt = convexHullPts[0]; minBaseSeg.p0 = convexHullPts[0]; minBaseSeg.p1 = convexHullPts[0]; } else if (convexHullPts.length == 2 || convexHullPts.length == 3) { minWidth = 0.0; minWidthPt = convexHullPts[0]; minBaseSeg.p0 = convexHullPts[0]; minBaseSeg.p1 = convexHullPts[1]; } else computeConvexRingMinDiameter(convexHullPts); }
public static Geometry replace(Geometry parent, Geometry original, Geometry replacement) { List elem = extractElements(parent, false); Collections.replaceAll(elem, original, replacement); return parent.getFactory().buildGeometry(elem); }
public static Geometry normalize(Geometry g) { Geometry g2 = (Geometry) g.clone(); g2.normalize(); return g2; }
/** * Finds all {@link PreparedGeometry}s which might interact with a query {@link Geometry}. * * @param g the geometry to query by * @return a list of candidate PreparedGeometrys */ public List query(Geometry g) { return index.query(g.getEnvelopeInternal()); }
/** * Inserts a collection of Geometrys into the index. * * @param geoms a collection of Geometrys to insert */ public void insert(Collection geoms) { for (Iterator i = geoms.iterator(); i.hasNext(); ) { Geometry geom = (Geometry) i.next(); index.insert(geom.getEnvelopeInternal(), PreparedGeometryFactory.prepare(geom)); } }
static Geometry createCircle(Coordinate centre, double radius) { Geometry centrePt = geomFact.createPoint(centre); return centrePt.buffer(radius, POLYGON_SIZE); }
private Coordinate[] createTestPoints(int nPts) { Point pt = geomFact.createPoint(new Coordinate(baseX, baseY)); Geometry circle = pt.buffer(2 * rectSize, nPts / 4); return circle.getCoordinates(); }
public static boolean isEqual(Geometry a, Geometry b) { Geometry a2 = normalize(a); Geometry b2 = normalize(b); return a2.equalsExact(b2); }
/** * Gets the segment forming the base of the minimum diameter * * @return the segment forming the base of the minimum diameter */ public LineString getSupportingSegment() { computeMinimumDiameter(); return inputGeom.getFactory().createLineString(new Coordinate[] {minBaseSeg.p0, minBaseSeg.p1}); }
private void checkValid(Geometry g) { if (!g.isValid()) { System.out.println("Snapped geometry is invalid"); } }