예제 #1
0
            /// <summary>
            ///
            /// </summary>
            /// <param name="mc1"></param>
            /// <param name="start1"></param>
            /// <param name="mc2"></param>
            /// <param name="start2"></param>
            public override void Overlap(MonotoneChain mc1, int start1, MonotoneChain mc2, int start2)
            {
                SegmentString ss1 = (SegmentString)mc1.Context;
                SegmentString ss2 = (SegmentString)mc2.Context;

                si.ProcessIntersections(ss1, start1, ss2, start2);
            }
        /// <summary>
        /// This method is called by clients
        /// of the <see cref="ISegmentIntersector" /> class to process
        /// intersections for two segments of the <see cref="SegmentString" />s being intersected.
        /// Note that some clients (such as <see cref="MonotoneChain" />s) may optimize away
        /// this call for segment pairs which they have determined do not intersect
        /// (e.g. by an disjoint envelope test).
        /// </summary>
        /// <param name="e0"></param>
        /// <param name="segIndex0"></param>
        /// <param name="e1"></param>
        /// <param name="segIndex1"></param>
        public void ProcessIntersections(SegmentString e0, int segIndex0, SegmentString e1, int segIndex1)
        {
            // don't bother intersecting a segment with itself
            if (e0 == e1 && segIndex0 == segIndex1)
            {
                return;
            }

            ICoordinate p00 = e0.Coordinates[segIndex0];
            ICoordinate p01 = e0.Coordinates[segIndex0 + 1];
            ICoordinate p10 = e1.Coordinates[segIndex1];
            ICoordinate p11 = e1.Coordinates[segIndex1 + 1];

            li.ComputeIntersection(p00, p01, p10, p11);

            if (li.HasIntersection)
            {
                if (li.IsInteriorIntersection())
                {
                    for (int intIndex = 0; intIndex < li.IntersectionNum; intIndex++)
                    {
                        interiorIntersections.Add(li.GetIntersection(intIndex));
                    }

                    e0.AddIntersections(li, segIndex0, 0);
                    e1.AddIntersections(li, segIndex1, 1);
                }
            }
        }
예제 #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SegmentNode"/> class.
 /// </summary>
 /// <param name="segString"></param>
 /// <param name="coord"></param>
 /// <param name="segmentIndex"></param>
 /// <param name="segmentOctant"></param>
 public SegmentNode(SegmentString segString, ICoordinate coord, int segmentIndex, Octants segmentOctant)
 {
     this.segString     = segString;
     this.Coordinate    = new Coordinate(coord);
     this.SegmentIndex  = segmentIndex;
     this.segmentOctant = segmentOctant;
     isInterior         = !coord.Equals2D(segString.GetCoordinate(segmentIndex));
 }
 /// <summary>
 /// Checks if a segment string contains a segment pattern a-b-a (which implies a self-intersection).
 /// </summary>
 private void CheckCollapses()
 {
     foreach (object obj in segStrings)
     {
         SegmentString ss = (SegmentString)obj;
         CheckCollapses(ss);
     }
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="ss"></param>
 private void CheckCollapses(SegmentString ss)
 {
     ICoordinate[] pts = ss.Coordinates;
     for (int i = 0; i < pts.Length - 2; i++)
     {
         CheckCollapse(pts[i], pts[i + 1], pts[i + 2]);
     }
 }
예제 #6
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="segStrings"></param>
 /// <returns></returns>
 private IList Scale(IList segStrings)
 {
     return(CollectionUtil.Transform(segStrings, delegate(object obj)
     {
         SegmentString ss = (SegmentString)obj;
         return new SegmentString(Scale(ss.Coordinates), ss.Data);
     }));
 }
예제 #7
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="segStrings"></param>
 /// <param name="resultEdgelist"></param>
 public static void GetNodedSubstrings(IList segStrings, IList resultEdgelist)
 {
     foreach (object obj in segStrings)
     {
         SegmentString ss = (SegmentString)obj;
         ss.NodeList.AddSplitEdges(resultEdgelist);
     }
 }
예제 #8
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="segStrings"></param>
 private void Rescale(IList segStrings)
 {
     CollectionUtil.Apply(segStrings, delegate(object obj)
     {
         SegmentString ss = (SegmentString)obj;
         Rescale(ss.Coordinates);
         return(null);
     });
 }
 /// <summary>
 /// Checks for intersections between an endpoint of a segment string
 /// and an interior vertex of another segment string
 /// </summary>
 private void CheckEndPtVertexIntersections()
 {
     foreach (object obj in segStrings)
     {
         SegmentString ss  = (SegmentString)obj;
         ICoordinate[] pts = ss.Coordinates;
         CheckEndPtVertexIntersections(pts[0], segStrings);
         CheckEndPtVertexIntersections(pts[pts.Length - 1], segStrings);
     }
 }
예제 #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="segStr"></param>
        private void Add(SegmentString segStr)
        {
            IList segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr);

            foreach (object obj in segChains)
            {
                MonotoneChain mc = (MonotoneChain)obj;
                mc.Id = idCounter++;
                index.Insert(mc.Envelope, mc);
                monoChains.Add(mc);
            }
        }
예제 #11
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="e0"></param>
 /// <param name="e1"></param>
 private void ComputeIntersects(SegmentString e0, SegmentString e1)
 {
     ICoordinate[] pts0 = e0.Coordinates;
     ICoordinate[] pts1 = e1.Coordinates;
     for (int i0 = 0; i0 < pts0.Length - 1; i0++)
     {
         for (int i1 = 0; i1 < pts1.Length - 1; i1++)
         {
             SegmentIntersector.ProcessIntersections(e0, i0, e1, i1);
         }
     }
 }
 /// <summary>
 /// Checks all pairs of segments for intersections at an interior point of a segment.
 /// </summary>
 private void CheckInteriorIntersections()
 {
     foreach (object obj0 in segStrings)
     {
         SegmentString ss0 = (SegmentString)obj0;
         foreach (object obj1 in segStrings)
         {
             SegmentString ss1 = (SegmentString)obj1;
             CheckInteriorIntersections(ss0, ss1);
         }
     }
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="ss0"></param>
 /// <param name="ss1"></param>
 private void CheckInteriorIntersections(SegmentString ss0, SegmentString ss1)
 {
     ICoordinate[] pts0 = ss0.Coordinates;
     ICoordinate[] pts1 = ss1.Coordinates;
     for (int i0 = 0; i0 < pts0.Length - 1; i0++)
     {
         for (int i1 = 0; i1 < pts1.Length - 1; i1++)
         {
             CheckInteriorIntersections(ss0, i0, ss1, i1);
         }
     }
 }
예제 #14
0
 /// <summary>
 /// Computes the noding for a collection of <see cref="SegmentString" />s.
 /// Some Noders may add all these nodes to the input <see cref="SegmentString" />s;
 /// others may only add some or none at all.
 /// </summary>
 /// <param name="inputSegStrings"></param>
 public override void ComputeNodes(IList inputSegStrings)
 {
     this.nodedSegStrings = inputSegStrings;
     foreach (object obj0 in inputSegStrings)
     {
         SegmentString edge0 = (SegmentString)obj0;
         foreach (object obj1 in inputSegStrings)
         {
             SegmentString edge1 = (SegmentString)obj1;
             ComputeIntersects(edge0, edge1);
         }
     }
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="testPt"></param>
 /// <param name="segStrings"></param>
 private void CheckEndPtVertexIntersections(ICoordinate testPt, IList segStrings)
 {
     foreach (object obj in segStrings)
     {
         SegmentString ss  = (SegmentString)obj;
         ICoordinate[] pts = ss.Coordinates;
         for (int j = 1; j < pts.Length - 1; j++)
         {
             if (pts[j].Equals(testPt))
             {
                 throw new Exception("found endpt/interior pt intersection at index " + j + " :pt " + testPt);
             }
         }
     }
 }
예제 #16
0
        /// <summary>
        /// Dissolve the given <see cref="SegmentString" />.
        /// </summary>
        /// <param name="segString"></param>
        public void Dissolve(SegmentString segString)
        {
            OrientedCoordinateArray oca      = new OrientedCoordinateArray(segString.Coordinates);
            SegmentString           existing = FindMatching(oca, segString);

            if (existing == null)
            {
                Add(oca, segString);
            }
            else
            {
                if (merger != null)
                {
                    bool isSameOrientation = CoordinateArrays.Equals(existing.Coordinates, segString.Coordinates);
                    merger.Merge(existing, segString, isSameOrientation);
                }
            }
        }
        /// <summary>
        /// Creates new edges for all the edges that the intersections in this
        /// list split the parent edge into.
        /// Adds the edges to the provided argument list
        /// (this is so a single list can be used to accumulate all split edges
        /// for a set of <see cref="SegmentString" />s).
        /// </summary>
        /// <param name="edgeList"></param>
        public void AddSplitEdges(IList edgeList)
        {
            // ensure that the list has entries for the first and last point of the edge
            AddEndPoints();
            AddCollapsedNodes();

            IEnumerator ie = GetEnumerator();

            ie.MoveNext();

            // there should always be at least two entries in the list, since the endpoints are nodes
            SegmentNode eiPrev = (SegmentNode)ie.Current;

            while (ie.MoveNext())
            {
                SegmentNode   ei      = (SegmentNode)ie.Current;
                SegmentString newEdge = CreateSplitEdge(eiPrev, ei);
                edgeList.Add(newEdge);
                eiPrev = ei;
            }
            // CheckSplitEdgesCorrectness(testingSplitEdges);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="e0"></param>
        /// <param name="segIndex0"></param>
        /// <param name="e1"></param>
        /// <param name="segIndex1"></param>
        private void CheckInteriorIntersections(SegmentString e0, int segIndex0, SegmentString e1, int segIndex1)
        {
            if (e0 == e1 && segIndex0 == segIndex1)
            {
                return;
            }

            ICoordinate p00 = e0.Coordinates[segIndex0];
            ICoordinate p01 = e0.Coordinates[segIndex0 + 1];
            ICoordinate p10 = e1.Coordinates[segIndex1];
            ICoordinate p11 = e1.Coordinates[segIndex1 + 1];

            li.ComputeIntersection(p00, p01, p10, p11);
            if (li.HasIntersection)
            {
                if (li.IsProper || HasInteriorIntersection(li, p00, p01) || HasInteriorIntersection(li, p10, p11))
                {
                    throw new Exception("found non-noded intersection at " + p00 + "-" + p01
                                        + " and " + p10 + "-" + p11);
                }
            }
        }
        /// <summary>
        /// This method is called by clients
        /// of the <see cref="ISegmentIntersector" /> class to process
        /// intersections for two segments of the <see cref="SegmentString" /> being intersected.
        /// Note that some clients (such as <see cref="MonotoneChain" />s) may optimize away
        /// this call for segment pairs which they have determined do not intersect
        /// (e.g. by an disjoint envelope test).
        /// </summary>
        /// <param name="e0"></param>
        /// <param name="segIndex0"></param>
        /// <param name="e1"></param>
        /// <param name="segIndex1"></param>
        public void ProcessIntersections(SegmentString e0, int segIndex0, SegmentString e1, int segIndex1)
        {
            if (e0 == e1 && segIndex0 == segIndex1)
            {
                return;
            }

            NumTests++;
            ICoordinate p00 = e0.Coordinates[segIndex0];
            ICoordinate p01 = e0.Coordinates[segIndex0 + 1];
            ICoordinate p10 = e1.Coordinates[segIndex1];
            ICoordinate p11 = e1.Coordinates[segIndex1 + 1];

            li.ComputeIntersection(p00, p01, p10, p11);
            if (li.HasIntersection)
            {
                NumIntersections++;
                if (li.IsInteriorIntersection())
                {
                    NumInteriorIntersections++;
                    hasInterior = true;
                }
                // if the segments are adjacent they have at least one trivial intersection,
                // the shared endpoint.  Don't bother adding it if it is the
                // only intersection.
                if (!IsTrivialIntersection(e0, segIndex0, e1, segIndex1))
                {
                    hasIntersection = true;
                    e0.AddIntersections(li, segIndex0, 0);
                    e1.AddIntersections(li, segIndex1, 1);
                    if (li.IsProper)
                    {
                        NumProperIntersections++;
                        hasProper         = true;
                        hasProperInterior = true;
                    }
                }
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="splitEdges"></param>
        private void CheckSplitEdgesCorrectness(IList splitEdges)
        {
            ICoordinate[] edgePts = edge.Coordinates;

            // check that first and last points of split edges are same as endpoints of edge
            SegmentString split0 = (SegmentString)splitEdges[0];
            ICoordinate   pt0    = split0.GetCoordinate(0);

            if (!pt0.Equals2D(edgePts[0]))
            {
                throw new Exception("bad split edge start point at " + pt0);
            }

            SegmentString splitn = (SegmentString)splitEdges[splitEdges.Count - 1];

            ICoordinate[] splitnPts = splitn.Coordinates;
            ICoordinate   ptn       = splitnPts[splitnPts.Length - 1];

            if (!ptn.Equals2D(edgePts[edgePts.Length - 1]))
            {
                throw new Exception("bad split edge end point at " + ptn);
            }
        }
 /// <summary>
 /// A trivial intersection is an apparent self-intersection which in fact
 /// is simply the point shared by adjacent line segments.
 /// Note that closed edges require a special check for the point shared by the beginning and end segments.
 /// </summary>
 /// <param name="e0"></param>
 /// <param name="segIndex0"></param>
 /// <param name="e1"></param>
 /// <param name="segIndex1"></param>
 /// <returns></returns>
 private bool IsTrivialIntersection(SegmentString e0, int segIndex0, SegmentString e1, int segIndex1)
 {
     if (e0 == e1)
     {
         if (li.IntersectionNum == 1)
         {
             if (IsAdjacentSegments(segIndex0, segIndex1))
             {
                 return(true);
             }
             if (e0.IsClosed)
             {
                 int maxSegIndex = e0.Count - 1;
                 if ((segIndex0 == 0 && segIndex1 == maxSegIndex) ||
                     (segIndex1 == 0 && segIndex0 == maxSegIndex))
                 {
                     return(true);
                 }
             }
         }
     }
     return(false);
 }
 NodeVertexIterator(SegmentNodeList nodeList)
 {
     this.nodeList = nodeList;
     edge          = nodeList.Edge;
     nodeIt        = nodeList.GetEnumerator();
 }
        private SegmentString edge  = null; // the parent edge

        /// <summary>
        /// Initializes a new instance of the <see cref="SegmentNodeList"/> class.
        /// </summary>
        /// <param name="edge">The edge.</param>
        public SegmentNodeList(SegmentString edge)
        {
            this.edge = edge;
        }
예제 #24
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="oca"></param>
 /// <param name="segString"></param>
 /// <returns></returns>
 private SegmentString FindMatching(OrientedCoordinateArray oca, SegmentString segString)
 {
     return((SegmentString)ocaMap[oca]);
 }
예제 #25
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="oca"></param>
 /// <param name="segString"></param>
 private void Add(OrientedCoordinateArray oca, SegmentString segString)
 {
     ocaMap.Add(oca, segString);
 }
예제 #26
0
 /// <summary>
 /// Returns a <see cref="IList"/> of fully noded <see cref="SegmentString"/>s.
 /// The <see cref="SegmentString"/>s have the same context as their parent.
 /// </summary>
 /// <returns></returns>
 public override IList GetNodedSubstrings()
 {
     return(SegmentString.GetNodedSubstrings(nodedSegStrings));
 }