Ejemplo n.º 1
0
		private Halfedge Init(Edge edge, LR lr) {
			this.edge = edge;
			leftRight = lr;
			nextInPriorityQueue = null;
			vertex = null;

			return this;
		}
Ejemplo n.º 2
0
		public void ReallyDispose() {
			edgeListLeftNeighbor = null;
			edgeListRightNeighbor = null;
			nextInPriorityQueue = null;
			edge = null;
			leftRight = null;
			vertex = null;
			pool.Enqueue(this);
		}
Ejemplo n.º 3
0
		public void Dispose() {
			Halfedge halfedge = leftEnd;
			Halfedge prevHe;
			while (halfedge != rightEnd) {
				prevHe = halfedge;
				halfedge = halfedge.edgeListRightNeighbor;
				prevHe.Dispose();
			}
			leftEnd = null;
			rightEnd.Dispose();
			rightEnd = null;

			hash = null;
		}
		public void Remove(Halfedge halfedge) {
			Halfedge previous;
			int removalBucket = Bucket(halfedge);

			if (halfedge.vertex != null) {
				previous = hash[removalBucket];
				while (previous.nextInPriorityQueue != halfedge) {
					previous = previous.nextInPriorityQueue;
				}
				previous.nextInPriorityQueue = halfedge.nextInPriorityQueue;
				count--;
				halfedge.vertex = null;
				halfedge.nextInPriorityQueue = null;
				halfedge.Dispose();
			}
		}
		public void Insert(Halfedge halfedge) {
			Halfedge previous, next;

			int insertionBucket = Bucket(halfedge);
			if (insertionBucket < minBucked) {
				minBucked = insertionBucket;
			}
			previous = hash[insertionBucket];
			while ((next = previous.nextInPriorityQueue) != null &&
			       (halfedge.ystar > next.ystar || (halfedge.ystar == next.ystar && halfedge.vertex.x > next.vertex.x))) {
				previous = next;
			}
			halfedge.nextInPriorityQueue = previous.nextInPriorityQueue;
			previous.nextInPriorityQueue = halfedge;
			count++;
		}
Ejemplo n.º 6
0
		public EdgeList(float xmin, float deltaX, int sqrtSitesNb) {
			this.xmin = xmin;
			this.deltaX = deltaX;
			hashSize = 2 * sqrtSitesNb;

			hash = new Halfedge[hashSize];

			// Two dummy Halfedges:
			leftEnd = Halfedge.CreateDummy();
			rightEnd = Halfedge.CreateDummy();
			leftEnd.edgeListLeftNeighbor = null;
			leftEnd.edgeListRightNeighbor = rightEnd;
			rightEnd.edgeListLeftNeighbor = leftEnd;
			rightEnd.edgeListRightNeighbor = null;
			hash[0] = leftEnd;
			hash[hashSize - 1] = rightEnd;
		}
Ejemplo n.º 7
0
        /*
         * This is the only way to make a Vertex
         *
         * @param halfedge0
         * @param halfedge1
         * @return
         *
         */
        public static Vertex Intersect(Halfedge halfedge0, Halfedge halfedge1)
        {
            Edge edge, edge0, edge1;
            Halfedge halfedge;
            float determinant, intersectionX, intersectionY;
            bool rightOfSite;

            edge0 = halfedge0.edge;
            edge1 = halfedge1.edge;
            if (edge0 == null || edge1 == null) {
                return null;
            }
            if (edge0.RightSite == edge1.RightSite) {
                return null;
            }

            determinant = edge0.a * edge1.b - edge0.b * edge1.a;
            if (Math.Pow(-1.0, 10) < determinant && determinant < Math.Pow(1.0, -10)) {
                // The edges are parallel
                return null;
            }

            intersectionX = (edge0.c * edge1.b - edge1.c * edge0.b)/determinant;
            intersectionY = (edge1.c * edge0.a - edge0.c * edge1.a)/determinant;

            if (Voronoi.CompareByYThenX(edge0.RightSite, edge1.RightSite) < 0) {
                halfedge = halfedge0;
                edge = edge0;
            } else {
                halfedge = halfedge1;
                edge = edge1;
            }
            rightOfSite = intersectionX >= edge.RightSite.x;
            if ((rightOfSite && halfedge.leftRight == LR.LEFT) ||
                (!rightOfSite && halfedge.leftRight == LR.RIGHT)) {
                return null;
            }

            return Vertex.Create(intersectionX, intersectionY);
        }
		private int Bucket(Halfedge halfedge) {
			int theBucket = (int)((halfedge.ystar - ymin)/deltaY * hashSize);
			if (theBucket < 0) theBucket = 0;
			if (theBucket >= hashSize) theBucket = hashSize - 1;
			return theBucket;
		}
Ejemplo n.º 9
0
 /*
  * This function only removes the Halfedge from the left-right list.
  * We cannot dispose it yet because we are still using it.
  * @param halfEdge
  */
 public void Remove(Halfedge halfedge)
 {
     halfedge.edgeListLeftNeighbor.edgeListRightNeighbor = halfedge.edgeListRightNeighbor;
     halfedge.edgeListRightNeighbor.edgeListLeftNeighbor = halfedge.edgeListLeftNeighbor;
     halfedge.edge = Edge.DELETED;
     halfedge.edgeListLeftNeighbor = halfedge.edgeListRightNeighbor = null;
 }
Ejemplo n.º 10
0
 /*
  * Insert newHalfedge to the right of lb
  * @param lb
  * @param newHalfedge
  */
 public void Insert(Halfedge lb, Halfedge newHalfedge)
 {
     newHalfedge.edgeListLeftNeighbor = lb;
     newHalfedge.edgeListRightNeighbor = lb.edgeListRightNeighbor;
     lb.edgeListRightNeighbor.edgeListLeftNeighbor = newHalfedge;
     lb.edgeListRightNeighbor = newHalfedge;
 }
Ejemplo n.º 11
0
 private Site RightRegion(Halfedge he, Site bottomMostSite)
 {
     Edge edge = he.edge;
     if (edge == null) {
         return bottomMostSite;
     }
     return edge.Site(LR.Other(he.leftRight));
 }
Ejemplo n.º 12
0
        private void FortunesAlgorithm()
        {
            Site     newSite, bottomSite, topSite, tempSite;
            Vertex   v, vertex;
            Vector2  newIntStar = Vector2.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 Triangle(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();
        }
Ejemplo n.º 13
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");
             */
        }