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 ... { } } }
/// <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; }