Beispiel #1
0
        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);
        }
Beispiel #2
0
        private void CreateFaces()
        {
            RBTreeMap <DCEL_HalfEdge, HalfEdgeData> halfEdgesData = new RBTreeMap <DCEL_HalfEdge, HalfEdgeData>(DCEL_Element.Compare);

            foreach (DCEL_HalfEdge halfEdge in outputSubdivision.HalfEdges.Keys)
            {
                halfEdgesData.Add(new RBTreeMapNode <DCEL_HalfEdge, HalfEdgeData>(halfEdge, new HalfEdgeData()));
            }

            RBTreeMap <DCEL_HalfEdge, CycleData> cyclesData = new RBTreeMap <DCEL_HalfEdge, CycleData>(DCEL_Element.Compare);

            List <bool> visited = outputSubdivision.HalfEdges.Keys.Select(e => false).ToList();

            DCEL_Face unboundedFace = new DCEL_Face();

            outputSubdivision.UnboundedFace = unboundedFace;
            outputSubdivision.Faces.Add(new RBTreeSetNode <DCEL_Face>(unboundedFace));

            foreach (var halfEdgeNode in halfEdgesData.Nodes)
            {
                DCEL_HalfEdge halfEdge = halfEdgeNode.Key;
                if (halfEdgeNode.Value.Visited)
                {
                    continue;
                }

                DCEL_HalfEdge cycle = halfEdge.CycleNext.Min((a, b) => a.Origin.CompareTo(b.Origin));
                {
                    cycle = cycle.CycleNext.Where(e => e.Origin == cycle.Origin).Max(AngleComparisonUpperList_HalfEdge(cycle.Origin.Position));
                }

                CycleType cycleType = GetCycleType(cycle);

                if (cycleType == CycleType.Interior)
                {
                    DCEL_Face interiorFace = new DCEL_Face();
                    outputSubdivision.Faces.Add(new RBTreeSetNode <DCEL_Face>(interiorFace));

                    interiorFace.OuterComponent = cycle;
                    foreach (DCEL_HalfEdge cycleHalfEdge in cycle.CycleNext)
                    {
                        cycleHalfEdge.IncidentFace = interiorFace;
                    }
                }

                cyclesData.Add(new RBTreeMapNode <DCEL_HalfEdge, CycleData>(cycle, new CycleData(cycleType)));

                foreach (DCEL_HalfEdge cycleHalfEdge in halfEdge.CycleNext)
                {
                    HalfEdgeData data = halfEdgesData[cycleHalfEdge].Value;
                    data.Cycle = cycle;
                }
            }

            foreach (var cycleNode in cyclesData.Nodes)
            {
                if (cycleNode.Value.CycleType == CycleType.Interior)
                {
                    continue;
                }

                DCEL_HalfEdge cycle = cycleNode.Key;

                DCEL_HalfEdge leftPick = leftPicksMap[cycle.Origin].Value;
                if (leftPick == null)
                {
                    unboundedFace.InnerComponents.AddLast(cycle);
                    foreach (DCEL_HalfEdge cycleHalfEdge in cycle.CycleNext)
                    {
                        cycleHalfEdge.IncidentFace = unboundedFace;
                    }
                    continue;
                }

                DCEL_HalfEdge leftPickCycle     = halfEdgesData[leftPick].Value.Cycle;
                CycleType     leftPickCycleType = cyclesData[leftPickCycle].Value.CycleType;

                //if (leftPickCycleType == CycleType.Interior)
                //{
                //    leftPickCycle.IncidentFace.InnerComponents.AddLast(cycle);
                //    foreach (DCEL_HalfEdge cycleHalfEdge in cycle.CycleNext)
                //        cycleHalfEdge.IncidentFace = leftPickCycle.IncidentFace;
                //}

                cyclesData[leftPickCycle].Value.Children.Add(cycle);
                cycleNode.Value.IsRoot = false;
            }



            foreach (var cycleChildrenNode in cyclesData.Nodes)
            {
                if (!cycleChildrenNode.Value.IsRoot)
                {
                    continue;
                }

                DCEL_HalfEdge parentCycle     = cycleChildrenNode.Key;
                CycleType     parentCycleType = cyclesData[parentCycle].Value.CycleType;

                DCEL_Face face = parentCycle.IncidentFace;

                List <DCEL_HalfEdge> childCycles = cycleChildrenNode.Value.Children;

                Stack <DCEL_HalfEdge> unattachedCycles = new Stack <DCEL_HalfEdge>();
                foreach (DCEL_HalfEdge childCycle in childCycles)
                {
                    unattachedCycles.Push(childCycle);
                }

                while (!unattachedCycles.IsEmpty())
                {
                    DCEL_HalfEdge exteriorCycle = unattachedCycles.Pop();
                    face.InnerComponents.AddLast(exteriorCycle);
                    foreach (DCEL_HalfEdge exteriorCycleHalfEdge in exteriorCycle.CycleNext)
                    {
                        exteriorCycleHalfEdge.IncidentFace = face;
                    }
                    foreach (DCEL_HalfEdge child in cyclesData[exteriorCycle].Value.Children)
                    {
                        unattachedCycles.Push(child);
                    }
                }
            }
        }
Beispiel #3
0
        private OA_Algorithm(IEnumerable <DCEL_Subdivision> inputSubdivisions)
        {
            this.inputSubdivisions = new List <DCEL_Subdivision>(inputSubdivisions);

            this.leftPicksMap = new RBTreeMap <DCEL_Vertex, DCEL_HalfEdge>(DCEL_Element.Compare);
        }
Beispiel #4
0
        private static void FindNewEvent(Segment s1, Segment s2, EventPoint eventPoint, RBTreeMap <EventPoint, LinkedList <Segment> > eventQueue)
        {
            //If two segments intersect below the sweep line, or on it and
            //to the right of the current event point, and the intersection
            //is not yet present as an event in Q:
            //then insert a new event point in Q for this intersection
            VecRat2 pointIntersection   = new VecRat2();
            SegRat2 segmentIntersection = new SegRat2();
            //bool intersectionExists = Segment.ComputeIntersection(s1, s2, out pointIntersection);
            //if (intersectionExists)
            SegmentIntersectionType result = GeomAid.SegmentIntersection(s1.ToSegRat2(), s2.ToSegRat2(), ref pointIntersection, ref segmentIntersection);

            if (result == SegmentIntersectionType.Point)
            {
                EventPoint newEventPoint = new EventPoint(null);
                newEventPoint.Position = pointIntersection;
                if (eventPoint.CompareTo(newEventPoint) < 0 && !eventQueue.ContainsKey(newEventPoint))
                {
                    LinkedList <Segment> upperList = new LinkedList <Segment>();
                    eventQueue.Add(new RBTreeMapNode <EventPoint, LinkedList <Segment> >(newEventPoint, upperList));
                }
            }
            else if (result == SegmentIntersectionType.Segment)
            {
                throw new NotImplementedException("Didn't think this would ever happen?!");
            }
        }
Beispiel #5
0
        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);
                }
            }
        }