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(); }
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(); }
static MapEdge SelectDownhill(MapNode node) { var dist = node.DistanceToCoast; MapEdge ret = node.Edges.First(); foreach (var e in node.Edges) if (e.To.DistanceToCoast < dist) ret = e; return ret; }
//void DetermineLandmass() // Sine //{ // var rand = new Random(seed); // int bumps = rand.Next(1, 7); // double startAngle = rand.NextDouble() * 2 * Math.PI; // double dipAngle = rand.NextDouble() * 2 * Math.PI; // double dipWidth = rand.NextDouble() / 2 + 0.2; // waters.Clear(); // foreach (var i in Polygons) // { // int total = 0; // int water = 0; // foreach (var j in i.Nodes) // { // var x = j.X; // var y = j.Y; // var angle = Math.Atan2(y, x); // var length = 0.5 * (Math.Max(Math.Abs(x), Math.Abs(y)) + Math.Sqrt(x * x + y * y)); // var r1 = 0.5 + 0.40 * Math.Sin(startAngle + bumps * angle + Math.Cos((bumps + 3) * angle)); // var r2 = 0.7 - 0.20 * Math.Sin(startAngle + bumps * angle - Math.Sin((bumps + 2) * angle)); // if (Math.Abs(angle - dipAngle) < dipWidth || // Math.Abs(angle - dipAngle + 2 * Math.PI) < dipWidth || // Math.Abs(angle - dipAngle - 2 * Math.PI) < dipWidth) // r1 = r2 = 0.2; // if (!(length < r1 || (length > r1 * 0.5 && length < r2))) // { // j.IsWater = true; // waters.Add(j); // water++; // } // total++; // } // } //} void FindOceans() { oceans.Clear(); foreach (var i in waters) { if (i.X == -1 || i.X == 1 || i.Y == -1 || i.Y == 1 || i.IsOcean || i.Edges.Select(_ => _.To).All(_ => _.IsWater)) { i.IsOcean = true; continue; } bool isOcean = false; Queue <MapNode> q = new Queue <MapNode>(); q.Enqueue(i); HashSet <MapNode> v = new HashSet <MapNode>(); do { MapNode current = q.Dequeue(); foreach (var j in current.Edges) { if (v.Contains(j.To) || !j.To.IsWater) { continue; } if (j.To.X == -1 || j.To.X == 1 || j.To.Y == -1 || j.To.Y == 1) { isOcean = true; q.Clear(); break; } q.Enqueue(j.To); v.Add(j.To); } } while (q.Count > 0); if (isOcean) { q.Clear(); v.Clear(); q.Enqueue(i); do { MapNode current = q.Dequeue(); oceans.Add(current); current.IsOcean = true; foreach (var j in current.Edges) { if (v.Contains(j.To) || !j.To.IsWater) { continue; } q.Enqueue(j.To); v.Add(j.To); } } while (q.Count > 0); } } }