/** */ public static double getSharedAreaRatio (Geometry geom1, Geometry geom2) { try { return geom1.intersection(geom2).getArea() / geom1.getArea(); } catch (TopologyException e) { // HACK: there appears to be a bug in JTS, but I can't // reproduce it consistently. Why should computing the // intersection with a MultiPolygon fail when computing // the intersection with each of its constituent Polygons // succeeds? I have no idea, but it does happen. This // seems to fix the problem, though. double result = 0.0; if (geom2 instanceof GeometryCollection) { GeometryCollection gc = (GeometryCollection)geom2; for (int j = 0; j < gc.getNumGeometries(); j += 1) { result += geom1.intersection(gc.getGeometryN(j)).getArea(); } return result / geom1.getArea(); } else { throw e; } } }
/** * JTS 1.14 does not support intersection on a {@link GeometryCollection}. This function works * around this by performing intersection on a flat list of geometry. The resulting list is * pre-filtered for invalid or empty geometry (outside of bounds). Invalid geometry are logged as * errors. * * @param envelope non-list geometry defines bounding area * @param dataGeoms geometry pre-passed through {@link #flatFeatureList(Geometry)} * @return list of geometry from {@code data} intersecting with {@code envelope}. */ private static List<Geometry> flatIntersection(Geometry envelope, List<Geometry> dataGeoms) { final List<Geometry> intersectedGeoms = new ArrayList<>(dataGeoms.size()); Geometry nextIntersected; for (Geometry nextGeom : dataGeoms) { try { // AABB intersection culling if (envelope.getEnvelopeInternal().intersects(nextGeom.getEnvelopeInternal())) { nextIntersected = envelope.intersection(nextGeom); if (!nextIntersected.isEmpty()) { nextIntersected.setUserData(nextGeom.getUserData()); intersectedGeoms.add(nextIntersected); } } } catch (TopologyException ex) { LoggerFactory.getLogger(JtsAdapter.class).error(ex.getMessage(), ex); } } return intersectedGeoms; }
private void bufferReducedPrecision() { // try and compute with decreasing precision for (int precDigits = MAX_PRECISION_DIGITS; precDigits >= 0; precDigits--) { try { this.bufferReducedPrecision(precDigits); } catch (TopologyException ex) { // update the saved exception to reflect the new input geometry this.saveException = ex; // don't propagate the exception - it will be detected by fact that resultGeometry is null } if (this.resultGeometry != null) { return; } } // tried everything - have to bail throw this.saveException; }
public void computeDepths(DirectedEdge de) { int edgeIndex = this.findIndex(de); Label label = de.getLabel(); int startDepth = de.getDepth(Position.LEFT); int targetLastDepth = de.getDepth(Position.RIGHT); // compute the depths from this edge up to the end of the edge array int nextDepth = this.computeDepths(edgeIndex + 1, this.edgeList.size(), startDepth); // compute the depths for the initial part of the array int lastDepth = this.computeDepths(0, edgeIndex, nextDepth); //Debug.print(lastDepth != targetLastDepth, this); //Debug.print(lastDepth != targetLastDepth, "mismatch: " + lastDepth + " / " + targetLastDepth); if (lastDepth != targetLastDepth) { throw new TopologyException("depth mismatch at " + de.getCoordinate()); } //Assert.isTrue(lastDepth == targetLastDepth, "depth mismatch at " + de.getCoordinate()); }
/** * Clip geometry according to buffer given at construct time. This method * can be overridden to change clipping behavior. See also * {@link #clipCovers(Geometry)}. * * @param geometry * @return */ protected Geometry clipGeometry(Geometry geometry) { try { Geometry original = geometry; geometry = clipGeometry.intersection(original); // some times a intersection is returned as an empty geometry. // going via wkt fixes the problem. if (geometry.isEmpty() && original.intersects(clipGeometry)) { Geometry originalViaWkt = new WKTReader().read(original.toText()); geometry = clipGeometry.intersection(originalViaWkt); } return geometry; } catch (TopologyException e) { // could not intersect. original geometry will be used instead. return geometry; } catch (ParseException e1) { // could not encode/decode WKT. original geometry will be used // instead. return geometry; } }
/** * Clips a geometry to a tile. * * @param way * the way * @param geometry * the geometry * @param tileCoordinate * the tile coordinate * @param enlargementInMeters * the bounding box buffer * @return the clipped geometry */ public static Geometry clipToTile(TDWay way, Geometry geometry, TileCoordinate tileCoordinate, int enlargementInMeters) { // clip geometry? Geometry tileBBJTS = null; Geometry ret = null; // create tile bounding box tileBBJTS = tileToJTSGeometry(tileCoordinate.getX(), tileCoordinate.getY(), tileCoordinate.getZoomlevel(), enlargementInMeters); // clip the polygon/ring by intersection with the bounding box of the tile // may throw a TopologyException try { // geometry = OverlayOp.overlayOp(tileBBJTS, geometry, OverlayOp.INTERSECTION); ret = tileBBJTS.intersection(geometry); } catch (TopologyException e) { LOGGER.log(Level.FINE, "JTS cannot clip way, not storing it in data file: " + way.getId(), e); way.setInvalid(true); return null; } return ret; }
/** * Simplifies a geometry using the Douglas Peucker algorithm. * * @param way * the way * @param geometry * the geometry * @param zoomlevel * the zoom level * @param simplificationFactor * the simplification factor * @return the simplified geometry */ public static Geometry simplifyGeometry(TDWay way, Geometry geometry, byte zoomlevel, double simplificationFactor) { Geometry ret = null; Envelope bbox = geometry.getEnvelopeInternal(); // compute maximal absolute latitude (so that we don't need to care if we // are on northern or southern hemisphere) double latMax = Math.max(Math.abs(bbox.getMaxY()), Math.abs(bbox.getMinY())); double deltaLat = MercatorProjection.deltaLat(simplificationFactor, latMax, zoomlevel); try { ret = TopologyPreservingSimplifier.simplify(geometry, deltaLat); } catch (TopologyException e) { LOGGER.log(Level.FINE, "JTS cannot simplify way due to an error, not simplifying way with id: " + way.getId(), e); way.setInvalid(true); return geometry; } return ret; }
/** * This method determines finds a containing shell for all holes * which have not yet been assigned to a shell. * These "free" holes should * all be <b>properly</b> contained in their parent shells, so it is safe to use the * <code>findEdgeRingContaining</code> method. * (This is the case because any holes which are NOT * properly contained (i.e. are connected to their * parent shell) would have formed part of a MaximalEdgeRing * and been handled in a previous step). * * @throws TopologyException if a hole cannot be assigned to a shell */ private void placeFreeHoles(List shellList, List freeHoleList) { for (Object aFreeHoleList : freeHoleList) { EdgeRing hole = (EdgeRing) aFreeHoleList; // only place this hole if it doesn't yet have a shell if (hole.getShell() == null) { EdgeRing shell = this.findEdgeRingContaining(hole, shellList); if (shell == null) { throw new TopologyException("unable to assign hole to a shell", hole.getCoordinate(0)); } // Assert.isTrue(shell != null, "unable to assign hole to a shell"); hole.setShell(shell); } } }
/** * Checks for an intersection and throws * a TopologyException if one is found. * * @throws TopologyException if an intersection is found */ public void checkValid() { this.execute(); if (!this.isValid) { throw new TopologyException(this.getErrorMessage(), this.segInt.getInteriorIntersection()); } }
/** * Fully nodes a list of {@link SegmentString}s, i.e. peforms noding iteratively * until no intersections are found between segments. * Maintains labelling of edges correctly through * the noding. * * @param segStrings a collection of SegmentStrings to be noded * @throws TopologyException if the iterated noding fails to converge. */ @Override public void computeNodes(Collection segStrings) throws TopologyException { int[] numInteriorIntersections = new int[1]; this.nodedSegStrings = segStrings; int nodingIterationCount = 0; int lastNodesCreated = -1; do { this.node(this.nodedSegStrings, numInteriorIntersections); nodingIterationCount++; int nodesCreated = numInteriorIntersections[0]; /** * Fail if the number of nodes created is not declining. * However, allow a few iterations at least before doing this */ //System.out.println("# nodes created: " + nodesCreated); if (lastNodesCreated > 0 && nodesCreated >= lastNodesCreated && nodingIterationCount > this.maxIter) { throw new TopologyException("Iterated noding failed to converge after " + nodingIterationCount + " iterations"); } lastNodesCreated = nodesCreated; } while (lastNodesCreated > 0); //System.out.println("# nodings = " + nodingIterationCount); }
/** * Collect all the points from the DirectedEdges of this ring into a contiguous list */ protected void computePoints(DirectedEdge start) { //System.out.println("buildRing"); this.startDe = start; DirectedEdge de = start; boolean isFirstEdge = true; do { // Assert.isTrue(de != null, "found null Directed Edge"); if (de == null) { throw new TopologyException("Found null DirectedEdge"); } if (de.getEdgeRing() == this) { throw new TopologyException("Directed Edge visited twice during ring-building at " + de.getCoordinate()); } this.edges.add(de); //Debug.println(de); //Debug.println(de.getEdge()); Label label = de.getLabel(); Assert.isTrue(label.isArea()); this.mergeLabel(label); this.addPoints(de.getEdge(), de.isForward(), isFirstEdge); isFirstEdge = false; this.setEdgeRing(de, this); de = this.getNext(de); } while (de != this.startDe); }
public void setDepth(int position, int depthVal) { if (this.depth[position] != -999) { // if (depth[position] != depthVal) { // Debug.print(this); // } if (this.depth[position] != depthVal) { throw new TopologyException("assigned depths do not match", this.getCoordinate()); } //Assert.isTrue(depth[position] == depthVal, "assigned depths do not match at " + getCoordinate()); } this.depth[position] = depthVal; }
@Override protected void updateGeometry() { if (this.coordinates == null) { LinearRing nullLR = new LinearRing(null, new GeometryFactory()); this.geom = new GeometryFactory().createPolygon(nullLR); } else { Coordinate[] newCoords = new Coordinate[coordinates.length+1]; for (int i = 0; i < coordinates.length; i++) { newCoords[i] = coordinates[i]; } newCoords[coordinates.length] = this.coordinates[0]; this.geom = new GeometryFactory().createPolygon(newCoords); if (!this.geom.isValid()) { try { this.geom = this.geom.symDifference(this.geom.getBoundary()); } catch(TopologyException e) { logger.info("Trying to fix GeometricShapeVariable " + this.getVariable().getID()); this.geom = this.geom.buffer(0.1); if (!this.geom.isValid()) { logger.severe("... giving up!"); throw e; } } } } }
/** * Computes which tiles on the given base zoom level need to include the given way (which may be a polygon). * * @param way * the way that is mapped to tiles * @param baseZoomLevel * the base zoom level which is used in the mapping * @param enlargementInMeter * amount of pixels that is used to enlarge the bounding box of the way and the tiles in the mapping * process * @return all tiles on the given base zoom level that need to include the given way, an empty set if no tiles are * matched */ public static Set<TileCoordinate> mapWayToTiles(final TDWay way, final byte baseZoomLevel, final int enlargementInMeter) { if (way == null) { LOGGER.fine("way is null in mapping to tiles"); return Collections.emptySet(); } HashSet<TileCoordinate> matchedTiles = new HashSet<TileCoordinate>(); Geometry wayGeometry = toJTSGeometry(way, !way.isForcePolygonLine()); if (wayGeometry == null) { LOGGER.fine("unable to create geometry from way: " + way.getId()); return matchedTiles; } TileCoordinate[] bbox = getWayBoundingBox(way, baseZoomLevel, enlargementInMeter); // calculate the tile coordinates and the corresponding bounding boxes try { for (int k = bbox[0].getX(); k <= bbox[1].getX(); k++) { for (int l = bbox[0].getY(); l <= bbox[1].getY(); l++) { Geometry bboxGeometry = tileToJTSGeometry(k, l, baseZoomLevel, enlargementInMeter); if (bboxGeometry.intersects(wayGeometry)) { matchedTiles.add(new TileCoordinate(k, l, baseZoomLevel)); } } } } catch (TopologyException e) { LOGGER.log(Level.FINE, "encountered error during mapping of a way to corresponding tiles, way id: " + way.getId()); return Collections.emptySet(); } return matchedTiles; }
/** * Internal conversion method to convert our internal data structure for ways to geometry objects in JTS. It will * care about ways and polygons and will create the right JTS onjects. * * @param way * TDway which will be converted. Null if we were not able to convert the way to a Geometry object. * @param area * true, if the way represents an area, i.e. a polygon instead of a linear ring * @return return Converted way as JTS object. */ private static Geometry toJTSGeometry(TDWay way, boolean area) { if (way.getWayNodes().length < 2) { LOGGER.fine("way has fewer than 2 nodes: " + way.getId()); return null; } Coordinate[] coordinates = new Coordinate[way.getWayNodes().length]; for (int i = 0; i < coordinates.length; i++) { TDNode currentNode = way.getWayNodes()[i]; coordinates[i] = new Coordinate(CoordinatesUtil.microdegreesToDegrees(currentNode.getLongitude()), CoordinatesUtil.microdegreesToDegrees(currentNode.getLatitude())); } Geometry res = null; try { // check for closed polygon if (way.isPolygon()) { if (area) { // polygon res = GEOMETRY_FACTORY.createPolygon(GEOMETRY_FACTORY.createLinearRing(coordinates), null); } else { // linear ring res = GEOMETRY_FACTORY.createLinearRing(coordinates); } } else { res = GEOMETRY_FACTORY.createLineString(coordinates); } } catch (TopologyException e) { LOGGER.log(Level.FINE, "error creating JTS geometry from way: " + way.getId(), e); return null; } return res; }
/** * Fully nodes a list of {@link SegmentString}s, i.e. peforms noding iteratively * until no intersections are found between segments. * Maintains labelling of edges correctly through * the noding. * * @param segStrings a collection of SegmentStrings to be noded * @throws TopologyException if the iterated noding fails to converge. */ public void computeNodes(Collection segStrings) throws TopologyException { int[] numInteriorIntersections = new int[1]; nodedSegStrings = segStrings; int nodingIterationCount = 0; int lastNodesCreated = -1; do { node(nodedSegStrings, numInteriorIntersections); nodingIterationCount++; int nodesCreated = numInteriorIntersections[0]; /** * Fail if the number of nodes created is not declining. * However, allow a few iterations at least before doing this */ //System.out.println("# nodes created: " + nodesCreated); if (lastNodesCreated > 0 && nodesCreated >= lastNodesCreated && nodingIterationCount > maxIter) { throw new TopologyException("Iterated noding failed to converge after " + nodingIterationCount + " iterations"); } lastNodesCreated = nodesCreated; } while (lastNodesCreated > 0); //System.out.println("# nodings = " + nodingIterationCount); }
public void computeDepths(DirectedEdge de) { int edgeIndex = findIndex(de); Label label = de.getLabel(); int startDepth = de.getDepth(Position.LEFT); int targetLastDepth = de.getDepth(Position.RIGHT); // compute the depths from this edge up to the end of the edge array int nextDepth = computeDepths(edgeIndex + 1, edgeList.size(), startDepth); // compute the depths for the initial part of the array int lastDepth = computeDepths(0, edgeIndex, nextDepth); //Debug.print(lastDepth != targetLastDepth, this); //Debug.print(lastDepth != targetLastDepth, "mismatch: " + lastDepth + " / " + targetLastDepth); if (lastDepth != targetLastDepth) throw new TopologyException("depth mismatch at " + de.getCoordinate()); //Assert.isTrue(lastDepth == targetLastDepth, "depth mismatch at " + de.getCoordinate()); }
public void setDepth(int position, int depthVal) { if (depth[position] != -999) { // if (depth[position] != depthVal) { // Debug.print(this); // } if (depth[position] != depthVal) throw new TopologyException("assigned depths do not match", getCoordinate()); //Assert.isTrue(depth[position] == depthVal, "assigned depths do not match at " + getCoordinate()); } depth[position] = depthVal; }
public boolean containsPoint(Point2D point) { try { return polygon.contains(polygon.getFactory().createPoint(new Coordinate(point.getX(), point.getY()))); } catch (TopologyException e) { return false; } }
protected void union( Geometry otherGeo ) { if (otherGeo == null) return; try { if (clusterGeo == null) { clusterGeo = otherGeo; } else if (clusterGeo instanceof Point) { clusterGeo = connectGeometryTool.connect( otherGeo, clusterGeo); } else { clusterGeo = connectGeometryTool.connect( clusterGeo, otherGeo); } } catch (TopologyException ex) { LOGGER.error( "Union failed due to non-simple geometries", ex); clusterGeo = connectGeometryTool.createHullFromGeometry( clusterGeo, Arrays.asList(otherGeo.getCoordinates()), false); } }
/** * Create the LinearRing. * * @param geometryFactory The geometry factory used for the build. * * @return LinearRing geometry created. */ public Geometry create(GeometryFactory geometryFactory) { try { Coordinate[] coords = (Coordinate[]) coordinateList.toArray(new Coordinate[coordinateList.size()]); LinearRing ring = geometryFactory.createLinearRing(coords); ring.setUserData( getSRS() ); ring.setSRID( getSRID() ); return ring; } catch (TopologyException e) { System.err.println( "Caught Topology exception in GMLLinearRingHandler"); return null; } }
@Override public double fetchSingle(Geometry feature, Geometry shape) { try { return feature.intersection(shape).getArea(); } catch (TopologyException e) { // see http://tsusiatsoftware.net/jts/jts-faq/jts-faq.html#D9 log.warn("Topology exception in feature calculation, " + "reducing precision of original model", e); feature = GeometryPrecisionReducer.reduce(feature, new PrecisionModel(PrecisionModel.FLOATING_SINGLE)); return feature.intersection(shape).getArea(); } }
public static Geometry symDifference(Geometry g1, Geometry g2) { try { return g1.symDifference(g2); } catch (TopologyException ex) { System.out.println(g1); } return null; }
private void testLinkResultDirectedEdges(DirectedEdgeStar deStar, int opCode) { // make sure edges are copied to resultAreaEdges list List ringEdges = this.getPotentialResultAreaEdges(deStar, opCode); // find first area edge (if any) to start linking at DirectedEdge firstOut = null; DirectedEdge incoming = null; int state = this.SCANNING_FOR_INCOMING; // link edges in CCW order for (Object ringEdge : ringEdges) { DirectedEdge nextOut = (DirectedEdge) ringEdge; DirectedEdge nextIn = nextOut.getSym(); // skip de's that we're not interested in if (!nextOut.getLabel().isArea()) { continue; } // record first outgoing edge, in order to link the last incoming edge if (firstOut == null && this.isPotentialResultAreaEdge(nextOut, opCode)) { firstOut = nextOut; } // assert: sym.isInResult() == false, since pairs of dirEdges should have been removed already switch (state) { case SCANNING_FOR_INCOMING: if (!this.isPotentialResultAreaEdge(nextIn, opCode)) { continue; } incoming = nextIn; state = this.LINKING_TO_OUTGOING; break; case LINKING_TO_OUTGOING: if (!this.isPotentialResultAreaEdge(nextOut, opCode)) { continue; } //incoming.setNext(nextOut); state = this.SCANNING_FOR_INCOMING; break; } } //Debug.print(this); if (state == this.LINKING_TO_OUTGOING) { //Debug.print(firstOut == null, this); if (firstOut == null) { throw new TopologyException("no outgoing dirEdge found", deStar.getCoordinate()); } } }
/** * Traverse the star of DirectedEdges, linking the included edges together. * To link two dirEdges, the <next> pointer for an incoming dirEdge * is set to the next outgoing edge. * <p> * DirEdges are only linked if: * <ul> * <li>they belong to an area (i.e. they have sides) * <li>they are marked as being in the result * </ul> * <p> * Edges are linked in CCW order (the order they are stored). * This means that rings have their face on the Right * (in other words, * the topological location of the face is given by the RHS label of the DirectedEdge) * <p> * PRECONDITION: No pair of dirEdges are both marked as being in the result */ public void linkResultDirectedEdges() { // make sure edges are copied to resultAreaEdges list this.getResultAreaEdges(); // find first area edge (if any) to start linking at DirectedEdge firstOut = null; DirectedEdge incoming = null; int state = this.SCANNING_FOR_INCOMING; // link edges in CCW order for (Object aResultAreaEdgeList : resultAreaEdgeList) { DirectedEdge nextOut = (DirectedEdge) aResultAreaEdgeList; DirectedEdge nextIn = nextOut.getSym(); // skip de's that we're not interested in if (!nextOut.getLabel().isArea()) { continue; } // record first outgoing edge, in order to link the last incoming edge if (firstOut == null && nextOut.isInResult()) { firstOut = nextOut; } // assert: sym.isInResult() == false, since pairs of dirEdges should have been removed already switch (state) { case SCANNING_FOR_INCOMING: if (!nextIn.isInResult()) { continue; } incoming = nextIn; state = this.LINKING_TO_OUTGOING; break; case LINKING_TO_OUTGOING: if (!nextOut.isInResult()) { continue; } incoming.setNext(nextOut); state = this.SCANNING_FOR_INCOMING; break; } } //Debug.print(this); if (state == this.LINKING_TO_OUTGOING) { //Debug.print(firstOut == null, this); if (firstOut == null) { throw new TopologyException("no outgoing dirEdge found", this.getCoordinate()); } //Assert.isTrue(firstOut != null, "no outgoing dirEdge found (at " + getCoordinate() ); Assert.isTrue(firstOut.isInResult(), "unable to link last incoming dirEdge"); incoming.setNext(firstOut); } }
private static List<FeatureEntry> makeSubFeatures(FeatureEntry featureEntry) { List<FeatureEntry> subFeatures = new ArrayList<FeatureEntry>(); Envelope envelope = featureEntry.location.envelope(); int numChildCells = featureEntry.location.reference.getLevelSize( featureEntry.location.level()); double childWidth = envelope.getWidth() / numChildCells; double childHeight = envelope.getHeight() / numChildCells; double startX = envelope.getMinX(); double startY = envelope.getMinY(); // Find the over-approximation of the child cell coverage by taking the envelope of the geometry Envelope geomEnvelope = featureEntry.geometry.getEnvelopeInternal(); int childCellXMin = (int) ((geomEnvelope.getMinX() - startX) / childWidth); int childCellXMax = Math.min(numChildCells - 1, (int) ((geomEnvelope.getMaxX() - startX) / childWidth)); int childCellYMin = (int) ((geomEnvelope.getMinY() - startY) / childHeight); int childCellYMax = Math.min(numChildCells - 1, (int) ((geomEnvelope.getMaxY() - startY) / childHeight)); try { // then just split geometry by the grid intersections, creating a new feature for each for (int longIdx = childCellXMin; longIdx <= childCellXMax; ++longIdx) { for (int latIdx = childCellYMin; latIdx <= childCellYMax; ++latIdx) { CellLocation childLocation = featureEntry.location.child(longIdx, latIdx); Geometry cellEnvelope = childLocation.envelopeGeometry(); if (cellEnvelope.intersects(featureEntry.geometry)) { subFeatures.add(new FeatureEntry( childLocation, featureEntry.getLabelEntry(), featureEntry.isWeakLabel(), cellEnvelope.intersection(featureEntry.geometry) )); } } } } catch (TopologyException te) { logger.warn("Failed to intersect geometry for entry: " + featureEntry); subFeatures.clear(); subFeatures.add(featureEntry); } catch (IllegalArgumentException ie) { logger.warn("Failed to intersect GeometryCollection for entry: " + featureEntry); subFeatures.clear(); subFeatures.add(featureEntry); } return subFeatures; }
private static HashMap<Feature, ArrayList<DissShare>> collectDissSharesByInd( String dissFldExpression, HashMap<Feature, ArrayList<Feature>> dissToInd) throws Exception { System.out.println( "accumulating diss shares under inds" ); HashMap<Feature,ArrayList<DissShare>> indDissShares = new HashMap<Feature,ArrayList<DissShare>>(); for( Entry<Feature, ArrayList<Feature>> entry : dissToInd.entrySet() ){ Feature diss = entry.getKey(); ArrayList<Feature> inds = entry.getValue(); // determine diss's magnitude double mag = getFieldsByExpression(dissFldExpression, diss); Geometry dissGeo = (Geometry)diss.getDefaultGeometryProperty().getValue(); double dissGeoArea = dissGeo.getArea(); for(Feature ind : inds){ // find the fraction of diss overlapping each ind shape Geometry indGeo = (Geometry)ind.getDefaultGeometryProperty().getValue(); Geometry overlap; try{ overlap = dissGeo.intersection(indGeo); } catch (TopologyException e){ if(GEOM_TOLERANT){ // something strange happened; carry on continue; } else{ throw e; } } double overlapArea = overlap.getArea(); double fraction = overlapArea/dissGeoArea; // assign the magnitude proportionately double share = fraction*mag; if(share==0.0){ continue; } // then register the diss feature's share with the ind feature ArrayList<DissShare> shares = indDissShares.get(ind); if(shares==null){ shares = new ArrayList<DissShare>(); indDissShares.put(ind, shares); } shares.add(new DissShare(diss,share)); } } return indDissShares; }
private void testLinkResultDirectedEdges(DirectedEdgeStar deStar, int opCode) { // make sure edges are copied to resultAreaEdges list List ringEdges = getPotentialResultAreaEdges(deStar, opCode); // find first area edge (if any) to start linking at DirectedEdge firstOut = null; DirectedEdge incoming = null; int state = SCANNING_FOR_INCOMING; // link edges in CCW order for (int i = 0; i < ringEdges.size(); i++) { DirectedEdge nextOut = (DirectedEdge) ringEdges.get(i); DirectedEdge nextIn = nextOut.getSym(); // skip de's that we're not interested in if (!nextOut.getLabel().isArea()) continue; // record first outgoing edge, in order to link the last incoming edge if (firstOut == null && isPotentialResultAreaEdge(nextOut, opCode)) firstOut = nextOut; // assert: sym.isInResult() == false, since pairs of dirEdges should have been removed already switch (state) { case SCANNING_FOR_INCOMING: if (!isPotentialResultAreaEdge(nextIn, opCode)) continue; incoming = nextIn; state = LINKING_TO_OUTGOING; break; case LINKING_TO_OUTGOING: if (!isPotentialResultAreaEdge(nextOut, opCode)) continue; //incoming.setNext(nextOut); state = SCANNING_FOR_INCOMING; break; } } //Debug.print(this); if (state == LINKING_TO_OUTGOING) { //Debug.print(firstOut == null, this); if (firstOut == null) throw new TopologyException("no outgoing dirEdge found", deStar.getCoordinate()); } }
/** * Traverse the star of DirectedEdges, linking the included edges together. * To link two dirEdges, the <next> pointer for an incoming dirEdge * is set to the next outgoing edge. * <p/> * DirEdges are only linked if: * <ul> * <li>they belong to an area (i.e. they have sides) * <li>they are marked as being in the result * </ul> * <p/> * Edges are linked in CCW order (the order they are stored). * This means that rings have their face on the Right * (in other words, * the topological location of the face is given by the RHS label of the DirectedEdge) * <p/> * PRECONDITION: No pair of dirEdges are both marked as being in the result */ public void linkResultDirectedEdges() { // make sure edges are copied to resultAreaEdges list getResultAreaEdges(); // find first area edge (if any) to start linking at DirectedEdge firstOut = null; DirectedEdge incoming = null; int state = SCANNING_FOR_INCOMING; // link edges in CCW order for (int i = 0; i < resultAreaEdgeList.size(); i++) { DirectedEdge nextOut = (DirectedEdge) resultAreaEdgeList.get(i); DirectedEdge nextIn = nextOut.getSym(); // skip de's that we're not interested in if (!nextOut.getLabel().isArea()) continue; // record first outgoing edge, in order to link the last incoming edge if (firstOut == null && nextOut.isInResult()) firstOut = nextOut; // assert: sym.isInResult() == false, since pairs of dirEdges should have been removed already switch (state) { case SCANNING_FOR_INCOMING: if (!nextIn.isInResult()) continue; incoming = nextIn; state = LINKING_TO_OUTGOING; break; case LINKING_TO_OUTGOING: if (!nextOut.isInResult()) continue; incoming.setNext(nextOut); state = SCANNING_FOR_INCOMING; break; } } //Debug.print(this); if (state == LINKING_TO_OUTGOING) { //Debug.print(firstOut == null, this); if (firstOut == null) throw new TopologyException("no outgoing dirEdge found", getCoordinate()); //Assert.isTrue(firstOut != null, "no outgoing dirEdge found (at " + getCoordinate() ); Assert.isTrue(firstOut.isInResult(), "unable to link last incoming dirEdge"); incoming.setNext(firstOut); } }
/** * Checks for an intersection and throws * a TopologyException if one is found. * * @throws TopologyException if an intersection is found */ public void checkValid() { execute(); if (!isValid) throw new TopologyException(getErrorMessage(), segInt.getInteriorIntersection()); }