public static bool isSimple(IList <Vector3> poly)
        {
            PriorityHeap <VertexEv> evQueue = setupEvQueue(poly);
            SweepLine SL = new SweepLine(poly);

            //Debug.LogWarning("Queue size=" + evQueue.Count);

            while (!evQueue.Empty)
            {
                VertexEv ev = evQueue.Pop();

                if (ev.type == VertexEv.vType.LEFT)
                {
                    int idx = SL.Add(ev.edge);

                    //Debug.Log("Left: " + idx + "/" + SL.Count);

                    if (SL.intersect(idx, idx - 1))
                    {
                        return(false);
                    }
                    if (SL.intersect(idx, idx + 1))
                    {
                        return(false);
                    }
                }
                else             // right vertex


                {
                    int idx = SL.Find(ev.edge);

                    //Debug.Log("Right: " + idx + "/" + SL.Count);

                    if (SL.intersect(idx - 1, idx + 1))
                    {
                        return(false);
                    }
                    SL.Remove(idx);
                }
            }

            return(true);
        }
        /*
         * List<List<Vector3>> decompose(List<Vector3> poly) {
         *
         * }
         */

        // returns one intersection point or null if polygon is simple

        static IntersectionPoint oneIntersection(IList <Vector3> poly)
        {
            PriorityHeap <VertexEv> evQueue = setupEvQueue(poly);
            SweepLine SL = new SweepLine(poly);

            IntersectionPoint I;

            while (!evQueue.Empty)
            {
                VertexEv ev = evQueue.Pop();

                if (ev.type == VertexEv.vType.LEFT)
                {
                    int idx = SL.Add(ev.edge);

                    I = SL.GetIntersectionPoint(idx, idx - 1);
                    if (I != null)
                    {
                        return(I);
                    }

                    I = SL.GetIntersectionPoint(idx, idx + 1);
                    if (I != null)
                    {
                        return(I);
                    }
                }
                else             // right vertex

                {
                    int idx = SL.Find(ev.edge);

                    I = SL.GetIntersectionPoint(idx - 1, idx + 1);
                    if (I != null)
                    {
                        return(I);
                    }
                    SL.Remove(idx);
                }
            }

            return(null);
        }
        /// <summary>
        ///  simple_Polygon(): test if a Polygon is simple or not
        ///     Input:  Pn = a polygon with n vertices V[]
        ///     Return: false(0) = is NOT simple
        ///             true(1)  = IS simple
        /// </summary>
        /// <param name="polygon"></param>
        /// <returns></returns>
        public bool IsSimple(Polygon polygon)
        {
            Require.ArgumentNotNull(polygon, nameof(polygon));

            EventQueue eventQueue = new EventQueue(polygon);
            SweepLine  sweepLine  = new SweepLine(polygon);
            Event      currentEvent;                         // the current event

            // This loop processes all events in the sorted queue
            // Events are only left or right vertices since
            // No new events will be added (an intersect => Done)
            while ((currentEvent = eventQueue.Next()) != null)
            {
                // while there are events
                if (currentEvent.EventType == EventType.Left)
                {                                                     // process a left vertex
                    var currentSegment = sweepLine.Add(currentEvent); // add it to the sweep line
                    if (sweepLine.Intersect(currentSegment, currentSegment.Above))
                    {
                        return(false);                             // Pn is NOT simple
                    }
                    if (sweepLine.Intersect(currentSegment, currentSegment.Below))
                    {
                        return(false);                             // Pn is NOT simple
                    }
                }
                else
                {                                      // processs a right vertex
                    var currentSegment = sweepLine.Find(currentEvent);
                    if (sweepLine.Intersect(currentSegment.Above, currentSegment.Below))
                    {
                        return(false);                             // Pn is NOT simple
                    }
                    sweepLine.Remove(currentSegment);              // remove it from the sweep line
                }
            }
            return(true);                 // Pn IS simple
        }
        /// <summary>
        /// Computes the intersection of one or more line strings.
        /// </summary>
        public void Compute()
        {
            // source: http://geomalgorithms.com/a09-_intersect-3.html

            _intersections = new List <Coordinate>();
            _edgeIndices   = new List <Tuple <Int32, Int32> >();
            Event              currentEvent = _eventQueue.Next();
            SweepLineSegment   segment;
            IList <Coordinate> intersections;

            while (currentEvent != null)
            {
                if (currentEvent is EndPointEvent)
                {
                    EndPointEvent endPointEvent = (EndPointEvent)currentEvent;
                    switch (endPointEvent.Type)
                    {
                    // Left endpoint event: check for possible intersection with below and / or above segments.
                    case EventType.Left:
                        segment = _sweepLine.Add(endPointEvent);
                        if (segment.Above != null)
                        {
                            intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate,
                                                                        segment.Above.LeftCoordinate, segment.Above.RightCoordinate,
                                                                        PrecisionModel);

                            if (intersections.Count > 0)
                            {
                                IntersectionEvent intersectionEvent = new IntersectionEvent
                                {
                                    Vertex = intersections[0],
                                    Below  = segment,
                                    Above  = segment.Above
                                };
                                _eventQueue.Add(intersectionEvent);
                            }
                        }
                        if (segment.Below != null)
                        {
                            intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate,
                                                                        segment.Below.LeftCoordinate, segment.Below.RightCoordinate,
                                                                        PrecisionModel);

                            if (intersections.Count > 0)
                            {
                                IntersectionEvent intersectionEvent = new IntersectionEvent
                                {
                                    Vertex = intersections[0],
                                    Below  = segment.Below,
                                    Above  = segment
                                };
                                _eventQueue.Add(intersectionEvent);
                            }
                        }
                        break;

                    // Right endpoint event: check for possible intersection of the below and above segments.
                    case EventType.Right:
                        segment = _sweepLine.Search(endPointEvent);
                        if (segment != null)
                        {
                            if (segment.Above != null && segment.Below != null)
                            {
                                intersections = LineAlgorithms.Intersection(segment.Above.LeftCoordinate,
                                                                            segment.Above.RightCoordinate,
                                                                            segment.Below.LeftCoordinate,
                                                                            segment.Below.RightCoordinate,
                                                                            PrecisionModel);

                                if (intersections.Count > 0)
                                {
                                    IntersectionEvent intersectionEvent = new IntersectionEvent
                                    {
                                        Vertex = intersections[0],
                                        Below  = segment.Below,
                                        Above  = segment.Above
                                    };
                                    if (!_eventQueue.Contains(intersectionEvent))
                                    {
                                        _eventQueue.Add(intersectionEvent);
                                    }
                                }
                            }
                            _sweepLine.Remove(segment);
                        }
                        break;
                    }
                }

                // Intersection point event: switch the two concerned segments and check for possible intersection with their below and above segments.
                else if (currentEvent is IntersectionEvent)
                {
                    IntersectionEvent intersectionEvent = (IntersectionEvent)currentEvent;

                    /*
                     * Segment order before intersection: segmentBelow <-> segmentAbove <-> segment <-> segmentAboveAbove
                     * Segment order after intersection:  segmentBelow <-> segment <-> segmentAbove <-> segmentAboveAbove
                     */
                    segment = intersectionEvent.Above;
                    SweepLineSegment segmentAbove = intersectionEvent.Below;

                    // Handle closing intersection points when segments (partially) overlap each other.
                    if (intersectionEvent.IsClose)
                    {
                        if (!_sweepLine.IsAdjacent(segment.Edge, segmentAbove.Edge))
                        {
                            _intersections.Add(currentEvent.Vertex);
                            _edgeIndices.Add(Tuple.Create(Math.Min(segment.Edge, segmentAbove.Edge),
                                                          Math.Max(segment.Edge, segmentAbove.Edge)));
                        }
                    }

                    // It is possible that the previously detected intersection point is not a real intersection, because a new segment started between them,
                    // therefore a repeated check is necessary to carry out.
                    else if (_sweepLine.Add(intersectionEvent))
                    {
                        if (!_sweepLine.IsAdjacent(segment.Edge, segmentAbove.Edge))
                        {
                            _intersections.Add(currentEvent.Vertex);
                            _edgeIndices.Add(Tuple.Create(Math.Min(segment.Edge, segmentAbove.Edge),
                                                          Math.Max(segment.Edge, segmentAbove.Edge)));

                            intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate,
                                                                        segmentAbove.LeftCoordinate, segmentAbove.RightCoordinate,
                                                                        PrecisionModel);

                            if (intersections.Count > 1 && !intersections[1].Equals(intersections[0]))
                            {
                                IntersectionEvent newIntersectionEvent = new IntersectionEvent
                                {
                                    Vertex  = intersections[1],
                                    Below   = segment,
                                    Above   = segmentAbove,
                                    IsClose = true,
                                };
                                _eventQueue.Add(newIntersectionEvent);
                            }
                        }

                        if (segmentAbove.Above != null)
                        {
                            intersections = LineAlgorithms.Intersection(segmentAbove.LeftCoordinate, segmentAbove.RightCoordinate,
                                                                        segmentAbove.Above.LeftCoordinate, segmentAbove.Above.RightCoordinate,
                                                                        PrecisionModel);

                            if (intersections.Count > 0 && intersections[0].X >= intersectionEvent.Vertex.X)
                            {
                                IntersectionEvent newIntersectionEvent = new IntersectionEvent
                                {
                                    Vertex = intersections[0],
                                    Below  = segmentAbove,
                                    Above  = segmentAbove.Above
                                };
                                if (!_eventQueue.Contains(newIntersectionEvent))
                                {
                                    _eventQueue.Add(newIntersectionEvent);
                                }
                            }
                        }

                        if (segment.Below != null)
                        {
                            intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate,
                                                                        segment.Below.LeftCoordinate, segment.Below.RightCoordinate,
                                                                        PrecisionModel);

                            if (intersections.Count > 0 && intersections[0].X >= intersectionEvent.Vertex.X)
                            {
                                IntersectionEvent newIntersectionEvent = new IntersectionEvent
                                {
                                    Vertex = intersections[0],
                                    Below  = segment.Below,
                                    Above  = segment
                                };
                                if (!_eventQueue.Contains(newIntersectionEvent))
                                {
                                    _eventQueue.Add(newIntersectionEvent);
                                }
                            }
                        }
                    }
                }

                currentEvent = _eventQueue.Next();
            }
            _hasResult = true;
        }
        public static void BentleyOttmann(IList <Vector3> poly)
        {
            PriorityHeap <VertexEv> evQ = setupEvQueue(poly);
            SweepLine SL = new SweepLine(poly);

            Dictionary <int, IntersectionPoint> intersectionPoints = new Dictionary <int, IntersectionPoint>();

            IntersectionPoint I;

            while (!evQ.Empty)
            {
                VertexEv ev = evQ.Pop();

                if (ev.type == VertexEv.vType.LEFT)
                {
                    int idx = SL.Add(ev.edge);

                    I = SL.GetIntersectionPoint(idx, idx - 1);

                    if (I != null)               // Intersection

                    {
                        int ID = I.Id(poly.Count);
                        if (!intersectionPoints.ContainsKey(ID))
                        {
                            intersectionPoints[ID] = I;
                            //evQ.Add(new VertexEv(I.v, I.Edge1, I.Edge2, VertexEv.vType.INTERSECT));
                            evQ.Add(new VertexEv(I));
                        }
                    }


                    I = SL.GetIntersectionPoint(idx, idx + 1);

                    if (I != null)               // intersection

                    {
                        int ID = I.Id(poly.Count);
                        if (!intersectionPoints.ContainsKey(ID))
                        {
                            intersectionPoints[ID] = I;
                            evQ.Add(new VertexEv(I.P, I.Edge1, I.Edge2, VertexEv.vType.INTERSECT));
                        }
                    }
                }
                else if (ev.type == VertexEv.vType.RIGHT)
                {
                    int idx = SL.Find(ev.edge);

                    I = SL.GetIntersectionPoint(idx - 1, idx + 1);

                    if (I != null)
                    {
                        int ID = I.Id(poly.Count);
                        if (!intersectionPoints.ContainsKey(ID))
                        {
                            intersectionPoints[ID] = I;
                            evQ.Add(new VertexEv(I));
                        }
                    }
                }
                else             // intersection point

                // unfinished business ...
                {
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Computes whether one or more line strings specified by coordinates intersects with each other.
        /// </summary>
        public void Compute()
        {
            // source: http://geomalgorithms.com/a09-_intersect-3.html

            EndPointEvent    e = _eventQueue.Next();
            SweepLineSegment segment;

            while (e != null)
            {
                switch (e.Type)
                {
                case EventType.Left:
                    segment = _sweepLine.Add(e);
                    if (segment.Above != null && _sweepLine.IsAdjacent(segment.Edge, segment.Above.Edge) && segment.LeftCoordinate == segment.Above.LeftCoordinate)
                    {
                        _sweepLine.Intersect(segment, segment.Above);
                    }
                    else if (segment.Below != null && _sweepLine.IsAdjacent(segment.Edge, segment.Below.Edge) && segment.LeftCoordinate == segment.Below.LeftCoordinate)
                    {
                        _sweepLine.Intersect(segment, segment.Below);
                    }

                    if (segment.Above != null && !_sweepLine.IsAdjacent(segment.Edge, segment.Above.Edge) &&
                        LineAlgorithms.Intersects(segment.LeftCoordinate, segment.RightCoordinate,
                                                  segment.Above.LeftCoordinate, segment.Above.RightCoordinate,
                                                  PrecisionModel))
                    {
                        _hasResult = true;
                        _result    = true;
                        return;
                    }
                    if (segment.Below != null && !_sweepLine.IsAdjacent(segment.Edge, segment.Below.Edge) &&
                        LineAlgorithms.Intersects(segment.LeftCoordinate, segment.RightCoordinate,
                                                  segment.Below.LeftCoordinate, segment.Below.RightCoordinate,
                                                  PrecisionModel))
                    {
                        _hasResult = true;
                        _result    = true;
                        return;
                    }
                    break;

                case EventType.Right:
                    segment = _sweepLine.Search(e);
                    if (segment != null)
                    {
                        if (segment.Above != null && segment.Below != null && !_sweepLine.IsAdjacent(segment.Below.Edge, segment.Above.Edge) &&
                            LineAlgorithms.Intersects(segment.Above.LeftCoordinate, segment.Above.RightCoordinate,
                                                      segment.Below.LeftCoordinate, segment.Below.RightCoordinate,
                                                      PrecisionModel))
                        {
                            _hasResult = true;
                            _result    = true;
                            return;
                        }
                        _sweepLine.Remove(segment);
                    }
                    break;
                }

                e = _eventQueue.Next();
            }

            _hasResult = true;
            _result    = false;
        }