/// <summary>
        /// This method is called by clients
        /// of the <see cref="ISegmentIntersector" /> class to process
        /// intersections for two segments of the <see cref="ISegmentString" />s being intersected.<br/>
        /// Note that some clients (such as <c>MonotoneChain</c>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(ISegmentString e0, int segIndex0, ISegmentString e1, int segIndex1)
        {
            // don't bother intersecting a segment with itself
            if (e0 == e1 && segIndex0 == segIndex1)
            {
                return;
            }

            Coordinate[] coordinates0 = e0.Coordinates;
            Coordinate   p00          = coordinates0[segIndex0];
            Coordinate   p01          = coordinates0[segIndex0 + 1];

            Coordinate[] coordinates1 = e1.Coordinates;
            Coordinate   p10          = coordinates1[segIndex1];
            Coordinate   p11          = coordinates1[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));
                    }

                    ((NodedSegmentString)e0).AddIntersections(_li, segIndex0, 0);
                    ((NodedSegmentString)e1).AddIntersections(_li, segIndex1, 1);
                }
            }
        }
        /// <summary>
        /// Test if two segments are adjacent segments on the same SegmentString.
        /// Note that closed edges require a special check for the point shared by the beginning
        /// and end segments.
        /// </summary>
        private static bool IsAdjacent(ISegmentString e0, int segIndex0, ISegmentString e1, int segIndex1)
        {
            if (e0 != e1)
            {
                return(false);
            }

            bool isAdjacent = Math.Abs(segIndex0 - segIndex1) == 1;

            if (isAdjacent)
            {
                return(true);
            }
            if (e0.IsClosed)
            {
                int maxSegIndex = e0.Count - 1;
                if ((segIndex0 == 0 && segIndex1 == maxSegIndex) ||
                    (segIndex1 == 0 && segIndex0 == maxSegIndex))
                {
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// If an endpoint of one segment is near
        /// the <i>interior</i> of the other segment, add it as an intersection.
        /// EXCEPT if the endpoint is also close to a segment endpoint
        /// (since this can introduce "zigs" in the linework).
        /// <para/>
        /// This resolves situations where
        /// a segment A endpoint is extremely close to another segment B,
        /// but is not quite crossing.  Due to robustness issues
        /// in orientation detection, this can
        /// result in the snapped segment A crossing segment B
        /// without a node being introduced.
        /// </summary>
        private void ProcessNearVertex(ISegmentString srcSS, int srcIndex, Coordinate p, ISegmentString ss, int segIndex, Coordinate p0, Coordinate p1)
        {
            /*
             * Don't add intersection if candidate vertex is near endpoints of segment.
             * This avoids creating "zig-zag" linework
             * (since the vertex could actually be outside the segment envelope).
             * Also, this should have already been snapped.
             */
            if (p.Distance(p0) < _snapTolerance)
            {
                return;
            }
            if (p.Distance(p1) < _snapTolerance)
            {
                return;
            }

            double distSeg = DistanceComputer.PointToSegment(p, p0, p1);

            if (distSeg < _snapTolerance)
            {
                // add vertex to target segment
                ((NodedSegmentString)ss).AddIntersection(p, segIndex);
                // add node at vertex to source SS
                ((NodedSegmentString)srcSS).AddIntersection(p, srcIndex);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Snaps (nodes) all interacting segments to this hot pixel.
        /// The hot pixel may represent a vertex of an edge,
        /// in which case this routine uses the optimization
        /// of not noding the vertex itself
        /// </summary>
        /// <param name="hotPixel">The hot pixel to snap to.</param>
        /// <param name="parentEdge">The edge containing the vertex, if applicable, or <c>null</c>.</param>
        /// <param name="hotPixelVertexIndex"></param>
        /// <returns><c>true</c> if a node was added for this pixel.</returns>
        public bool Snap(HotPixel hotPixel, ISegmentString parentEdge, int hotPixelVertexIndex)
        {
            var pixelEnv           = hotPixel.GetSafeEnvelope();
            var hotPixelSnapAction = new HotPixelSnapAction(hotPixel, parentEdge, hotPixelVertexIndex);

            _index.Query(pixelEnv, new QueryVisitor(pixelEnv, hotPixelSnapAction));
            return(hotPixelSnapAction.IsNodeAdded);
        }
 private void CheckInteriorIntersections(ISegmentString ss0, ISegmentString ss1)
 {
     var pts0 = ss0.Coordinates;
     var pts1 = ss1.Coordinates;
     for (var i0 = 0; i0 < pts0.Length - 1; i0++)
         for (var i1 = 0; i1 < pts1.Length - 1; i1++)
             CheckInteriorIntersections(ss0, i0, ss1, i1);            
 }
 private static void AddToMonoChains(ISegmentString segStr, List<MonotoneChain> monotoneChains)
 {
     var segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr);
     foreach (var mc in segChains)
     {
         monotoneChains.Add(mc);
     }
 }
 private void AddToIndex(ISegmentString segStr)
 {
     var segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr);
     foreach (var mc in segChains)
     {
         _index.Insert(mc.Envelope, mc);
     }
 }
Ejemplo n.º 8
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="e0"></param>
 /// <param name="e1"></param>
 private void ComputeIntersects(ISegmentString e0, ISegmentString e1)
 {
     Coordinate[] pts0 = e0.Coordinates;
     Coordinate[] 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);
 }
Ejemplo n.º 9
0
        private static void CheckCollapses(ISegmentString ss)
        {
            var pts = ss.Coordinates;

            for (int i = 0; i < pts.Length - 2; i++)
            {
                CheckCollapse(pts[i], pts[i + 1], pts[i + 2]);
            }
        }
        private static void AddToMonoChains(ISegmentString segStr, List <MonotoneChain> monotoneChains)
        {
            var segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr);

            foreach (var mc in segChains)
            {
                monotoneChains.Add(mc);
            }
        }
        private void AddToIndex(ISegmentString segStr)
        {
            var segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr);

            foreach (var mc in segChains)
            {
                _index.Insert(mc.Envelope, mc);
            }
        }
        private void AddToMonoChains(ISegmentString segStr, List <MonotoneChain> monotoneChains)
        {
            IList <MonotoneChain> segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr);

            foreach (MonotoneChain mc in segChains)
            {
                mc.Id = _processCounter++;
                monotoneChains.Add(mc);
            }
        }
        private void AddToIndex(ISegmentString segStr)
        {
            IList <MonotoneChain> segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr);

            foreach (MonotoneChain mc in segChains)
            {
                mc.Id = _indexCounter++;
                _index.Insert(mc.Envelope, mc);
            }
        }
        ///<summary>
        /// This method is called by clients of the <see cref="ISegmentIntersector"/> class to process
        /// intersections for two segments of the <see cref="ISegmentString"/>s being intersected.<br/>
        /// Note that some clients (such as <c>MonotoneChain</c>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(
            ISegmentString e0, int segIndex0,
            ISegmentString e1, int segIndex1
            )
        {
            // short-circuit if intersection already found
            if (!FindAllIntersections && HasIntersection)
            {
                return;
            }

            // don't bother intersecting a segment with itself
            if (e0 == e1 && segIndex0 == segIndex1)
            {
                return;
            }

            /*
             * If enabled, only test end segments (on either segString).
             *
             */
            if (CheckEndSegmentsOnly)
            {
                Boolean isEndSegPresent = IsEndSegment(e0, segIndex0) || IsEndSegment(e1, segIndex1);
                if (!isEndSegPresent)
                {
                    return;
                }
            }

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

            _li.ComputeIntersection(p00, p01, p10, p11);
            if (_li.HasIntersection)
            {
                if (_li.IsInteriorIntersection())
                {
                    _intSegments    = new Coordinate[4];
                    _intSegments[0] = p00;
                    _intSegments[1] = p01;
                    _intSegments[2] = p10;
                    _intSegments[3] = p11;

                    _interiorIntersection = _li.GetIntersection(0);
                    if (KeepIntersections)
                    {
                        _intersections.Add(_interiorIntersection);
                    }
                    intersectionCount++;
                }
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="segStr"></param>
        private void Add(ISegmentString segStr)
        {
            var segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr);

            foreach (var mc in segChains)
            {
                mc.Id = _idCounter++;
                _index.Insert(mc.Envelope, mc);
                _monoChains.Add(mc);
            }
        }
Ejemplo n.º 16
0
 private static IGeometry ConvertSegStrings(IEnumerator<ISegmentString> it)
 {
     var fact = new GeometryFactory();
     var lines = new List<IGeometry>();
     while (it.MoveNext())
     {
         ISegmentString ss = it.Current;
         ILineString line = fact.CreateLineString(ss.Coordinates);
         lines.Add(line);
     }
     return fact.BuildGeometry(lines);
 }
Ejemplo n.º 17
0
 ///<summary>
 /// Tests whether a segment in a <see cref="ISegmentString" /> is an end segment.
 /// (either the first or last).
 ///</summary>
 ///<param name="segStr">a segment string</param>
 ///<param name="index">the index of a segment in the segment string</param>
 ///<returns>true if the segment is an end segment</returns>
 private static Boolean IsEndSegment(ISegmentString segStr, int index)
 {
     if (index == 0)
     {
         return(true);
     }
     if (index >= segStr.Count - 2)
     {
         return(true);
     }
     return(false);
 }
Ejemplo n.º 18
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="segStr"></param>
        private void Add(ISegmentString segStr)
        {
            var segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr);

            foreach (var mc in segChains)
            {
                mc.Id = _idCounter++;
                //mc.OverlapTolerance = _overlapTolerance;
                _index.Insert(mc.GetEnvelope(_overlapTolerance), mc);
                _monoChains.Add(mc);
            }
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Test if the segmentString is a collapsed edge
        /// of the form ABA.
        /// These should not be returned by noding.
        /// </summary>
        /// <param name="s">A segment string</param>
        /// <returns><c>true</c> if the segment string is collapsed</returns>
        private bool IsCollapsed(ISegmentString s)
        {
            if (s.Count != 3)
            {
                return(false);
            }
            bool isEndsEqual       = s.Coordinates[0].Equals2D(s.Coordinates[2]);
            bool isMiddleDifferent = !s.Coordinates[0].Equals2D(s.Coordinates[1]);
            bool isCollapsed       = isEndsEqual && isMiddleDifferent;

            return(isCollapsed);
        }
Ejemplo n.º 20
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="e0"></param>
 /// <param name="e1"></param>
 private void ComputeIntersects(ISegmentString e0, ISegmentString e1)
 {
     Coordinate[] pts0 = e0.Coordinates;
     Coordinate[] 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);
         }
     }
 }
Ejemplo n.º 21
0
        private void CheckInteriorIntersections(ISegmentString ss0, ISegmentString ss1)
        {
            var pts0 = ss0.Coordinates;
            var 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);
                }
            }
        }
        ///<summary>
        /// This method is called by clients of the <see cref="ISegmentIntersector"/> class to process
        /// intersections for two segments of the <see cref="ISegmentString"/>s being intersected.
        ///</summary>
        /// <remarks>
        /// 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).
        /// </remarks>
        public void ProcessIntersections(
            ISegmentString e0, int segIndex0,
            ISegmentString e1, int segIndex1
            )
        {
            // don't intersect segment with itself
            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() && li.isProper()) Debug.println(li);
            if (li.HasIntersection)
            {
                //intersectionFound = true;
                NumIntersections++;
                if (li.IsInteriorIntersection())
                {
                    NumInteriorIntersections++;
                    _hasInterior = true;
                    //System.out.println(li);
                }
                // 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;

                    // only add intersection to test geom (the line)
                    ((NodedSegmentString)e1).AddIntersections(li, segIndex1, 1);

                    if (li.IsProper)
                    {
                        NumProperIntersections++;
                        //Debug.println(li.toString());  Debug.println(li.getIntersection(0));
                        //properIntersectionPoint = (Coordinate) li.getIntersection(0).clone();
                        _hasProper         = true;
                        _hasProperInterior = true;
                    }
                }
            }
        }
 /// <summary>
 /// Processes all of the segment pairs in the given segment strings
 /// using the given <paramref name="segInt">SegmentIntersector</paramref>.
 /// </summary>
 /// <param name="ss0">A segment string</param>
 /// <param name="ss1">A segment string</param>
 /// <param name="segInt">The segment intersector to use</param>
 private static void Intersect(ISegmentString ss0, ISegmentString ss1, ISegmentIntersector segInt)
 {
     var pts0 = ss0.Coordinates;
     var pts1 = ss1.Coordinates;
     for (var i0 = 0; i0 < pts0.Length - 1; i0++)
     {
         for (var i1 = 0; i1 < pts1.Length - 1; i1++)
         {
             segInt.ProcessIntersections(ss0, i0, ss1, i1);
             if (segInt.IsDone)
                 return;
         }
     }
 }
Ejemplo n.º 24
0
        private static void ExtractSegments(ISegmentString ss, List <ISegmentString> segList)
        {
            var    coords  = ss.Coordinates;
            object context = ss.Context;
            int    cnt     = ss.Count;

            for (int i = 0; i < cnt - 1; i++)
            {
                var p0  = coords[i];
                var p1  = coords[i + 1];
                var seg = new BasicSegmentString(new Coordinate[] { p0, p1 }, context);
                segList.Add(seg);
            }
        }
        private void CheckInteriorIntersections(ISegmentString e0, int segIndex0, ISegmentString e1, int segIndex1)
        {
            if (e0 == e1 && segIndex0 == segIndex1) 
                return;

            var p00 = e0.Coordinates[segIndex0];
            var p01 = e0.Coordinates[segIndex0 + 1];
            var p10 = e1.Coordinates[segIndex1];
            var 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 ApplicationException(String.Format(
                        "found non-noded intersection at {0}-{1} and {2}-{3}", p00, p01, 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="ISegmentString"/>s being intersected.
        /// Note that some clients (such as <c>MonotoneChain</c>s) may optimize away
        /// this call for segment pairs which they have determined do not intersect
        /// (e.g. by an disjoint envelope test).
        /// </summary>
        public void ProcessIntersections(
            ISegmentString seg0, int segIndex0,
            ISegmentString seg1, int segIndex1
            )
        {
            // don't bother intersecting a segment with itself
            if (seg0 == seg1 && segIndex0 == segIndex1)
            {
                return;
            }

            var p00 = seg0.Coordinates[segIndex0];
            var p01 = seg0.Coordinates[segIndex0 + 1];
            var p10 = seg1.Coordinates[segIndex1];
            var p11 = seg1.Coordinates[segIndex1 + 1];

            /*
             * Don't node intersections which are just
             * due to the shared vertex of adjacent segments.
             */
            if (!IsAdjacent(seg0, segIndex0, seg1, segIndex1))
            {
                _li.ComputeIntersection(p00, p01, p10, p11);
                //if (_li.HasIntersection && _li.IsProper) System.Diagnostics.Debug.WriteLine(_li);

                /*
                 * Process single point intersections only.
                 * Two-point (colinear) ones will be handled by the near-vertex code
                 */
                if (_li.HasIntersection && _li.IntersectionNum == 1)
                {
                    var intPt  = _li.GetIntersection(0);
                    var snapPt = _snapPointIndex.Snap(intPt);

                    ((NodedSegmentString)seg0).AddIntersection(snapPt, segIndex0);
                    ((NodedSegmentString)seg1).AddIntersection(snapPt, segIndex1);
                }
            }

            /*
             * The segments must also be snapped to the other segment endpoints.
             */
            ProcessNearVertex(seg0, segIndex0, p00, seg1, segIndex1, p10, p11);
            ProcessNearVertex(seg0, segIndex0, p01, seg1, segIndex1, p10, p11);
            ProcessNearVertex(seg1, segIndex1, p10, seg0, segIndex0, p00, p01);
            ProcessNearVertex(seg1, segIndex1, p11, seg0, segIndex0, p00, p01);
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Processes all of the segment pairs in the given segment strings
        /// using the given <paramref name="segInt">SegmentIntersector</paramref>.
        /// </summary>
        /// <param name="ss0">A segment string</param>
        /// <param name="ss1">A segment string</param>
        /// <param name="segInt">The segment intersector to use</param>
        private static void Intersect(ISegmentString ss0, ISegmentString ss1, ISegmentIntersector segInt)
        {
            var pts0 = ss0.Coordinates;
            var pts1 = ss1.Coordinates;

            for (int i0 = 0; i0 < pts0.Length - 1; i0++)
            {
                for (int i1 = 0; i1 < pts1.Length - 1; i1++)
                {
                    segInt.ProcessIntersections(ss0, i0, ss1, i1);
                    if (segInt.IsDone)
                    {
                        return;
                    }
                }
            }
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Dissolve the given <see cref="ISegmentString" />.
        /// </summary>
        /// <param name="segString"></param>
        public void Dissolve(ISegmentString segString)
        {
            var oca      = new OrientedCoordinateArray(segString.Coordinates);
            var 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);
                }
            }
        }
Ejemplo n.º 29
0
        /// <summary>
        /// This method is called by clients
        /// of the <see cref="ISegmentIntersector"/> class to process
        /// intersections for two segments of the <see cref="ISegmentString"/>
        /// s being intersected.
        /// Note that some clients (such as <c>MonotoneChain</c> s) may optimize away
        /// this call for segment pairs which they have determined do not intersect
        /// (e.g.by an disjoint envelope test).
        /// </summary>
        public void ProcessIntersections(
            ISegmentString e0, int segIndex0,
            ISegmentString e1, int segIndex1
            )
        {
            // don't bother intersecting a segment with itself
            if (e0 == e1 && segIndex0 == segIndex1)
            {
                return;
            }

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

            _li.ComputeIntersection(p00, p01, p10, p11);
            //if (li.hasIntersection() && li.isProper()) Debug.println(li);

            if (_li.HasIntersection)
            {
                if (_li.IsInteriorIntersection())
                {
                    for (int intIndex = 0; intIndex < _li.IntersectionNum; intIndex++)
                    {
                        Intersections.Add(_li.GetIntersection(intIndex));
                    }
                    ((NodedSegmentString)e0).AddIntersections(_li, segIndex0, 0);
                    ((NodedSegmentString)e1).AddIntersections(_li, segIndex1, 1);
                    return;
                }
            }

            /*
             * Segments did not actually intersect, within the limits of orientation index robustness.
             *
             * To avoid certain robustness issues in snap-rounding,
             * also treat very near vertex-segment situations as intersections.
             */
            ProcessNearVertex(p00, e1, segIndex1, p10, p11);
            ProcessNearVertex(p01, e1, segIndex1, p10, p11);
            ProcessNearVertex(p10, e0, segIndex0, p00, p01);
            ProcessNearVertex(p11, e0, segIndex0, p00, p01);
        }
Ejemplo n.º 30
0
        /// <summary>
        /// This method is called by clients
        /// of the <see cref="ISegmentIntersector" /> class to process
        /// intersections for two segments of the <see cref="ISegmentString" /> being intersected.<br/>
        /// Note that some clients (such as <c>MonotoneChain</c>") 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(ISegmentString e0, int segIndex0, ISegmentString e1, int segIndex1)
        {
            if (e0 == e1 && segIndex0 == segIndex1)
            {
                return;
            }

            NumTests++;
            Coordinate[] coordinates0 = e0.Coordinates;
            Coordinate   p00          = coordinates0[segIndex0];
            Coordinate   p01          = coordinates0[segIndex0 + 1];

            Coordinate[] coordinates1 = e1.Coordinates;
            Coordinate   p10          = coordinates1[segIndex1];
            Coordinate   p11          = coordinates1[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;
                    ((NodedSegmentString)e0).AddIntersections(_li, segIndex0, 0);
                    ((NodedSegmentString)e1).AddIntersections(_li, segIndex1, 1);
                    if (_li.IsProper)
                    {
                        NumProperIntersections++;
                        _hasProper         = true;
                        _hasProperInterior = true;
                    }
                }
            }
        }
Ejemplo n.º 31
0
        private void CheckInteriorIntersections(ISegmentString e0, int segIndex0, ISegmentString e1, int segIndex1)
        {
            if (e0 == e1 && segIndex0 == segIndex1)
            {
                return;
            }

            var p00 = e0.Coordinates[segIndex0];
            var p01 = e0.Coordinates[segIndex0 + 1];
            var p10 = e1.Coordinates[segIndex1];
            var 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 ApplicationException(string.Format(
                                                       "found non-noded intersection at {0}-{1} and {2}-{3}", p00, p01, p10, p11));
                }
            }
        }
 /// <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(ISegmentString e0, int segIndex0, ISegmentString 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);
 }
Ejemplo n.º 33
0
        /// <summary>
        /// If an endpoint of one segment is near
        /// the <i>interior</i> of the other segment, add it as an intersection.
        /// EXCEPT if the endpoint is also close to a segment endpoint
        /// (since this can introduce "zigs" in the linework).
        /// <para/>
        /// This resolves situations where
        /// a segment A endpoint is extremely close to another segment B,
        /// but is not quite crossing.Due to robustness issues
        /// in orientation detection, this can
        /// result in the snapped segment A crossing segment B
        /// without a node being introduced.
        /// </summary>
        private void ProcessNearVertex(Coordinate p, ISegmentString edge, int segIndex, Coordinate p0, Coordinate p1)
        {
            /*
             * Don't add intersection if candidate vertex is near endpoints of segment.
             * This avoids creating "zig-zag" linework
             * (since the vertex could actually be outside the segment envelope).
             */
            if (p.Distance(p0) < _nearnessTol)
            {
                return;
            }
            if (p.Distance(p1) < _nearnessTol)
            {
                return;
            }

            double distSeg = DistanceComputer.PointToSegment(p, p0, p1);

            if (distSeg < _nearnessTol)
            {
                Intersections.Add(p);
                ((NodedSegmentString)edge).AddIntersection(p, segIndex);
            }
        }
        /// <summary>
        /// This method is called by clients
        /// of the <see cref="ISegmentIntersector" /> class to process
        /// intersections for two segments of the <see cref="ISegmentString" />s being intersected.<br/>
        /// Note that some clients (such as <c>MonotoneChain</c>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(ISegmentString e0, int segIndex0, ISegmentString e1, int segIndex1)
        {
            // don't bother intersecting a segment with itself
            if (e0 == e1 && segIndex0 == segIndex1)
                return;

            Coordinate[] coordinates0 = e0.Coordinates;
            Coordinate p00 = coordinates0[segIndex0];
            Coordinate p01 = coordinates0[segIndex0 + 1];
            Coordinate[] coordinates1 = e1.Coordinates;
            Coordinate p10 = coordinates1[segIndex1];
            Coordinate p11 = coordinates1[segIndex1 + 1];
            _li.ComputeIntersection(p00, p01, p10, p11);

            if (!_li.HasIntersection) return;
            if (!_li.IsInteriorIntersection()) return;
            for (int intIndex = 0; intIndex < _li.IntersectionNum; intIndex++)
                _interiorIntersections.Add(_li.GetIntersection(intIndex));

            NodedSegmentString nss0 = (NodedSegmentString)e0;
            nss0.AddIntersections(_li, segIndex0, 0);
            NodedSegmentString nss1 = (NodedSegmentString)e1;
            nss1.AddIntersections(_li, segIndex1, 1);
        }
Ejemplo n.º 35
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="segStr"></param>
 private void Add(ISegmentString segStr)
 {
     var segChains = MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr);
     foreach (var mc in segChains)
     {
         mc.Id = _idCounter++;
         _index.Insert(mc.Envelope, mc);
         _monoChains.Add(mc);
     }
 }
 ///<summary>
 /// A trivial intersection is an apparent self-intersection which in fact
 /// is simply the point shared by adjacent line segments.
 ///</summary>
 /// <remarks>
 /// Note that closed edges require a special check for the point shared by the beginning
 /// and end segments.
 /// </remarks>
 private bool IsTrivialIntersection(ISegmentString e0, int segIndex0, ISegmentString 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;
 }
 /// <summary>
 /// Dissolve the given <see cref="ISegmentString" />.
 /// </summary>
 /// <param name="segString"></param>
 public void Dissolve(ISegmentString segString)
 {
     OrientedCoordinateArray oca = new OrientedCoordinateArray(segString.Coordinates);
     ISegmentString 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>
 /// 
 /// </summary>
 /// <param name="oca"></param>
 /// <param name="segString"></param>
 private void Add(OrientedCoordinateArray oca, ISegmentString segString)
 {
     _ocaMap.Add(oca, segString);
 }
Ejemplo n.º 39
0
 private static void CheckCollapses(ISegmentString ss)
 {
     var pts = ss.Coordinates;
     for (var i = 0; i < pts.Length - 2; i++)
         CheckCollapse(pts[i], pts[i + 1], pts[i + 2]);
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="nodeList"></param>
 NodeVertexIterator(SegmentNodeList nodeList)
 {
     _nodeList = nodeList;
     _edge     = nodeList.Edge;
     _nodeIt   = nodeList.GetEnumerator();
 }
        /// <summary>
        /// This method is called by clients
        /// of the <see cref="ISegmentIntersector" /> class to process
        /// intersections for two segments of the <see cref="ISegmentString" /> being intersected.<br/>
        /// Note that some clients (such as <c>MonotoneChain</c>") 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(ISegmentString e0, int segIndex0, ISegmentString e1, int segIndex1)
        {
            if (e0 == e1 && segIndex0 == segIndex1)
                return;

            NumTests++;
            Coordinate[] coordinates0 = e0.Coordinates;
            Coordinate p00 = coordinates0[segIndex0];
            Coordinate p01 = coordinates0[segIndex0 + 1];
            Coordinate[] coordinates1 = e1.Coordinates;
            Coordinate p10 = coordinates1[segIndex1];
            Coordinate p11 = coordinates1[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;
                    ((NodedSegmentString)e0).AddIntersections(_li, segIndex0, 0);
                    ((NodedSegmentString)e1).AddIntersections(_li, segIndex1, 1);
                    if (_li.IsProper)
                    {
                        NumProperIntersections++;
                        _hasProper = true;
                        _hasProperInterior = true;
                    }
                }
            }
        }
        ///<summary>
        /// This method is called by clients of the <see cref="ISegmentIntersector"/> class to process
        /// intersections for two segments of the <see cref="ISegmentString"/>s being intersected.
        ///</summary>
        /// <remarks>
        /// 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).
        /// </remarks>
        public void ProcessIntersections(
          ISegmentString e0, int segIndex0,
          ISegmentString e1, int segIndex1
           )
        {
            // don't intersect segment with itself
            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() && li.isProper()) Debug.println(li);
            if (li.HasIntersection)
            {
                //intersectionFound = true;
                NumIntersections++;
                if (li.IsInteriorIntersection())
                {
                    NumInteriorIntersections++;
                    _hasInterior = true;
                    //System.out.println(li);
                }
                // 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;

                    // only add intersection to test geom (the line)
                    ((NodedSegmentString)e1).AddIntersections(li, segIndex1, 1);

                    if (li.IsProper)
                    {
                        NumProperIntersections++;
                        //Debug.println(li.toString());  Debug.println(li.getIntersection(0));
                        //properIntersectionPoint = (Coordinate) li.getIntersection(0).clone();
                        _hasProper = true;
                        _hasProperInterior = true;
                    }
                }
            }
        }
 ///<summary>
 /// Tests whether a segment in a <see cref="ISegmentString" /> is an end segment.
 /// (either the first or last).
 ///</summary>
 ///<param name="segStr">a segment string</param>
 ///<param name="index">the index of a segment in the segment string</param>
 ///<returns>true if the segment is an end segment</returns>
 private static Boolean IsEndSegment(ISegmentString segStr, int index)
 {
     if (index == 0) return true;
     if (index >= segStr.Count - 2) return true;
     return false;
 }
        ///<summary>
        /// This method is called by clients of the <see cref="ISegmentIntersector"/> class to process
        /// intersections for two segments of the <see cref="ISegmentString"/>s being intersected.<br/>
        /// Note that some clients (such as <c>MonotoneChain</c>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(
            ISegmentString e0, int segIndex0,
            ISegmentString e1, int segIndex1
            )
        {
            // short-circuit if intersection already found
            if (!FindAllIntersections && HasIntersection)
                return;

            // don't bother intersecting a segment with itself
            if (e0 == e1 && segIndex0 == segIndex1) return;

            /*
             * If enabled, only test end segments (on either segString).
             *
             */
            if (CheckEndSegmentsOnly)
            {
                Boolean isEndSegPresent = IsEndSegment(e0, segIndex0) || IsEndSegment(e1, segIndex1);
                if (!isEndSegPresent)
                    return;
            }

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

            _li.ComputeIntersection(p00, p01, p10, p11);
            if (_li.HasIntersection)
            {
                if (_li.IsInteriorIntersection())
                {
                    _intSegments = new Coordinate[4];
                    _intSegments[0] = p00;
                    _intSegments[1] = p01;
                    _intSegments[2] = p10;
                    _intSegments[3] = p11;

                    _interiorIntersection = _li.GetIntersection(0);
                    if (KeepIntersections)
                        _intersections.Add(_interiorIntersection);
                    intersectionCount++;
                }
            }
        }
        ///<summary>
        /// This method is called by clients of the <see cref="ISegmentIntersector"/> class to process
        /// intersections for two segments of the <see cref="ISegmentString"/>s being intersected.
        ///</summary>
        /// <remarks>
        /// Note that some clients (such as <c>MonotoneChain</c>s) may optimize away
        /// this call for segment pairs which they have determined do not intersect
        /// (e.g. by an disjoint envelope test).
        /// </remarks>
        public void ProcessIntersections(
            ISegmentString e0, int segIndex0,
            ISegmentString e1, int segIndex1
            )
        {
            // don't bother intersecting a segment with itself
            if (e0 == e1 && segIndex0 == segIndex1) return;

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

            _li.ComputeIntersection(p00, p01, p10, p11);
            //  if (li.hasIntersection() && li.isProper()) Debug.println(li);

            if (_li.HasIntersection)
            {
                // System.out.println(li);

                // record intersection info
                _hasIntersection = true;

                var isProper = _li.IsProper;
                if (isProper)
                    _hasProperIntersection = true;
                if (!isProper)
                    _hasNonProperIntersection = true;

                /*
                 * If this is the kind of intersection we are searching for
                 * OR no location has yet been recorded
                 * save the location data
                 */
                var saveLocation = !(FindProper && !isProper);
                /*
                bool saveLocation = true;
                if (_findProper && !isProper) saveLocation = false;
                 */

                if (_intPt == null || saveLocation)
                {

                    // record intersection location (approximate)
                    _intPt = _li.GetIntersection(0);

                    // record intersecting segments
                    _intSegments = new Coordinate[4];
                    _intSegments[0] = p00;
                    _intSegments[1] = p01;
                    _intSegments[2] = p10;
                    _intSegments[3] = p11;
                }
            }
        }
Ejemplo n.º 46
0
 /// <summary>
 /// Creates a new instance from a <see cref="ISegmentString"/>.
 /// </summary>
 /// <param name="ss">The segment string to use.</param>
 public NodedSegmentString(ISegmentString ss)
     : this(ss.Coordinates, ss.Context)
 {
     //_pts = ss.Coordinates;
     //Context = ss.Context;
 }
Ejemplo n.º 47
0
 /// <summary>
 /// Initializes a new instance of the <see cref="HotPixelSnapAction"/> class.
 /// </summary>
 /// <param name="hotPixel"></param>
 /// <param name="parentEdge"></param>
 /// <param name="hotPixelVertexIndex"></param>
 public HotPixelSnapAction(HotPixel hotPixel, ISegmentString parentEdge, int hotPixelVertexIndex)
 {
     _hotPixel            = hotPixel;
     _parentEdge          = parentEdge;
     _hotPixelVertexIndex = hotPixelVertexIndex;
 }