string GetBiome(TerrainTile tile) { if (tile.PolygonId == -1) { return("unknown"); } MapPolygon poly = map.Polygons[tile.PolygonId]; if (beaches.Contains(poly)) { return("beach"); } else if (poly.IsWater) { if (poly.IsCoast) { return("coast"); } else if (poly.IsOcean) { return("ocean"); } else { return("water"); } } else { if (tile.Elevation >= elevationThreshold[3]) { if (tile.Moisture > moistureThreshold[4]) { return("snowy"); } else { return("mountain"); } } else if (tile.Elevation > elevationThreshold[2]) { if (tile.Moisture > moistureThreshold[4]) { return("dryland"); } else if (tile.Moisture > moistureThreshold[2]) { return("taiga"); } else { return("desert"); } } else if (tile.Elevation > elevationThreshold[1]) { if (tile.Moisture > moistureThreshold[4]) { return("forest"); } else if (tile.Moisture > moistureThreshold[2]) { return("shrub"); } else { return("desert"); } } else { if (tile.Moisture > moistureThreshold[4]) { return("rainforest"); } else if (tile.Moisture > moistureThreshold[3]) { return("forest"); } else if (tile.Moisture > moistureThreshold[2]) { return("grassland"); } else { return("desert"); } } } return("unknown"); }
public void Generate(int pointCount) { //Generate random points var hashSet = new HashSet<Coordinate>(); { var rand = new Random(seed); while (hashSet.Count < pointCount) { var x = rand.NextDouble()*2 - 1; var y = rand.NextDouble()*2 - 1; if (x < -0.99 || y < -0.99 || x > 0.99 || y > 0.99) continue; hashSet.Add(new Coordinate(x, y)); } } //Optimize points { var points = hashSet.ToArray(); for (var i = 0; i < 2; i++) { var builder = new VoronoiDiagramBuilder(); builder.SetSites(points); VoronoiDiagram = builder.GetDiagram(new GeometryFactory()); for (var j = 0; j < points.Length; j++) { var poly = VoronoiDiagram[j] as Polygon; points[j] = new Coordinate(poly.Centroid.X, poly.Centroid.Y); } } } //Build graph PlanarGraph graph; { VoronoiDiagram = ClipGeometryCollection(VoronoiDiagram, new Envelope(-1, 1, -1, 1)); graph = new PlanarGraph(new OverlayNodeFactory()); var edges = new List<Edge>(); for (var i = 0; i < VoronoiDiagram.Count; i++) { var poly = VoronoiDiagram[i] as Polygon; var coords = poly.Coordinates; for (var j = 1; j < coords.Length; j++) { edges.Add(new Edge(new[] {coords[j - 1], coords[j]}, new Label(Location.Boundary))); } } graph.AddEdges(edges); } //Convert graph Dictionary<Node, MapNode> nodeDict; { var polys = new Dictionary<MapPolygon, HashSet<MapPolygon>>(); nodeDict = new Dictionary<Node, MapNode>(); var dats = new Dictionary<MapNode, Tuple<HashSet<MapPolygon>, HashSet<MapEdge>>>(); for (var i = 0; i < VoronoiDiagram.Count; i++) { var nodes = new List<MapNode>(); var poly = new MapPolygon { CentroidX = VoronoiDiagram[i].Centroid.X, CentroidY = VoronoiDiagram[i].Centroid.Y, Polygon = VoronoiDiagram[i] as Polygon }; foreach (var j in VoronoiDiagram[i].Coordinates.Skip(1)) { var n = graph.Find(j); MapNode mapNode; if (!nodeDict.TryGetValue(n, out mapNode)) { mapNode = new MapNode {X = j.X, Y = j.Y}; dats[mapNode] = new Tuple<HashSet<MapPolygon>, HashSet<MapEdge>>(new HashSet<MapPolygon> {poly}, new HashSet<MapEdge>()); } else dats[mapNode].Item1.Add(poly); nodes.Add(nodeDict[n] = mapNode); } poly.Nodes = nodes.ToArray(); polys.Add(poly, new HashSet<MapPolygon>()); } foreach (var i in nodeDict) { foreach (var j in dats[i.Value].Item1) foreach (var k in dats[i.Value].Item1) if (j != k) { polys[j].Add(k); polys[k].Add(j); } foreach (var j in i.Key.Edges) { var from = nodeDict[graph.Find(j.Coordinate)]; var to = nodeDict[graph.Find(j.DirectedCoordinate)]; dats[from].Item2.Add(new MapEdge {From = from, To = to}); } } var ftrh = dats.Count(_ => _.Value.Item2.Count == 0); foreach (var i in dats) i.Key.Edges = i.Value.Item2.ToArray(); var x = polys.ToArray(); for (var i = 0; i < x.Length; i++) { x[i].Key.Neighbour = x[i].Value.ToArray(); x[i].Key.Id = i; } Polygons = x.Select(_ => _.Key).ToArray(); } //Generate map DetermineLandmass(); FindOceans(); ComputeDistances(); RedistributeElevation(nodeDict.Values); FindLakesAndCoasts(); }
TerrainType GetBiomeTerrain(TerrainTile tile) { if (tile.PolygonId == -1) { return(TerrainType.None); } MapPolygon poly = map.Polygons[tile.PolygonId]; if (!poly.IsWater && beaches.Contains(poly)) { return(TerrainType.ShoreSand); } else if (poly.IsWater) { return(TerrainType.None); } else { if (tile.Elevation >= elevationThreshold[3]) { return(TerrainType.Mountains); } else if (tile.Elevation > elevationThreshold[2]) { if (tile.Moisture > moistureThreshold[4]) { return(TerrainType.HighPlains); } else if (tile.Moisture > moistureThreshold[2]) { return(TerrainType.HighForest); } else { return(TerrainType.HighSand); } } else if (tile.Elevation > elevationThreshold[1]) { if (tile.Moisture > moistureThreshold[4]) { return(TerrainType.MidForest); } else if (tile.Moisture > moistureThreshold[2]) { return(TerrainType.MidPlains); } else { return(TerrainType.MidSand); } } else { if (poly.Neighbour.Any(_ => beaches.Contains(_))) { if (tile.Moisture > moistureThreshold[2]) { return(TerrainType.ShorePlains); } } if (tile.Moisture > moistureThreshold[3]) { return(TerrainType.LowForest); } else if (tile.Moisture > moistureThreshold[2]) { return(TerrainType.LowPlains); } else { return(TerrainType.LowSand); } } } return(TerrainType.None); }
public IEnumerable <Coordinate[]> GenerateRoads() { double[] heights = map.Polygons .Select(_ => _.DistanceToCoast.Value) .Distinct() .OrderBy(_ => _).ToArray(); double[] roadHeights = { heights[heights.Length * 1 / 10], heights[heights.Length * 3 / 10], heights[heights.Length * 5 / 10], 1 }; Dictionary <MapPolygon, int> centerContour = new Dictionary <MapPolygon, int>(); Queue <MapPolygon> queue = new Queue <MapPolygon>(); foreach (MapPolygon i in map.Polygons) { if (i.IsOcean) { queue.Enqueue(i); } } do { MapPolygon n = queue.Dequeue(); foreach (MapPolygon i in n.Neighbour) { int newLevel; if (!centerContour.TryGetValue(n, out newLevel)) { newLevel = 0; } while (i.DistanceToCoast > roadHeights[newLevel]) { newLevel++; } int iLevel; if (!centerContour.TryGetValue(i, out iLevel)) { iLevel = int.MaxValue; } if (newLevel < iLevel) { centerContour[i] = newLevel; queue.Enqueue(i); } } } while (queue.Count > 0); Dictionary <MapNode, int> cornerContour = new Dictionary <MapNode, int>(); foreach (MapPolygon i in map.Polygons) { foreach (MapNode j in i.Nodes) { int curr; if (!cornerContour.TryGetValue(j, out curr)) { curr = int.MaxValue; } int poly; if (!centerContour.TryGetValue(i, out poly)) { poly = int.MaxValue; } cornerContour[j] = Math.Min(curr, poly); } } List <Coordinate>[] points = new List <Coordinate> [roadHeights.Length - 1]; for (int i = 0; i < points.Length; i++) { points[i] = new List <Coordinate>(); } foreach (MapEdge i in map.Polygons.SelectMany(_ => _.Nodes).SelectMany(_ => _.Edges).Distinct()) { if (cornerContour[i.From] < cornerContour[i.To]) { points[cornerContour[i.From]].Add(new Coordinate( (i.From.X + i.To.X) / 2, (i.From.Y + i.To.Y) / 2)); } } foreach (List <Coordinate> i in points) { List <Coordinate> pts = new List <Coordinate>(); List <Coordinate[]> paths = new List <Coordinate[]>(); for (int j = 0; j < i.Count; j++) { double minDist = double.MaxValue; for (int k = j + 1; k < i.Count; k++) { double dx = i[j].X - i[k].X; double dy = i[j].Y - i[k].Y; double d = dx * dx + dy * dy; if (d < minDist) { minDist = d; Coordinate tmp = i[j + 1]; i[j + 1] = i[k]; i[k] = tmp; } } if (minDist > 0.1 && minDist != double.MaxValue) { if (pts.Count > 0) { pts.Add(pts[0]); } paths.Add(pts.ToArray()); pts.Clear(); } else { pts.Add(i[j]); } } if (pts.Count > 0) { pts.Add(pts[0]); } paths.Add(pts.ToArray()); pts.Clear(); foreach (Coordinate[] j in paths) { if (j.Length < 4) { continue; } yield return(j); } } }
public void Generate(int pointCount) { //Generate random points HashSet <Coordinate> hashSet = new HashSet <Coordinate>(); { Random rand = new Random(seed); while (hashSet.Count < pointCount) { var x = rand.NextDouble() * 2 - 1; var y = rand.NextDouble() * 2 - 1; if (x < -0.99 || y < -0.99 || x > 0.99 || y > 0.99) { continue; } hashSet.Add(new Coordinate(x, y)); } } //Optimize points { Coordinate[] points = hashSet.ToArray(); for (int i = 0; i < 2; i++) { var builder = new VoronoiDiagramBuilder(); builder.SetSites(points); VoronoiDiagram = builder.GetDiagram(new GeometryFactory()); for (int j = 0; j < points.Length; j++) { Polygon poly = VoronoiDiagram[j] as Polygon; points[j] = new Coordinate(poly.Centroid.X, poly.Centroid.Y); } } } //Build graph PlanarGraph graph; { VoronoiDiagram = ClipGeometryCollection(VoronoiDiagram, new Envelope(-1, 1, -1, 1)); graph = new PlanarGraph(new OverlayNodeFactory()); var edges = new List <Edge>(); for (int i = 0; i < VoronoiDiagram.Count; i++) { Polygon poly = VoronoiDiagram[i] as Polygon; var coords = poly.Coordinates; for (int j = 1; j < coords.Length; j++) { edges.Add(new Edge(new Coordinate[] { coords[j - 1], coords[j] }, new Label(Location.Boundary))); } } graph.AddEdges(edges); } //Convert graph Dictionary <Node, MapNode> nodeDict; { Dictionary <MapPolygon, HashSet <MapPolygon> > polys = new Dictionary <MapPolygon, HashSet <MapPolygon> >(); nodeDict = new Dictionary <Node, MapNode>(); Dictionary <MapNode, Tuple <HashSet <MapPolygon>, HashSet <MapEdge> > > dats = new Dictionary <MapNode, Tuple <HashSet <MapPolygon>, HashSet <MapEdge> > >(); for (int i = 0; i < VoronoiDiagram.Count; i++) { List <MapNode> nodes = new List <MapNode>(); var poly = new MapPolygon() { CentroidX = VoronoiDiagram[i].Centroid.X, CentroidY = VoronoiDiagram[i].Centroid.Y, Polygon = VoronoiDiagram[i] as Polygon }; foreach (var j in VoronoiDiagram[i].Coordinates.Skip(1)) { Node n = graph.Find(j); MapNode mapNode; if (!nodeDict.TryGetValue(n, out mapNode)) { mapNode = new MapNode() { X = j.X, Y = j.Y }; dats[mapNode] = new Tuple <HashSet <MapPolygon>, HashSet <MapEdge> >(new HashSet <MapPolygon>() { poly }, new HashSet <MapEdge>()); } else { dats[mapNode].Item1.Add(poly); } nodes.Add(nodeDict[n] = mapNode); } poly.Nodes = nodes.ToArray(); polys.Add(poly, new HashSet <MapPolygon>()); } foreach (var i in nodeDict) { foreach (var j in dats[i.Value].Item1) { foreach (var k in dats[i.Value].Item1) { if (j != k) { polys[j].Add(k); polys[k].Add(j); } } } foreach (var j in i.Key.Edges) { var from = nodeDict[graph.Find(j.Coordinate)]; var to = nodeDict[graph.Find(j.DirectedCoordinate)]; dats[from].Item2.Add(new MapEdge() { From = from, To = to }); } } int ftrh = dats.Count(_ => _.Value.Item2.Count == 0); foreach (var i in dats) { i.Key.Edges = i.Value.Item2.ToArray(); } var x = polys.ToArray(); for (int i = 0; i < x.Length; i++) { x[i].Key.Neighbour = x[i].Value.ToArray(); x[i].Key.Id = i; } Polygons = x.Select(_ => _.Key).ToArray(); } //Generate map DetermineLandmass(); FindOceans(); ComputeDistances(); RedistributeElevation(nodeDict.Values); FindLakesAndCoasts(); }
private string GetBiome(TerrainTile tile) { if (tile.PolygonId == -1) { return("unknown"); } if (tile.TileId == TileTypes.Road) { return("road"); } if (tile.TileId == TileTypes.Water) { return("river"); } MapPolygon poly = _map.Polygons[tile.PolygonId]; if (tile.TileId == 0xb4) { return("towel"); } if (_beaches.Contains(poly)) { return("beach"); } if (poly.IsWater) { if (poly.IsCoast) { return("coast"); } if (poly.IsOcean) { return("ocean"); } return("water"); } if (tile.Elevation >= _elevationThreshold[3]) { if (tile.Moisture > _moistureThreshold[4]) { return("snowy"); } return("mountain"); } if (tile.Elevation > _elevationThreshold[2]) { if (tile.Moisture > _moistureThreshold[4]) { return("dryland"); } if (tile.Moisture > _moistureThreshold[2]) { return("taiga"); } return("desert"); } if (tile.Elevation > _elevationThreshold[1]) { if (tile.Moisture > _moistureThreshold[4]) { return("forest"); } if (tile.Moisture > _moistureThreshold[2]) { return("shrub"); } return("desert"); } if (tile.Moisture > _moistureThreshold[4]) { return("rainforest"); } if (tile.Moisture > _moistureThreshold[3]) { return("forest"); } if (tile.Moisture > _moistureThreshold[2]) { return("grassland"); } return("desert"); //return "unknown"; }
private TerrainType GetBiomeTerrain(TerrainTile tile) { if (tile.PolygonId == -1 || tile.TileId == TileTypes.Road || tile.TileId == TileTypes.Water) { return(TerrainType.None); } MapPolygon poly = _map.Polygons[tile.PolygonId]; if (!poly.IsWater && _beaches.Contains(poly)) { return(TerrainType.ShoreSand); } if (poly.IsWater) { return(TerrainType.None); } if (tile.Elevation >= _elevationThreshold[3]) { return(TerrainType.Mountains); } if (tile.Elevation > _elevationThreshold[2]) { if (tile.Moisture > _moistureThreshold[4]) { return(TerrainType.HighPlains); } if (tile.Moisture > _moistureThreshold[2]) { return(TerrainType.HighForest); } return(TerrainType.HighSand); } if (tile.Elevation > _elevationThreshold[1]) { if (tile.Moisture > _moistureThreshold[4]) { return(TerrainType.MidForest); } if (tile.Moisture > _moistureThreshold[2]) { return(TerrainType.MidPlains); } return(TerrainType.MidSand); } if (poly.Neighbour.Any(_ => _beaches.Contains(_))) { if (tile.Moisture > _moistureThreshold[2]) { return(TerrainType.ShorePlains); } } if (tile.Moisture > _moistureThreshold[3]) { return(TerrainType.LowForest); } if (tile.Moisture > _moistureThreshold[2]) { return(TerrainType.LowPlains); } return(TerrainType.LowSand); //return TerrainType.None; }