abstract protected object GetBiome(Center p);
private void BuildGraph(FortunesAlgorithm <PortableColor> v) { var pointCenterMap = new Dictionary <PointDouble, Center>(); var points = v.GetSiteCoordinates(); points.ForEach((p) => { var c = new Center(); c.loc = p; c.index = centers.Count; centers.Add(c); pointCenterMap[p] = c; }); //bug fix centers.ForEach((c) => { v.GetRegion(c.loc); }); var libedges = v.Edges; var pointCornerMap = new Dictionary <int, Corner>(); foreach (var libedge in libedges) { LineSegment vEdge = libedge.VoronoiEdge(); LineSegment dEdge = libedge.DelaunayLine(); var edge = new Edge(); edge.index = edges.Count; edges.Add(edge); edge.v0 = MakeCorner(pointCornerMap, vEdge.p0); edge.v1 = MakeCorner(pointCornerMap, vEdge.p1); edge.d0 = pointCenterMap[dEdge.p0]; edge.d1 = pointCenterMap[dEdge.p1]; // Centers point to edges. Corners point to edges. if (edge.d0 != null) { edge.d0.borders.Add(edge); } if (edge.d1 != null) { edge.d1.borders.Add(edge); } if (edge.v0 != null) { edge.v0.protrudes.Add(edge); } if (edge.v1 != null) { edge.v1.protrudes.Add(edge); } // Centers point to centers. if (edge.d0 != null && edge.d1 != null) { AddToCenterList(edge.d0.neighbors, edge.d1); AddToCenterList(edge.d1.neighbors, edge.d0); } // Corners point to corners if (edge.v0 != null && edge.v1 != null) { AddToCornerList(edge.v0.adjacent, edge.v1); AddToCornerList(edge.v1.adjacent, edge.v0); } // Centers point to corners if (edge.d0 != null) { AddToCornerList(edge.d0.corners, edge.v0); AddToCornerList(edge.d0.corners, edge.v1); } if (edge.d1 != null) { AddToCornerList(edge.d1.corners, edge.v0); AddToCornerList(edge.d1.corners, edge.v1); } // Corners point to centers if (edge.v0 != null) { AddToCenterList(edge.v0.touches, edge.d0); AddToCenterList(edge.v0.touches, edge.d1); } if (edge.v1 != null) { AddToCenterList(edge.v1.touches, edge.d0); AddToCenterList(edge.v1.touches, edge.d1); } } }
private void DrawPolygon3D <T>(Center c, PortableColor color, IVertexFactory <T> factory, List <T> vertexBuffer) { //only used if Center c is on the edge of the graph. allows for completely filling in the outer polygons Corner edgeCorner1 = null; Corner edgeCorner2 = null; foreach (Center n in c.neighbors) { var e = EdgeWithCenters(c, n); if (e.v0 == null) { //outermost voronoi edges aren't stored in the graph continue; } //find a corner on the exterior of the graph //if this Edge e has one, then it must have two, //finding these two corners will give us the missing //triangle to render. this special triangle is handled //outside this for loop var cornerWithOneAdjacent = e.v0.border ? e.v0 : e.v1; if (cornerWithOneAdjacent.border) { if (edgeCorner1 == null) { edgeCorner1 = cornerWithOneAdjacent; } else { edgeCorner2 = cornerWithOneAdjacent; } } var p = Transform((float)c.loc.X, (float)c.loc.Y, (float)c.elevation); var q = Transform((float)e.v0.loc.X, (float)e.v0.loc.Y, (float)e.v0.elevation); var r = Transform((float)e.v1.loc.X, (float)e.v1.loc.Y, (float)e.v1.elevation); AddTriangle(p, r, q, color, factory, vertexBuffer); } //handle the missing triangle if (edgeCorner2 != null) { //if these two outer corners are NOT on the same exterior edge of the graph, //then we actually must render a polygon (w/ 4 points) and take into consideration //one of the four corners (either 0,0 or 0,height or width,0 or width,height) //note: the 'missing polygon' may have more than just 4 points. this //is common when the number of sites are quite low (less than 5), but not a problem //with a more useful number of sites. //TODO: find a way to fix this if (CloseEnough(edgeCorner1.loc.X, edgeCorner2.loc.X, 1)) { var p = Transform((float)c.loc.X, (float)c.loc.Y, (float)c.elevation); var q = Transform((float)edgeCorner1.loc.X, (float)edgeCorner1.loc.Y, (float)edgeCorner1.elevation); var r = Transform((float)edgeCorner2.loc.X, (float)edgeCorner2.loc.Y, (float)edgeCorner2.elevation); AddTriangle(p, r, q, color, factory, vertexBuffer); } else { /* * var points = new PointInt32[] { * new PointInt32((int)c.loc.X, (int)c.loc.Y), * new PointInt32((int)edgeCorner1.loc.X, (int)edgeCorner1.loc.Y), * new PointInt32((int)((CloseEnough(edgeCorner1.loc.X, bounds.x, 1) || CloseEnough(edgeCorner2.loc.X, bounds.x, .5)) ? bounds.x : bounds.right), (int)((CloseEnough(edgeCorner1.loc.Y, bounds.y, 1) || CloseEnough(edgeCorner2.loc.Y, bounds.y, .5)) ? bounds.y : bounds.bottom)), * new PointInt32((int)edgeCorner2.loc.X, (int)edgeCorner2.loc.Y), * }; * * g.FillPolygon(color, points); * c.area += 0; //TODO: area of polygon given vertices*/ } } }
private void DrawPolygon(IGraphics g, Center c, PortableColor color) { //only used if Center c is on the edge of the graph. allows for completely filling in the outer polygons Corner edgeCorner1 = null; Corner edgeCorner2 = null; c.area = 0; foreach (Center n in c.neighbors) { Edge e = EdgeWithCenters(c, n); if (e.v0 == null) { //outermost voronoi edges aren't stored in the graph continue; } //find a corner on the exterior of the graph //if this Edge e has one, then it must have two, //finding these two corners will give us the missing //triangle to render. this special triangle is handled //outside this for loop Corner cornerWithOneAdjacent = e.v0.border ? e.v0 : e.v1; if (cornerWithOneAdjacent.border) { if (edgeCorner1 == null) { edgeCorner1 = cornerWithOneAdjacent; } else { edgeCorner2 = cornerWithOneAdjacent; } } DrawTriangle(g, color, e.v0, e.v1, c); c.area += Math.Abs(c.loc.X * (e.v0.loc.Y - e.v1.loc.Y) + e.v0.loc.X * (e.v1.loc.Y - c.loc.Y) + e.v1.loc.X * (c.loc.Y - e.v0.loc.Y)) / 2; } //handle the missing triangle if (edgeCorner2 != null) { //if these two outer corners are NOT on the same exterior edge of the graph, //then we actually must render a polygon (w/ 4 points) and take into consideration //one of the four corners (either 0,0 or 0,height or width,0 or width,height) //note: the 'missing polygon' may have more than just 4 points. this //is common when the number of sites are quite low (less than 5), but not a problem //with a more useful number of sites. //TODO: find a way to fix this if (CloseEnough(edgeCorner1.loc.X, edgeCorner2.loc.X, 1)) { DrawTriangle(g, color, edgeCorner1, edgeCorner2, c); } else { var points = new PointInt32[] { new PointInt32((int)c.loc.X, (int)c.loc.Y), new PointInt32((int)edgeCorner1.loc.X, (int)edgeCorner1.loc.Y), new PointInt32((int)((CloseEnough(edgeCorner1.loc.X, bounds.x, 1) || CloseEnough(edgeCorner2.loc.X, bounds.x, .5)) ? bounds.x : bounds.right), (int)((CloseEnough(edgeCorner1.loc.Y, bounds.y, 1) || CloseEnough(edgeCorner2.loc.Y, bounds.y, .5)) ? bounds.y : bounds.bottom)), new PointInt32((int)edgeCorner2.loc.X, (int)edgeCorner2.loc.Y), }; g.FillPolygon(color, points); c.area += 0; //TODO: area of polygon given vertices } } }
private void DrawTriangle(IGraphics g, PortableColor c, Corner c1, Corner c2, Center center) { var points = new PointInt32[] { new PointInt32((int)center.loc.X, (int)center.loc.Y), new PointInt32((int)c1.loc.X, (int)c1.loc.Y), new PointInt32((int)c2.loc.X, (int)c2.loc.Y), }; g.DrawPolygon(c, points); }