/** * Get feature from store and split it. * * @return a list of feature ids that have been updated * @throws Exception when there is an error communication with the datastore of when the arguments * are invalid. In case of an exception the transaction will be rolled back */ private List<FeatureId> splitFeature() throws Exception { List<FeatureId> ids = new ArrayList(); Transaction transaction = new DefaultTransaction("split"); try { store.setTransaction(transaction); // get the feature to split from database using the FID FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(); Filter filter = ff.id(new FeatureIdImpl(this.splitFeatureFID)); FeatureCollection fc = store.getFeatures(filter); SimpleFeature f = null; if (fc.features().hasNext()) { f = (SimpleFeature) fc.features().next(); } else { throw new IllegalArgumentException( String.format( "Feature to split having ID: (%s) not found in datastore.", this.splitFeatureFID)); } String geomAttribute = store.getSchema().getGeometryDescriptor().getLocalName(); Geometry toSplit = (Geometry) f.getProperty(geomAttribute).getValue(); // get split line Geometry splitWith = new WKTReader().read(this.toSplitWithFeature); List<? extends Geometry> geoms = null; switch (toSplit.getDimension()) { case 1: geoms = splitLine(toSplit, splitWith); break; case 2: geoms = splitPolygon(toSplit, splitWith); break; default: throw new IllegalArgumentException( "Unsupported dimension (" + toSplit.getDimension() + ") for splitting, must be 1 or 2"); } ids = handleStrategy(f, geoms, filter, this.store, this.strategy); transaction.commit(); afterSplit(ids); } catch (Exception e) { transaction.rollback(); throw e; } finally { transaction.close(); } if (this.strategy.equalsIgnoreCase("replace")) { ids.add(0, new FeatureIdImpl(this.splitFeatureFID)); } return ids; }
/** * Tests whether this PreparedPolygon intersects a given geometry. * * @param geom the test geometry * @return true if the test geometry intersects */ public boolean intersects(Geometry geom) { /** * Do point-in-poly tests first, since they are cheaper and may result in a quick positive * result. * * <p>If a point of any test components lie in target, result is true */ boolean isInPrepGeomArea = isAnyTestComponentInTarget(geom); if (isInPrepGeomArea) return true; /** If any segments intersect, result is true */ List lineSegStr = SegmentStringUtil.extractSegmentStrings(geom); // only request intersection finder if there are segments (ie NOT for point inputs) if (lineSegStr.size() > 0) { boolean segsIntersect = prepPoly.getIntersectionFinder().intersects(lineSegStr); if (segsIntersect) return true; } /** * If the test has dimension = 2 as well, it is necessary to test for proper inclusion of the * target. Since no segments intersect, it is sufficient to test representative points. */ if (geom.getDimension() == 2) { // TODO: generalize this to handle GeometryCollections boolean isPrepGeomInArea = isAnyTargetComponentInAreaTest(geom, prepPoly.getRepresentativePoints()); if (isPrepGeomInArea) return true; } return false; }
/** * Extract the coordinate arrays for a geometry into a List. * * @param g the Geometry to extract from * @param coordArrayList the List to add the coordinate arrays to * @param orientPolygons whether or not the arrays in the List should be oriented (clockwise for * the shell, counterclockwise for the holes) */ public static void addCoordinateArrays(Geometry g, boolean orientPolygons, List coordArrayList) { if (g.getDimension() <= 0) { return; } else if (g instanceof LineString) { LineString l = (LineString) g; coordArrayList.add(l.getCoordinates()); } else if (g instanceof Polygon) { Polygon poly = (Polygon) g; Coordinate[] shell = poly.getExteriorRing().getCoordinates(); if (orientPolygons) { shell = ensureOrientation(shell, CGAlgorithms.CLOCKWISE); } coordArrayList.add(shell); for (int i = 0; i < poly.getNumInteriorRing(); i++) { Coordinate[] hole = poly.getInteriorRingN(i).getCoordinates(); if (orientPolygons) { hole = ensureOrientation(hole, CGAlgorithms.COUNTERCLOCKWISE); } coordArrayList.add(hole); } } else if (g instanceof GeometryCollection) { GeometryCollection gc = (GeometryCollection) g; for (int i = 0; i < gc.getNumGeometries(); i++) { addCoordinateArrays(gc.getGeometryN(i), orientPolygons, coordArrayList); } } else { Assert.shouldNeverReachHere("Geometry of type " + g.getClass().getName() + " not handled"); } }
/** * Tests whether this geometry intersects a given geometry. * * @param geom the test geometry * @return true if the test geometry intersects */ public boolean intersects(Geometry geom) { /** If any segments intersect, obviously intersects = true */ List lineSegStr = SegmentStringUtil.extractSegmentStrings(geom); boolean segsIntersect = prepLine.getIntersectionFinder().intersects(lineSegStr); // MD - performance testing // boolean segsIntersect = false; if (segsIntersect) return true; /** For L/L case we are done */ if (geom.getDimension() == 1) return false; /** For L/A case, need to check for proper inclusion of the target in the test */ if (geom.getDimension() == 2 && prepLine.isAnyTargetComponentInTest(geom)) return true; /** For L/P case, need to check if any points lie on line(s) */ if (geom.getDimension() == 0) return isAnyTestPointInTarget(geom); // return prepLine.getGeometry().intersects(geom); return false; }
/** * Gets the AWT {@link Shape} we'll use to represent {@code geom} on the map. * * @param geom The geometry we want to draw. * @param generalize If true we'll perform generalization * @return An AWT Shape instance. */ public Shape getShape(Geometry geom, boolean generalize) { if (generalize) { Rectangle2DDouble rectangle2dDouble = toPixel(geom.getEnvelopeInternal()); if ((rectangle2dDouble.getHeight() <= MAXPIXEL_DISPLAY) && (rectangle2dDouble.getWidth() <= MAXPIXEL_DISPLAY)) { if (geom.getDimension() == 1) { Coordinate[] coords = geom.getCoordinates(); return getShapeWriter() .toShape( geom.getFactory() .createLineString(new Coordinate[] {coords[0], coords[coords.length - 1]})); } else { return rectangle2dDouble; } } } return getShapeWriter().toShape(geom); }
/** * Evaluate the <tt>contains</tt> or <tt>covers</tt> relationship for the given geometry. * * @param geom the test geometry * @return true if the test geometry is contained */ protected boolean eval(Geometry geom) { /** * Do point-in-poly tests first, since they are cheaper and may result in a quick negative * result. * * <p>If a point of any test components does not lie in target, result is false */ boolean isAllInTargetArea = isAllTestComponentsInTarget(geom); if (!isAllInTargetArea) return false; /** * If the test geometry consists of only Points, then it is now sufficient to test if any of * those points lie in the interior of the target geometry. If so, the test is contained. If * not, all points are on the boundary of the area, which implies not contained. */ if (requireSomePointInInterior && geom.getDimension() == 0) { boolean isAnyInTargetInterior = isAnyTestComponentInTargetInterior(geom); return isAnyInTargetInterior; } /** * Check if there is any intersection between the line segments in target and test. In some * important cases, finding a proper interesection implies that the test geometry is NOT * contained. These cases are: * * <ul> * <li>If the test geometry is polygonal * <li>If the target geometry is a single polygon with no holes * <ul> * In both of these cases, a proper intersection implies that there is some portion of * the interior of the test geometry lying outside the target, which means that the test * is not contained. */ boolean properIntersectionImpliesNotContained = isProperIntersectionImpliesNotContainedSituation(geom); // MD - testing only // properIntersectionImpliesNotContained = true; // find all intersection types which exist findAndClassifyIntersections(geom); if (properIntersectionImpliesNotContained && hasProperIntersection) return false; /** * If all intersections are proper (i.e. no non-proper intersections occur) we can conclude that * the test geometry is not contained in the target area, by the Epsilon-Neighbourhood Exterior * Intersection condition. In real-world data this is likely to be by far the most common * situation, since natural data is unlikely to have many exact vertex segment intersections. * Thus this check is very worthwhile, since it avoid having to perform a full topological * check. * * <p>(If non-proper (vertex) intersections ARE found, this may indicate a situation where two * shells touch at a single vertex, which admits the case where a line could cross between the * shells and still be wholely contained in them. */ if (hasSegmentIntersection && !hasNonProperIntersection) return false; /** * If there is a segment intersection and the situation is not one of the ones above, the only * choice is to compute the full topological relationship. This is because contains/covers is * very sensitive to the situation along the boundary of the target. */ if (hasSegmentIntersection) { return fullTopologicalPredicate(geom); // System.out.println(geom); } /** * This tests for the case where a ring of the target lies inside a test polygon - which implies * the exterior of the Target intersects the interior of the Test, and hence the result is false */ if (geom instanceof Polygonal) { // TODO: generalize this to handle GeometryCollections boolean isTargetInTestArea = isAnyTargetComponentInAreaTest(geom, prepPoly.getRepresentativePoints()); if (isTargetInTestArea) return false; } return true; }