Пример #1
0
 /// <summary>
 /// This method can also be called to clear the object of any of its data from a previous run. You do this when you 
 /// want to create some blue noise. For instance with the Lloyd Relaxation iterations.
 /// </summary>
 /// <created>Dennis Steinmeijer</created>
 /// <date>2013-07-20</date>
 public void Reset()
 {
     this.SiteList.Clear();
     this.Sites.Clear();
     this.Cells.Clear();
     this.FirstCircle = null;
     this.Edges.Clear();
     this.BeachLines = new RBTree();
     this.Circles = new RBTree();
     this.BeachJunkyard.Clear();
     this.CircleJunkyard.Clear();
     this.EdgeVertices.Clear();
 }
Пример #2
0
        /// <summary>
        /// Checks to see if a circle event is available in the junkyard and uses it,
        /// or makes a new one and returns it.
        /// </summary>
        private Circle GetCircle()
        {
            Circle objCircle = null;

            // Check to see whether the stack is empty.
            if (this.CircleJunkyard.Count > 0)
            {
                // Try to retrieve a circle vent from the junkyard.
                objCircle = this.CircleJunkyard.Pop();
            }

            // If we don't find a circle event in the junkyard we'll make a new one.
            if (objCircle == null)
            {
                objCircle = new Circle();
            }

            // And give it back!
            return objCircle;
        }
Пример #3
0
        /// <summary>
        /// Attach a circle event.
        /// </summary>
        private void AttachCircle(Beach objArc)
        {
            // This is a node in the RBTree which points to a beachsection.
            Beach objArcLeft = objArc.Previous as Beach;
            Beach objArcRight = objArc.Next as Beach;

            if (objArcLeft == null || objArcRight == null)
            {
                return;
            } // Does that ever happen?

            Point objSiteLeft = objArcLeft.Site;
            Point objSite = objArc.Site;
            Point objSiteRight = objArcRight.Site;

            // If site of left beachsection is same as site of right beachsection, there can't be convergence.
            if (objSiteLeft == objSiteRight)
            {
                return;
            }

            // Find the circumscribed circle for the three sites associated
            // with the beachsection triplet.
            // rhill 2011-05-26: It is more efficient to calculate in-place
            // rather than getting the resulting circumscribed circle from an
            // object returned by calling Voronoi.circumcircle()
            // http://mathforum.org/library/drmath/view/55002.html
            // Except that I bring the origin at cSite to simplify calculations.
            // The bottom-most part of the circumcircle is our Fortune 'circle
            // event', and its center is a vertex potentially part of the final
            // Voronoi diagram.
            double bx = objSite.x;
            double by = objSite.y;
            double ax = objSiteLeft.x - bx;
            double ay = objSiteLeft.y - by;
            double cx = objSiteRight.x - bx;
            double cy = objSiteRight.y - by;

            // If points l->c->r are clockwise, then center beach section does not
            // collapse, hence it can't end up as a vertex (we reuse 'd' here, which
            // sign is reverse of the orientation, hence we reverse the test.
            // http://en.wikipedia.org/wiki/Curve_orientation#Orientation_of_a_simple_polygon
            // rhill 2011-05-21: Nasty finite precision error which caused circumcircle() to
            // return infinites: 1e-12 seems to fix the problem.
            double d = 2 * (ax * cy - ay * cx);
            if (d >= -2e-12)
            {
                return;
            }

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

            // Important: ybottom should always be under or at sweep, so no need
            // to waste CPU cycles by checking

            // Recycle circle event object if possible.
            Circle objCircle = this.GetCircle();

            objCircle.Arc = objArc;
            objCircle.Site = objSite;
            objCircle.x = x + bx;
            objCircle.y = ycenter + Math.Sqrt(x * x + y * y); // y bottom
            objCircle.ycenter = ycenter;
            objArc.Circle = objCircle;

            // find insertion point in RB-tree: circle events are ordered from
            // smallest to largest
            Circle objNodePrevious = null;
            Circle objNode = this.Circles.Root as Circle;

            while (objNode != null)
            {
                if (objCircle.y < objNode.y || (objCircle.y == objNode.y && objCircle.x <= objNode.x))
                {
                    if (objNode.Left != null)
                    {
                        objNode = objNode.Left as Circle;
                    }
                    else
                    {
                        objNodePrevious = objNode.Previous as Circle;
                        break;
                    }
                }
                else
                {
                    if (objNode.Right != null)
                    {
                        objNode = objNode.Right as Circle;
                    }
                    else
                    {
                        objNodePrevious = objNode;
                        break;
                    }
                }
            }

            this.Circles.InsertSuccessor(objNodePrevious, objCircle);
            if (objNodePrevious == null)
            {
                this.FirstCircle = objCircle;
            }
        }
Пример #4
0
        /// <summary>
        /// Detach a circle event.
        /// </summary>
        private void DetachCircleEvent(Beach objArc)
        {
            Circle objCircle = objArc.Circle;

            if (objCircle == null)
            {
                return;
            }

            if (objCircle.Previous == null)
            {
                this.FirstCircle = objCircle.Next as Circle;
            }

            // Remove from RBTree.
            this.Circles.RemoveNode(objCircle);
            this.CircleJunkyard.Push(objCircle);
            objArc.Circle = null;
        }