public IEnumerable <Coordinate[]> GenerateRoads() { var heights = map.Polygons .Select(_ => _.DistanceToCoast.Value) .Distinct() .OrderBy(_ => _).ToArray(); double[] roadHeights = new double[] { 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 (var i in map.Polygons) { if (i.IsOcean) { queue.Enqueue(i); } } do { MapPolygon n = queue.Dequeue(); foreach (var 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 (var i in map.Polygons) { foreach (var 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 (var 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 (var 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; var 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 (var 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(); }
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(); }