Exemple #1
0
        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);
            }
        }
Exemple #2
0
        private void SetLeftPick(OA_EventPoint eventPoint)
        {
            RBTreeSetNode <OA_Segment> leftPick_node = sweepline.Status.FindMax(OA_Segment.IntersectsSweeplineLeftOfEventPointExclusive);

            if (leftPick_node != null)
            {
                eventPoint.LeftPick = leftPick_node.Key;
            }
            else
            {
                eventPoint.LeftPick = null;
            }
        }
Exemple #3
0
        private Dictionary <DCEL_Subdivision, DCEL_Vertex> CreateSourceLookup(OA_EventPoint eventPoint)
        {
            Dictionary <DCEL_Subdivision, DCEL_Vertex> sourceLookup = new Dictionary <DCEL_Subdivision, DCEL_Vertex>(2);

            foreach (OA_Source <DCEL_Vertex> source in eventPoint.Source)
            {
                sourceLookup.Add(source.Subdivision, source.Element);
            }

            foreach (DCEL_Subdivision inputSubdivision in inputSubdivisions)
            {
                if (!sourceLookup.ContainsKey(inputSubdivision))
                {
                    sourceLookup.Add(inputSubdivision, null);
                }
            }

            return(sourceLookup);
        }
Exemple #4
0
        private void HandleIntersection_SplittingPhase(OA_EventPoint eventPoint, List <OA_Segment> upperList, List <OA_Segment> middleList, List <OA_Segment> lowerList)
        {
            //if (upperList.Count() + middleList.Count() + lowerList.Count() <= 1)
            if (middleList.Count == 0)
            {
                return;
            }

            //If there are any subdivisions which don't have a vertex at this location,
            //then we will create one momentarily. For the moment, set the
            //(key, value) = (subdivision, null).
            Dictionary <DCEL_Subdivision, DCEL_Vertex> vertexLookup = CreateSourceLookup(eventPoint);

            //Make all segments meet at a vertex here, within each subdivision.
            //HalfEdges associated with segments in the middleList will be transformed
            //into HalfEdges associated with segments in the upperList. (With the associated
            //segments transforming as well.)
            foreach (OA_Segment middle in middleList)
            {
                foreach (OA_Source <DCEL_HalfEdge> source in middle.Source)
                {
                    DCEL_Subdivision subdivision = source.Subdivision;
                    DCEL_HalfEdge    halfEdge    = source.Element;
                    DCEL_Vertex      vertex      = vertexLookup[subdivision];

                    //Create the vertex on-demand if it doesn't exist
                    if (vertex == null)
                    {
                        vertex = new DCEL_Vertex(eventPoint.Position);
                        vertexLookup[subdivision] = vertex;
                        subdivision.Vertices.Add(new RBTreeSetNode <DCEL_Vertex>(vertex));
                    }

                    SplitEdge(subdivision, halfEdge, vertex);

                    if (!eventPoint.Source.Any(OA_Source <DCEL_Vertex> .IsFrom(subdivision)))
                    {
                        eventPoint.Source.Add(new OA_Source <DCEL_Vertex>(subdivision, vertex));
                    }
                }
            }
        }
Exemple #5
0
        public void SetEndpoints(OA_EventPoint a, OA_EventPoint b)
        {
            int comp = a.CompareTo(b);

            if (comp == 0)
            {
                throw new InvalidOperationException("Trivial line segment.");
            }

            if (comp < 0)
            {
                Upper = a;
                Lower = b;
            }
            else
            {
                Upper = b;
                Lower = a;
            }
        }
Exemple #6
0
        private void FindNewEventPoint(OA_Segment segment1, OA_Segment segment2, OA_EventPoint eventPoint)
        {
            VecRat2 pointIntersection   = new VecRat2();
            SegRat2 segmentIntersection = new SegRat2();

            SegmentIntersectionType result = GeomAid.SegmentIntersection(segment1.ToSegRat2(), segment2.ToSegRat2(), ref pointIntersection, ref segmentIntersection);

            if (result == SegmentIntersectionType.Point)
            {
                OA_EventPoint newEventPoint = new OA_EventPoint(pointIntersection);
                if (eventPoint.CompareTo(newEventPoint) < 0)
                {
                    //Add the new event point if it isn't already in the event queue
                    eventQueue.Add(new RBTreeSetNode <OA_EventPoint>(newEventPoint));
                }
            }
            else if (result == SegmentIntersectionType.Segment)
            {
                throw new NotImplementedException("Didn't think this would ever happen?!");
            }
        }
Exemple #7
0
        private void HandleIntersection_MergingPhase(OA_EventPoint eventPoint, List <OA_Segment> upperList, List <OA_Segment> middleList, List <OA_Segment> lowerList)
        {
            if (middleList.Count != 0)
            {
                throw new Exception("MergingPhase: Something went wrong in the SplittingPhase, because there is an intersection with nonempty middleList.");
            }

            //Dictionary<DCEL_Subdivision, DCEL_Vertex> vertexLookup = CreateSourceLookup(eventPoint);
            //DCEL_Vertex mergedVertex = vertexLookup.Values.First();

            DCEL_Vertex mergedVertex = eventPoint.Source.First().Element;

            lowerList.Sort(AngleComparisonLowerList(mergedVertex.Position));
            upperList.Sort(AngleComparisonUpperList(mergedVertex.Position));

            //JoinNext all consecutive pairs around circle, and join origins to mergedVertex
            {
                //Outgoing half edges in CCW order
                List <DCEL_HalfEdge> bothList = new List <DCEL_HalfEdge>();
                bothList.AddRange(lowerList.Select(segment => segment.Source.First().Element.Twin));
                bothList.AddRange(upperList.Select(segment => segment.Source.First().Element));

                if (bothList.Count > 1)
                {
                    DCEL_HalfEdge e, e_next;
                    for (int i = 1; i < bothList.Count; i++)
                    {
                        e      = bothList[i].Twin;
                        e_next = bothList[i - 1];
                        DCEL_Helper.JoinNext(e, e_next);
                    }

                    e      = bothList.First().Twin;
                    e_next = bothList.Last();
                    DCEL_Helper.JoinNext(e, e_next);
                }
                else
                {
                    DCEL_HalfEdge e      = bothList[0].Twin;
                    DCEL_HalfEdge e_next = e.Twin;
                    DCEL_Helper.JoinNext(e, e_next);
                }

                //Set the origins to the mergedVertex
                foreach (DCEL_HalfEdge e in bothList)
                {
                    e.Origin = mergedVertex;
                }
                mergedVertex.IncidentEdge = bothList.First();
            }

            outputSubdivision.Vertices.Add(new RBTreeSetNode <DCEL_Vertex>(mergedVertex));

            foreach (OA_Segment upper in upperList)
            {
                DCEL_HalfEdge e = upper.Source.First().Element;
                outputSubdivision.HalfEdges.Add(new RBTreeSetNode <DCEL_HalfEdge>(e));
                outputSubdivision.HalfEdges.Add(new RBTreeSetNode <DCEL_HalfEdge>(e.Twin));

                //HACK?/////////////////////////////////////////
                e.IncidentFace      = null;
                e.Twin.IncidentFace = null;
                //HACK?/////////////////////////////////////////
            }

            //Store the left pick for the mergedVertex
            if (eventPoint.LeftPick != null)
            {
                leftPicksMap.Add(new RBTreeMapNode <DCEL_Vertex, DCEL_HalfEdge>(mergedVertex, eventPoint.LeftPick.Source.First().Element));
            }
            else
            {
                leftPicksMap.Add(new RBTreeMapNode <DCEL_Vertex, DCEL_HalfEdge>(mergedVertex, null));
            }
        }
Exemple #8
0
        private void HandleEventPoint(OA_EventPoint eventPoint)
        {
            AssertValidSweeplineStatus();

            //Sweep to before the event point
            sweepline.IncidentEventPoint = eventPoint;
            sweepline.BeforeEventPoint   = true;

            AssertValidSweeplineStatus();

            if (phase == Phase.MergingPhase)
            {
                SetLeftPick(eventPoint);
            }

            //Determine all segments that contain the event point, and partition them
            List <OA_Segment> upperList = eventPoint.UpperList;
            List <OA_Segment> middleList;
            List <OA_Segment> lowerList;

            sweepline.Status
            .FindRange(OA_Segment.CompareSweeplineIntersectionToCurrentEventPoint).Select(node => node.Key)
            .Partition(OA_Segment.LowerIsCurrentEventPoint, out lowerList, out middleList);

            //upperList gets added, middleList gets reversed, lowerList gets removed
            EventPointTransition(upperList, middleList, lowerList);

            AssertValidSweeplineStatus();

            switch (phase)
            {
            case Phase.SplittingPhase:
                HandleIntersection_SplittingPhase(eventPoint, upperList, middleList, lowerList);
                break;

            case Phase.MergingPhase:
                HandleIntersection_MergingPhase(eventPoint, upperList, middleList, lowerList);
                break;

            default:
                throw new Exception();
            }

            AssertValidSweeplineStatus();

            if (upperList.IsEmpty() && middleList.IsEmpty())
            {
                RBTreeSetNode <OA_Segment> predecessorNode = sweepline.Status.FindMax(OA_Segment.IntersectsSweeplineLeftOfEventPointInclusive);
                RBTreeSetNode <OA_Segment> successorNode   = sweepline.Status.FindMin(OA_Segment.IntersectsSweeplineRightOfEventPointInclusive);
                if (predecessorNode != null && successorNode != null)
                {
                    FindNewEventPoint(predecessorNode.Key, successorNode.Key, eventPoint);
                }
            }
            else
            {
                var leftmostIntersectingNode = sweepline.Status.FindMin(OA_Segment.IntersectsSweeplineRightOfEventPointInclusive);
                var leftmostPredecessorNode  = leftmostIntersectingNode.Predecessor;
                if (leftmostPredecessorNode != null)
                {
                    FindNewEventPoint(leftmostPredecessorNode.Key, leftmostIntersectingNode.Key, eventPoint);
                }

                var rightmostIntersectingNode = sweepline.Status.FindMax(OA_Segment.IntersectsSweeplineLeftOfEventPointInclusive);
                var rightmostSuccessorNode    = rightmostIntersectingNode.Successor;
                if (rightmostSuccessorNode != null)
                {
                    FindNewEventPoint(rightmostIntersectingNode.Key, rightmostSuccessorNode.Key, eventPoint);
                }
            }
        }