/// <summary> /// /// </summary> /// <param name="edges"></param> /// <param name="si"></param> /// <param name="testAllSegments"></param> public override void ComputeIntersections(IList edges, SegmentIntersector si, bool testAllSegments) { for (IEnumerator i0 = edges.GetEnumerator(); i0.MoveNext(); ) { Edge edge0 = (Edge)i0.Current; for (IEnumerator i1 = edges.GetEnumerator(); i1.MoveNext(); ) { Edge edge1 = (Edge)i1.Current; if (testAllSegments || edge0 != edge1) ComputeIntersects(edge0, edge1, si); } } }
/// <summary> /// /// </summary> /// <param name="edges"></param> /// <param name="si"></param> /// <param name="testAllSegments"></param> public override void ComputeIntersections(IList edges, SegmentIntersector si, bool testAllSegments) { if (testAllSegments) Add(edges, null); else Add(edges); ComputeIntersections(si); }
/// <summary> /// Performs a brute-force comparison of every segment in each Edge. /// This has n^2 performance, and is about 100 times slower than using /// monotone chains. /// </summary> /// <param name="e0"></param> /// <param name="e1"></param> /// <param name="si"></param> private static void ComputeIntersects(Edge e0, Edge e1, SegmentIntersector si) { IList<Coordinate> pts0 = e0.Coordinates; IList<Coordinate> pts1 = e1.Coordinates; for (int i0 = 0; i0 < pts0.Count - 1; i0++) for (int i1 = 0; i1 < pts1.Count - 1; i1++) si.AddIntersections(e0, i0, e1, i1); }
/// <summary> /// /// </summary> /// <param name="edges0"></param> /// <param name="edges1"></param> /// <param name="si"></param> public override void ComputeIntersections(IList edges0, IList edges1, SegmentIntersector si) { for (IEnumerator i0 = edges0.GetEnumerator(); i0.MoveNext(); ) { Edge edge0 = (Edge)i0.Current; for (IEnumerator i1 = edges1.GetEnumerator(); i1.MoveNext(); ) { Edge edge1 = (Edge)i1.Current; ComputeIntersects(edge0, edge1, si); } } }
/// <summary> /// Computes all self-intersections between edges in a set of edges, /// allowing client to choose whether self-intersections are computed. /// </summary> /// <param name="edges">A list of edges to test for intersections.</param> /// <param name="si">The SegmentIntersector to use.</param> /// <param name="testAllSegments"><c>true</c> if self-intersections are to be tested as well.</param> public abstract void ComputeIntersections(IList edges, SegmentIntersector si, bool testAllSegments);
/// <summary> /// /// </summary> /// <param name="start0"></param> /// <param name="end0"></param> /// <param name="mce"></param> /// <param name="start1"></param> /// <param name="end1"></param> /// <param name="ei"></param> private void ComputeIntersectsForChain(int start0, int end0, MonotoneChainEdge mce, int start1, int end1, SegmentIntersector ei) { Coordinate p00 = _pts[start0]; Coordinate p01 = _pts[end0]; Coordinate p10 = mce._pts[start1]; Coordinate p11 = mce._pts[end1]; // Console.WriteLine("computeIntersectsForChain:" + p00 + p01 + p10 + p11); // terminating condition for the recursion if (end0 - start0 == 1 && end1 - start1 == 1) { ei.AddIntersections(_e, start0, mce._e, start1); return; } // nothing to do if the envelopes of these chains don't overlap _env1.Init(p00, p01); _env2.Init(p10, p11); if (!_env1.Intersects(_env2)) return; // the chains overlap, so split each in half and iterate (binary search) int mid0 = (start0 + end0) / 2; int mid1 = (start1 + end1) / 2; // check terminating conditions before recursing if (start0 < mid0) { if (start1 < mid1) ComputeIntersectsForChain(start0, mid0, mce, start1, mid1, ei); if (mid1 < end1) ComputeIntersectsForChain(start0, mid0, mce, mid1, end1, ei); } if (mid0 < end0) { if (start1 < mid1) ComputeIntersectsForChain(mid0, end0, mce, start1, mid1, ei); if (mid1 < end1) ComputeIntersectsForChain(mid0, end0, mce, mid1, end1, ei); } }
/// <summary> /// /// </summary> /// <param name="chainIndex0"></param> /// <param name="mce"></param> /// <param name="chainIndex1"></param> /// <param name="si"></param> public virtual void ComputeIntersectsForChain(int chainIndex0, MonotoneChainEdge mce, int chainIndex1, SegmentIntersector si) { ComputeIntersectsForChain(_startIndex[chainIndex0], _startIndex[chainIndex0 + 1], mce, mce._startIndex[chainIndex1], mce._startIndex[chainIndex1 + 1], si); }
/// <summary> /// /// </summary> /// <param name="mce"></param> /// <param name="si"></param> public virtual void ComputeIntersects(MonotoneChainEdge mce, SegmentIntersector si) { for (int i = 0; i < _startIndex.Length - 1; i++) { for (int j = 0; j < mce._startIndex.Length - 1; j++) { ComputeIntersectsForChain(i, mce, j, si); } } }
/// <summary> /// /// </summary> /// <param name="start0"></param> /// <param name="end0"></param> /// <param name="mce"></param> /// <param name="start1"></param> /// <param name="end1"></param> /// <param name="ei"></param> private void ComputeIntersectsForChain(int start0, int end0, MonotoneChainEdge mce, int start1, int end1, SegmentIntersector ei) { Coordinate p00 = _pts[start0]; Coordinate p01 = _pts[end0]; Coordinate p10 = mce._pts[start1]; Coordinate p11 = mce._pts[end1]; // Console.WriteLine("computeIntersectsForChain:" + p00 + p01 + p10 + p11); // terminating condition for the recursion if (end0 - start0 == 1 && end1 - start1 == 1) { ei.AddIntersections(_e, start0, mce._e, start1); return; } // nothing to do if the envelopes of these chains don't overlap _env1.Init(p00, p01); _env2.Init(p10, p11); if (!_env1.Intersects(_env2)) { return; } // the chains overlap, so split each in half and iterate (binary search) int mid0 = (start0 + end0) / 2; int mid1 = (start1 + end1) / 2; // check terminating conditions before recursing if (start0 < mid0) { if (start1 < mid1) { ComputeIntersectsForChain(start0, mid0, mce, start1, mid1, ei); } if (mid1 < end1) { ComputeIntersectsForChain(start0, mid0, mce, mid1, end1, ei); } } if (mid0 < end0) { if (start1 < mid1) { ComputeIntersectsForChain(mid0, end0, mce, start1, mid1, ei); } if (mid1 < end1) { ComputeIntersectsForChain(mid0, end0, mce, mid1, end1, ei); } } }
/// <summary> /// /// </summary> /// <param name="g"></param> /// <param name="li"></param> /// <param name="includeProper"></param> /// <returns></returns> public virtual SegmentIntersector ComputeEdgeIntersections(GeometryGraph g, LineIntersector li, bool includeProper) { SegmentIntersector si = new SegmentIntersector(li, includeProper, true); si.SetBoundaryNodes(BoundaryNodes, g.BoundaryNodes); EdgeSetIntersector esi = CreateEdgeSetIntersector(); esi.ComputeIntersections(Edges, g.Edges, si); return si; }
/// <summary> /// /// </summary> /// <param name="edges0"></param> /// <param name="edges1"></param> /// <param name="si"></param> public override void ComputeIntersections(IList edges0, IList edges1, SegmentIntersector si) { Add(edges0, edges0); Add(edges1, edges1); ComputeIntersections(si); }
/// <summary> /// /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="ev0"></param> /// <param name="si"></param> private void ProcessOverlaps(int start, int end, SweepLineEvent ev0, SegmentIntersector si) { SweepLineSegment ss0 = (SweepLineSegment)ev0.Object; /* * Since we might need to test for self-intersections, * include current insert event object in list of event objects to test. * Last index can be skipped, because it must be a Delete event. */ for (int i = start; i < end; i++) { SweepLineEvent ev1 = (SweepLineEvent)_events[i]; if (ev1.IsInsert) { SweepLineSegment ss1 = (SweepLineSegment)ev1.Object; if (ev0.EdgeSet == null || (ev0.EdgeSet != ev1.EdgeSet)) ss0.ComputeIntersections(ss1, si); _nOverlaps++; } } }
/// <summary> /// /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="ev0"></param> /// <param name="si"></param> private void ProcessOverlaps(int start, int end, SweepLineEvent ev0, SegmentIntersector si) { MonotoneChain mc0 = (MonotoneChain)ev0.Object; /* * Since we might need to test for self-intersections, * include current insert event object in list of event objects to test. * Last index can be skipped, because it must be a Delete event. */ for (int i = start; i < end; i++) { SweepLineEvent ev1 = (SweepLineEvent)_events[i]; if (ev1.IsInsert) { MonotoneChain mc1 = (MonotoneChain)ev1.Object; // don't compare edges in same group // null group indicates that edges should be compared if (ev0.EdgeSet == null) { // This null situation is problematic } if (ev0.EdgeSet == null || (ev0.EdgeSet != ev1.EdgeSet)) { mc0.ComputeIntersections(mc1, si); _nOverlaps++; } } } }
/// <summary> /// /// </summary> /// <param name="si"></param> private void ComputeIntersections(SegmentIntersector si) { _nOverlaps = 0; PrepareEvents(); for (int i = 0; i < _events.Count; i++) { SweepLineEvent ev = (SweepLineEvent)_events[i]; if (ev.IsInsert) ProcessOverlaps(i, ev.DeleteEventIndex, ev, si); } }
/// <summary> /// Computes all mutual intersections between two sets of edges. /// </summary> public abstract void ComputeIntersections(IList edges0, IList edges1, SegmentIntersector si);
/// <summary> /// /// </summary> /// <param name="ss"></param> /// <param name="si"></param> public virtual void ComputeIntersections(SweepLineSegment ss, SegmentIntersector si) { si.AddIntersections(_edge, _ptIndex, ss._edge, ss._ptIndex); }
/// <summary> /// Compute self-nodes, taking advantage of the Geometry type to /// minimize the number of intersection tests. (E.g. rings are /// not tested for self-intersection, since they are assumed to be valid). /// </summary> /// <param name="li">The <c>LineIntersector</c> to use.</param> /// <param name="computeRingSelfNodes">If <c>false</c>, intersection checks are optimized to not test rings for self-intersection.</param> /// <returns>The SegmentIntersector used, containing information about the intersections found.</returns> public virtual SegmentIntersector ComputeSelfNodes(LineIntersector li, bool computeRingSelfNodes) { SegmentIntersector si = new SegmentIntersector(li, true, false); EdgeSetIntersector esi = CreateEdgeSetIntersector(); // optimized test for Polygons and Rings if (!computeRingSelfNodes && (_parentGeom is ILinearRing || _parentGeom is IPolygon || _parentGeom is IMultiPolygon)) esi.ComputeIntersections(Edges, si, false); else esi.ComputeIntersections(Edges, si, true); AddSelfIntersectionNodes(_argIndex); return si; }
/// <summary> /// /// </summary> /// <param name="intersector"></param> /// <param name="im"></param> private void ComputeProperIntersectionIm(SegmentIntersector intersector, IIntersectionMatrix im) { // If a proper intersection is found, we can set a lower bound on the IM. DimensionType dimA = _arg[0].Geometry.Dimension; DimensionType dimB = _arg[1].Geometry.Dimension; bool hasProper = intersector.HasProperIntersection; bool hasProperInterior = intersector.HasProperInteriorIntersection; // For Geometry's of dim 0 there can never be proper intersections. /* * If edge segments of Areas properly intersect, the areas must properly overlap. */ if (dimA == DimensionType.Surface && dimB == DimensionType.Surface) { if (hasProper) { im.SetAtLeast("212101212"); } } else if (dimA == DimensionType.Surface && dimB == DimensionType.Curve) { /* * If an Line segment properly intersects an edge segment of an Area, * it follows that the Interior of the Line intersects the Boundary of the Area. * If the intersection is a proper <i>interior</i> intersection, then * there is an Interior-Interior intersection too. * Notice that it does not follow that the Interior of the Line intersects the Exterior * of the Area, since there may be another Area component which contains the rest of the Line. */ if (hasProper) { im.SetAtLeast("FFF0FFFF2"); } if (hasProperInterior) { im.SetAtLeast("1FFFFF1FF"); } } else if (dimA == DimensionType.Curve && dimB == DimensionType.Surface) { if (hasProper) { im.SetAtLeast("F0FFFFFF2"); } if (hasProperInterior) { im.SetAtLeast("1F1FFFFFF"); } } else if (dimA == DimensionType.Curve && dimB == DimensionType.Curve) { /* If edges of LineStrings properly intersect *in an interior point*, all we can deduce is that the interiors intersect. (We can NOT deduce that the exteriors intersect, since some other segments in the geometries might cover the points in the neighbourhood of the intersection.) It is important that the point be known to be an interior point of both Geometries, since it is possible in a self-intersecting point to have a proper intersection on one segment that is also a boundary point of another segment. */ if (hasProperInterior) { im.SetAtLeast("0FFFFFFFF"); } } }