private void FortunesAlgorithm()
{
Site newSite, bottomSite, topSite, tempSite;
Vertex v, vertex;
PointF newintstar = PointF.Empty;
LR leftRight;
Halfedge lbnd, rbnd, llbnd, rrbnd, bisector;
Edge edge;
RectangleF dataBounds = _sites.GetSitesBounds();
int sqrt_nsites = (int)(Math.Sqrt(_sites.Length + 4));
HalfedgePriorityQueue heap = new HalfedgePriorityQueue(dataBounds.Y, dataBounds.Height, sqrt_nsites);
EdgeList edgeList = new EdgeList(dataBounds.X, dataBounds.Width, sqrt_nsites);
List <Halfedge> halfEdges = new List <Halfedge>();
List <Vertex> vertices = new List <Vertex>();
Site bottomMostSite = _sites.Next();
newSite = _sites.Next();
for (; ;)
{
if (heap.Empty() == false)
{
newintstar = heap.Min();
}
if (newSite != null &&
(heap.Empty() || CompareByYThenX(newSite, newintstar) < 0))
{
/* new site is smallest */
//trace("smallest: new site " + newSite);
// Step 8:
lbnd = edgeList.EdgeListLeftNeighbor(newSite.Coord()); // the Halfedge just to the left of newSite
//trace("lbnd: " + lbnd);
rbnd = lbnd.edgeListRightNeighbor; // the Halfedge just to the right
//trace("rbnd: " + rbnd);
bottomSite = RightRegion(lbnd, bottomMostSite); // this is the same as leftRegion(rbnd)
// this Site determines the region containing the new site
//trace("new Site is in region of existing site: " + bottomSite);
// Step 9:
edge = Edge.CreateBisectingEdge(bottomSite, newSite);
//trace("new edge: " + edge);
_edges.Add(edge);
bisector = Halfedge.Create(edge, LR.LEFT);
halfEdges.Add(bisector);
// inserting two Halfedges into edgeList static readonlyitutes 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() == false)
{
/* 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)));
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 edge2 in _edges)
{
edge2.ClipVertices(_plotBounds);
}
// but we don't actually ever use them again!
foreach (Vertex vertex2 in vertices)
{
vertex2.Dispose();
}
vertices.Clear();
}