using System.Collections; using GeoAPI.Geometries; using GisSharpBlog.NetTopologySuite.GeometriesGraph; namespace GisSharpBlog.NetTopologySuite.Operation.Relate { /// /// Implements the simple graph of Nodes and EdgeEnd which is all that is /// required to determine topological relationships between Geometries. /// Also supports building a topological graph of a single Geometry, to /// allow verification of valid topology. /// It is not necessary to create a fully linked /// PlanarGraph to determine relationships, since it is sufficient /// to know how the Geometries interact locally around the nodes. /// In fact, this is not even feasible, since it is not possible to compute /// exact intersection points, and hence the topology around those nodes /// cannot be computed robustly. /// The only Nodes that are created are for improper intersections; /// that is, nodes which occur at existing vertices of the Geometries. /// Proper intersections (e.g. ones which occur between the interior of line segments) /// have their topology determined implicitly, without creating a Node object /// to represent them. /// public class RelateNodeGraph { private readonly NodeMap nodes = new NodeMap(new RelateNodeFactory()); /// /// /// public RelateNodeGraph() {} /// /// /// /// public IEnumerator GetNodeEnumerator() { return nodes.GetEnumerator(); } /// /// /// /// public void Build(GeometryGraph geomGraph) { // compute nodes for intersections between previously noded edges ComputeIntersectionNodes(geomGraph, 0); /* * Copy the labelling for the nodes in the parent Geometry. These override * any labels determined by intersections. */ CopyNodesAndLabels(geomGraph, 0); /* * Build EdgeEnds for all intersections. */ EdgeEndBuilder eeBuilder = new EdgeEndBuilder(); IList eeList = eeBuilder.ComputeEdgeEnds(geomGraph.GetEdgeEnumerator()); InsertEdgeEnds(eeList); } /// /// 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. /// Precondition: edge intersections have been computed. /// /// /// public void ComputeIntersectionNodes(GeometryGraph geomGraph, int argIndex) { for (IEnumerator edgeIt = geomGraph.GetEdgeEnumerator(); edgeIt.MoveNext();) { Edge e = (Edge) edgeIt.Current; Locations eLoc = e.Label.GetLocation(argIndex); for (IEnumerator eiIt = e.EdgeIntersectionList.GetEnumerator(); eiIt.MoveNext();) { EdgeIntersection ei = (EdgeIntersection) eiIt.Current; RelateNode n = (RelateNode) nodes.AddNode(ei.Coordinate); if (eLoc == Locations.Boundary) { n.SetLabelBoundary(argIndex); } else if (n.Label.IsNull(argIndex)) { n.SetLabel(argIndex, Locations.Interior); } } } } /// /// Copy all nodes from an arg point into this graph. /// The node label in the arg point overrides any previously computed /// label for that argIndex. /// (E.g. a node may be an intersection node with /// a computed label of Boundary, /// but in the original arg Geometry it is actually /// in the interior due to the Boundary Determination Rule). /// /// /// public void CopyNodesAndLabels(GeometryGraph geomGraph, int argIndex) { for (IEnumerator nodeIt = geomGraph.GetNodeEnumerator(); nodeIt.MoveNext();) { Node graphNode = (Node) nodeIt.Current; Node newNode = nodes.AddNode(graphNode.Coordinate); newNode.SetLabel(argIndex, graphNode.Label.GetLocation(argIndex)); } } /// /// /// /// public void InsertEdgeEnds(IList ee) { for (IEnumerator i = ee.GetEnumerator(); i.MoveNext();) { EdgeEnd e = (EdgeEnd) i.Current; nodes.Add(e); } } } }