Exemplo n.º 1
0
 public QueueItem(CircleEvent ce)
 {
     CircleEvent = ce;
     X           = ce.Site.X;
     Y           = ce.Site.Y;
     Type        = 1;
     IsVoided    = false;
 }
Exemplo n.º 2
0
        private string GetReallyShortString()
        {
            var nodeShort = "(x=" + X + ", y=" + Y + "), color=" + (Color == 0 ? "Red" : "Black") + ", details: ";

            var siteStr  = (Site == null) ? "null" : Site.ToString();
            var beachStr = (BeachSection == null) ? "null" : BeachSection.ToString();
            var ceStr    = (CircleEvent == null) ? "null" : CircleEvent.ToString();

            return(nodeShort + "[site=" + siteStr + ", beach=" + beachStr + ", circleEvent=" + ceStr + "]");
        }
Exemplo n.º 3
0
        public string GetFullString(int level, bool doNotFollow = false)
        {
            String str = "";

            for (int i = 0; i < 3 * level; i++)
            {
                str = str + " ";
            }

            var nodeShort = "(x=" + X + ", y=" + Y + "), color=" + (Color == 0 ? "Red" : "Black") + ", details: ";

            var siteStr  = (Site == null) ? "null" : Site.ToString();
            var beachStr = (BeachSection == null) ? "null" : BeachSection.ToString();
            var ceStr    = (CircleEvent == null) ? "null" : CircleEvent.ToString();

            return(str + nodeShort + "[site=" + siteStr + ", beach=" + beachStr + ", circleEvent=" + ceStr + "]\n"
                   + str + ("(" + level + ") ") + "LEFT: " + NodeString(Left, level + 1, doNotFollow) + "\n"
                   + str + ("(" + level + ") ") + "RIGHT: " + NodeString(Right, level + 1, doNotFollow) + "\n"
                   + str + ("(" + level + ") ") + "PREVIOUS: " + NodeString(Previous, level, true) + "\n"
                   + str + ("(" + level + ") ") + "NEXT: " + NodeString(Next, level, true) + "\n");
        }
Exemplo n.º 4
0
        public void DetachCircleEvent(TreeNode arc)
        {
            //var circleEvent = arc.circleEvent;
            //if (circleEvent)
            //{
            //    if (!circleEvent.rbPrevious)
            //    {
            //        this.firstCircleEvent = circleEvent.rbNext;
            //    }
            //    this.circleEvents.rbRemoveNode(circleEvent); // remove from RB-tree
            //    this.circleEventJunkyard.push(circleEvent);
            //    arc.circleEvent = null;
            //}

            //var circleEvent = n.AsCircleEvent();
            //var circleEvent = n.BeachSection.Site;
            var circleEvent = arc.CircleEvent;

            if (circleEvent != null)
            {
                if (arc.CircleEventNode.Previous == null)
                {
                    firstCircleEvent = arc.Next.CircleEvent;

                    //firstCircleEventNode = n.Next;

                    //if(firstCircleEvent.CircleEvent == null)
                    //{
                    //    Console.WriteLine("ERROR2");
                    //}
                }

                CircleEvents.RemoveNode(arc.CircleEventNode);
                CircleEvents.Dump("circleEvents, detachCircleEvent remove", circleEventCounter++);

                arc.CircleEvent     = null;
                arc.CircleEventNode = null;
            }
        }
Exemplo n.º 5
0
        public void AttachCircleEvent(TreeNode n)
        {
            // start

            //        var lArc = arc.rbPrevious,
            //rArc = arc.rbNext;
            //        if (!lArc || !rArc) { return; } // does that ever happen?
            //        var lSite = lArc.site,
            //            cSite = arc.site,
            //            rSite = rArc.site;

            var lArc = n.Previous;
            var rArc = n.Next;

            if (lArc == null || rArc == null)
            {
                Console.WriteLine("SHOULD NOT HAPPEN");
                return;
            }

            var lSite = lArc.BeachSection.Site;
            var cSite = n.BeachSection.Site;
            var rSite = rArc.BeachSection.Site;

            //        if (lSite === rSite) { return; }

            if (lSite.X == rSite.X && lSite.Y == rSite.Y)
            {
                return;
            }

            //        var bx = cSite.x,
            //            by = cSite.y,
            //            ax = lSite.x - bx,
            //            ay = lSite.y - by,
            //            cx = rSite.x - bx,
            //            cy = rSite.y - by;

            var bx = cSite.X;
            var by = cSite.Y;
            var ax = lSite.X - bx;
            var ay = lSite.Y - by;
            var cx = rSite.X - bx;
            var cy = rSite.Y - by;

            //        var d = 2 * (ax * cy - ay * cx);
            //        if (d >= -2e-12) { return; }

            var d = 2 * (ax * cy - ay * cx);

            if (d >= -2e-12)
            {
                return;
            }

            //        var ha = ax * ax + ay * ay,
            //            hc = cx * cx + cy * cy,
            //            x = (cy * ha - ay * hc) / d,
            //            y = (ax * hc - cx * ha) / d,
            //            ycenter = y + by;

            var ha      = ax * ax + ay * ay;
            var hc      = cx * cx + cy * cy;
            var x       = (cy * ha - ay * hc) / d;
            var y       = (ax * hc - cx * ha) / d;
            var ycenter = y + by;

            //        var circleEvent = this.circleEventJunkyard.pop();
            //        if (!circleEvent)
            //        {
            //            circleEvent = new this.CircleEvent();
            //        }

            var circleEvent = new CircleEvent();

            //        circleEvent.arc = arc;
            //        circleEvent.site = cSite;
            //        circleEvent.x = x + bx;
            //        circleEvent.y = ycenter + this.sqrt(x * x + y * y); // y bottom
            //        circleEvent.ycenter = ycenter;
            //        arc.circleEvent = circleEvent;

            circleEvent.Arc     = n;
            circleEvent.Site    = cSite;
            circleEvent.X       = x + bx;
            circleEvent.Y       = ycenter + Math.Sqrt(x * x + y * y);
            circleEvent.CenterY = ycenter;

            n.CircleEvent = circleEvent;

            //n.X = circleEvent.X; // probably remove
            //n.Y = circleEvent.Y; // probably remove

            TreeNode predecessor = null;
            TreeNode node        = CircleEvents.root;

            //        var predecessor = null,
            //            node = this.circleEvents.root;
            //        while (node)
            //        {
            //            if (circleEvent.y < node.y || (circleEvent.y === node.y && circleEvent.x <= node.x))
            //            {
            //                if (node.rbLeft)
            //                {
            //                    node = node.rbLeft;
            //                }
            //                else
            //                {
            //                    predecessor = node.rbPrevious;
            //                    break;
            //                }
            //            }
            //            else
            //            {
            //                if (node.rbRight)
            //                {
            //                    node = node.rbRight;
            //                }
            //                else
            //                {
            //                    predecessor = node;
            //                    break;
            //                }
            //            }
            //        }

            while (node != null)
            {
                if (circleEvent.Y < node.Y || (circleEvent.Y == node.Y && circleEvent.X <= node.X))
                {
                    if (node.Left != null)
                    {
                        node = node.Left;
                    }
                    else
                    {
                        predecessor = node.Previous;
                        break;
                    }
                }
                else
                {
                    if (node.Right != null)
                    {
                        node = node.Right;
                    }
                    else
                    {
                        predecessor = node;
                        break;
                    }
                }
            }

            //        this.circleEvents.rbInsertSuccessor(predecessor, circleEvent);
            //        if (!predecessor)
            //        {
            //            this.firstCircleEvent = circleEvent;
            //        }

            var circleNode = new TreeNode {
                BeachSection = n.BeachSection, CircleEvent = circleEvent, X = circleEvent.X, Y = circleEvent.Y
            };

            CircleEvents.InsertSuccessor(predecessor, circleNode);

            n.CircleEventNode = circleNode;

            //dumpTree(this.circleEvents, "circleEvents, attachCircleEvent insert", circleEventCounter);
            CircleEvents.Dump("circleEvents, attachCircleEvent insert", circleEventCounter++);

            if (predecessor == null)
            {
                //firstCircleEvent = circleNode;
                //firstCircleEventNode = circleNode;
                //firstCircleEvent = circleEvent;
                firstCircleEvent = circleNode.CircleEvent;

                //if(circleNode.CircleEvent == null)
                //{
                //    Console.WriteLine("ERROR");
                //}
            }
            // end
        }
Exemplo n.º 6
0
        public void RemoveBeachSection(CircleEvent circle) //TreeNode beachSectionNode) //BeachSection b, TreeNode beachSectionNode)
        {
            //var circle = beachsection.circleEvent,
            //    x = circle.x,
            //    y = circle.ycenter,
            //    vertex = this.createVertex(x, y),
            //    previous = beachsection.rbPrevious,
            //    next = beachsection.rbNext,
            //    disappearingTransitions = [beachsection],
            //    abs_fn = Math.abs;

            //var circle = b.CircleEvent.CircleEvent;
            //var circle = beachSectionNode.CircleEvent;
            var beachSectionNode = circle.Arc;
            var x        = circle.X;
            var y        = circle.CenterY;
            var vertex   = CreateVertex(x, y);
            var previous = beachSectionNode.Previous;
            var next     = beachSectionNode.Next;
            //var disappearingTransitions = new List<BeachSection>();
            var disappearingTransitions = new List <TreeNode>();

            disappearingTransitions.Add(beachSectionNode);

            //this.detachBeachsection(beachsection);
            DetachBeachSection(beachSectionNode);

            //var lArc = previous;
            //while (lArc.circleEvent && abs_fn(x - lArc.circleEvent.x) < 1e-9 && abs_fn(y - lArc.circleEvent.ycenter) < 1e-9)
            //{
            //    previous = lArc.rbPrevious;
            //    disappearingTransitions.unshift(lArc);
            //    this.detachBeachsection(lArc); // mark for reuse
            //    lArc = previous;
            //}
            //disappearingTransitions.unshift(lArc);
            //this.detachCircleEvent(lArc);

            var lArc = previous;

            while (lArc.CircleEvent != null &&
                   Math.Abs(x - lArc.CircleEvent.X) < epsilon &&
                   Math.Abs(y - lArc.CircleEvent.CenterY) < epsilon)
            {
                previous = lArc.Previous;
                disappearingTransitions.Insert(0, lArc);
                //DetachBeachSection(lArc.BeachSection, lArc);
                DetachBeachSection(lArc);
                lArc = previous;
            }
            disappearingTransitions.Insert(0, lArc);
            DetachCircleEvent(lArc);

            //// look right
            //var rArc = next;
            //while (rArc.circleEvent && abs_fn(x - rArc.circleEvent.x) < 1e-9 && abs_fn(y - rArc.circleEvent.ycenter) < 1e-9)
            //{
            //    next = rArc.rbNext;
            //    disappearingTransitions.push(rArc);
            //    this.detachBeachsection(rArc); // mark for reuse
            //    rArc = next;
            //}
            //disappearingTransitions.push(rArc);
            //this.detachCircleEvent(rArc);

            var rArc = next;

            while (rArc.CircleEvent != null &&
                   Math.Abs(x - rArc.CircleEvent.X) < epsilon &&
                   Math.Abs(y - rArc.CircleEvent.CenterY) < epsilon)
            {
                next = rArc.Next;
                disappearingTransitions.Add(rArc);
                //DetachBeachSection(rArc.BeachSection, rArc);
                DetachBeachSection(rArc);
                rArc = next;
            }
            disappearingTransitions.Add(rArc);
            DetachCircleEvent(rArc);

            //var nArcs = disappearingTransitions.length,
            //    iArc;
            //for (iArc = 1; iArc < nArcs; iArc++)
            //{
            //    rArc = disappearingTransitions[iArc];
            //    lArc = disappearingTransitions[iArc - 1];
            //    this.setEdgeStartpoint(rArc.edge, lArc.site, rArc.site, vertex);
            //}

            var nArcs = disappearingTransitions.Count;
            int iArc;

            for (iArc = 1; iArc < nArcs; iArc++)
            {
                rArc = disappearingTransitions[iArc];
                lArc = disappearingTransitions[iArc - 1];
                rArc.BeachSection.Edge.SetStartPoint(lArc.BeachSection.Site, rArc.BeachSection.Site, vertex);
            }

            //lArc = disappearingTransitions[0];
            //rArc = disappearingTransitions[nArcs - 1];
            //rArc.edge = this.createEdge(lArc.site, rArc.site, undefined, vertex);

            lArc = disappearingTransitions[0];
            rArc = disappearingTransitions[nArcs - 1];
            rArc.BeachSection.Edge = CreateEdge(lArc.BeachSection.Site, rArc.BeachSection.Site, null, vertex);

            //this.a--ttachCircleEvent(lArc);
            //this.a--ttachCircleEvent(rArc);

            AttachCircleEvent(lArc);
            AttachCircleEvent(rArc);
        }
Exemplo n.º 7
0
        public void Compute(List <Site> input)
        {
            //this.reset();
            Reset();

            //// any diagram data available for recycling?
            //// I do that here so that this is included in execution time
            //if (this.toRecycle)
            //{
            //    this.vertexJunkyard = this.vertexJunkyard.concat(this.toRecycle.vertices);
            //    this.edgeJunkyard = this.edgeJunkyard.concat(this.toRecycle.edges);
            //    this.cellJunkyard = this.cellJunkyard.concat(this.toRecycle.cells);
            //    this.toRecycle = null;
            //}

            //// Initialize site event queue
            //var siteEvents = sites.slice(0);
            //siteEvents.sort(function(a, b){
            //    var r = b.y - a.y;
            //    if (r) { return r; }
            //    return b.x - a.x;
            //});
            Sites = new List <Site>();

            Console.WriteLine("+++ INITIALIZING WITH " + input.Count + " SITES");
            for (int i = 0; i < input.Count; i++)
            {
                var s = Input[i];

                Sites.Add(s);
            }

            Sites.Sort();

            //// process queue
            //var site = siteEvents.pop(),
            //    siteid = 0,
            //    xsitex, // to avoid duplicate sites
            //    xsitey,
            //    cells = this.cells,
            //    circle;

            var         site = PopSite();
            double      xsitex = -1, xsitey = -1;
            CircleEvent circle = null;

            //// main loop
            //for (; ; )
            //{
            //    // we need to figure whether we handle a site or circle event
            //    // for this we find out if there is a site event and it is
            //    // 'earlier' than the circle event
            //    circle = this.firstCircleEvent;
            for (; ;)
            {
                circle = firstCircleEvent;
                //circle = firstCircleEvent == null ? null : firstCircleEvent.Arc;

                if (site != null && (circle == null ||
                                     site.Y < circle.Y ||
                                     (site.Y == circle.Y && site.X < circle.X)
                                     )
                    )
                {
                    if (site.X != xsitex || site.Y != xsitey)
                    {
                        //GetCell(site.Id) = CreateCell(site);
                        Cells.Add(site.Id, CreateCell(site));
                        AddBeachSection(site);
                        xsitex = site.X;
                        xsitey = site.Y;
                    }

                    site = PopSite();
                }
                else if (circle != null)
                {
                    //RemoveBeachSection(circle.BeachSection, circle);
                    //RemoveBeachSection(circle.CircleEvent.Arc);
                    RemoveBeachSection(circle);
                }
                else
                {
                    break;
                }
            }

            //    // add beach section
            //    if (site && (!circle || site.y < circle.y || (site.y === circle.y && site.x < circle.x)))
            //    {
            //        // only if site is not a duplicate
            //        if (site.x !== xsitex || site.y !== xsitey)
            //        {
            //            // first create cell for new site
            //            cells[siteid] = this.createCell(site);
            //            site.voronoiId = siteid++;
            //            // then create a beachsection for that site
            //            this.addBeachsection(site);
            //            // remember last site coords to detect duplicate
            //            xsitey = site.y;
            //            xsitex = site.x;
            //        }
            //        site = siteEvents.pop();
            //    }

            //    // remove beach section
            //    else if (circle)
            //    {
            //        this.removeBeachsection(circle.arc);
            //    }

            //    // all done, quit
            //    else
            //    {
            //        break;
            //    }
            //}
        }
Exemplo n.º 8
0
        public void RemoveArc(CircleEvent e)
        {
            //        var x = event.center.x;
            //    var y = event.center.y;
            //    var sweep = event.y;
            //    var deletionPoint = this.findDeletionPoint(x, sweep);
            //    // there could be more than one empty arc at the deletion point, this
            //    // happens when more than two edges are linked by the same vertex,
            //    // so we will collect all those edges by looking up both sides of
            //    // the deletion point

            var x  = e.CenterX;
            var y  = e.CenterY;
            var sw = e.Y;

            int deletionPoint = FindDeletionPoint(x, sw);

            //    // look left
            //    var iLeft = deletionPoint;
            //    while (iLeft-1 > 0 && this.equalWithEpsilon(x, this.leftBreakPoint(iLeft-1, sweep)) ) {
            //        iLeft--;
            //    }
            int iLeft = deletionPoint;

            while (iLeft - 1 > 0 && equals(x, GetLeftBreakPoint(iLeft - 1, sw)))
            {
                iLeft--;
            }

            //// look right
            ///
            //var iRight = deletionPoint;
            //    while (iRight+1 < this.arcs.length && this.equalWithEpsilon(x,this.rightBreakPoint(iRight+1, sweep)) ) {
            //    iRight++;
            //}
            int iRight = deletionPoint;

            while (iRight + 1 < Arcs.Count && equals(x, GetRightBreakPoint(iRight + 1, sw)))
            {
                iRight++;
            }

            //// walk through all the collapsed beach sections and set the start point
            //// of their left edge
            //var lArc, rArc;
            //    for (var iArc=iLeft; iArc<=iRight+1; iArc++) {
            //    lArc = this.arcs[iArc - 1];
            //    rArc = this.arcs[iArc];
            //    this.setEdgeStartpoint(rArc.edge, lArc.site, rArc.site, new this.Vertex(x, y));
            //}
            BeachSection lArc, rArc;

            for (int iArc = iLeft; iArc <= iRight + 1; iArc++)
            {
                lArc = Arcs[iArc - 1];
                rArc = Arcs[iArc];

                rArc.Edge.SetStartPoint(lArc.Site, rArc.Site, new Vertex(x, y));
            }


            //    // void circle events of collapsed beach sections and adjacent beach sections
            //    this.voidCircleEvents(iLeft-1,iRight+1);
            VoidCircleEvents(iLeft - 1, iRight + 1);

            //    // removed collapsed beach sections from beachline
            //    this.arcs.splice(iLeft,iRight-iLeft+1);
            Arcs.RemoveRange(iLeft, iRight - iLeft + 1);

            //// create new edge as we have a new transition between
            //// two beach sections which were previously not adjacent
            //lArc = this.arcs [iLeft-1];
            //rArc = this.arcs [iLeft];
            lArc = Arcs[iLeft - 1];
            rArc = Arcs[iLeft];

            //rArc.edge = this.createEdge(lArc.site,rArc.site,undefined,new this.Vertex(x, y));
            rArc.Edge = CreateEdge(lArc.Site, rArc.Site, null, new Vertex(x, y));

            //    // create circle events if any for beach sections left in the beachline
            //    // adjacent to collapsed sections
            //    this.addCircleEvents(iLeft-1,sweep);
            //    this.addCircleEvents(iLeft,sweep);

            AddCircleEvents(iLeft - 1, sw);
            AddCircleEvents(iLeft, sw);
        }
Exemplo n.º 9
0
        public QueueItem QueuePushCircle(CircleEvent item)
        {
            var o = new QueueItem(item);

            //var q = this.circEvents;
            //var r = q.length;
            //if (r)
            //{
            //    var l = 0;
            //    var i, c;
            //    while (l < r)
            //    {
            //        i = (l + r) >> 1;
            //        c = o.y - q[i].y;
            //        if (!c) { c = o.x - q[i].x; }
            //        if (c > 0) { r = i; }
            //        else { l = i + 1; }
            //    }
            //    q.splice(l, 0, o);
            //}
            //else
            //{
            //    q.push(o);
            //}

            var q = CircleEvents;
            var r = q.Count;

            if (r > 0)
            {
                int    l = 0;
                int    i;
                double c;

                while (l < r)
                {
                    i = (l + r) / 2;
                    c = o.Y - q[i].Y;
                    if (c == 0)
                    {
                        c = o.X - q[i].X;
                    }
                    if (c > 0)
                    {
                        r = i;
                    }
                    else
                    {
                        l = i + 1;
                    }
                }

                q.Insert(l, o);
            }
            else
            {
                q.Add(o);
            }

            return(o);
        }
Exemplo n.º 10
0
        public void AddCircleEvents(int iArc, double sw)
        {
            //    addCircleEvents: function(iArc, sweep) {

            //        if (iArc <= 0 || iArc >= this.arcs.length - 1) { return; }
            if (iArc <= 0 || iArc >= Arcs.Count - 1)
            {
                return;
            }

            //        var arc = this.arcs[iArc];
            //        var lSite = this.arcs[iArc - 1].site;
            //        var cSite = this.arcs[iArc].site;
            //        var rSite = this.arcs[iArc + 1].site;
            var arc   = Arcs[iArc];
            var lSite = Arcs[iArc - 1].Site;
            var cSite = Arcs[iArc].Site;
            var rSite = Arcs[iArc + 1].Site;

            //        // if any two sites are repeated in the same beach section triplet,
            //        // there can't be convergence
            //        if (lSite.id == rSite.id || lSite.id == cSite.id || cSite.id == rSite.id) { return; }
            if (lSite.Id == rSite.Id || lSite.Id == cSite.Id || cSite.Id == rSite.Id)
            {
                return;
            }

            //        // if points l->c->r are clockwise, then center beach section does not
            //        // converge, hence it can't end up as a vertex
            //        if ((lSite.y - cSite.y) * (rSite.x - cSite.x) <= (lSite.x - cSite.x) * (rSite.y - cSite.y)) { return; }

            if ((lSite.Y - cSite.Y) * (rSite.X - cSite.X) <= (lSite.X - cSite.X) * (rSite.Y - cSite.Y))
            {
                return;
            }

            //        // find circumscribed circle
            //        var circle = this.circumcircle(lSite, cSite, rSite);

            var circle = CalculateCircle(lSite, cSite, rSite);

            //        // not valid if the bottom-most point of the circumcircle
            //        // is above the sweep line
            //        // TODO: And what if it is on the sweep line, should it be discarded if it is
            //        // *before* the last processed x value? Need to think about this.

            //        var ybottom = circle.y + circle.radius;

            var ybottom = circle.Y + circle.Radius;

            //        if (!this.greaterThanOrEqualWithEpsilon(ybottom, sweep)) { return; }
            if (!gte(ybottom, sw))
            {
                return;
            }

            //        var circEvent ={
            //    type: this.CIRCLE_EVENT,
            //    site: cSite,
            //    x: circle.x,
            //    y: ybottom,
            //    center: { x: circle.x, y: circle.y}
            //    };
            //    arc.circleEvent = circEvent;
            //    this.queuePushCircle(circEvent);
            //},
            var ce = new CircleEvent {
                Site = cSite, X = circle.X, Y = ybottom, CenterX = circle.X, CenterY = circle.Y
            };

            arc.CircleEvent = QueuePushCircle(ce);
        }