private void AssignOceanCoastAndLand() { Queue <Center> queue = new Queue <Center>(); double waterThreshold = 0.40; foreach (Center c in centers) { int numWater = 0; foreach (Corner cr in c.corners) { if (cr.border) { c.border = true; c.water = true; c.ocean = true; queue.Enqueue(c); } if (cr.water) { numWater++; } } c.water = (c.ocean || ((double)numWater / c.corners.Count >= waterThreshold)); } while (queue.Count > 0) { Center c = queue.Dequeue(); foreach (Center n in c.neighbors) { if (n.water && !n.ocean) { n.ocean = true; queue.Enqueue(n); } } } foreach (Center c in centers) { bool oNeighbor = false; bool lNeighbor = false; foreach (Center n in c.neighbors) { oNeighbor |= n.ocean; lNeighbor |= !n.water; } c.coast = oNeighbor & lNeighbor; } foreach (Corner c in corners) { int nO = 0; int nL = 0; foreach (Center cn in c.touches) { nO += cn.ocean ? 1 : 0; nL += !cn.water ? 1 : 0; } c.ocean = nO == c.touches.Count; c.coast = nO > 0 && nL > 0; c.water = c.border || ((nL != c.touches.Count) && !c.coast); } }
private void BuildGraph(Voronoi v) { Dictionary <Point, Center> pCMap = new Dictionary <Point, Center>(); List <Point> points = v.SiteCoords(); // For each point create a center foreach (Point p in points) { Center c = new Center(); c.loc = p; c.index = centers.Count; centers.Add(c); pCMap[p] = c; } // For each center, assign a region foreach (Center c in centers) { v.Region(c.loc); } List <Edge> libEdges = v.Edges(); Dictionary <int, Corner> pCRMap = new Dictionary <int, Corner>(); // For each edge in the voronoi edges foreach (Edge e in libEdges) { LineSegment vEdge = e.VoronoiEdge(); LineSegment dEdge = e.DelaunayLine(); DelaunayEdge dE = new DelaunayEdge(); dE.index = edges.Count; edges.Add(dE); // Setup midpoints for viable voronoi edges for noisy edge generation if (vEdge.p0 != null && vEdge.p1 != null) { dE.midPoint = InterpolatePoint(vEdge.p0, vEdge.p1, 0.5); } // Create corners for the voronoi vertices of the edge dE.v0 = MakeCorner(pCRMap, vEdge.p0); dE.v1 = MakeCorner(pCRMap, vEdge.p1); dE.d0 = pCMap[dEdge.p0]; dE.d1 = pCMap[dEdge.p1]; // Add borders for delaunay edges if (dE.d0 != null) { dE.d0.borders.Add(dE); } if (dE.d1 != null) { dE.d1.borders.Add(dE); } if (dE.v0 != null) { dE.v0.protrudes.Add(dE); } if (dE.v1 != null) { dE.v1.protrudes.Add(dE); } if (dE.d0 != null && dE.d1 != null) { AddToCenterList(dE.d0.neighbors, dE.d1); AddToCenterList(dE.d1.neighbors, dE.d0); } if (dE.v0 != null && dE.v1 != null) { AddToCornerList(dE.v0.adjacent, dE.v1); AddToCornerList(dE.v1.adjacent, dE.v0); } if (dE.d0 != null) { AddToCornerList(dE.d0.corners, dE.v0); AddToCornerList(dE.d0.corners, dE.v1); } if (dE.d1 != null) { AddToCornerList(dE.d1.corners, dE.v0); AddToCornerList(dE.d1.corners, dE.v1); } if (dE.v0 != null) { AddToCenterList(dE.v0.touches, dE.d0); AddToCenterList(dE.v0.touches, dE.d1); } if (dE.v1 != null) { AddToCenterList(dE.v1.touches, dE.d0); AddToCenterList(dE.v1.touches, dE.d1); } } }
// Draws a voronoi polygon private void DrawPolygon(System.Drawing.Graphics g, Center c, System.Drawing.Color color, bool noisyEdges, bool smoothBlending, bool lighting, bool drawBiomes) { Corner eC1 = null; Corner eC2 = null; c.area = 0; foreach (Center n in c.neighbors) { DelaunayEdge e = EdgeWithCenters(c, n); //Experimental Color (Biome Blending) if (smoothBlending && drawBiomes) { color = BlendBiome(color, c, n); } //Experimental Lighting (Light Vectors) if (lighting && drawBiomes) { color = ColorWithSlope(color, c, n, e); } // If noisy edges is off, draw triangles to create voronoi polygons (center to vertices of each edge) if (!noisyEdges) { if (e.v0 == null) { continue; } Corner corner1A = e.v0.border ? e.v0 : e.v1; if (corner1A.border) { if (eC1 == null) { eC1 = corner1A; } else { eC2 = corner1A; } } DrawTriangle(g, e.v0, e.v1, c, color); 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; } //Experimental Polygon Drawing using noisy (natural) edges if (noisyEdges) { // For each of the noisy edge paths fill the polygon created betweeen them and the center if (path0[e.index] != null) { List <Point> tPath = path0[e.index]; System.Drawing.Point[] tA = new System.Drawing.Point[tPath.Count + 2]; tA[0] = new System.Drawing.Point((int)c.loc.x, (int)c.loc.y); for (int i = 0; i < tPath.Count; i++) { tA[i + 1] = new System.Drawing.Point((int)tPath[i].x, (int)tPath[i].y); } tA[tA.Count() - 1] = new System.Drawing.Point((int)c.loc.x, (int)c.loc.y); g.FillPolygon(new System.Drawing.SolidBrush(color), tA); } if (path1[e.index] != null) { List <Point> tPath = path1[e.index]; System.Drawing.Point[] tA = new System.Drawing.Point[tPath.Count + 2]; tA[0] = new System.Drawing.Point((int)c.loc.x, (int)c.loc.y); for (int i = 0; i < tPath.Count; i++) { tA[i + 1] = new System.Drawing.Point((int)tPath[i].x, (int)tPath[i].y); } tA[tA.Count() - 1] = new System.Drawing.Point((int)c.loc.x, (int)c.loc.y); g.FillPolygon(new System.Drawing.SolidBrush(color), tA); } } } if (eC2 != null) { if (CloseEnough(eC1.loc.x, eC2.loc.x, 1)) { DrawTriangle(g, eC1, eC2, c, color); } else { System.Drawing.Point[] points = new System.Drawing.Point[4]; points[0] = new System.Drawing.Point((int)c.loc.x, (int)c.loc.y); points[1] = new System.Drawing.Point((int)eC1.loc.x, (int)eC1.loc.y); int tX = (int)((CloseEnough(eC1.loc.x, bounds.x, 1) || CloseEnough(eC2.loc.x, bounds.x, 0.5)) ? bounds.x : bounds.right); int tY = (int)((CloseEnough(eC1.loc.y, bounds.y, 1) || CloseEnough(eC2.loc.y, bounds.y, 0.5)) ? bounds.y : bounds.bottom); points[2] = new System.Drawing.Point(tX, tY); points[3] = new System.Drawing.Point((int)eC2.loc.x, (int)eC2.loc.y); g.FillPolygon(new System.Drawing.SolidBrush(color), points); c.area += 0; } } }
// Implemented in GraphImplementation abstract protected Enum GetBiome(Center p);
protected override Enum GetBiome(Center p) { if (p.ocean) { if (p.elevation > 0.9) { return(ColorData.OCEAN); } else if (p.elevation > 0.3) { return(ColorData.OCEAN); } else { return(ColorData.OCEAN); } } else if (p.water) { if (p.elevation < 0.1) { return(ColorData.MARSH); } else if (p.elevation > 0.8) { return(ColorData.ICE); } else { return(ColorData.LAKE); } } else if (p.coast) { return(ColorData.BEACH); } else if (p.elevation > 0.8) { if (p.moisture > 0.50) { return(ColorData.SNOW); } else if (p.moisture > 0.33) { return(ColorData.TUNDRA); } else if (p.moisture > 0.16) { return(ColorData.BARE); } else { return(ColorData.SCORCHED); } } else if (p.elevation > 0.6) { if (p.moisture > 0.66) { return(ColorData.TAIGA); } else if (p.moisture > 0.33) { return(ColorData.SHRUBLAND); } else { return(ColorData.TEMPERATE_DESERT); } } else if (p.elevation > 0.3) { if (p.moisture > 0.83) { return(ColorData.TEMPERATE_RAIN_FOREST); } else if (p.moisture > 0.5) { return(ColorData.TEMPERATE_DECIDUOUS_FOREST); } else if (p.moisture > 0.16) { return(ColorData.GRASSLAND); } else { return(ColorData.TEMPERATE_DESERT); } } else { if (p.moisture > 0.66) { return(ColorData.TROPICAL_RAIN_FOREST); } else if (p.moisture > 0.33) { return(ColorData.TROPICAL_SEASONAL_FOREST); } else if (p.moisture > 0.16) { return(ColorData.GRASSLAND); } else { return(ColorData.SUBTROPICAL_DESERT); } } }