using System.Collections; using System.IO; using GeoAPI.Geometries; using GisSharpBlog.NetTopologySuite.Geometries; using Wintellect.PowerCollections; namespace GisSharpBlog.NetTopologySuite.GeometriesGraph { /// /// A list of edge intersections along an Edge. /// public class EdgeIntersectionList { // a list of EdgeIntersections private readonly IDictionary nodeMap = new OrderedDictionary(); private readonly Edge edge; // the parent edge /// /// /// /// public EdgeIntersectionList(Edge edge) { this.edge = edge; } /// /// /// public int Count { get { return nodeMap.Count; } } /// /// Adds an intersection into the list, if it isn't already there. /// The input segmentIndex and dist are expected to be normalized. /// /// /// /// /// The EdgeIntersection found or added. public EdgeIntersection Add(ICoordinate intPt, int segmentIndex, double dist) { EdgeIntersection eiNew = new EdgeIntersection(intPt, segmentIndex, dist); EdgeIntersection ei = (EdgeIntersection) nodeMap[eiNew]; if (ei != null) { return ei; } nodeMap[eiNew] = eiNew; return eiNew; } /// /// Returns an iterator of EdgeIntersections. /// public IEnumerator GetEnumerator() { return nodeMap.Values.GetEnumerator(); } /// /// /// /// /// public bool IsIntersection(ICoordinate pt) { for (IEnumerator it = GetEnumerator(); it.MoveNext();) { EdgeIntersection ei = (EdgeIntersection) it.Current; if (ei.Coordinate.Equals(pt)) { return true; } } return false; } /// /// Adds entries for the first and last points of the edge to the list. /// public void AddEndpoints() { int maxSegIndex = edge.Points.Length - 1; Add(edge.Points[0], 0, 0.0); Add(edge.Points[maxSegIndex], maxSegIndex, 0.0); } /// /// Creates new edges for all the edges that the intersections in this /// list split the parent edge into. /// Adds the edges to the input list (this is so a single list /// can be used to accumulate all split edges for a Geometry). /// /// public void AddSplitEdges(IList edgeList) { // ensure that the list has entries for the first and last point of the edge AddEndpoints(); IEnumerator it = GetEnumerator(); it.MoveNext(); // there should always be at least two entries in the list EdgeIntersection eiPrev = (EdgeIntersection) it.Current; while (it.MoveNext()) { EdgeIntersection ei = (EdgeIntersection) it.Current; Edge newEdge = CreateSplitEdge(eiPrev, ei); edgeList.Add(newEdge); eiPrev = ei; } } /// /// Create a new "split edge" with the section of points between /// (and including) the two intersections. /// The label for the new edge is the same as the label for the parent edge. /// /// /// public Edge CreateSplitEdge(EdgeIntersection ei0, EdgeIntersection ei1) { int npts = ei1.SegmentIndex - ei0.SegmentIndex + 2; ICoordinate lastSegStartPt = edge.Points[ei1.SegmentIndex]; // if the last intersection point is not equal to the its segment start pt, // add it to the points list as well. // (This check is needed because the distance metric is not totally reliable!) // The check for point equality is 2D only - Z values are ignored bool useIntPt1 = ei1.Distance > 0.0 || !ei1.Coordinate.Equals2D(lastSegStartPt); if (!useIntPt1) { npts--; } ICoordinate[] pts = new ICoordinate[npts]; int ipt = 0; pts[ipt++] = new Coordinate(ei0.Coordinate); for (int i = ei0.SegmentIndex + 1; i <= ei1.SegmentIndex; i++) { pts[ipt++] = edge.Points[i]; } if (useIntPt1) { pts[ipt] = ei1.Coordinate; } return new Edge(pts, new Label(edge.Label)); } /// /// /// /// public void Write(StreamWriter outstream) { outstream.WriteLine("Intersections:"); for (IEnumerator it = GetEnumerator(); it.MoveNext();) { EdgeIntersection ei = (EdgeIntersection) it.Current; ei.Write(outstream); } } } }