public OA_Sweepline() { IncidentEventPoint = null; BeforeEventPoint = true; Status = new RBTreeSet <OA_Segment>(OA_Segment.Compare); }
public DCEL_Subdivision() { ID = NextID++; Vertices = new RBTreeSet <DCEL_Vertex>(DCEL_Element.Compare); HalfEdges = new RBTreeSet <DCEL_HalfEdge>(DCEL_Element.Compare); Faces = new RBTreeSet <DCEL_Face>(DCEL_Element.Compare); UnboundedFace = new DCEL_Face(); }
private void Initialize() { sweepline = new OA_Sweepline(); eventQueue = new RBTreeSet <OA_EventPoint>(OA_EventPoint.Compare); outputSubdivision = new DCEL_Subdivision(); foreach (DCEL_Subdivision inputSubdivision in inputSubdivisions) { foreach (DCEL_HalfEdge inputHalfEdge in inputSubdivision.HalfEdges.Keys) { OA_EventPoint upper = new OA_EventPoint(inputHalfEdge.Origin.Position); OA_EventPoint lower = new OA_EventPoint(inputHalfEdge.Destination.Position); //We want to take only one of the twins from every pair of half edges. if (upper.CompareTo(lower) > 0) { continue; } RBTreeSetNode <OA_EventPoint> upper_node = new RBTreeSetNode <OA_EventPoint>(upper); RBTreeSetNode <OA_EventPoint> lower_node = new RBTreeSetNode <OA_EventPoint>(lower); //If we didn't add the newly created event point, it already existed. if (!eventQueue.Add(ref upper_node)) { upper = upper_node.Key; } if (!eventQueue.Add(ref lower_node)) { lower = lower_node.Key; } OA_Segment segment = new OA_Segment(sweepline); segment.Source.Add(new OA_Source <DCEL_HalfEdge>(inputSubdivision, inputHalfEdge)); segment.Upper = upper; segment.Lower = lower; //***May be adding a duplicate if segment is in both subdivisions! upper.UpperList.Add(segment); if (!upper.Source.Any(OA_Source <DCEL_Vertex> .IsFrom(inputSubdivision))) { upper.Source.Add(new OA_Source <DCEL_Vertex>(inputSubdivision, inputHalfEdge.Origin)); } if (!lower.Source.Any(OA_Source <DCEL_Vertex> .IsFrom(inputSubdivision))) { lower.Source.Add(new OA_Source <DCEL_Vertex>(inputSubdivision, inputHalfEdge.Destination)); } } } foreach (OA_EventPoint eventPoint in eventQueue.Keys) { //***Remove those duplicates here, joining their source lists. eventPoint.UpperList.RemoveDuplicates(OA_Segment.CompareEndpoints, OA_Segment.JoinSource); } }
public IEnumerable <DCEL_Face> AdjacentFaces() { RBTreeSet <DCEL_Face> faceSet = new RBTreeSet <DCEL_Face>(DCEL_Element.Compare); foreach (DCEL_HalfEdge halfEdge in IncidentHalfEdges) { if (halfEdge.Twin.IncidentFace != this) { faceSet.Add(new RBTreeSetNode <DCEL_Face>(halfEdge.Twin.IncidentFace)); } } return(faceSet.Keys); }
public static LinkedList <LineSegmentIntersection> FindIntersections(IEnumerable <DCEL_HalfEdge> lineSegments) { LinkedList <LineSegmentIntersection> result = new LinkedList <LineSegmentIntersection>(); Sweepline sweepline = new Sweepline(); RBTreeMap <EventPoint, LinkedList <Segment> > eventQueue = new RBTreeMap <EventPoint, LinkedList <Segment> >((x, y) => x.CompareTo(y)); var segments = lineSegments.Where(lineSegment => lineSegment.Origin.Position != lineSegment.Destination.Position) .Select(lineSegment => new Segment(lineSegment, sweepline)); //segments = FixOverlappingSegments(segments); foreach (var segment in segments) { var node = eventQueue.Find(segment.Upper); LinkedList <Segment> upperList = (node != null ? node.Value : null); if (upperList == null) { upperList = new LinkedList <Segment>(); eventQueue.Add(new RBTreeMapNode <EventPoint, LinkedList <Segment> >(new EventPoint(segment.Upper), upperList)); } upperList.AddLast(segment); if (!eventQueue.ContainsKey(segment.Lower)) { eventQueue.Add(new RBTreeMapNode <EventPoint, LinkedList <Segment> >(new EventPoint(segment.Lower), new LinkedList <Segment>())); } } RBTreeSet <Segment> status = new RBTreeSet <Segment>((x, y) => x.CompareTo(y)); while (eventQueue.Count > 0) { var pair = eventQueue.MinNode; eventQueue.RemoveMin(); EventPoint nextEventPoint = pair.Key; LinkedList <Segment> upperList = pair.Value; LineSegmentIntersection reportedIntersection; HandleEventPoint(nextEventPoint, upperList, sweepline, eventQueue, status, out reportedIntersection); if (reportedIntersection != null) { result.AddLast(reportedIntersection); } } return(result); }
private static void HandleEventPoint(EventPoint eventPoint, LinkedList <Segment> upperList, Sweepline sweepline, RBTreeMap <EventPoint, LinkedList <Segment> > eventQueue, RBTreeSet <Segment> status, out LineSegmentIntersection reportedIntersection) { reportedIntersection = null; sweepline.IncidentEventPoint = eventPoint; sweepline.BeforeEventPoint = true; //1. //upperList brought in as part of the input. None of its elements currently intersect the sweepline! //2. IEnumerable <Segment> middleList, lowerList; status.FindRange(Segment.CompareSweeplineIntersectionToCurrentEventPoint).Select(node => node.Key) .Partition(Segment.LowerIsCurrentEventPoint, out lowerList, out middleList); //3. if (upperList.Count + middleList.Count() + lowerList.Count() > 1) { //4. reportedIntersection = new LineSegmentIntersection( eventPoint.Position, upperList.Concat(middleList).Concat(lowerList).Select(segment => segment.Source)); } //5. foreach (var lower in lowerList) { status.Remove(lower); } foreach (var middle in middleList) { status.Remove(middle); } sweepline.BeforeEventPoint = false; //6. foreach (var middle in middleList) { status.Add(new RBTreeSetNode <Segment>(middle)); } foreach (var upper in upperList) { status.Add(new RBTreeSetNode <Segment>(upper)); } //7. //Just a comment in the book //8. if (upperList.IsEmpty() && middleList.IsEmpty()) { //9. var predecessorNode = status.FindMax(Segment.IntersectsSweeplineLeftOfEventPoint); var successorNode = status.FindMin(Segment.IntersectsSweeplineRightOfEventPoint); //10. if (predecessorNode != null && successorNode != null) { FindNewEvent(predecessorNode.Key, successorNode.Key, eventPoint, eventQueue); } } else { //11. var leftmostIntersectingNode = status.FindMin(Segment.IntersectsSweeplineRightOfEventPoint); //14. var rightmostIntersectingNode = status.FindMax(Segment.IntersectsSweeplineLeftOfEventPoint); //12. var leftmostPredecessorNode = leftmostIntersectingNode.Predecessor; //15. var rightmostSuccessorNode = rightmostIntersectingNode.Successor; //13. if (leftmostPredecessorNode != null) { //RemoveFutureEvent(leftmostPredecessor, rightmostIntersecting, eventPoint, eventQueue); FindNewEvent(leftmostPredecessorNode.Key, leftmostIntersectingNode.Key, eventPoint, eventQueue); } //16. if (rightmostSuccessorNode != null) { //RemoveFutureEvent(leftmostIntersecting, rightmostSuccessor, eventPoint, eventQueue); FindNewEvent(rightmostIntersectingNode.Key, rightmostSuccessorNode.Key, eventPoint, eventQueue); } } }