/// <summary> /// Finds and removes all cut edges from the graph. /// </summary> /// <returns>A list of the <c>LineString</c>s forming the removed cut edges.</returns> public IList <ILineString> DeleteCutEdges() { ComputeNextCWEdges(); // label the current set of edgerings FindLabeledEdgeRings(dirEdges); /* * Cut Edges are edges where both dirEdges have the same label. * Delete them, and record them */ IList <ILineString> cutLines = new List <ILineString>(); foreach (PolygonizeDirectedEdge de in dirEdges) { if (de.IsMarked) { continue; } PolygonizeDirectedEdge sym = (PolygonizeDirectedEdge)de.Sym; if (de.Label == sym.Label) { de.Marked = true; sym.Marked = true; // save the line as a cut edge PolygonizeEdge e = (PolygonizeEdge)de.Edge; cutLines.Add(e.Line); } } return(cutLines); }
/// <summary> /// Add a <c>LineString</c> forming an edge of the polygon graph. /// </summary> /// <param name="line">The line to add.</param> public void AddEdge(ILineString line) { if (line.IsEmpty) { return; } Coordinate[] linePts = CoordinateArrays.RemoveRepeatedPoints(line.Coordinates); if (linePts.Length < 2) { return; } Coordinate startPt = linePts[0]; Coordinate endPt = linePts[linePts.Length - 1]; Node nStart = GetNode(startPt); Node nEnd = GetNode(endPt); DirectedEdge de0 = new PolygonizeDirectedEdge(nStart, nEnd, linePts[1], true); DirectedEdge de1 = new PolygonizeDirectedEdge(nEnd, nStart, linePts[linePts.Length - 2], false); Edge edge = new PolygonizeEdge(line); edge.SetDirectedEdges(de0, de1); Add(edge); }
/// <summary> /// /// </summary> /// <param name="startDE"></param> /// <returns></returns> private EdgeRing FindEdgeRing(PolygonizeDirectedEdge startDE) { var er = new EdgeRing(_factory); er.Build(startDE); return(er); }
/// <summary> /// /// </summary> /// <param name="node"></param> private static void ComputeNextCWEdges(Node node) { DirectedEdgeStar deStar = node.OutEdges; PolygonizeDirectedEdge startDE = null; PolygonizeDirectedEdge prevDE = null; // the edges are stored in CCW order around the star foreach (PolygonizeDirectedEdge outDE in deStar.Edges) { if (outDE.IsMarked) { continue; } if (startDE == null) { startDE = outDE; } if (prevDE != null) { PolygonizeDirectedEdge sym = (PolygonizeDirectedEdge)prevDE.Sym; sym.Next = outDE; } prevDE = outDE; } if (prevDE != null) { PolygonizeDirectedEdge sym = (PolygonizeDirectedEdge)prevDE.Sym; sym.Next = startDE; } }
/// <summary> /// Computes the next edge pointers going CCW around the given node, for the /// given edgering label. /// This algorithm has the effect of converting maximal edgerings into minimal edgerings /// </summary> /// <param name="node"></param> /// <param name="label"></param> private static void ComputeNextCCWEdges(Node node, long label) { DirectedEdgeStar deStar = node.OutEdges; //PolyDirectedEdge lastInDE = null; PolygonizeDirectedEdge firstOutDE = null; PolygonizeDirectedEdge prevInDE = null; // the edges are stored in CCW order around the star IList <DirectedEdge> edges = deStar.Edges; //for (IEnumerator i = deStar.Edges.GetEnumerator(); i.MoveNext(); ) { for (int i = edges.Count - 1; i >= 0; i--) { PolygonizeDirectedEdge de = (PolygonizeDirectedEdge)edges[i]; PolygonizeDirectedEdge sym = (PolygonizeDirectedEdge)de.Sym; PolygonizeDirectedEdge outDE = null; if (de.Label == label) { outDE = de; } PolygonizeDirectedEdge inDE = null; if (sym.Label == label) { inDE = sym; } if (outDE == null && inDE == null) { continue; // this edge is not in edgering } if (inDE != null) { prevInDE = inDE; } if (outDE != null) { if (prevInDE != null) { prevInDE.Next = outDE; prevInDE = null; } if (firstOutDE == null) { firstOutDE = outDE; } } } if (prevInDE != null) { Assert.IsTrue(firstOutDE != null); prevInDE.Next = firstOutDE; } }
/// <summary> /// Traverses the polygonized edge rings in the graph /// and computes the depth parity (odd or even) /// relative to the exterior of the graph. /// /// If the client has requested that the output /// be polygonally valid, only odd polygons will be constructed. /// </summary> public void ComputeDepthParity() { while (true) { PolygonizeDirectedEdge de = null; //findLowestDirEdge(); if (de == null) { return; } ComputeDepthParity(de); } }
public void Build(PolygonizeDirectedEdge startDE) { PolygonizeDirectedEdge de = startDE; do { Add(de); de.Ring = this; de = de.Next; Utilities.Assert.IsTrue(de != null, "found null DE in ring"); Utilities.Assert.IsTrue(de == startDE || !de.IsInRing, "found DE already in ring"); } while (de != startDE); }
/// <summary> /// Traverses a ring of DirectedEdges, accumulating them into a list. /// This assumes that all dangling directed edges have been removed /// from the graph, so that there is always a next dirEdge. /// </summary> /// <param name="startDE">The DirectedEdge to start traversing at.</param> /// <returns>A List of DirectedEdges that form a ring.</returns> private static IEnumerable <DirectedEdge> FindDirEdgesInRing(PolygonizeDirectedEdge startDE) { PolygonizeDirectedEdge de = startDE; IList <DirectedEdge> edges = new List <DirectedEdge>(); do { edges.Add(de); de = de.Next; Assert.IsTrue(de != null, "found null DE in ring"); Assert.IsTrue(de == startDE || !de.IsInRing, "found DE already in ring"); }while (de != startDE); return(edges); }
/// <summary> /// Deletes all edges at a node. /// </summary> /// <param name="node"></param> public static void DeleteAllEdges(Node node) { IList <DirectedEdge> edges = node.OutEdges.Edges; foreach (PolygonizeDirectedEdge de in edges) { de.Marked = true; PolygonizeDirectedEdge sym = (PolygonizeDirectedEdge)de.Sym; if (sym != null) { sym.Marked = true; } } }
/** * Traverses a ring of DirectedEdges, accumulating them into a list. * This assumes that all dangling directed edges have been removed * from the graph, so that there is always a next dirEdge. * * @param startDE the DirectedEdge to start traversing at * @return a List of DirectedEdges that form a ring */ public static List <DirectedEdge> FindDirEdgesInRing(PolygonizeDirectedEdge startDE) { var de = startDE; var edges = new List <DirectedEdge>(); do { edges.Add(de); de = de.Next; Utilities.Assert.IsTrue(de != null, "found null DE in ring"); Utilities.Assert.IsTrue(de == startDE || !de.IsInRing, "found DE already in ring"); } while (de != startDE); return(edges); }
/// <summary> /// /// </summary> /// <param name="startDE"></param> /// <returns></returns> private EdgeRing FindEdgeRing(PolygonizeDirectedEdge startDE) { PolygonizeDirectedEdge de = startDE; EdgeRing er = new EdgeRing(_factory); do { er.Add(de); de.Ring = er; de = de.Next; Assert.IsTrue(de != null, "found null DE in ring"); Assert.IsTrue(de == startDE || !de.IsInRing, "found DE already in ring"); }while (de != startDE); return(er); }
/// <summary> /// Marks all edges from the graph which are "dangles". /// Dangles are which are incident on a node with degree 1. /// This process is recursive, since removing a dangling edge /// may result in another edge becoming a dangle. /// In order to handle large recursion depths efficiently, /// an explicit recursion stack is used. /// </summary> /// <returns>A List containing the <see cref="ILineString"/>s that formed dangles.</returns> public ICollection <ILineString> DeleteDangles() { var nodesToRemove = FindNodesOfDegree(1); HashSet <ILineString> dangleLines = new HashSet <ILineString>(); Stack <Node> nodeStack = new Stack <Node>(); foreach (Node node in nodesToRemove) { nodeStack.Push(node); } while (nodeStack.Count != 0) { Node node = nodeStack.Pop(); DeleteAllEdges(node); IList <DirectedEdge> nodeOutEdges = node.OutEdges.Edges; foreach (PolygonizeDirectedEdge de in nodeOutEdges) { // delete this edge and its sym de.Marked = true; PolygonizeDirectedEdge sym = (PolygonizeDirectedEdge)de.Sym; if (sym != null) { sym.Marked = true; } // save the line as a dangle PolygonizeEdge e = (PolygonizeEdge)de.Edge; dangleLines.Add(e.Line); Node toNode = de.ToNode; // add the toNode to the list to be processed, if it is now a dangle if (GetDegreeNonDeleted(toNode) == 1) { nodeStack.Push(toNode); } } } var dangleArray = new ILineString[dangleLines.Count]; dangleLines.CopyTo(dangleArray, 0); return(new ReadOnlyCollection <ILineString>(dangleArray)); //new ArrayList(dangleLines.CastPlatform()); }
/// <summary> /// Add a <c>LineString</c> forming an edge of the polygon graph. /// </summary> /// <param name="line">The line to add.</param> public void AddEdge(ILineString line) { if (line.IsEmpty) return; Coordinate[] linePts = CoordinateArrays.RemoveRepeatedPoints(line.Coordinates); Coordinate startPt = linePts[0]; Coordinate endPt = linePts[linePts.Length - 1]; Node nStart = GetNode(startPt); Node nEnd = GetNode(endPt); DirectedEdge de0 = new PolygonizeDirectedEdge(nStart, nEnd, linePts[1], true); DirectedEdge de1 = new PolygonizeDirectedEdge(nEnd, nStart, linePts[linePts.Length - 2], false); Edge edge = new PolygonizeEdge(line); edge.SetDirectedEdges(de0, de1); Add(edge); }
/// <summary> /// Updates the included status for currently non-included shells /// based on whether they are adjacent to an included shell. /// </summary> internal void UpdateIncluded() { if (IsHole) { return; } for (int i = 0; i < _deList.Count; i++) { PolygonizeDirectedEdge de = (PolygonizeDirectedEdge)_deList[i]; EdgeRing adjShell = ((PolygonizeDirectedEdge)de.Sym).Ring.Shell; if (adjShell != null && adjShell.IsIncludedSet) { // adjacent ring has been processed, so set included to inverse of adjacent included IsIncluded = !adjShell.IsIncluded; return; } } }
/// <summary> /// Finds all nodes in a maximal edgering which are self-intersection nodes /// </summary> /// <param name="startDE"></param> /// <param name="label"></param> /// <returns> /// The list of intersection nodes found, /// or null if no intersection nodes were found. /// </returns> private static IEnumerable <Node> FindIntersectionNodes(PolygonizeDirectedEdge startDE, long label) { PolygonizeDirectedEdge de = startDE; IList <Node> intNodes = null; do { Node node = de.FromNode; if (GetDegree(node, label) > 1) { if (intNodes == null) { intNodes = new List <Node>(); } intNodes.Add(node); } de = de.Next; Assert.IsTrue(de != null, "found null DE in ring"); Assert.IsTrue(de == startDE || !de.IsInRing, "found DE already in ring"); }while (de != startDE); return(intNodes); }
/// <summary> /// /// </summary> /// <param name="startDE"></param> /// <returns></returns> private EdgeRing FindEdgeRing(PolygonizeDirectedEdge startDE) { PolygonizeDirectedEdge de = startDE; EdgeRing er = new EdgeRing(_factory); do { er.Add(de); de.Ring = er; de = de.Next; Assert.IsTrue(de != null, "found null DE in ring"); Assert.IsTrue(de == startDE || ! de.IsInRing, "found DE already in ring"); } while (de != startDE); return er; }
/// <summary> /// Finds all nodes in a maximal edgering which are self-intersection nodes /// </summary> /// <param name="startDE"></param> /// <param name="label"></param> /// <returns> /// The list of intersection nodes found, /// or null if no intersection nodes were found. /// </returns> private static IEnumerable<Node> FindIntersectionNodes(PolygonizeDirectedEdge startDE, long label) { PolygonizeDirectedEdge de = startDE; IList<Node> intNodes = null; do { Node node = de.FromNode; if (GetDegree(node, label) > 1) { if (intNodes == null) intNodes = new List<Node>(); intNodes.Add(node); } de = de.Next; Assert.IsTrue(de != null, "found null DE in ring"); Assert.IsTrue(de == startDE || ! de.IsInRing, "found DE already in ring"); } while (de != startDE); return intNodes; }
/// <summary> /// /// </summary> /// <param name="startDE"></param> /// <returns></returns> private EdgeRing FindEdgeRing(PolygonizeDirectedEdge startDE) { var er = new EdgeRing(_factory); er.Build(startDE); return er; }
///<summary> /// Traverses all connected edges, computing the depth parity of the associated polygons. ///</summary> /// <param name="de"></param> private void ComputeDepthParity(PolygonizeDirectedEdge de) { }
/// <summary> /// Traverses a ring of DirectedEdges, accumulating them into a list. /// This assumes that all dangling directed edges have been removed /// from the graph, so that there is always a next dirEdge. /// </summary> /// <param name="startDE">The DirectedEdge to start traversing at.</param> /// <returns>A List of DirectedEdges that form a ring.</returns> private static IEnumerable<DirectedEdge> FindDirEdgesInRing(PolygonizeDirectedEdge startDE) { PolygonizeDirectedEdge de = startDE; IList<DirectedEdge> edges = new List<DirectedEdge>(); do { edges.Add(de); de = de.Next; Assert.IsTrue(de != null, "found null DE in ring"); Assert.IsTrue(de == startDE || ! de.IsInRing, "found DE already in ring"); } while (de != startDE); return edges; }