/** * Insert nodes for all intersections on the edges of a Geometry. * Label the created nodes the same as the edge label if they do not already have a label. * This allows nodes created by either self-intersections or * mutual intersections to be labelled. * Endpoint nodes will already be labelled from when they were inserted. */ private void computeIntersectionNodes(int argIndex) { for (Iterator i = this.arg[argIndex].getEdgeIterator(); i.hasNext(); ) { Edge e = (Edge) i.next(); int eLoc = e.getLabel().getLocation(argIndex); for (Iterator eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext(); ) { EdgeIntersection ei = (EdgeIntersection) eiIt.next(); RelateNode n = (RelateNode) this.nodes.addNode(ei.coord); if (eLoc == Location.BOUNDARY) { n.setLabelBoundary(argIndex); } else { if (n.getLabel().isNull(argIndex)) { n.setLabel(argIndex, Location.INTERIOR); } } //Debug.println(n); } } }
/** * For all intersections on the edges of a Geometry, * label the corresponding node IF it doesn't already have a label. * This allows nodes created by either self-intersections or * mutual intersections to be labelled. * Endpoint nodes will already be labelled from when they were inserted. */ private void labelIntersectionNodes(int argIndex) { for (Iterator i = this.arg[argIndex].getEdgeIterator(); i.hasNext(); ) { Edge e = (Edge) i.next(); int eLoc = e.getLabel().getLocation(argIndex); for (Iterator eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext(); ) { EdgeIntersection ei = (EdgeIntersection) eiIt.next(); RelateNode n = (RelateNode) this.nodes.find(ei.coord); if (n.getLabel().isNull(argIndex)) { if (eLoc == Location.BOUNDARY) { n.setLabelBoundary(argIndex); } else { n.setLabel(argIndex, Location.INTERIOR); } } //n.print(System.out); } } }
/** * Insert nodes for all intersections on the edges of a Geometry. * Label the created nodes the same as the edge label if they do not already have a label. * This allows nodes created by either self-intersections or * mutual intersections to be labelled. * Endpoint nodes will already be labelled from when they were inserted. * <p> * Precondition: edge intersections have been computed. */ public void computeIntersectionNodes(GeometryGraph geomGraph, int argIndex) { for (Iterator edgeIt = geomGraph.getEdgeIterator(); edgeIt.hasNext(); ) { Edge e = (Edge) edgeIt.next(); int eLoc = e.getLabel().getLocation(argIndex); for (Iterator eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext(); ) { EdgeIntersection ei = (EdgeIntersection) eiIt.next(); RelateNode n = (RelateNode) this.nodes.addNode(ei.coord); if (eLoc == Location.BOUNDARY) { n.setLabelBoundary(argIndex); } else { if (n.getLabel().isNull(argIndex)) { n.setLabel(argIndex, Location.INTERIOR); } } //Debug.println(n); } } }
/** * This computes the overall edge label for the set of * edges in this EdgeStubBundle. It essentially merges * the ON and side labels for each edge. These labels must be compatible */ @Override public void computeLabel(BoundaryNodeRule boundaryNodeRule) { // create the label. If any of the edges belong to areas, // the label must be an area label boolean isArea = false; for (Iterator it = this.iterator(); it.hasNext(); ) { EdgeEnd e = (EdgeEnd) it.next(); if (e.getLabel().isArea()) { isArea = true; } } if (isArea) { this.label = new Label(Location.NONE, Location.NONE, Location.NONE); } else { this.label = new Label(Location.NONE); } // compute the On label, and the side labels if present for (int i = 0; i < 2; i++) { this.computeLabelOn(i, boundaryNodeRule); if (isArea) { this.computeLabelSides(i); } } }
private void visitInteriorRing(LineString ring, PlanarGraph graph) { Coordinate[] pts = ring.getCoordinates(); Coordinate pt0 = pts[0]; /** * Find first point in coord list different to initial point. * Need special check since the first point may be repeated. */ Coordinate pt1 = findDifferentPoint(pts, pt0); Edge e = graph.findEdgeInSameDirection(pt0, pt1); DirectedEdge de = (DirectedEdge) graph.findEdgeEnd(e); DirectedEdge intDe = null; if (de.getLabel().getLocation(0, Position.RIGHT) == Location.INTERIOR) { intDe = de; } else if (de.getSym().getLabel().getLocation(0, Position.RIGHT) == Location.INTERIOR) { intDe = de.getSym(); } Assert.isTrue(intDe != null, "unable to find dirEdge with Interior on RHS"); this.visitLinkedDirectedEdges(intDe); }
/** * This method will handle arguments of Location.NONE correctly * * @return true if the locations correspond to the opCode */ public static boolean isResultOfOp(int loc0, int loc1, int opCode) { if (loc0 == Location.BOUNDARY) { loc0 = Location.INTERIOR; } if (loc1 == Location.BOUNDARY) { loc1 = Location.INTERIOR; } switch (opCode) { case INTERSECTION: return loc0 == Location.INTERIOR && loc1 == Location.INTERIOR; case UNION: return loc0 == Location.INTERIOR || loc1 == Location.INTERIOR; case DIFFERENCE: return loc0 == Location.INTERIOR && loc1 != Location.INTERIOR; case SYMDIFFERENCE: return (loc0 == Location.INTERIOR && loc1 != Location.INTERIOR) || (loc0 != Location.INTERIOR && loc1 == Location.INTERIOR); } return false; }
/** * Computes the topological relationship ({@link Location}) of a single point * to a Geometry. * It handles both single-element * and multi-element Geometries. * The algorithm for multi-part Geometries * takes into account the SFS Boundary Determination Rule. * * @return the {@link Location} of the point relative to the input Geometry */ public int locate(Coordinate p, Geometry geom) { if (geom.isEmpty()) { return Location.EXTERIOR; } if (geom instanceof LineString) { return this.locate(p, (LineString) geom); } else if (geom instanceof Polygon) { return this.locate(p, (Polygon) geom); } this.isIn = false; this.numBoundaries = 0; this.computeLocation(p, geom); if (this.boundaryRule.isInBoundary(this.numBoundaries)) { return Location.BOUNDARY; } if (this.numBoundaries > 0 || this.isIn) { return Location.INTERIOR; } return Location.EXTERIOR; }
private int locate(Coordinate p, LineString l) { // bounding-box check if (!l.getEnvelopeInternal().intersects(p)) { return Location.EXTERIOR; } Coordinate[] pt = l.getCoordinates(); if (!l.isClosed()) { if (p.equals(pt[0]) || p.equals(pt[pt.length - 1])) { return Location.BOUNDARY; } } if (CGAlgorithms.isOnLine(p, pt)) { return Location.INTERIOR; } return Location.EXTERIOR; }
/** * Compute the labelling for all dirEdges in this star, as well * as the overall labelling */ @Override public void computeLabelling(GeometryGraph[] geom) { //Debug.print(this); super.computeLabelling(geom); // determine the overall labelling for this DirectedEdgeStar // (i.e. for the node it is based at) this.label = new Label(Location.NONE); for (Iterator it = this.iterator(); it.hasNext(); ) { EdgeEnd ee = (EdgeEnd) it.next(); Edge e = ee.getEdge(); Label eLabel = e.getLabel(); for (int i = 0; i < 2; i++) { int eLoc = eLabel.getLocation(i); if (eLoc == Location.INTERIOR || eLoc == Location.BOUNDARY) { this.label.setLocation(i, Location.INTERIOR); } } } //Debug.print(this); }
/** * Updates the label of a node to BOUNDARY, * obeying the mod-2 boundaryDetermination rule. */ public void setLabelBoundary(int argIndex) { if (this.label == null) { return; } // determine the current location for the point (if any) int loc = Location.NONE; if (this.label != null) { loc = this.label.getLocation(argIndex); } // flip the loc int newLoc; switch (loc) { case Location.BOUNDARY: newLoc = Location.INTERIOR; break; case Location.INTERIOR: newLoc = Location.BOUNDARY; break; default: newLoc = Location.BOUNDARY; break; } this.label.setLocation(argIndex, newLoc); }
/** * This method implements the Boundary Determination Rule * for determining whether * a component (node or edge) that appears multiple times in elements * of a MultiGeometry is in the boundary or the interior of the Geometry * <br> * The SFS uses the "Mod-2 Rule", which this function implements * <br> * An alternative (and possibly more intuitive) rule would be * the "At Most One Rule": * isInBoundary = (componentCount == 1) */ /* public static boolean isInBoundary(int boundaryCount) { // the "Mod-2 Rule" return boundaryCount % 2 == 1; } public static int determineBoundary(int boundaryCount) { return isInBoundary(boundaryCount) ? Location.BOUNDARY : Location.INTERIOR; } */ public static int determineBoundary(BoundaryNodeRule boundaryNodeRule, int boundaryCount) { return boundaryNodeRule.isInBoundary(boundaryCount) ? Location.BOUNDARY : Location.INTERIOR; }
private void addPolygon(Polygon p) { this.addPolygonRing( (LinearRing) p.getExteriorRing(), Location.EXTERIOR, Location.INTERIOR); for (int i = 0; i < p.getNumInteriorRing(); i++) { LinearRing hole = (LinearRing) p.getInteriorRingN(i); // Holes are topologically labelled opposite to the shell, since // the interior of the polygon lies on their opposite side // (on the left, if the hole is oriented CW) this.addPolygonRing( hole, Location.INTERIOR, Location.EXTERIOR); } }
private void addLineString(LineString line) { Coordinate[] coord = CoordinateArrays.removeRepeatedPoints(line.getCoordinates()); if (coord.length < 2) { this.hasTooFewPoints = true; this.invalidPoint = coord[0]; return; } // add the edge for the LineString // line edges do not have locations for their left and right sides Edge e = new Edge(coord, new Label(this.argIndex, Location.INTERIOR)); this.lineEdgeMap.put(line, e); this.insertEdge(e); /** * Add the boundary points of the LineString, if any. * Even if the LineString is closed, add both points as if they were endpoints. * This allows for the case that the node already exists and is a boundary point. */ Assert.isTrue(coord.length >= 2, "found LineString with single point"); this.insertBoundaryPoint(this.argIndex, coord[0]); this.insertBoundaryPoint(this.argIndex, coord[coord.length - 1]); }
/** * Adds candidate boundary points using the current {@link BoundaryNodeRule}. * This is used to add the boundary * points of dim-1 geometries (Curves/MultiCurves). */ private void insertBoundaryPoint(int argIndex, Coordinate coord) { Node n = this.nodes.addNode(coord); // nodes always have labels Label lbl = n.getLabel(); // the new point to insert is on a boundary int boundaryCount = 1; // determine the current location for the point (if any) int loc = Location.NONE; loc = lbl.getLocation(argIndex, Position.ON); if (loc == Location.BOUNDARY) { boundaryCount++; } // determine the boundary status of the point according to the Boundary Determination Rule int newLoc = determineBoundary(this.boundaryNodeRule, boundaryCount); lbl.setLocation(argIndex, newLoc); }
/** * merge updates only the NULL attributes of this object * with the attributes of another. */ public void merge(TopologyLocation gl) { // if the src is an Area label & and the dest is not, increase the dest to be an Area if (gl.location.length > this.location.length) { int[] newLoc = new int[3]; newLoc[Position.ON] = this.location[Position.ON]; newLoc[Position.LEFT] = Location.NONE; newLoc[Position.RIGHT] = Location.NONE; this.location = newLoc; } for (int i = 0; i < this.location.length; i++) { if (this.location[i] == Location.NONE && i < gl.location.length) { this.location[i] = gl.location[i]; } } }
/** * Insert nodes for all intersections on the edges of a Geometry. * Label the created nodes the same as the edge label if they do not already have a label. * This allows nodes created by either self-intersections or * mutual intersections to be labelled. * Endpoint nodes will already be labelled from when they were inserted. */ private void computeIntersectionNodes(int argIndex) { for (Iterator i = arg[argIndex].getEdgeIterator(); i.hasNext(); ) { Edge e = (Edge) i.next(); int eLoc = e.getLabel().getLocation(argIndex); for (Iterator eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext(); ) { EdgeIntersection ei = (EdgeIntersection) eiIt.next(); RelateNode n = (RelateNode) nodes.addNode(ei.coord); if (eLoc == Location.BOUNDARY) n.setLabelBoundary(argIndex); else { if (n.getLabel().isNull(argIndex)) n.setLabel(argIndex, Location.INTERIOR); } //Debug.println(n); } } }
/** * For all intersections on the edges of a Geometry, * label the corresponding node IF it doesn't already have a label. * This allows nodes created by either self-intersections or * mutual intersections to be labelled. * Endpoint nodes will already be labelled from when they were inserted. */ private void labelIntersectionNodes(int argIndex) { for (Iterator i = arg[argIndex].getEdgeIterator(); i.hasNext(); ) { Edge e = (Edge) i.next(); int eLoc = e.getLabel().getLocation(argIndex); for (Iterator eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext(); ) { EdgeIntersection ei = (EdgeIntersection) eiIt.next(); RelateNode n = (RelateNode) nodes.find(ei.coord); if (n.getLabel().isNull(argIndex)) { if (eLoc == Location.BOUNDARY) n.setLabelBoundary(argIndex); else n.setLabel(argIndex, Location.INTERIOR); } //n.print(System.out); } } }
/** * Insert nodes for all intersections on the edges of a Geometry. * Label the created nodes the same as the edge label if they do not already have a label. * This allows nodes created by either self-intersections or * mutual intersections to be labelled. * Endpoint nodes will already be labelled from when they were inserted. * <p/> * Precondition: edge intersections have been computed. */ public void computeIntersectionNodes(GeometryGraph geomGraph, int argIndex) { for (Iterator edgeIt = geomGraph.getEdgeIterator(); edgeIt.hasNext(); ) { Edge e = (Edge) edgeIt.next(); int eLoc = e.getLabel().getLocation(argIndex); for (Iterator eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext(); ) { EdgeIntersection ei = (EdgeIntersection) eiIt.next(); RelateNode n = (RelateNode) nodes.addNode(ei.coord); if (eLoc == Location.BOUNDARY) n.setLabelBoundary(argIndex); else { if (n.getLabel().isNull(argIndex)) n.setLabel(argIndex, Location.INTERIOR); } //Debug.println(n); } } }
/** * This computes the overall edge label for the set of * edges in this EdgeStubBundle. It essentially merges * the ON and side labels for each edge. These labels must be compatible */ public void computeLabel(BoundaryNodeRule boundaryNodeRule) { // create the label. If any of the edges belong to areas, // the label must be an area label boolean isArea = false; for (Iterator it = iterator(); it.hasNext(); ) { EdgeEnd e = (EdgeEnd) it.next(); if (e.getLabel().isArea()) isArea = true; } if (isArea) label = new Label(Location.NONE, Location.NONE, Location.NONE); else label = new Label(Location.NONE); // compute the On label, and the side labels if present for (int i = 0; i < 2; i++) { computeLabelOn(i, boundaryNodeRule); if (isArea) computeLabelSides(i); } }
/** * Compute the labelling for all dirEdges in this star, as well * as the overall labelling */ public void computeLabelling(GeometryGraph[] geom) { //Debug.print(this); super.computeLabelling(geom); // determine the overall labelling for this DirectedEdgeStar // (i.e. for the node it is based at) label = new Label(Location.NONE); for (Iterator it = iterator(); it.hasNext(); ) { EdgeEnd ee = (EdgeEnd) it.next(); Edge e = ee.getEdge(); Label eLabel = e.getLabel(); for (int i = 0; i < 2; i++) { int eLoc = eLabel.getLocation(i); if (eLoc == Location.INTERIOR || eLoc == Location.BOUNDARY) label.setLocation(i, Location.INTERIOR); } } //Debug.print(this); }
/** * Updates the label of a node to BOUNDARY, * obeying the mod-2 boundaryDetermination rule. */ public void setLabelBoundary(int argIndex) { if (label == null) return; // determine the current location for the point (if any) int loc = Location.NONE; if (label != null) loc = label.getLocation(argIndex); // flip the loc int newLoc; switch (loc) { case Location.BOUNDARY: newLoc = Location.INTERIOR; break; case Location.INTERIOR: newLoc = Location.BOUNDARY; break; default: newLoc = Location.BOUNDARY; break; } label.setLocation(argIndex, newLoc); }
public void add(Label lbl) { for (int i = 0; i < 2; i++) { for (int j = 1; j < 3; j++) { int loc = lbl.getLocation(i, j); if (loc == Location.EXTERIOR || loc == Location.INTERIOR) { // initialize depth if it is null, otherwise add this location value if (isNull(i, j)) { depth[i][j] = depthAtLocation(loc); } else depth[i][j] += depthAtLocation(loc); } } } }
/** * merge updates only the NULL attributes of this object * with the attributes of another. */ public void merge(TopologyLocation gl) { // if the src is an Area label & and the dest is not, increase the dest to be an Area if (gl.location.length > location.length) { int [] newLoc = new int[3]; newLoc[Position.ON] = location[Position.ON]; newLoc[Position.LEFT] = Location.NONE; newLoc[Position.RIGHT] = Location.NONE; location = newLoc; } for (int i = 0; i < location.length; i++) { if (location[i] == Location.NONE && i < gl.location.length) location[i] = gl.location[i]; } }
/** * This is ten times faster than the absolutely correct * version above, and it's only off by an average of 1%. * Note that the first argument MUST be rectangular, or * your results will be meaningless. */ public static double fastGetSharedAreaRatio (Geometry geom1, Geometry geom2) { Envelope env1 = geom1.getEnvelopeInternal(); if ((SimplePointInAreaLocator.locate(new Coordinate(env1.getMinX(),env1.getMinY()), geom2) == Location.INTERIOR) && (SimplePointInAreaLocator.locate(new Coordinate(env1.getMaxX(),env1.getMaxY()), geom2) == Location.INTERIOR) && (SimplePointInAreaLocator.locate(new Coordinate(env1.getMaxX(),env1.getMinY()), geom2) == Location.INTERIOR) && (SimplePointInAreaLocator.locate(new Coordinate(env1.getMinX(),env1.getMaxY()), geom2) == Location.INTERIOR)) { // I suppose it is possible for a valid polygon geometry // to contain all four corners and share considerably less // than 100% of its area with the envelope in question. // But if you're that worried about correctness you // shouldn't be using this method in the first place. return 1.0; } double xInc = env1.getWidth() / 9.0; double yInc = env1.getHeight() / 9.0; double x = env1.getMinX(); double y = env1.getMinY(); double ct = 0; for (int i = 0; i < 10; i += 1) { y = env1.getMinY(); for (int j = 0; j < 10; j += 1) { if (SimplePointInAreaLocator.locate(new Coordinate(x,y), geom2) == Location.INTERIOR) { ct += 1; } y += yInc; } x += xInc; } return (ct / 100.0); }
public Geometry union() { PointLocator locater = new PointLocator(); // use a set to eliminate duplicates, as required for union Set exteriorCoords = new TreeSet(); for (int i = 0; i < this.pointGeom.getNumGeometries(); i++) { Point point = (Point) this.pointGeom.getGeometryN(i); Coordinate coord = point.getCoordinate(); int loc = locater.locate(coord, this.otherGeom); if (loc == Location.EXTERIOR) { exteriorCoords.add(coord); } } // if no points are in exterior, return the other geom if (exteriorCoords.size() == 0) { return this.otherGeom; } // make a puntal geometry of appropriate size Geometry ptComp = null; Coordinate[] coords = CoordinateArrays.toCoordinateArray(exteriorCoords); if (coords.length == 1) { ptComp = this.geomFact.createPoint(coords[0]); } else { ptComp = this.geomFact.createMultiPoint(coords); } // add point component to the other geometry return GeometryCombiner.combine(ptComp, this.otherGeom); }
/** * If the Geometries are disjoint, we need to enter their dimension and * boundary dimension in the Ext rows in the IM */ private void computeDisjointIM(IntersectionMatrix im) { Geometry ga = this.arg[0].getGeometry(); if (!ga.isEmpty()) { im.set(Location.INTERIOR, Location.EXTERIOR, ga.getDimension()); im.set(Location.BOUNDARY, Location.EXTERIOR, ga.getBoundaryDimension()); } Geometry gb = this.arg[1].getGeometry(); if (!gb.isEmpty()) { im.set(Location.EXTERIOR, Location.INTERIOR, gb.getDimension()); im.set(Location.EXTERIOR, Location.BOUNDARY, gb.getBoundaryDimension()); } }
/** * Label an isolated edge of a graph with its relationship to the target geometry. * If the target has dim 2 or 1, the edge can either be in the interior or the exterior. * If the target has dim 0, the edge must be in the exterior */ private void labelIsolatedEdge(Edge e, int targetIndex, Geometry target) { // this won't work for GeometryCollections with both dim 2 and 1 geoms if (target.getDimension() > 0) { // since edge is not in boundary, may not need the full generality of PointLocator? // Possibly should use ptInArea locator instead? We probably know here // that the edge does not touch the bdy of the target Geometry int loc = this.ptLocator.locate(e.getCoordinate(), target); e.getLabel().setAllLocations(targetIndex, loc); } else { e.getLabel().setAllLocations(targetIndex, Location.EXTERIOR); } //System.out.println(e.getLabel()); }
/** * To compute the summary label for a side, the algorithm is: * FOR all edges * IF any edge's location is INTERIOR for the side, side location = INTERIOR * ELSE IF there is at least one EXTERIOR attribute, side location = EXTERIOR * ELSE side location = NULL * <br> * Note that it is possible for two sides to have apparently contradictory information * i.e. one edge side may indicate that it is in the interior of a geometry, while * another edge side may indicate the exterior of the same geometry. This is * not an incompatibility - GeometryCollections may contain two Polygons that touch * along an edge. This is the reason for Interior-primacy rule above - it * results in the summary label having the Geometry interior on <b>both</b> sides. */ private void computeLabelSide(int geomIndex, int side) { for (Iterator it = this.iterator(); it.hasNext(); ) { EdgeEnd e = (EdgeEnd) it.next(); if (e.getLabel().isArea()) { int loc = e.getLabel().getLocation(geomIndex, side); if (loc == Location.INTERIOR) { this.label.setLocation(geomIndex, side, Location.INTERIOR); return; } else if (loc == Location.EXTERIOR) { this.label.setLocation(geomIndex, side, Location.EXTERIOR); } } } }
private void setInteriorEdgesInResult(PlanarGraph graph) { for (Object o : graph.getEdgeEnds()) { DirectedEdge de = (DirectedEdge) o; if (de.getLabel().getLocation(0, Position.RIGHT) == Location.INTERIOR) { de.setInResult(true); } } }
private boolean checkValid(int overlayOp, Coordinate pt) { this.location[0] = this.locFinder[0].getLocation(pt); this.location[1] = this.locFinder[1].getLocation(pt); this.location[2] = this.locFinder[2].getLocation(pt); /** * If any location is on the Boundary, can't deduce anything, so just return true */ if (hasLocation(this.location, Location.BOUNDARY)) { return true; } return this.isValidResult(overlayOp, this.location); }
private boolean isValidResult(int overlayOp, int[] location) { boolean expectedInterior = OverlayOp.isResultOfOp(location[0], location[1], overlayOp); boolean resultInInterior = (location[2] == Location.INTERIOR); // MD use simpler: boolean isValid = (expectedInterior == resultInInterior); boolean isValid = expectedInterior == resultInInterior; if (!isValid) { this.reportResult(overlayOp, location, expectedInterior); } return isValid; }
private void reportResult(int overlayOp, int[] location, boolean expectedInterior) { System.out.println( "Overlay result invalid - A:" + Location.toLocationSymbol(location[0]) + " B:" + Location.toLocationSymbol(location[1]) + " expected:" + (expectedInterior ? 'i' : 'e') + " actual:" + Location.toLocationSymbol(location[2]) ); }
public int getLocation(Coordinate pt) { if (this.isWithinToleranceOfBoundary(pt)) { return Location.BOUNDARY; } /* double dist = linework.distance(point); // if point is close to boundary, it is considered to be on the boundary if (dist < tolerance) return Location.BOUNDARY; */ // now we know point must be clearly inside or outside geometry, so return actual location value return this.ptLocator.locate(pt, this.g); }
/** * @return true if the coord is located in the interior or boundary of * a geometry in the list. */ private boolean isCovered(Coordinate coord, List geomList) { for (Object aGeomList : geomList) { Geometry geom = (Geometry) aGeomList; int loc = this.ptLocator.locate(coord, geom); if (loc != Location.EXTERIOR) { return true; } } return false; }
/** * Compute the change in depth as an edge is crossed from R to L */ private static int depthDelta(Label label) { int lLoc = label.getLocation(0, Position.LEFT); int rLoc = label.getLocation(0, Position.RIGHT); if (lLoc == Location.INTERIOR && rLoc == Location.EXTERIOR) { return 1; } else if (lLoc == Location.EXTERIOR && rLoc == Location.INTERIOR) { return -1; } return 0; }
/** * Creates a {@link SegmentString} for a coordinate list which is a raw offset curve, * and adds it to the list of buffer curves. * The SegmentString is tagged with a Label giving the topology of the curve. * The curve may be oriented in either direction. * If the curve is oriented CW, the locations will be: * <br>Left: Location.EXTERIOR * <br>Right: Location.INTERIOR */ private void addCurve(Coordinate[] coord, int leftLoc, int rightLoc) { // don't add null or trivial curves if (coord == null || coord.length < 2) { return; } // add the edge for a coordinate list which is a raw offset curve SegmentString e = new NodedSegmentString(coord, new Label(0, Location.BOUNDARY, leftLoc, rightLoc)); this.curveList.add(e); }