Ejemplo n.º 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);
        }
Ejemplo n.º 2
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?!");
            }
        }
Ejemplo n.º 3
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);
                    }
                }
            }
        }
Ejemplo n.º 4
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));
            }
        }