Example #1
0
        /*
         * Set clippedVertices to contain the two ends of the portion of the Voronoi edge that is visible
         * within the bounds. If no part of the Edge falls within the bounds, leave clippedVertices null
         * @param bounds
         */
        public void ClipVertices(Rectf bounds)
        {
            float xmin = bounds.x;
            float ymin = bounds.y;
            float xmax = bounds.right;
            float ymax = bounds.bottom;

            Vertex vertex0, vertex1;
            float  x0, x1, y0, y1;

            if (a == 1 && b >= 0)
            {
                vertex0 = rightVertex;
                vertex1 = leftVertex;
            }
            else
            {
                vertex0 = leftVertex;
                vertex1 = rightVertex;
            }

            if (a == 1)
            {
                y0 = ymin;
                if (vertex0 != null && vertex0.y > ymin)
                {
                    y0 = vertex0.y;
                }
                if (y0 > ymax)
                {
                    return;
                }
                x0 = c - b * y0;

                y1 = ymax;
                if (vertex1 != null && vertex1.y < ymax)
                {
                    y1 = vertex1.y;
                }
                if (y1 < ymin)
                {
                    return;
                }
                x1 = c - b * y1;

                if ((x0 > xmax && x1 > xmax) || (x0 < xmin && x1 < xmin))
                {
                    return;
                }

                if (x0 > xmax)
                {
                    x0 = xmax;
                    y0 = (c - x0) / b;
                }
                else if (x0 < xmin)
                {
                    x0 = xmin;
                    y0 = (c - x0) / b;
                }

                if (x1 > xmax)
                {
                    x1 = xmax;
                    y1 = (c - x1) / b;
                }
                else if (x1 < xmin)
                {
                    x1 = xmin;
                    y1 = (c - x1) / b;
                }
            }
            else
            {
                x0 = xmin;
                if (vertex0 != null && vertex0.x > xmin)
                {
                    x0 = vertex0.x;
                }
                if (x0 > xmax)
                {
                    return;
                }
                y0 = c - a * x0;

                x1 = xmax;
                if (vertex1 != null && vertex1.x < xmax)
                {
                    x1 = vertex1.x;
                }
                if (x1 < xmin)
                {
                    return;
                }
                y1 = c - a * x1;

                if ((y0 > ymax && y1 > ymax) || (y0 < ymin && y1 < ymin))
                {
                    return;
                }

                if (y0 > ymax)
                {
                    y0 = ymax;
                    x0 = (c - y0) / a;
                }
                else if (y0 < ymin)
                {
                    y0 = ymin;
                    x0 = (c - y0) / a;
                }

                if (y1 > ymax)
                {
                    y1 = ymax;
                    x1 = (c - y1) / a;
                }
                else if (y1 < ymin)
                {
                    y1 = ymin;
                    x1 = (c - y1) / a;
                }
            }

            clippedVertices = new Dictionary <LR, Vector2f>();
            if (vertex0 == leftVertex)
            {
                clippedVertices[LR.LEFT]  = new Vector2f(x0, y0);
                clippedVertices[LR.RIGHT] = new Vector2f(x1, y1);
            }
            else
            {
                clippedVertices[LR.RIGHT] = new Vector2f(x0, y0);
                clippedVertices[LR.LEFT]  = new Vector2f(x1, y1);
            }
        }
Example #2
0
 public Voronoi(List <Vector2f> points, Rectf plotBounds)
 {
     weigthDistributor = new Random();
     Init(points, plotBounds, new List <Vector2f>());
 }
Example #3
0
        private void Connect(ref List <Vector2f> points, int j, Rectf bounds, bool closingUp)
        {
            Vector2f rightPoint     = points[points.Count - 1];
            Edge     newEdge        = edges[j];
            LR       newOrientation = edgeOrientations[j];

            // The point that must be conected to rightPoint:
            Vector2f newPoint = newEdge.ClippedEnds[newOrientation];

            if (!CloseEnough(rightPoint, newPoint))
            {
                // The points do not coincide, so they must have been clipped at the bounds;
                // see if they are on the same border of the bounds:
                if (rightPoint.x != newPoint.x && rightPoint.y != newPoint.y)
                {
                    // They are on different borders of the bounds;
                    // insert one or two corners of bounds as needed to hook them up:
                    // (NOTE this will not be correct if the region should take up more than
                    // half of the bounds rect, for then we will have gone the wrong way
                    // around the bounds and included the smaller part rather than the larger)
                    int   rightCheck = BoundsCheck.Check(rightPoint, bounds);
                    int   newCheck = BoundsCheck.Check(newPoint, bounds);
                    float px, py;
                    if ((rightCheck & BoundsCheck.RIGHT) != 0)
                    {
                        px = bounds.right;

                        if ((newCheck & BoundsCheck.BOTTOM) != 0)
                        {
                            py = bounds.bottom;
                            points.Add(new Vector2f(px, py));
                        }
                        else if ((newCheck & BoundsCheck.TOP) != 0)
                        {
                            py = bounds.top;
                            points.Add(new Vector2f(px, py));
                        }
                        else if ((newCheck & BoundsCheck.LEFT) != 0)
                        {
                            if (rightPoint.y - bounds.y + newPoint.y - bounds.y < bounds.height)
                            {
                                py = bounds.top;
                            }
                            else
                            {
                                py = bounds.bottom;
                            }
                            points.Add(new Vector2f(px, py));
                            points.Add(new Vector2f(bounds.left, py));
                        }
                    }
                    else if ((rightCheck & BoundsCheck.LEFT) != 0)
                    {
                        px = bounds.left;

                        if ((newCheck & BoundsCheck.BOTTOM) != 0)
                        {
                            py = bounds.bottom;
                            points.Add(new Vector2f(px, py));
                        }
                        else if ((newCheck & BoundsCheck.TOP) != 0)
                        {
                            py = bounds.top;
                            points.Add(new Vector2f(px, py));
                        }
                        else if ((newCheck & BoundsCheck.RIGHT) != 0)
                        {
                            if (rightPoint.y - bounds.y + newPoint.y - bounds.y < bounds.height)
                            {
                                py = bounds.top;
                            }
                            else
                            {
                                py = bounds.bottom;
                            }
                            points.Add(new Vector2f(px, py));
                            points.Add(new Vector2f(bounds.right, py));
                        }
                    }
                    else if ((rightCheck & BoundsCheck.TOP) != 0)
                    {
                        py = bounds.top;

                        if ((newCheck & BoundsCheck.RIGHT) != 0)
                        {
                            px = bounds.right;
                            points.Add(new Vector2f(px, py));
                        }
                        else if ((newCheck & BoundsCheck.LEFT) != 0)
                        {
                            px = bounds.left;
                            points.Add(new Vector2f(px, py));
                        }
                        else if ((newCheck & BoundsCheck.BOTTOM) != 0)
                        {
                            if (rightPoint.x - bounds.x + newPoint.x - bounds.x < bounds.width)
                            {
                                px = bounds.left;
                            }
                            else
                            {
                                px = bounds.right;
                            }
                            points.Add(new Vector2f(px, py));
                            points.Add(new Vector2f(px, bounds.bottom));
                        }
                    }
                    else if ((rightCheck & BoundsCheck.BOTTOM) != 0)
                    {
                        py = bounds.bottom;

                        if ((newCheck & BoundsCheck.RIGHT) != 0)
                        {
                            px = bounds.right;
                            points.Add(new Vector2f(px, py));
                        }
                        else if ((newCheck & BoundsCheck.LEFT) != 0)
                        {
                            px = bounds.left;
                            points.Add(new Vector2f(px, py));
                        }
                        else if ((newCheck & BoundsCheck.TOP) != 0)
                        {
                            if (rightPoint.x - bounds.x + newPoint.x - bounds.x < bounds.width)
                            {
                                px = bounds.left;
                            }
                            else
                            {
                                px = bounds.right;
                            }
                            points.Add(new Vector2f(px, py));
                            points.Add(new Vector2f(px, bounds.top));
                        }
                    }
                }
                if (closingUp)
                {
                    // newEdge's ends have already been added
                    return;
                }
                points.Add(newPoint);
            }
            Vector2f newRightPoint = newEdge.ClippedEnds[LR.Other(newOrientation)];

            if (!CloseEnough(points[0], newRightPoint))
            {
                points.Add(newRightPoint);
            }
        }
Example #4
0
        private void FortunesAlgorithm()
        {
            Site     newSite, bottomSite, topSite, tempSite;
            Vertex   v, vertex;
            Vector2f newIntStar = Vector2f.zero;
            LR       leftRight;
            Halfedge lbnd, rbnd, llbnd, rrbnd, bisector;
            Edge     edge;

            Rectf dataBounds = sites.GetSitesBounds();

            int sqrtSitesNb            = (int)Math.Sqrt(sites.Count() + 4);
            HalfedgePriorityQueue heap = new HalfedgePriorityQueue(dataBounds.y, dataBounds.height, sqrtSitesNb);
            EdgeList        edgeList   = new EdgeList(dataBounds.x, dataBounds.width, sqrtSitesNb);
            List <Halfedge> halfEdges  = new List <Halfedge>();
            List <Vertex>   vertices   = new List <Vertex>();

            Site bottomMostSite = sites.Next();

            newSite = sites.Next();

            while (true)
            {
                if (!heap.Empty())
                {
                    newIntStar = heap.Min();
                }

                if (newSite != null &&
                    (heap.Empty() || CompareByYThenX(newSite, newIntStar) < 0))
                {
                    // New site is smallest
                    //Debug.Log("smallest: new site " + newSite);

                    // Step 8:
                    lbnd = edgeList.EdgeListLeftNeighbor(newSite.Coord);                // The halfedge just to the left of newSite
                    //UnityEngine.Debug.Log("lbnd: " + lbnd);
                    rbnd = lbnd.edgeListRightNeighbor;                                  // The halfedge just to the right
                    //UnityEngine.Debug.Log("rbnd: " + rbnd);
                    bottomSite = RightRegion(lbnd, bottomMostSite);                     // This is the same as leftRegion(rbnd)
                    // This Site determines the region containing the new site
                    //UnityEngine.Debug.Log("new Site is in region of existing site: " + bottomSite);

                    // Step 9
                    edge = Edge.CreateBisectingEdge(bottomSite, newSite);
                    //UnityEngine.Debug.Log("new edge: " + edge);
                    edges.Add(edge);

                    bisector = Halfedge.Create(edge, LR.LEFT);
                    halfEdges.Add(bisector);
                    // Inserting two halfedges into edgelist constitutes Step 10:
                    // Insert bisector to the right of lbnd:
                    edgeList.Insert(lbnd, bisector);

                    // First half of Step 11:
                    if ((vertex = Vertex.Intersect(lbnd, bisector)) != null)
                    {
                        vertices.Add(vertex);
                        heap.Remove(lbnd);
                        lbnd.vertex = vertex;
                        lbnd.ystar  = vertex.y + newSite.Dist(vertex);
                        heap.Insert(lbnd);
                    }

                    lbnd     = bisector;
                    bisector = Halfedge.Create(edge, LR.RIGHT);
                    halfEdges.Add(bisector);
                    // Second halfedge for Step 10::
                    // Insert bisector to the right of lbnd:
                    edgeList.Insert(lbnd, bisector);

                    // Second half of Step 11:
                    if ((vertex = Vertex.Intersect(bisector, rbnd)) != null)
                    {
                        vertices.Add(vertex);
                        bisector.vertex = vertex;
                        bisector.ystar  = vertex.y + newSite.Dist(vertex);
                        heap.Insert(bisector);
                    }

                    newSite = sites.Next();
                }
                else if (!heap.Empty())
                {
                    // Intersection is smallest
                    lbnd       = heap.ExtractMin();
                    llbnd      = lbnd.edgeListLeftNeighbor;
                    rbnd       = lbnd.edgeListRightNeighbor;
                    rrbnd      = rbnd.edgeListRightNeighbor;
                    bottomSite = LeftRegion(lbnd, bottomMostSite);
                    topSite    = RightRegion(rbnd, bottomMostSite);
                    // These three sites define a Delaunay triangle
                    // (not actually using these for anything...)
                    // triangles.Add(new SiteTriangle(bottomSite, topSite, RightRegion(lbnd, bottomMostSite)));

                    v = lbnd.vertex;
                    v.SetIndex();
                    lbnd.edge.SetVertex(lbnd.leftRight, v);
                    rbnd.edge.SetVertex(rbnd.leftRight, v);
                    edgeList.Remove(lbnd);
                    heap.Remove(rbnd);
                    edgeList.Remove(rbnd);
                    leftRight = LR.LEFT;
                    if (bottomSite.y > topSite.y)
                    {
                        tempSite   = bottomSite;
                        bottomSite = topSite;
                        topSite    = tempSite;
                        leftRight  = LR.RIGHT;
                    }
                    edge = Edge.CreateBisectingEdge(bottomSite, topSite);
                    edges.Add(edge);
                    bisector = Halfedge.Create(edge, leftRight);
                    halfEdges.Add(bisector);
                    edgeList.Insert(llbnd, bisector);
                    edge.SetVertex(LR.Other(leftRight), v);
                    if ((vertex = Vertex.Intersect(llbnd, bisector)) != null)
                    {
                        vertices.Add(vertex);
                        heap.Remove(llbnd);
                        llbnd.vertex = vertex;
                        llbnd.ystar  = vertex.y + bottomSite.Dist(vertex);
                        heap.Insert(llbnd);
                    }
                    if ((vertex = Vertex.Intersect(bisector, rrbnd)) != null)
                    {
                        vertices.Add(vertex);
                        bisector.vertex = vertex;
                        bisector.ystar  = vertex.y + bottomSite.Dist(vertex);
                        heap.Insert(bisector);
                    }
                }
                else
                {
                    break;
                }
            }

            // Heap should be empty now
            heap.Dispose();
            edgeList.Dispose();

            foreach (Halfedge halfedge in halfEdges)
            {
                halfedge.ReallyDispose();
            }
            halfEdges.Clear();

            // we need the vertices to clip the edges
            foreach (Edge e in edges)
            {
                e.ClipVertices(plotBounds);
            }
            // But we don't actually ever use them again!
            foreach (Vertex ve in vertices)
            {
                ve.Dispose();
            }
            vertices.Clear();
        }
Example #5
0
        public void LloydRelaxation(int nbIterations, Vector2f[] ignores)
        {
            // Reapeat the whole process for the number of iterations asked
            for (int i = 0; i < nbIterations; i++)
            {
                List <Vector2f> newPoints = new List <Vector2f>();
                // Go thourgh all sites
                sites.ResetListIndex();
                Site site = sites.Next();

                while (site != null)
                {
                    if (ignores.Contains(site.Coord))
                    {
                        site = sites.Next();
                        continue;
                    }
                    // Loop all corners of the site to calculate the centroid
                    List <Vector2f> region = site.Region(plotBounds);
                    if (region.Count < 1)
                    {
                        site = sites.Next();
                        continue;
                    }

                    Vector2f centroid   = Vector2f.zero;
                    float    signedArea = 0;
                    float    x0         = 0;
                    float    y0         = 0;
                    float    x1         = 0;
                    float    y1         = 0;
                    float    a          = 0;
                    // For all vertices except last
                    for (int j = 0; j < region.Count - 1; j++)
                    {
                        x0          = region[j].x;
                        y0          = region[j].y;
                        x1          = region[j + 1].x;
                        y1          = region[j + 1].y;
                        a           = x0 * y1 - x1 * y0;
                        signedArea += a;
                        centroid.x += (x0 + x1) * a;
                        centroid.y += (y0 + y1) * a;
                    }
                    // Do last vertex
                    x0          = region[region.Count - 1].x;
                    y0          = region[region.Count - 1].y;
                    x1          = region[0].x;
                    y1          = region[0].y;
                    a           = x0 * y1 - x1 * y0;
                    signedArea += a;
                    centroid.x += (x0 + x1) * a;
                    centroid.y += (y0 + y1) * a;

                    signedArea *= 0.5f;
                    centroid.x /= (6 * signedArea);
                    centroid.y /= (6 * signedArea);
                    // Move site to the centroid of its Voronoi cell
                    newPoints.Add(centroid);
                    site = sites.Next();
                }

                // Between each replacement of the cendroid of the cell,
                // we need to recompute Voronoi diagram:
                Rectf origPlotBounds = this.plotBounds;
                Dispose();
                Init(newPoints, origPlotBounds, ignores.ToList());
            }
        }
Example #6
0
 public Voronoi(List <Vector2> points, Rectf plotBounds)
 {
     weigthDistributor = new System.Random();
     Init(points, plotBounds);
 }
Example #7
0
 public Voronoi(List <Vector2> points, Rectf plotBounds, int lloydIterations)
 {
     weigthDistributor = new System.Random();
     Init(points, plotBounds);
     LloydRelaxation(lloydIterations);
 }
Example #8
0
        /*
         * Set clipped vertices to contain the two ends of the portion of the Voronoi edge that is
         * visible within the bounds. If no part of the edge falls within the bounds, leave clipped
         * vertices null.
         * @param bounds
         */
        public void ClipVertices(Rectf bounds)
        {
            float xmin = bounds.X;
            float ymin = bounds.Y;
            float xmax = bounds.Right;
            float ymax = bounds.Bottom;

            Vertex vertex0, vertex1;
            float  x0, x1, y0, y1;

            if (a == 1 && b >= 0)
            {
                vertex0 = this.RightVertex;
                vertex1 = this.LeftVertex;
            }
            else
            {
                vertex0 = this.LeftVertex;
                vertex1 = this.RightVertex;
            }

            if (a == 1)
            {
                y0 = ymin;
                if (vertex0 != null && vertex0.Y > ymin)
                {
                    y0 = vertex0.Y;
                }
                if (y0 > ymax)
                {
                    return;
                }
                x0 = c - b * y0;

                y1 = ymax;
                if (vertex1 != null && vertex1.Y < ymax)
                {
                    y1 = vertex1.Y;
                }
                if (y1 < ymin)
                {
                    return;
                }
                x1 = c - b * y1;

                if ((x0 > xmax && x1 > xmax) || (x0 < xmin && x1 < xmin))
                {
                    return;
                }

                if (x0 > xmax)
                {
                    x0 = xmax;
                    y0 = (c - x0) / b;
                }
                else if (x0 < xmin)
                {
                    x0 = xmin;
                    y0 = (c - x0) / b;
                }

                if (x1 > xmax)
                {
                    x1 = xmax;
                    y1 = (c - x1) / b;
                }
                else if (x1 < xmin)
                {
                    x1 = xmin;
                    y1 = (c - x1) / b;
                }
            }
            else
            {
                x0 = xmin;
                if (vertex0 != null && vertex0.X > xmin)
                {
                    x0 = vertex0.X;
                }
                if (x0 > xmax)
                {
                    return;
                }
                y0 = c - a * x0;

                x1 = xmax;
                if (vertex1 != null && vertex1.X < xmax)
                {
                    x1 = vertex1.X;
                }
                if (x1 < xmin)
                {
                    return;
                }
                y1 = c - a * x1;

                if ((y0 > ymax && y1 > ymax) || (y0 < ymin && y1 < ymin))
                {
                    return;
                }

                if (y0 > ymax)
                {
                    y0 = ymax;
                    x0 = (c - y0) / a;
                }
                else if (y0 < ymin)
                {
                    y0 = ymin;
                    x0 = (c - y0) / a;
                }

                if (y1 > ymax)
                {
                    y1 = ymax;
                    x1 = (c - y1) / a;
                }
                else if (y1 < ymin)
                {
                    y1 = ymin;
                    x1 = (c - y1) / a;
                }
            }

            this.ClippedVertices = new Dictionary <LR, Vector2f>();
            if (vertex0 == this.LeftVertex)
            {
                this.ClippedVertices[LR.LEFT]  = new Vector2f(x0, y0);
                this.ClippedVertices[LR.RIGHT] = new Vector2f(x1, y1);
            }
            else
            {
                this.ClippedVertices[LR.RIGHT] = new Vector2f(x0, y0);
                this.ClippedVertices[LR.LEFT]  = new Vector2f(x1, y1);
            }
        }
Example #9
0
 public Voronoi(List <Vector2f> points, Rectf plotBounds, int lloydIterations)
     : this(new VoronoiManager(points.Count), points, plotBounds, lloydIterations)
 {
 }
Example #10
0
 public Voronoi(List <Vector2f> points, Rectf plotBounds)
     : this(new VoronoiManager(points.Count), points, plotBounds, 0)
 {
 }
Example #11
0
        private void FortunesAlgorithm()
        {
            Profiler.BeginSample("DAll HEs");
            Halfedge.DisposeAll();
            Edge.DisposeAll();
            Profiler.EndSample();

            //UnityEngine.Debug.Log("HE pool: " + Halfedge.unusedPool.Count);

            currentSiteIndex = 0;
            nVertices        = 0;

            // vars

            Profiler.BeginSample("Fortunes: initing");
            Site     newSite, bottomSite, topSite, tempSite;
            Vertex   v, vertex;
            Vector2f newIntStar = Vector2f.zero;
            bool     leftRight;

            Halfedge lbnd     = null;
            Halfedge rbnd     = null;
            Halfedge llbnd    = null;
            Halfedge rrbnd    = null;
            Halfedge bisector = null;

            Edge edge;

            Profiler.EndSample();

            // Data bounds
            Profiler.BeginSample("Fortunes: Getting data bounds");
            Rectf dataBounds = Site.GetSitesBounds(sites);

            Profiler.EndSample();

            int sqrtSitesNb = (int)Math.Sqrt(sites.Count + 4); // WTF

            Profiler.BeginSample("Fortunes: Init heap");

            if (heap == null)
            {
                heap = new HalfedgePriorityQueue(dataBounds.y, dataBounds.height, sqrtSitesNb);
            }
            else
            {
                heap.ReinitNoSizeChange(dataBounds.y, dataBounds.height);
            }

            Profiler.EndSample();

            Profiler.BeginSample("Fortunes: Init EdgeList");
            if (edgeList == null)
            {
                edgeList = new EdgeList(dataBounds.x, dataBounds.width, sqrtSitesNb);
            }
            else
            {
                edgeList.ClearNoResize(dataBounds.x, dataBounds.width);
            }

            //edgeList = new EdgeList(dataBounds.x, dataBounds.width, sqrtSitesNb);
            Profiler.EndSample();

            Profiler.BeginSample("Fortunes: Init HEs and vertices");
            if (halfEdges == null) // TODO: Move to init
            {
                halfEdges = new List <Halfedge>();
                vertices  = new List <Vertex>();
            }
            else
            {
                halfEdges.Clear();
                vertices.Clear();
            }
            Profiler.EndSample();

            Site bottomMostSite = GetNextSite();

            newSite = GetNextSite();

            Profiler.BeginSample("Fortunes: Main Loop");
            while (true)
            {
                if (heap.count > 0)
                {
                    newIntStar = heap.Min();
                }

                if (newSite != null &&
                    (heap.count == 0 || CompareByYThenX(newSite, newIntStar) < 0))
                {
                    // New site is smallest
                    //Debug.Log("smallest: new site " + newSite);

                    // Step 8:
                    // The halfedge just to the left of newSite
                    //UnityEngine.Debug.Log("lbnd: " + lbnd);
                    lbnd = edgeList.EdgeListLeftNeighbor(newSite.Coord);
                    // The halfedge just to the right
                    rbnd = lbnd.edgeListRightNeighbor;
                    //UnityEngine.Debug.Log("rbnd: " + rbnd);

                    // This is the same as leftRegion(rbnd)
                    // This Site determines the region containing the new site
                    bottomSite = RightRegion(lbnd, bottomMostSite);
                    //UnityEngine.Debug.Log("new Site is in region of existing site: " + bottomSite);

                    // Step 9
                    Profiler.BeginSample("CreateBisectingEdge");
                    edge = Edge.CreateBisectingEdge(bottomSite, newSite);
                    Profiler.EndSample();
                    //UnityEngine.Debug.Log("new edge: " + edge);
                    Edges.Add(edge);

                    bisector = Halfedge.Create(edge, false);
                    halfEdges.Add(bisector);
                    // Inserting two halfedges into edgelist constitutes Step 10:
                    // Insert bisector to the right of lbnd:
                    edgeList.Insert(lbnd, bisector);

                    // First half of Step 11:
                    if ((vertex = Vertex.Intersect(lbnd, bisector)) != null)
                    {
                        vertices.Add(vertex);
                        heap.Remove(lbnd);
                        lbnd.vertex = vertex;
                        lbnd.ystar  = vertex.y + newSite.Dist(vertex);
                        heap.Insert(lbnd);
                    }

                    lbnd     = bisector;
                    bisector = Halfedge.Create(edge, true);
                    halfEdges.Add(bisector);
                    // Second halfedge for Step 10::
                    // Insert bisector to the right of lbnd:
                    edgeList.Insert(lbnd, bisector);

                    // Second half of Step 11:
                    if ((vertex = Vertex.Intersect(bisector, rbnd)) != null)
                    {
                        vertices.Add(vertex);
                        bisector.vertex = vertex;
                        bisector.ystar  = vertex.y + newSite.Dist(vertex);
                        heap.Insert(bisector);
                    }

                    newSite = GetNextSite();
                }
                else if (heap.count > 0)
                {
                    // Intersection is smallest
                    lbnd       = heap.ExtractMin();
                    llbnd      = lbnd.edgeListLeftNeighbor;
                    rbnd       = lbnd.edgeListRightNeighbor;
                    rrbnd      = rbnd.edgeListRightNeighbor;
                    bottomSite = LeftRegion(lbnd, bottomMostSite);
                    topSite    = RightRegion(rbnd, bottomMostSite);
                    // These three sites define a Delaunay triangle
                    // (not actually using these for anything...)
#if TRIANGLES
                    triangles.Add(new Triangle(bottomSite, topSite, RightRegion(lbnd, bottomMostSite)));
#endif

                    v             = lbnd.vertex;
                    v.VertexIndex = nVertices++;
                    lbnd.edge.SetVertex(lbnd.leftRight, v);
                    rbnd.edge.SetVertex(rbnd.leftRight, v);
                    edgeList.Remove(lbnd);
                    heap.Remove(rbnd);
                    edgeList.Remove(rbnd);
                    leftRight = false;

                    if (bottomSite.y > topSite.y)
                    {
                        tempSite   = bottomSite;
                        bottomSite = topSite;
                        topSite    = tempSite;
                        leftRight  = true;
                    }

                    edge = Edge.CreateBisectingEdge(bottomSite, topSite);

                    Profiler.BeginSample("addedge");
                    Edges.Add(edge);
                    Profiler.EndSample();

                    bisector = Halfedge.Create(edge, leftRight);

                    halfEdges.Add(bisector);

                    edgeList.Insert(llbnd, bisector);

                    edge.SetVertex(!leftRight, v);

                    if ((vertex = Vertex.Intersect(llbnd, bisector)) != null)
                    {
                        vertices.Add(vertex);
                        heap.Remove(llbnd);
                        llbnd.vertex = vertex;
                        llbnd.ystar  = vertex.y + bottomSite.Dist(vertex);
                        heap.Insert(llbnd);
                    }
                    if ((vertex = Vertex.Intersect(bisector, rrbnd)) != null)
                    {
                        vertices.Add(vertex);
                        bisector.vertex = vertex;
                        bisector.ystar  = vertex.y + bottomSite.Dist(vertex);
                        heap.Insert(bisector);
                    }
                }
                else
                {
                    break;
                }
            }
            Profiler.EndSample();

            // DISPOSE

            // Heap should be empty now
            Profiler.BeginSample("Fortunes: Heap dispose");
            heap.Dispose();
            Profiler.EndSample();
            Profiler.BeginSample("Fortunes: Edgelist dispose");
            edgeList.Dispose();
            Profiler.EndSample();

            Profiler.BeginSample("Fortunes: Halfedges REALLY dispose");
            for (int i = 0; i < halfEdges.Count; i++)
            {
                halfEdges[i].ReallyDispose();
            }
            halfEdges.Clear();
            Profiler.EndSample();

            Profiler.BeginSample("Fortunes: ClipVertices");
            // we need the vertices to clip the edges
            for (int i = 0; i < Edges.Count; i++)
            {
                Edges[i].ClipVertices(PlotBounds, true);
            }
            Profiler.EndSample();

            // But we don't actually ever use them again!
            if (!disposeVerticesManually)
            {
                Profiler.BeginSample("Vertices dispose");
                DisposeVertices();
                Profiler.EndSample();
                UnityEngine.Debug.Log("Disposing vertices!");
            }

            /*
             * UnityEngine.Debug.Assert(Halfedge.unusedPool.Contains(lbnd), "lbnd");
             * UnityEngine.Debug.Assert(Halfedge.unusedPool.Contains(rbnd), "rbnd");
             * UnityEngine.Debug.Assert(Halfedge.unusedPool.Contains(llbnd), "llbnd");
             * UnityEngine.Debug.Assert(Halfedge.unusedPool.Contains(rrbnd), "rrbnd");
             * UnityEngine.Debug.Assert(Halfedge.unusedPool.Contains(bisector), "bisector");
             */
        }
Example #12
0
 public void Redo(List <Vector2f> points, Rectf plotBounds)
 {
     Clear();
     Init(points, plotBounds);
 }