예제 #1
0
 /**
  * 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);
 }
예제 #2
0
  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;
 }
예제 #4
0
 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;
 }
예제 #5
0
  /**
   * 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});
  }
예제 #6
0
  /**
   * 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;
  }
예제 #7
0
 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));
 }
예제 #8
0
 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;
 }
예제 #10
0
  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;
  }
예제 #11
0
  /**
   * 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);
  }
예제 #12
0
  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");
  }
예제 #13
0
  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");
  }
예제 #14
0
    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;
    }
예제 #15
0
  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");
  }
예제 #16
0
  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);
  }
예제 #17
0
  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;
  }
예제 #18
0
 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);
   }
 }
예제 #19
0
  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);
  }
예제 #20
0
 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);
 }
예제 #21
0
 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);
 }
예제 #25
0
 private Coordinate[] createTestPoints(int nPts) {
   Point pt = geomFact.createPoint(new Coordinate(baseX, baseY));
   Geometry circle = pt.buffer(2 * rectSize, nPts / 4);
   return circle.getCoordinates();
 }
예제 #26
0
 public static boolean isEqual(Geometry a, Geometry b) {
   Geometry a2 = normalize(a);
   Geometry b2 = normalize(b);
   return a2.equalsExact(b2);
 }
예제 #27
0
 /**
  * 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});
 }
예제 #28
0
 private void checkValid(Geometry g) {
   if (!g.isValid()) {
     System.out.println("Snapped geometry is invalid");
   }
 }