Esempio n. 1
0
        void HeapInsert(SweepEvent[] heap, int heapsize, SweepEvent newevent)
        {
            double eventx, eventy;
            int eventnum;
            int parent;
            bool notdone;

            eventx = newevent.xkey;
            eventy = newevent.ykey;
            eventnum = heapsize;
            notdone = eventnum > 0;
            while (notdone)
            {
                parent = (eventnum - 1) >> 1;
                if ((heap[parent].ykey < eventy) ||
                    ((heap[parent].ykey == eventy)
                     && (heap[parent].xkey <= eventx)))
                {
                    notdone = false;
                }
                else
                {
                    heap[eventnum] = heap[parent];
                    heap[eventnum].heapposition = eventnum;

                    eventnum = parent;
                    notdone = eventnum > 0;
                }
            }
            heap[eventnum] = newevent;
            newevent.heapposition = eventnum;
        }
Esempio n. 2
0
        void Heapify(SweepEvent[] heap, int heapsize, int eventnum)
        {
            SweepEvent thisevent;
            double eventx, eventy;
            int leftchild, rightchild;
            int smallest;
            bool notdone;

            thisevent = heap[eventnum];
            eventx = thisevent.xkey;
            eventy = thisevent.ykey;
            leftchild = 2 * eventnum + 1;
            notdone = leftchild < heapsize;
            while (notdone)
            {
                if ((heap[leftchild].ykey < eventy) ||
                    ((heap[leftchild].ykey == eventy)
                     && (heap[leftchild].xkey < eventx)))
                {
                    smallest = leftchild;
                }
                else
                {
                    smallest = eventnum;
                }
                rightchild = leftchild + 1;
                if (rightchild < heapsize)
                {
                    if ((heap[rightchild].ykey < heap[smallest].ykey) ||
                        ((heap[rightchild].ykey == heap[smallest].ykey)
                         && (heap[rightchild].xkey < heap[smallest].xkey)))
                    {
                        smallest = rightchild;
                    }
                }
                if (smallest == eventnum)
                {
                    notdone = false;
                }
                else
                {
                    heap[eventnum] = heap[smallest];
                    heap[eventnum].heapposition = eventnum;
                    heap[smallest] = thisevent;
                    thisevent.heapposition = smallest;

                    eventnum = smallest;
                    leftchild = 2 * eventnum + 1;
                    notdone = leftchild < heapsize;
                }
            }
        }
Esempio n. 3
0
            // Правильнее было назвать GetList()
            internal void ForEach(List <SweepEvent> list, Visit visit, SweepEvent lo = null, SweepEvent hi = null)
            {
                if (this.root == null)
                {
                    return;
                }
                int arguments_length = 3;

                if (hi == null)
                {
                    arguments_length--;
                }
                if (lo == null)
                {
                    arguments_length--;
                }
                if (visit == null)
                {
                    return;
                }

                switch (arguments_length)
                {
                case 1:
                    doVisitFull(list, visit, this.root);
                    break;

                case 2:
                    doVisitHalf(lo, this.compare, list, visit, this.root);
                    break;

                case 3:
                    if (this.compare(lo, hi) >= 0)
                    {
                        return;
                    }

                    doVisit(lo, hi, this.compare, list, visit, this.root);
                    break;
                }
            }
Esempio n. 4
0
            //Insert a new item into the tree
            internal RedBlackTree insert(SweepEvent key, SweepEvent value)
            {
                Comporator cmp = this.compare;
                //Find point to insert new node at
                RBNode        n1      = this.root;
                List <RBNode> n_stack = new List <RBNode>();
                List <int?>   d_stack = new List <int?>();

                while (n1 != null)
                {
                    int?d = cmp(key, n1.key);
                    n_stack.Add(n1);
                    d_stack.Add(d);
                    if (d <= 0)
                    {
                        n1 = n1.left;
                    }
                    else
                    {
                        n1 = n1.right;
                    }
                }

                //Rebuild path to leaf node
                n_stack.Add(new RBNode(RBTreeNodeColor.RED, key, value, null, null, 1));
                for (int i = n_stack.Count - 2; i > -1; i--)
                {
                    RBNode n_i = n_stack[i];
                    if (d_stack[i] <= 0)
                    {
                        n_stack[i] = new RBNode(n_i.color, n_i.key, n_i.value, n_stack[i + 1], n_i.right, n_i.count + 1);
                    }
                    else
                    {
                        n_stack[i] = new RBNode(n_i.color, n_i.key, n_i.value, n_i.left, n_stack[i + 1], n_i.count + 1);
                    }
                }

                //Rebalance tree using rotations
                for (int i = n_stack.Count - 1; i > 1; i--)
                {
                    RBNode p = n_stack[i - 1];
                    RBNode n = n_stack[i];
                    if (p.color == RBTreeNodeColor.BLACK || n.color == RBTreeNodeColor.BLACK)
                    {
                        break;
                    }

                    RBNode pp = n_stack[i - 2];
                    if (pp.left == p)
                    {
                        if (p.left == n)
                        {
                            RBNode y = pp.right;
                            if (y != null && y.color == RBTreeNodeColor.RED)
                            {
                                p.color  = RBTreeNodeColor.BLACK;
                                pp.right = y.repaint(RBTreeNodeColor.BLACK);
                                pp.color = RBTreeNodeColor.RED;
                                i--;
                            }
                            else
                            {
                                pp.color       = RBTreeNodeColor.RED;
                                pp.left        = p.right;
                                p.color        = RBTreeNodeColor.BLACK;
                                p.right        = pp;
                                n_stack[i - 2] = p;
                                n_stack[i - 1] = n;
                                pp.recount();
                                p.recount();
                                if (i >= 3)
                                {
                                    RBNode ppp = n_stack[i - 3];
                                    if (ppp.left == pp)
                                    {
                                        ppp.left = p;
                                    }
                                    else
                                    {
                                        ppp.right = p;
                                    }
                                }
                                break;
                            }
                        }
                        else
                        {
                            RBNode y = pp.right;
                            if (y != null && y.color == RBTreeNodeColor.RED)
                            {
                                p.color  = RBTreeNodeColor.BLACK;
                                pp.right = y.repaint(RBTreeNodeColor.BLACK);
                                pp.color = RBTreeNodeColor.RED;
                                i--;
                            }
                            else
                            {
                                p.right        = n.left;
                                pp.color       = RBTreeNodeColor.RED;
                                pp.left        = n.right;
                                n.color        = RBTreeNodeColor.BLACK;
                                n.left         = p;
                                n.right        = pp;
                                n_stack[i - 2] = n;
                                n_stack[i - 1] = p;
                                pp.recount();
                                p.recount();
                                n.recount();
                                if (i >= 3)
                                {
                                    RBNode ppp = n_stack[i - 3];
                                    if (ppp.left == pp)
                                    {
                                        ppp.left = n;
                                    }
                                    else
                                    {
                                        ppp.right = n;
                                    }
                                }
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (p.right == n)
                        {
                            RBNode y = pp.left;
                            if (y != null && y.color == RBTreeNodeColor.RED)
                            {
                                p.color  = RBTreeNodeColor.BLACK;
                                pp.left  = y.repaint(RBTreeNodeColor.BLACK);
                                pp.color = RBTreeNodeColor.RED;
                                i--;
                            }
                            else
                            {
                                pp.color       = RBTreeNodeColor.RED;
                                pp.right       = p.left;
                                p.color        = RBTreeNodeColor.BLACK;
                                p.left         = pp;
                                n_stack[i - 2] = p;
                                n_stack[i - 1] = n;
                                pp.recount();
                                p.recount();
                                if (i >= 3)
                                {
                                    RBNode ppp = n_stack[i - 3];
                                    if (ppp.right == pp)
                                    {
                                        ppp.right = p;
                                    }
                                    else
                                    {
                                        ppp.left = p;
                                    }
                                }
                                break;
                            }
                        }
                        else
                        {
                            RBNode y = pp.left;
                            if (y != null && y.color == RBTreeNodeColor.RED)
                            {
                                p.color  = RBTreeNodeColor.BLACK;
                                pp.left  = y.repaint(RBTreeNodeColor.BLACK);
                                pp.color = RBTreeNodeColor.RED;
                                i--;
                            }
                            else
                            {
                                p.left         = n.right;
                                pp.color       = RBTreeNodeColor.RED;
                                pp.right       = n.left;
                                n.color        = RBTreeNodeColor.BLACK;
                                n.right        = p;
                                n.left         = pp;
                                n_stack[i - 2] = n;
                                n_stack[i - 1] = p;
                                pp.recount();
                                p.recount();
                                n.recount();
                                if (i >= 3)
                                {
                                    RBNode ppp = n_stack[i - 3];
                                    if (ppp.right == pp)
                                    {
                                        ppp.right = n;
                                    }
                                    else
                                    {
                                        ppp.left = n;
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
                //Return new tree
                n_stack[0].color = RBTreeNodeColor.BLACK;
                return(new RedBlackTree(cmp, n_stack[0]));
            }
Esempio n. 5
0
        internal static int possibleIntersection(SweepEvent se1, SweepEvent se2, TinyQueue queue)
        {
            // that disallows self-intersecting polygons,
            // did cost us half a day, so I'll leave it
            // out of respect
            // if (se1.isSubject === se2.isSubject) return;
            var inter = SegmentIntersection(se1.point, se1.otherEvent.point, se2.point, se2.otherEvent.point);

            var nintersections = inter != null ? inter.Length : 0;

            if (nintersections == 0)
            {
                return(0); // no intersection
            }
            // the line segments intersect at an endpoint of both line segments
            if ((nintersections == 1) && (equals(se1.point, se2.point) || equals(se1.otherEvent.point, se2.otherEvent.point)))
            {
                return(0);
            }

            if (nintersections == 2 && se1.isSubject == se2.isSubject)
            {
                // if(se1.contourId === se2.contourId){
                // console.warn('Edges of the same polygon overlap',
                //   se1.point, se1.otherEvent.point, se2.point, se2.otherEvent.point);
                // }
                //throw new Error('Edges of the same polygon overlap');
                return(0);
            }

            // The line segments associated to se1 and se2 intersect
            if (nintersections == 1)
            {
                // if the intersection point is not an endpoint of se1
                if (!equals(se1.point, inter[0]) && !equals(se1.otherEvent.point, inter[0]))
                {
                    divideSegment(se1, inter[0], queue);
                }

                // if the intersection point is not an endpoint of se2
                if (!equals(se2.point, inter[0]) && !equals(se2.otherEvent.point, inter[0]))
                {
                    divideSegment(se2, inter[0], queue);
                }

                return(1);
            }

            // The line segments associated to se1 and se2 overlap
            var events        = new List <SweepEvent>();
            var leftCoincide  = false;
            var rightCoincide = false;

            if (equals(se1.point, se2.point))
            {
                leftCoincide = true; // linked
            }
            else if (compareEvents(se1, se2) == 1)
            {
                events.Add(se2);
                events.Add(se1);
            }
            else
            {
                events.Add(se1);
                events.Add(se2);
            }

            if (equals(se1.otherEvent.point, se2.otherEvent.point))
            {
                rightCoincide = true;
            }
            else if (compareEvents(se1.otherEvent, se2.otherEvent) == 1)
            {
                events.Add(se2.otherEvent);
                events.Add(se1.otherEvent);
            }
            else
            {
                events.Add(se1.otherEvent);
                events.Add(se2.otherEvent);
            }

            if ((leftCoincide && rightCoincide) || leftCoincide)                    // both line segments are equal or share the left endpoint
            {
                se1.type = EdgeType.NON_CONTRIBUTING;
                se2.type = (se1.inOut == se2.inOut) ? EdgeType.SAME_TRANSITION : EdgeType.DIFFERENT_TRANSITION;

                if (leftCoincide && !rightCoincide)
                {
                    // honestly no idea, but changing events selection from [2, 1] to [0, 1] fixes the overlapping self-intersecting polygons issue
                    divideSegment(events[1].otherEvent, events[0].point, queue);
                }

                return(2);
            }

            if (rightCoincide)                                                      // the line segments share the right endpoint
            {
                divideSegment(events[0], events[1].point, queue);
                return(3);
            }

            if (events[0] != events[3].otherEvent)              // no line segment includes totally the other one
            {
                divideSegment(events[0], events[1].point, queue);
                divideSegment(events[1], events[2].point, queue);
                return(3);
            }

            // one line segment includes the other one
            divideSegment(events[0], events[1].point, queue);
            divideSegment(events[3].otherEvent, events[2].point, queue);

            return(3);
        }
Esempio n. 6
0
        void Check4DeadEvent(ref Otri checktri, SweepEvent[] eventheap, ref int heapsize)
        {
            SweepEvent deadevent;
            SweepEventVertex eventvertex;
            int eventnum = -1;

            eventvertex = checktri.Org() as SweepEventVertex;
            if (eventvertex != null)
            {
                deadevent = eventvertex.evt;
                eventnum = deadevent.heapposition;

                HeapDelete(eventheap, heapsize, eventnum);
                heapsize--;
                checktri.SetOrg(null);
            }
        }
Esempio n. 7
0
        void CreateHeap(out SweepEvent[] eventheap)
        {
            Vertex thisvertex;
            int maxevents;
            int i;
            SweepEvent evt;

            maxevents = (3 * mesh.invertices) / 2;
            eventheap = new SweepEvent[maxevents];

            i = 0;
            foreach (var v in mesh.vertices.Values)
            {
                thisvertex = v;
                evt = new SweepEvent();
                evt.vertexEvent = thisvertex;
                evt.xkey = thisvertex.x;
                evt.ykey = thisvertex.y;
                HeapInsert(eventheap, i++, evt);
                
            }
        }
Esempio n. 8
0
            public Polygon Compute(OperationType ot)
            {
                connector.OnAddEdgeEvent += OnAddEdge;

                if (subject == null)
                {
                    return(clipper);
                }
                else if (clipper == null)
                {
                    return(subject);
                }

                Polygon result = new Polygon();

                futureSweepLineEvents.Clear();

                // Test 1 for trivial result case
                if (subject.GetNumPaths() * clipper.GetNumPaths() == 0)
                {
                    // At least one of the polygons is empty
                    if (ot == OperationType.DIFFERENCE)
                    {
                        result = subject;
                    }
                    if (ot == OperationType.UNION)
                    {
                        result = (subject.GetNumPaths() == 0) ? clipper : subject;
                    }

                    return(result);
                }

                // Test 2 for trivial result case
                bbSubject = subject.GetBoundingBox();
                bbClipper = clipper.GetBoundingBox();

                if (bbSubject.min.x > bbClipper.max.x ||
                    bbSubject.min.y > bbClipper.max.y ||
                    bbClipper.min.x > bbSubject.max.x ||
                    bbClipper.min.y > bbSubject.max.y)
                {
                    // the bounding boxes do not overlap
                    if (ot == OperationType.DIFFERENCE)
                    {
                        result = subject;
                    }
                    if (ot == OperationType.UNION)
                    {
                        result = subject;

                        for (int i = 0; i < clipper.GetNumPaths(); ++i)
                        {
                            result.Add(clipper.GetPath(i));
                        }
                    }

                    return(result);
                }

                // Insert all the endpoints associated to the line segments into the event queue

                for (int currentPath = 0; currentPath < subject.GetNumPaths(); ++currentPath)
                {
                    for (int currentEdge = 0; currentEdge < subject.GetPath(currentPath).GetNumPoints(); ++currentEdge)
                    {
                        ProcessEdge(subject.GetPath(currentPath).GetEdge(currentEdge), Operand.SUBJECT);
                    }
                }

                for (int currentPath = 0; currentPath < clipper.GetNumPaths(); ++currentPath)
                {
                    for (int currentEdge = 0; currentEdge < clipper.GetPath(currentPath).GetNumPoints(); ++currentEdge)
                    {
                        ProcessEdge(clipper.GetPath(currentPath).GetEdge(currentEdge), Operand.CLIPPER);
                    }
                }

                minMaxX = Mathf.Min(bbSubject.max.x, bbClipper.max.x);

                while (!futureSweepLineEvents.IsEmpty())
                {
                    SweepEvent currentEvent = futureSweepLineEvents.ExtractFirst();

                    currentEvent.Number = ++seCounter;

                    if (AlreadyFinished(ref result, ot, currentEvent))
                    {
                        return(result);
                    }

                    if (currentEvent.Left)
                    {
                        HandleLeftEvent(currentEvent);
                    }
                    else
                    {
                        HandleRightEvent(ot, currentEvent);
                    }
                }

                return(connector.CreatePolygon());
            }
Esempio n. 9
0
        public Mesh Triangulate(List <Vertex> points)
        {
            mesh = TrianglePool.AllocMesh();
            mesh.TransferNodes(points);

            // Nonexistent x value used as a flag to mark circle events in sweepline
            // Delaunay algorithm.
            xminextreme = 10 * mesh.bounds.Left - 9 * mesh.bounds.Right;

            SweepEvent[] eventheap;

            SweepEvent nextevent;
            SweepEvent newevent;
            SplayNode  splayroot;
            Otri       bottommost = default(Otri);
            Otri       searchtri  = default(Otri);
            Otri       fliptri;
            Otri       lefttri = default(Otri);
            Otri       righttri = default(Otri);
            Otri       farlefttri = default(Otri);
            Otri       farrighttri = default(Otri);
            Otri       inserttri = default(Otri);
            Vertex     firstvertex, secondvertex;
            Vertex     nextvertex, lastvertex;
            Vertex     connectvertex;
            Vertex     leftvertex, midvertex, rightvertex;
            double     lefttest, righttest;
            int        heapsize;
            bool       check4events, farrightflag = false;

            splaynodes = new List <SplayNode>();
            splayroot  = null;

            CreateHeap(out eventheap); //, out events, out freeevents);
            heapsize = mesh.invertices;

            mesh.MakeTriangle(ref lefttri);
            mesh.MakeTriangle(ref righttri);
            lefttri.Bond(ref righttri);
            lefttri.Lnext();
            righttri.Lprev();
            lefttri.Bond(ref righttri);
            lefttri.Lnext();
            righttri.Lprev();
            lefttri.Bond(ref righttri);
            firstvertex = eventheap[0].vertexEvent;

            HeapDelete(eventheap, heapsize, 0);
            heapsize--;
            do
            {
                if (heapsize == 0)
                {
                    throw new Exception("Input vertices are all identical.");
                }

                secondvertex = eventheap[0].vertexEvent;
                HeapDelete(eventheap, heapsize, 0);
                heapsize--;
                if ((firstvertex.X == secondvertex.X) &&
                    (firstvertex.Y == secondvertex.Y))
                {
                    secondvertex.type = VertexType.UndeadVertex;
                    mesh.undeads++;
                }
            } while ((firstvertex.X == secondvertex.X) &&
                     (firstvertex.Y == secondvertex.Y));
            lefttri.SetOrg(firstvertex);
            lefttri.SetDest(secondvertex);
            righttri.SetOrg(secondvertex);
            righttri.SetDest(firstvertex);
            lefttri.Lprev(ref bottommost);
            lastvertex = secondvertex;

            while (heapsize > 0)
            {
                nextevent = eventheap[0];
                HeapDelete(eventheap, heapsize, 0);
                heapsize--;
                check4events = true;
                if (nextevent.xkey < mesh.bounds.Left)
                {
                    fliptri = nextevent.otriEvent;
                    fliptri.Oprev(ref farlefttri);
                    Check4DeadEvent(ref farlefttri, eventheap, ref heapsize);
                    fliptri.Onext(ref farrighttri);
                    Check4DeadEvent(ref farrighttri, eventheap, ref heapsize);

                    if (farlefttri.Equal(bottommost))
                    {
                        fliptri.Lprev(ref bottommost);
                    }
                    mesh.Flip(ref fliptri);
                    fliptri.SetApex(null);
                    fliptri.Lprev(ref lefttri);
                    fliptri.Lnext(ref righttri);
                    lefttri.Sym(ref farlefttri);

                    if (randomnation(SAMPLERATE) == 0)
                    {
                        fliptri.Sym();
                        leftvertex  = fliptri.Dest();
                        midvertex   = fliptri.Apex();
                        rightvertex = fliptri.Org();
                        splayroot   = CircleTopInsert(splayroot, lefttri, leftvertex, midvertex, rightvertex,
                                                      nextevent.ykey);
                    }
                }
                else
                {
                    nextvertex = nextevent.vertexEvent;
                    if ((nextvertex.X == lastvertex.X) &&
                        (nextvertex.Y == lastvertex.Y))
                    {
                        nextvertex.type = VertexType.UndeadVertex;
                        mesh.undeads++;
                        check4events = false;
                    }
                    else
                    {
                        lastvertex = nextvertex;

                        splayroot = FrontLocate(splayroot, bottommost, nextvertex, ref searchtri, ref farrightflag);

                        //bottommost.Copy(ref searchtri);
                        //farrightflag = false;
                        //while (!farrightflag && RightOfHyperbola(ref searchtri, nextvertex))
                        //{
                        //    searchtri.OnextSelf();
                        //    farrightflag = searchtri.Equal(bottommost);
                        //}

                        Check4DeadEvent(ref searchtri, eventheap, ref heapsize);

                        searchtri.Copy(ref farrighttri);
                        searchtri.Sym(ref farlefttri);
                        mesh.MakeTriangle(ref lefttri);
                        mesh.MakeTriangle(ref righttri);
                        connectvertex = farrighttri.Dest();
                        lefttri.SetOrg(connectvertex);
                        lefttri.SetDest(nextvertex);
                        righttri.SetOrg(nextvertex);
                        righttri.SetDest(connectvertex);
                        lefttri.Bond(ref righttri);
                        lefttri.Lnext();
                        righttri.Lprev();
                        lefttri.Bond(ref righttri);
                        lefttri.Lnext();
                        righttri.Lprev();
                        lefttri.Bond(ref farlefttri);
                        righttri.Bond(ref farrighttri);
                        if (!farrightflag && farrighttri.Equal(bottommost))
                        {
                            lefttri.Copy(ref bottommost);
                        }

                        if (randomnation(SAMPLERATE) == 0)
                        {
                            splayroot = SplayInsert(splayroot, lefttri, nextvertex);
                        }
                        else if (randomnation(SAMPLERATE) == 0)
                        {
                            righttri.Lnext(ref inserttri);
                            splayroot = SplayInsert(splayroot, inserttri, nextvertex);
                        }
                    }
                }

                if (check4events)
                {
                    leftvertex  = farlefttri.Apex();
                    midvertex   = lefttri.Dest();
                    rightvertex = lefttri.Apex();
                    lefttest    = RobustPredicates.CounterClockwise(leftvertex, midvertex, rightvertex);
                    if (lefttest > 0.0)
                    {
                        newevent = new SweepEvent();

                        newevent.xkey      = xminextreme;
                        newevent.ykey      = CircleTop(leftvertex, midvertex, rightvertex, lefttest);
                        newevent.otriEvent = lefttri;
                        HeapInsert(eventheap, heapsize, newevent);
                        heapsize++;
                        lefttri.SetOrg(new SweepEventVertex(newevent));
                    }
                    leftvertex  = righttri.Apex();
                    midvertex   = righttri.Org();
                    rightvertex = farrighttri.Apex();
                    righttest   = RobustPredicates.CounterClockwise(leftvertex, midvertex, rightvertex);
                    if (righttest > 0.0)
                    {
                        newevent = new SweepEvent();

                        newevent.xkey      = xminextreme;
                        newevent.ykey      = CircleTop(leftvertex, midvertex, rightvertex, righttest);
                        newevent.otriEvent = farrighttri;
                        HeapInsert(eventheap, heapsize, newevent);
                        heapsize++;
                        farrighttri.SetOrg(new SweepEventVertex(newevent));
                    }
                }
            }

            splaynodes.Clear();
            bottommost.Lprev();

            mesh.hullsize = RemoveGhosts(ref bottommost);

            return(mesh);
        }
Esempio n. 10
0
        // Return value is whether or not we added a new segment.
        bool AddSegment(Point start, Point end, Obstacle eventObstacle
                        , BasicObstacleSide lowNborSide, BasicObstacleSide highNborSide
                        , SweepEvent action, double weight)
        {
            DevTraceInfoVgGen(1, "Adding Segment [{0} -> {1} {2}] weight {3}", start, end, weight);
            DevTraceInfoVgGen(2, "     side {0}", lowNborSide);
            DevTraceInfoVgGen(2, "  -> side {0}", highNborSide);
            if (PointComparer.Equal(start, end))
            {
                return(false);
            }

            // See if the new segment subsumes or can be subsumed by the last one.  gbcList may be null.
            PointAndCrossingsList gbcList = CurrentGroupBoundaryCrossingMap.GetOrderedListBetween(start, end);
            bool extendStart, extendEnd;
            bool wasSubsumed = ScanSegment.Subsume(ref hintScanSegment, start, end, weight, gbcList, ScanDirection
                                                   , ParallelScanSegments, out extendStart, out extendEnd);

            if (!wasSubsumed)
            {
                Debug.Assert((weight != ScanSegment.ReflectionWeight) || (ParallelScanSegments.Find(start, end) == null),
                             "Reflection segments already in the ScanSegmentTree should should have been detected before calling AddSegment");
                hintScanSegment = ParallelScanSegments.InsertUnique(new ScanSegment(start, end, weight, gbcList)).Item;
            }
            else if (weight == ScanSegment.ReflectionWeight)
            {
                // Do not continue this; it is probably a situation where a side is at a tiny angle from the axis,
                // resulting in an initial reflection segment that is parallel and very close to the extreme-vertex-derived
                // segment, so as the staircase progresses they eventually converge due to floating-point rounding.
                // See RectilinearFilesTest.ReflectionStaircasesConverge.
                return(false);
            }

            // Do reflections only if the new segment is not overlapped.
            if (ScanSegment.OverlappedWeight != weight)
            {
                // If these fire, it's probably an indication that isOverlapped is not correctly set
                // and one of the neighbors is an OverlapSide from CreateScanSegments.
                Debug.Assert(lowNborSide is HighObstacleSide, "lowNbor is not HighObstacleSide");
                Debug.Assert(highNborSide is LowObstacleSide, "highNbor is not LowObstacleSide");

                // If we are closing the obstacle then the initial Obstacles of the reflections (the ones it
                // will bounce between) are the opposite neighbors.  Otherwise, the OpenVertexEvent obstacle
                // is the ReflectionEvent initial obstacle.
                if (action is CloseVertexEvent)
                {
                    // If both neighbor sides reflect upward, they can't intersect, so we don't need
                    // to store a lookahead site (if neither reflect upward, StoreLookaheadSite no-ops).
                    if (!SideReflectsUpward(lowNborSide) || !SideReflectsUpward(highNborSide))
                    {
                        // Try to store both; only one will "take" (for the upward-reflecting side).
                        // The initial Obstacle is the opposite neighbor.
                        if (extendStart)
                        {
                            this.StoreLookaheadSite(highNborSide.Obstacle, lowNborSide, start, wantExtreme: false);
                        }

                        if (extendEnd)
                        {
                            this.StoreLookaheadSite(lowNborSide.Obstacle, highNborSide, end, wantExtreme: false);
                        }
                    }
                }
                else
                {
                    if (extendStart)
                    {
                        StoreLookaheadSite(eventObstacle, LowNeighborSides.GroupSideInterveningBeforeLowNeighbor, lowNborSide, start);
                    }

                    if (extendEnd)
                    {
                        StoreLookaheadSite(eventObstacle, HighNeighborSides.GroupSideInterveningBeforeHighNeighbor, highNborSide, end);
                    }
                }
            }

            DevTraceInfoVgGen(2, "HintScanSegment {0}{1}", hintScanSegment, wasSubsumed ? " (subsumed)" : "");
            DevTrace_DumpScanSegmentsDuringAdd(3);
            return(true);
        }
Esempio n. 11
0
 public bool BelongsToSamePolygonAs(SweepEvent o)
 {
     return(o.owningPolygon == this.owningPolygon);
 }
Esempio n. 12
0
 public bool IsCollinearTo(SweepEvent se)
 {
     return(Orientation(Point, Other.Point, se.Point) == 0 &&
            Orientation(Point, Other.Point, se.Other.Point) == 0);
 }
Esempio n. 13
0
            public void ComputeHoles()
            {
                exteriors.Clear();

                if (GetNumPaths() < 2)
                {
                    if (GetNumPaths() == 1 && GetPath(0).IsClockwise())
                    {
                        GetPath(0).ToggleDirection();
                        exteriors.Add(0);
                    }

                    return;
                }

                List <SweepEvent> events = CreateHoleEvents();

                AVLTree <SweepEvent> sweepLineEvents = new AVLTree <SweepEvent>(new EdgeComparer());

                List <bool> processed = new List <bool>(Enumerable.Repeat(false, GetNumPaths()));
                List <int>  holeOf    = new List <int>(Enumerable.Repeat(-1, GetNumPaths()));

                int numProcessedEvents = 0;

                for (int i = 0; i < events.Count && numProcessedEvents < GetNumPaths(); ++i)
                {
                    SweepEvent currentEvent = events[i];

                    if (currentEvent.Left)
                    {
                        currentEvent.positionInS = sweepLineEvents.Insert(currentEvent);

                        if (!processed[currentEvent.OwningPolygon])
                        {
                            processed[currentEvent.OwningPolygon] = true;

                            ++numProcessedEvents;

                            AVLNode <SweepEvent> prevNode = currentEvent.positionInS.GetPredecessor();

                            if (prevNode == null)
                            {
                                GetPath(currentEvent.OwningPolygon).SetCounterClockwise();
                                exteriors.Add(currentEvent.OwningPolygon);
                            }
                            else
                            {
                                SweepEvent prev = prevNode.Value;

                                if (!prev.InOut)
                                {
                                    holeOf[currentEvent.OwningPolygon] = prev.OwningPolygon;
                                    GetPath(currentEvent.OwningPolygon).SetHole(true);
                                    GetPath(prev.OwningPolygon).AddHole(currentEvent.OwningPolygon);

                                    if (GetPath(prev.OwningPolygon).IsCounterClockwise())
                                    {
                                        GetPath(currentEvent.OwningPolygon).SetClockwise();
                                    }
                                    else
                                    {
                                        GetPath(currentEvent.OwningPolygon).SetCounterClockwise();
                                        exteriors.Add(currentEvent.OwningPolygon);
                                    }
                                }
                                else if (holeOf[prev.OwningPolygon] != -1)
                                {
                                    holeOf[currentEvent.OwningPolygon] = holeOf[prev.OwningPolygon];
                                    GetPath(currentEvent.OwningPolygon).SetHole(true);
                                    GetPath(holeOf[currentEvent.OwningPolygon]).AddHole(currentEvent.OwningPolygon);

                                    if (GetPath(holeOf[currentEvent.OwningPolygon]).IsCounterClockwise())
                                    {
                                        GetPath(currentEvent.OwningPolygon).SetClockwise();
                                    }
                                    else
                                    {
                                        GetPath(currentEvent.OwningPolygon).SetCounterClockwise();
                                        exteriors.Add(currentEvent.OwningPolygon);
                                    }
                                }
                                else
                                {
                                    GetPath(currentEvent.OwningPolygon).SetCounterClockwise();
                                    exteriors.Add(currentEvent.OwningPolygon);
                                }
                            }
                        }
                    }
                    else // remove the edge from the sweep line status
                    {
                        // sweepLineEvents.Delete(currentEvent.Other.positionInS);
                        sweepLineEvents.Remove(currentEvent.Other);
                    }
                }
            }
Esempio n. 14
0
        ///* eslint-disable no-unused-vars, no-debugger, no-undef */
        //function iteratorEquals(it1, it2) {
        //  return it1._cursor === it2._cursor;
        //}


        //function _renderSweepLine(sweepLine, pos, _event)
        //{
        //var map = window.map;
        //if (!map) return;
        //if (window.sws) window.sws.forEach(function (p) {
        //map.removeLayer(p);
        //});
        //window.sws = [];
        //sweepLine.forEach(function (e) {
        //var poly = L.polyline([
        //    e.point.slice().reverse(),
        //    e.otherEvent.point.slice().reverse()
        //], {color: 'green'}).addTo(map);
        //window.sws.push(poly);
        //});

        //if (window.vt) map.removeLayer(window.vt);
        //var v = pos.slice();
        //var b = map.getBounds();
        //window.vt = L.polyline([
        //[b.getNorth(), v[0]],
        //[b.getSouth(), v[0]]
        //], {color: 'green', weight: 1}).addTo(map);

        //if (window.ps) map.removeLayer(window.ps);
        //window.ps = L.polyline([
        //_event.point.slice().reverse(),
        //_event.otherEvent.point.slice().reverse()
        //], {color: 'black', weight: 9, opacity: 0.4}).addTo(map);
        //debugger;
        //}
        ///* eslint-enable no-unused-vars, no-debugger, no-undef */


        internal static List <SweepEvent> subdivideSegments(TinyQueue eventQueue, Point[][][] subject, Point[][][] clipping, double[] sbbox, double[] cbbox, Operation operation)
        {
            RedBlackTree      sweepLine    = new RedBlackTree(_comp_Segm);
            List <SweepEvent> sortedEvents = new List <SweepEvent>();

            double rightbound = Math.Min(sbbox[2], cbbox[2]);

            RedBlackTreeIterator prev, next;

            SweepEvent prevEvent, prevprevEvent;

            while (eventQueue.length > 0)
            {
                SweepEvent _event = eventQueue.pop();
                sortedEvents.Add(_event);

                // optimization by bboxes for intersection and difference goes here  - коммент оригинала
                if ((operation == Operation.INTERSECTION && _event.point.X > rightbound) || (operation == Operation.DIFFERENCE && _event.point.X > sbbox[2]))
                {
                    break;
                }

                if (_event.left)
                {
                    sweepLine = sweepLine.insert(_event, _event);
                    //_renderSweepLine(sweepLine, _event.point, _event);  - коммент оригинала

                    next            = sweepLine.find(_event);
                    prev            = sweepLine.find(_event);
                    _event.iterator = sweepLine.find(_event);

                    if (!prev.node.Equals(sweepLine.begin.node))                                             // ??? (prev.node !== sweepLine.begin)
                    {
                        prev.prev();
                    }
                    else
                    {
                        prev = sweepLine.begin;
                        prev.prev();
                        prev.next();
                    }
                    next.next();

                    //---  prevEvent = (prev.key || null), prevprevEvent;
                    prevEvent = (SweepEvent)Convert.ChangeType(prev.key, typeof(SweepEvent));
                    computeFields(_event, prevEvent, operation);
                    if (next.node != null)
                    {
                        if (possibleIntersection(_event, (SweepEvent)Convert.ChangeType(next.key, typeof(SweepEvent)), eventQueue) == 2)
                        {
                            computeFields(_event, prevEvent, operation);
                            computeFields(_event, (SweepEvent)Convert.ChangeType(next.key, typeof(SweepEvent)), operation);
                        }
                    }

                    if (prev.node != null)
                    {
                        if (possibleIntersection((SweepEvent)Convert.ChangeType(prev.key, typeof(SweepEvent)), _event, eventQueue) == 2)
                        {
                            RedBlackTreeIterator prevprev = sweepLine.find((SweepEvent)Convert.ChangeType(prev.key, typeof(SweepEvent)));
                            if (!prevprev.node.Equals(sweepLine.begin.node))                            //prevprev.node != sweepLine.begin
                            {
                                prevprev.prev();
                            }
                            else
                            {
                                prevprev = sweepLine.find((SweepEvent)Convert.ChangeType(sweepLine.end.key, typeof(SweepEvent)));
                                prevprev.next();
                            }
                            prevprevEvent = (SweepEvent)Convert.ChangeType(prevprev.key, typeof(SweepEvent));
                            computeFields(prevEvent, prevprevEvent, operation);
                            computeFields(_event, prevEvent, operation);
                        }
                    }
                }
                else
                {
                    _event = _event.otherEvent;
                    next   = sweepLine.find(_event);
                    prev   = sweepLine.find(_event);

                    // _renderSweepLine(sweepLine, _event.otherEvent.point, _event);  - коммент оригинала

                    if (!(prev != null && next != null))
                    {
                        continue;
                    }

                    if (!prev.node.Equals(sweepLine.begin.node))                                        // prev.node !=  sweepLine.begin
                    {
                        prev.prev();
                    }
                    else
                    {
                        prev = sweepLine.begin;
                        prev.prev();
                        prev.next();
                    }
                    next.next();
                    sweepLine = sweepLine.remove(_event);

                    // _renderSweepLine(sweepLine, _event.otherEvent.point, _event);  - коммент оригинала

                    if (next.node != null && prev.node != null)
                    {
                        if (prev.node.value != null && next.node.value != null)    //-- if (typeof prev.node.value != 'undefined' && typeof next.node.value != 'undefined')
                        {
                            possibleIntersection((SweepEvent)Convert.ChangeType(prev.key, typeof(SweepEvent)), (SweepEvent)Convert.ChangeType(next.key, typeof(SweepEvent)), eventQueue);
                        }
                    }
                }
            }
            return(sortedEvents);
        }
Esempio n. 15
0
        public int Triangulate(Mesh mesh)
        {
            this.mesh = mesh;

            // Nonexistent x value used as a flag to mark circle events in sweepline
            // Delaunay algorithm.
            xminextreme = 10 * mesh.bounds.Xmin - 9 * mesh.bounds.Xmax;

            SweepEvent[] eventheap;

            SweepEvent nextevent;
            SweepEvent newevent;
            SplayNode  splayroot;
            Otri       bottommost = default(Otri);
            Otri       searchtri  = default(Otri);
            Otri       fliptri;
            Otri       lefttri = default(Otri);
            Otri       righttri = default(Otri);
            Otri       farlefttri = default(Otri);
            Otri       farrighttri = default(Otri);
            Otri       inserttri = default(Otri);
            Vertex     firstvertex, secondvertex;
            Vertex     nextvertex, lastvertex;
            Vertex     connectvertex;
            Vertex     leftvertex, midvertex, rightvertex;
            float      lefttest, righttest;
            int        heapsize;
            bool       check4events, farrightflag = false;

            splaynodes = new List <SplayNode>();
            splayroot  = null;

            CreateHeap(out eventheap);//, out events, out freeevents);
            heapsize = mesh.invertices;

            mesh.MakeTriangle(ref lefttri);
            mesh.MakeTriangle(ref righttri);
            lefttri.Bond(ref righttri);
            lefttri.LnextSelf();
            righttri.LprevSelf();
            lefttri.Bond(ref righttri);
            lefttri.LnextSelf();
            righttri.LprevSelf();
            lefttri.Bond(ref righttri);
            firstvertex = eventheap[0].vertexEvent;

            HeapDelete(eventheap, heapsize, 0);
            heapsize--;
            do
            {
                if (heapsize == 0)
                {
                    SimpleLog.Instance.Error("Input vertices are all identical.", "SweepLine.SweepLineDelaunay()");
                    throw new Exception("Input vertices are all identical.");
                }
                secondvertex = eventheap[0].vertexEvent;
                HeapDelete(eventheap, heapsize, 0);
                heapsize--;
                if ((firstvertex.x == secondvertex.x) &&
                    (firstvertex.y == secondvertex.y))
                {
                    if (Behavior.Verbose)
                    {
                        SimpleLog.Instance.Warning("A duplicate vertex appeared and was ignored.",
                                                   "SweepLine.SweepLineDelaunay().1");
                    }
                    secondvertex.type = VertexType.UndeadVertex;
                    mesh.undeads++;
                }
            } while ((firstvertex.x == secondvertex.x) &&
                     (firstvertex.y == secondvertex.y));
            lefttri.SetOrg(firstvertex);
            lefttri.SetDest(secondvertex);
            righttri.SetOrg(secondvertex);
            righttri.SetDest(firstvertex);
            lefttri.Lprev(ref bottommost);
            lastvertex = secondvertex;

            while (heapsize > 0)
            {
                nextevent = eventheap[0];
                HeapDelete(eventheap, heapsize, 0);
                heapsize--;
                check4events = true;
                if (nextevent.xkey < mesh.bounds.Xmin)
                {
                    fliptri = nextevent.otriEvent;
                    fliptri.Oprev(ref farlefttri);
                    Check4DeadEvent(ref farlefttri, eventheap, ref heapsize);
                    fliptri.Onext(ref farrighttri);
                    Check4DeadEvent(ref farrighttri, eventheap, ref heapsize);

                    if (farlefttri.Equal(bottommost))
                    {
                        fliptri.Lprev(ref bottommost);
                    }
                    mesh.Flip(ref fliptri);
                    fliptri.SetApex(null);
                    fliptri.Lprev(ref lefttri);
                    fliptri.Lnext(ref righttri);
                    lefttri.Sym(ref farlefttri);

                    if (randomnation(SAMPLERATE) == 0)
                    {
                        fliptri.SymSelf();
                        leftvertex  = fliptri.Dest();
                        midvertex   = fliptri.Apex();
                        rightvertex = fliptri.Org();
                        splayroot   = CircleTopInsert(splayroot, lefttri, leftvertex, midvertex, rightvertex, nextevent.ykey);
                    }
                }
                else
                {
                    nextvertex = nextevent.vertexEvent;
                    if ((nextvertex.x == lastvertex.x) &&
                        (nextvertex.y == lastvertex.y))
                    {
                        if (Behavior.Verbose)
                        {
                            SimpleLog.Instance.Warning("A duplicate vertex appeared and was ignored.",
                                                       "SweepLine.SweepLineDelaunay().2");
                        }
                        nextvertex.type = VertexType.UndeadVertex;
                        mesh.undeads++;
                        check4events = false;
                    }
                    else
                    {
                        lastvertex = nextvertex;

                        splayroot = FrontLocate(splayroot, bottommost, nextvertex,
                                                ref searchtri, ref farrightflag);
                        //
                        bottommost.Copy(ref searchtri);
                        farrightflag = false;
                        while (!farrightflag && RightOfHyperbola(ref searchtri, nextvertex))
                        {
                            searchtri.OnextSelf();
                            farrightflag = searchtri.Equal(bottommost);
                        }


                        Check4DeadEvent(ref searchtri, eventheap, ref heapsize);

                        searchtri.Copy(ref farrighttri);
                        searchtri.Sym(ref farlefttri);
                        mesh.MakeTriangle(ref lefttri);
                        mesh.MakeTriangle(ref righttri);
                        connectvertex = farrighttri.Dest();
                        lefttri.SetOrg(connectvertex);
                        lefttri.SetDest(nextvertex);
                        righttri.SetOrg(nextvertex);
                        righttri.SetDest(connectvertex);
                        lefttri.Bond(ref righttri);
                        lefttri.LnextSelf();
                        righttri.LprevSelf();
                        lefttri.Bond(ref righttri);
                        lefttri.LnextSelf();
                        righttri.LprevSelf();
                        lefttri.Bond(ref farlefttri);
                        righttri.Bond(ref farrighttri);
                        if (!farrightflag && farrighttri.Equal(bottommost))
                        {
                            lefttri.Copy(ref bottommost);
                        }

                        if (randomnation(SAMPLERATE) == 0)
                        {
                            splayroot = SplayInsert(splayroot, lefttri, nextvertex);
                        }
                        else if (randomnation(SAMPLERATE) == 0)
                        {
                            righttri.Lnext(ref inserttri);
                            splayroot = SplayInsert(splayroot, inserttri, nextvertex);
                        }
                    }
                }

                if (check4events)
                {
                    leftvertex  = farlefttri.Apex();
                    midvertex   = lefttri.Dest();
                    rightvertex = lefttri.Apex();
                    lefttest    = Primitives.CounterClockwise(leftvertex, midvertex, rightvertex);
                    if (lefttest > 0.0)
                    {
                        newevent = new SweepEvent();

                        newevent.xkey      = xminextreme;
                        newevent.ykey      = CircleTop(leftvertex, midvertex, rightvertex, lefttest);
                        newevent.otriEvent = lefttri;
                        HeapInsert(eventheap, heapsize, newevent);
                        heapsize++;
                        lefttri.SetOrg(new SweepEventVertex(newevent));
                    }
                    leftvertex  = righttri.Apex();
                    midvertex   = righttri.Org();
                    rightvertex = farrighttri.Apex();
                    righttest   = Primitives.CounterClockwise(leftvertex, midvertex, rightvertex);
                    if (righttest > 0.0)
                    {
                        newevent = new SweepEvent();

                        newevent.xkey      = xminextreme;
                        newevent.ykey      = CircleTop(leftvertex, midvertex, rightvertex, righttest);
                        newevent.otriEvent = farrighttri;
                        HeapInsert(eventheap, heapsize, newevent);
                        heapsize++;
                        farrighttri.SetOrg(new SweepEventVertex(newevent));
                    }
                }
            }

            splaynodes.Clear();
            bottommost.LprevSelf();
            return(RemoveGhosts(ref bottommost));
        }
Esempio n. 16
0
 public SweepEventVertex(SweepEvent e)
 {
     evt = e;
 }
Esempio n. 17
0
        private void HandleEvent(IBST <SweepEvent> events, IBST <StatusItem> status, SweepEvent ev)
        {
            ResultEvents.Add(ev);

            // Optimization 2
            if ((Operation == OperationType.Intersection && ev.Point.x > RightBound) ||
                (Operation == OperationType.Difference && ev.Point.x > SubjectBoundingBox.xMax))
            {
                // We need to connect edges now, so just clear all events. This will result in us immediately
                // going to ConnectEdges() since there are no more events to handle.
                InitializeEvents(new List <SweepEvent>());
                return;
            }

            if (ev.IsStart) // The line segment must be inserted into status
            {
                ev.StatusItem = new StatusItem(ev);
                if (!status.Insert(ev.StatusItem))
                {
                    throw new ArgumentException("Failed to insert into state");
                }

                StatusItem prev;
                var        prevFound = status.FindNextSmallest(ev.StatusItem, out prev);

                ComputeFields(ev, prev, prevFound);

                StatusItem next;
                if (status.FindNextBiggest(ev.StatusItem, out next))
                {
                    // Process a possible intersection between "ev" and its next neighbor in status
                    if (PossibleIntersection(ev, next.SweepEvent, events) == 2)
                    {
                        ComputeFields(ev, prev, prevFound);
                        ComputeFields(next.SweepEvent, ev.StatusItem, true);
                    }
                }

                // Process a possible intersection between "ev" and its previous neighbor in status
                if (prevFound)
                {
                    if (PossibleIntersection(prev.SweepEvent, ev, events) == 2)
                    {
                        StatusItem prevprev;
                        var        prevprevFound = status.FindNextSmallest(prev, out prevprev);

                        ComputeFields(prev.SweepEvent, prevprev, prevprevFound);
                        ComputeFields(ev, prev, prevFound);
                    }
                }
            }
            else
            {
                // The line segment must be removed from status
                ev = ev.OtherEvent; // We work with the left event

                StatusItem prev, next;
                var        prevFound = status.FindNextSmallest(ev.StatusItem, out prev);
                var        nextFound = status.FindNextBiggest(ev.StatusItem, out next);

                // Delete line segment associated to "ev" from status and check for intersection between the neighbors of "ev" in status
                status.Delete(ev.StatusItem);

                if (nextFound && prevFound)
                {
                    PossibleIntersection(prev.SweepEvent, next.SweepEvent, events);
                }
            }
        }
Esempio n. 18
0
        void HeapDelete(SweepEvent[] heap, int heapsize, int eventnum)
        {
            SweepEvent moveevent;
            double eventx, eventy;
            int parent;
            bool notdone;

            moveevent = heap[heapsize - 1];
            if (eventnum > 0)
            {
                eventx = moveevent.xkey;
                eventy = moveevent.ykey;
                do
                {
                    parent = (eventnum - 1) >> 1;
                    if ((heap[parent].ykey < eventy) ||
                        ((heap[parent].ykey == eventy)
                         && (heap[parent].xkey <= eventx)))
                    {
                        notdone = false;
                    }
                    else
                    {
                        heap[eventnum] = heap[parent];
                        heap[eventnum].heapposition = eventnum;

                        eventnum = parent;
                        notdone = eventnum > 0;
                    }
                } while (notdone);
            }
            heap[eventnum] = moveevent;
            moveevent.heapposition = eventnum;
            Heapify(heap, heapsize - 1, eventnum);
        }
Esempio n. 19
0
        private int PossibleIntersection(SweepEvent ev1, SweepEvent ev2, IBST <SweepEvent> events)
        {
            Vector2D intersectionPoint;
            var      nIntersections = FindIntersections(ev1.Point, ev1.OtherEvent.Point, ev2.Point, ev2.OtherEvent.Point,
                                                        out intersectionPoint);

            if (nIntersections == 0)
            {
                return(0); // no intersection
            }

            // If the intersection is between two endpoints
            if (nIntersections == 1 && (ev1.Point.Equals(ev2.Point) ||
                                        ev1.OtherEvent.Point.Equals(ev2.OtherEvent.Point)))
            {
                return(0); // the line segments intersect at an endpoint of both line segments
            }

            if (nIntersections == 2 && ev1.PolygonType == ev2.PolygonType)
            {
                // The line segments overlap, but they belong to the same polygon
                throw new ArgumentException(string.Format("Sorry, edges of the same polygon overlap ({0} and {1})", ev1,
                                                          ev2));
            }

            // The line segments associated to ev1 and ev2 intersect
            if (nIntersections == 1)
            {
                if (!ev1.Point.Equals(intersectionPoint) && !ev1.OtherEvent.Point.Equals(intersectionPoint)
                    ) // If the intersection point is not an endpoint of ev1.Segment
                {
                    DivideSegment(ev1, intersectionPoint, events);
                }

                if (!ev2.Point.Equals(intersectionPoint) && !ev2.OtherEvent.Point.Equals(intersectionPoint)
                    ) // If the intersection point is not an endpoint of ev2.Segment
                {
                    DivideSegment(ev2, intersectionPoint, events);
                }

                return(1);
            }

            // The line segments associated to ev1 and ev2 overlap
            var sortedEvents = new List <SweepEvent>();
            var leftEqual    = false;
            var rightEqual   = false;

            if (ev1.Point.Equals(ev2.Point))
            {
                leftEqual = true;
            }
            else if (SweepEvent.CompareTo(ev1, ev2) == 1)
            {
                sortedEvents.Add(ev2);
                sortedEvents.Add(ev1);
            }
            else
            {
                sortedEvents.Add(ev1);
                sortedEvents.Add(ev2);
            }

            if (ev1.OtherEvent.Point.Equals(ev2.OtherEvent.Point))
            {
                rightEqual = true;
            }
            else if (SweepEvent.CompareTo(ev1.OtherEvent, ev2.OtherEvent) == 1)
            {
                sortedEvents.Add(ev2.OtherEvent);
                sortedEvents.Add(ev1.OtherEvent);
            }
            else
            {
                sortedEvents.Add(ev1.OtherEvent);
                sortedEvents.Add(ev2.OtherEvent);
            }

            if (leftEqual)
            {
                // Both line segments are equal or share the left endpoint
                ev2.EdgeType = EdgeType.NonContributing;
                ev1.EdgeType = (ev2.InOut == ev1.InOut) ? EdgeType.SameTransition : EdgeType.DifferentTransition;
                if (!rightEqual)
                {
                    DivideSegment(sortedEvents[1].OtherEvent, sortedEvents[0].Point, events);
                }

                return(2);
            }

            if (rightEqual)
            {
                // The line segments share the right endpoint
                DivideSegment(sortedEvents[0], sortedEvents[1].Point, events);
                return(3);
            }

            if (sortedEvents[0] != sortedEvents[3].OtherEvent)
            {
                // No line segment includes totally the other one
                DivideSegment(sortedEvents[0], sortedEvents[1].Point, events);
                DivideSegment(sortedEvents[1], sortedEvents[2].Point, events);
                return(3);
            }

            // One line segment includes the other one
            DivideSegment(sortedEvents[0], sortedEvents[1].Point, events);
            DivideSegment(sortedEvents[3].OtherEvent, sortedEvents[2].Point, events);
            return(3);
        }
Esempio n. 20
0
        private ContourPolygon ConnectEdges()
        {
            var result = new ContourPolygon();

            var resultEvents = ResultEvents
                               .Where(it => (it.IsStart && it.InResult) || (!it.IsStart && it.OtherEvent.InResult)).ToList();

            // Due to overlapping edges the resultEvents list can be not wholly sorted
            var sorted = false;

            while (!sorted)
            {
                sorted = true;
                for (int i = 0; i < resultEvents.Count; i++)
                {
                    if (i + 1 < resultEvents.Count && SweepEvent.CompareTo(resultEvents[i], resultEvents[i + 1]) == 1)
                    {
                        var tmp = resultEvents[i];
                        resultEvents[i]     = resultEvents[i + 1];
                        resultEvents[i + 1] = tmp;
                        sorted = false;
                    }
                }
            }

            // We cannot do a foreach because we need to set PositionInResult
            for (int i = 0; i < resultEvents.Count; i++)
            {
                var resultEvent = resultEvents[i];
                resultEvent.PositionInResult = i;
            }

            foreach (var resultEvent in resultEvents)
            {
                if (!resultEvent.IsStart)
                {
                    var tmp = resultEvent.PositionInResult;
                    resultEvent.PositionInResult            = resultEvent.OtherEvent.PositionInResult;
                    resultEvent.OtherEvent.PositionInResult = tmp;
                }
            }

            var processed = new BitArray(resultEvents.Count);
            var depth     = new List <int>();
            var holeOf    = new List <int>();

            for (int i = 0; i < resultEvents.Count; i++)
            {
                if (processed[i])
                {
                    continue;
                }

                var contour = new Contour();
                result.Add(contour);
                var contourId = result.NumberOfContours - 1;
                depth.Add(0);
                holeOf.Add(-1);
                if (resultEvents[i].PreviousInResult != null)
                {
                    var lowerContourId = resultEvents[i].PreviousInResult.ContourId;
                    if (!resultEvents[i].PreviousInResult.ResultInOut)
                    {
                        result[lowerContourId].AddHole(contourId);
                        holeOf[contourId] = lowerContourId;
                        depth[contourId]  = depth[lowerContourId] + 1;
                        contour.External  = false;
                    }
                    else if (!result[lowerContourId].External)
                    {
                        result[holeOf[lowerContourId]].AddHole(contourId);
                        holeOf[contourId] = holeOf[lowerContourId];
                        depth[contourId]  = depth[lowerContourId];
                        contour.External  = false;
                    }
                }

                var pos     = i;
                var initial = resultEvents[i].Point;
                contour.AddVertex(initial);
                while (pos >= i)
                {
                    processed[pos] = true;
                    if (resultEvents[pos].IsStart)
                    {
                        resultEvents[pos].ResultInOut = false;
                        resultEvents[pos].ContourId   = contourId;
                    }
                    else
                    {
                        resultEvents[pos].OtherEvent.ResultInOut = true;
                        resultEvents[pos].OtherEvent.ContourId   = contourId;
                    }

                    pos            = resultEvents[pos].PositionInResult;
                    processed[pos] = true;
                    contour.AddVertex(resultEvents[pos].Point);
                    pos = NextPos(pos, resultEvents, processed, i);
                }

                pos = pos == -1 ? i : pos;

                processed[pos] = processed[resultEvents[pos].PositionInResult] = true;
                resultEvents[pos].OtherEvent.ResultInOut = true;
                resultEvents[pos].OtherEvent.ContourId   = contourId;
                if ((depth[contourId] & 1) != 0)
                {
                    contour.ChangeOrientation();
                }
            }

            return(result);
        }
Esempio n. 21
0
 public bool Equals(SweepEvent other)
 {
     throw new NotImplementedException();
 }
Esempio n. 22
0
        public int Triangulate(Mesh mesh)
        {
            this.mesh = mesh;

            // Nonexistent x value used as a flag to mark circle events in sweepline
            // Delaunay algorithm.
            xminextreme = 10 * mesh.bounds.Xmin - 9 * mesh.bounds.Xmax;

            SweepEvent[] eventheap;

            SweepEvent nextevent;
            SweepEvent newevent;
            SplayNode splayroot;
            Otri bottommost = default(Otri);
            Otri searchtri = default(Otri);
            Otri fliptri;
            Otri lefttri = default(Otri);
            Otri righttri = default(Otri);
            Otri farlefttri = default(Otri);
            Otri farrighttri = default(Otri);
            Otri inserttri = default(Otri);
            Vertex firstvertex, secondvertex;
            Vertex nextvertex, lastvertex;
            Vertex connectvertex;
            Vertex leftvertex, midvertex, rightvertex;
            double lefttest, righttest;
            int heapsize;
            bool check4events, farrightflag = false;

            splaynodes = new List<SplayNode>();
            splayroot = null;

            CreateHeap(out eventheap);//, out events, out freeevents);
            heapsize = mesh.invertices;

            mesh.MakeTriangle(ref lefttri);
            mesh.MakeTriangle(ref righttri);
            lefttri.Bond(ref righttri);
            lefttri.LnextSelf();
            righttri.LprevSelf();
            lefttri.Bond(ref righttri);
            lefttri.LnextSelf();
            righttri.LprevSelf();
            lefttri.Bond(ref righttri);
            firstvertex = eventheap[0].vertexEvent;

            HeapDelete(eventheap, heapsize, 0);
            heapsize--;
            do
            {
                if (heapsize == 0)
                {
                    SimpleLog.Instance.Error("Input vertices are all identical.", "SweepLine.SweepLineDelaunay()");
                    throw new Exception("Input vertices are all identical.");
                }
                secondvertex = eventheap[0].vertexEvent;
                HeapDelete(eventheap, heapsize, 0);
                heapsize--;
                if ((firstvertex.x == secondvertex.x) &&
                    (firstvertex.y == secondvertex.y))
                {
                    if (Behavior.Verbose)
                    {
                        SimpleLog.Instance.Warning("A duplicate vertex appeared and was ignored.", 
                            "SweepLine.SweepLineDelaunay().1");
                    }
                    secondvertex.type = VertexType.UndeadVertex;
                    mesh.undeads++;
                }
            } while ((firstvertex.x == secondvertex.x) &&
                     (firstvertex.y == secondvertex.y));
            lefttri.SetOrg(firstvertex);
            lefttri.SetDest(secondvertex);
            righttri.SetOrg(secondvertex);
            righttri.SetDest(firstvertex);
            lefttri.Lprev(ref bottommost);
            lastvertex = secondvertex;

            while (heapsize > 0)
            {
                nextevent = eventheap[0];
                HeapDelete(eventheap, heapsize, 0);
                heapsize--;
                check4events = true;
                if (nextevent.xkey < mesh.bounds.Xmin)
                {
                    fliptri = nextevent.otriEvent;
                    fliptri.Oprev(ref farlefttri);
                    Check4DeadEvent(ref farlefttri, eventheap, ref heapsize);
                    fliptri.Onext(ref farrighttri);
                    Check4DeadEvent(ref farrighttri, eventheap, ref heapsize);

                    if (farlefttri.Equal(bottommost))
                    {
                        fliptri.Lprev(ref bottommost);
                    }
                    mesh.Flip(ref fliptri);
                    fliptri.SetApex(null);
                    fliptri.Lprev(ref lefttri);
                    fliptri.Lnext(ref righttri);
                    lefttri.Sym(ref farlefttri);

                    if (randomnation(SAMPLERATE) == 0)
                    {
                        fliptri.SymSelf();
                        leftvertex = fliptri.Dest();
                        midvertex = fliptri.Apex();
                        rightvertex = fliptri.Org();
                        splayroot = CircleTopInsert(splayroot, lefttri, leftvertex, midvertex, rightvertex, nextevent.ykey);
                    }
                }
                else
                {
                    nextvertex = nextevent.vertexEvent;
                    if ((nextvertex.x == lastvertex.x) &&
                        (nextvertex.y == lastvertex.y))
                    {
                        if (Behavior.Verbose)
                        {
                            SimpleLog.Instance.Warning("A duplicate vertex appeared and was ignored.", 
                                "SweepLine.SweepLineDelaunay().2");
                        }
                        nextvertex.type = VertexType.UndeadVertex;
                        mesh.undeads++;
                        check4events = false;
                    }
                    else
                    {
                        lastvertex = nextvertex;

                        splayroot = FrontLocate(splayroot, bottommost, nextvertex,
                                                ref searchtri, ref farrightflag);
                        //
                        bottommost.Copy(ref searchtri);
                        farrightflag = false;
                        while (!farrightflag && RightOfHyperbola(ref searchtri, nextvertex))
                        {
                            searchtri.OnextSelf();
                            farrightflag = searchtri.Equal(bottommost);
                        }


                        Check4DeadEvent(ref searchtri, eventheap, ref heapsize);

                        searchtri.Copy(ref farrighttri);
                        searchtri.Sym(ref farlefttri);
                        mesh.MakeTriangle(ref lefttri);
                        mesh.MakeTriangle(ref righttri);
                        connectvertex = farrighttri.Dest();
                        lefttri.SetOrg(connectvertex);
                        lefttri.SetDest(nextvertex);
                        righttri.SetOrg(nextvertex);
                        righttri.SetDest(connectvertex);
                        lefttri.Bond(ref righttri);
                        lefttri.LnextSelf();
                        righttri.LprevSelf();
                        lefttri.Bond(ref righttri);
                        lefttri.LnextSelf();
                        righttri.LprevSelf();
                        lefttri.Bond(ref farlefttri);
                        righttri.Bond(ref farrighttri);
                        if (!farrightflag && farrighttri.Equal(bottommost))
                        {
                            lefttri.Copy(ref bottommost);
                        }

                        if (randomnation(SAMPLERATE) == 0)
                        {
                            splayroot = SplayInsert(splayroot, lefttri, nextvertex);
                        }
                        else if (randomnation(SAMPLERATE) == 0)
                        {
                            righttri.Lnext(ref inserttri);
                            splayroot = SplayInsert(splayroot, inserttri, nextvertex);
                        }
                    }
                }

                if (check4events)
                {
                    leftvertex = farlefttri.Apex();
                    midvertex = lefttri.Dest();
                    rightvertex = lefttri.Apex();
                    lefttest = Primitives.CounterClockwise(leftvertex, midvertex, rightvertex);
                    if (lefttest > 0.0)
                    {
                        newevent = new SweepEvent();

                        newevent.xkey = xminextreme;
                        newevent.ykey = CircleTop(leftvertex, midvertex, rightvertex, lefttest);
                        newevent.otriEvent = lefttri;
                        HeapInsert(eventheap, heapsize, newevent);
                        heapsize++;
                        lefttri.SetOrg(new SweepEventVertex(newevent));
                    }
                    leftvertex = righttri.Apex();
                    midvertex = righttri.Org();
                    rightvertex = farrighttri.Apex();
                    righttest = Primitives.CounterClockwise(leftvertex, midvertex, rightvertex);
                    if (righttest > 0.0)
                    {
                        newevent = new SweepEvent();

                        newevent.xkey = xminextreme;
                        newevent.ykey = CircleTop(leftvertex, midvertex, rightvertex, righttest);
                        newevent.otriEvent = farrighttri;
                        HeapInsert(eventheap, heapsize, newevent);
                        heapsize++;
                        farrighttri.SetOrg(new SweepEventVertex(newevent));
                    }
                }
            }

            splaynodes.Clear();
            bottommost.LprevSelf();
            return RemoveGhosts(ref bottommost);
        }
Esempio n. 23
0
 internal StatusItem(SweepEvent sweepEvent)
 {
     SweepEvent = sweepEvent;
 }
Esempio n. 24
0
 public SweepEventVertex(SweepEvent e)
 {
     evt = e;
 }
Esempio n. 25
0
            //public int defaultCompare(SweepEvent a, SweepEvent b)
            //{
            //    return a < b ? -1 : a > b ? 1 : 0;
            //}

            internal void push(SweepEvent item)
            {
                this.data.Add(item);
                this.length++;
                this._up(this.length - 1);
            }