refaktoryzacja rozmieszczenia miast

This commit is contained in:
Kacper Donat 2019-11-10 23:20:24 +01:00
parent e7f759acc5
commit 9b606119c4
22 changed files with 449 additions and 523 deletions

View File

@ -1,36 +0,0 @@
using System;
using Assets;
using UnityEditor;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Assets.Editor
{
[CustomEditor(typeof(CityGenerator))]
public class CityGeneratorUI : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
CityGenerator generator = (CityGenerator)target;
DrawDefaultInspector();
// if (GUILayout.Button("Reset"))
// {
// generator.Reset();
// }
//
// if (GUILayout.Button("Generate"))
// {
// generator.Reset();
// generator.Generate();
// }
//
// if (GUILayout.Button("New City"))
// {
// generator.NewCity();
// }
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 86bc882017a8bcb459fc88d1ef89f4b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,208 @@
using System.Collections.Generic;
using System.Linq;
using Assets.Cities;
using Assets.Common;
using Assets.Voronoi;
namespace Assets.AnnotationPass
{
public class CityFieldsPass : IAnnotationPass
{
private System.Random _random;
private Graph<Point> _voronoiGraph;
private Graph<Location> _locationGraph;
private Graph<MapSite> _basicGraph;
private List<int> verticesForRoads;
private List<int> verticesForCitites;
List<City> cities = new List<City>();
Graph<MapSite> roads = new Graph<MapSite>();
Graph<Point> mainRoads = new Graph<Point>();
double minimumAngle;
List<int> CountProbablitityOfCity(List<int> vertices)
{
List<int> probabilities = new List<int>();
vertices.ForEach(v => probabilities.Add((v % 2 == 0 ? _random.Next(0, 50) : _random.Next(50, 100))));
return probabilities;
}
List<int> LocateCities()
{
// var verticesForCitites = CountProbablitityOfCity(ChoosePoints(20));
// verticesForCitites.Sort();
// return verticesForCitites.GetRange(0, 10);
return ChoosePoints(20);
}
public bool IsPointInsideCity(City city, Point point)
{
return city.sites.Any(s => PointUtils.IsPointInside(point, s.Boundary.Select(i => _voronoiGraph[i]).ToArray()));
}
City CreateCity(int vertex, int size)
{
City newCity = new City(_basicGraph);
var site = _basicGraph.Vertices[vertex];
var sites = new List<MapSite> { site };
var location = site.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty);
for (int i = 0; i < size - 1; i++)
{
var neighbours = _basicGraph.Neighbours(site.Index).Select(j => _basicGraph.Vertices[j]).Where(s => s.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty) == location).ToList();
site = neighbours[_random.Next(neighbours.Count)];
sites.Add(site);
}
foreach (var s in sites.Distinct())
{
newCity.AddSite(s);
}
newCity.CreateRoadGraph(_voronoiGraph.Vertices);
var edges = newCity.roads.Edges.ToList();
foreach (var (a, b) in edges)
{
var (va, vb) = (newCity.roads[a], newCity.roads[b]);
var center = (va + vb) / 2;
if (!IsPointInsideCity(newCity, center))
newCity.roads.DeleteEdge(a, b);
}
ConnectPointsIntoRoads(newCity);
FixRoadsDensity(newCity, minimumAngle);
CreateFieldBoundaries(newCity);
return newCity;
}
List<int> ChoosePoints(int number)
{
var vertices = new List<int>();
for (int i = 0; i < number; i++)
{
var randomLocation = _locationGraph.Vertices[_random.Next(1, _locationGraph.Vertices.Count())];
var count = randomLocation.Sites.Count();
var randomPoint = randomLocation.Sites[_random.Next(0, count)];
vertices.Add(randomPoint.Index);
}
return vertices;
}
void ConnectPointsIntoRoads(City city)
{
var original = city.roads.Morph(s => s, e => Point.Dist(city.roads[e.Item1], city.roads[e.Item2]));
//1.Sort all the edges in non - decreasing order of their weight.
//2.Pick the smallest edge.Check if it forms a cycle with the spanning tree formed so far. If cycle is not formed, include this edge.Else, discard it.
//3.Repeat step#2 until there are (V-1) edges in the spanning tree.
var edges = original.Edges.OrderByDescending(e => original.GetEdgeData(e));
Graph<Point> roads = new Graph<Point>() { Vertices = city.roads.Vertices };
foreach (var edge in original.Edges)
{
roads.AddEdge(edge.Item1, edge.Item2);
if (Graph<Point>.HasCycle(roads))
roads.DeleteEdge(edge.Item1, edge.Item2);
if (roads.Edges.Count() == roads.Vertices.Count() - 1)
break;
}
city.roads = roads;
}
private void CreateFieldBoundaries(City city)
{
foreach (var (a, b) in city.roads.Edges)
city.fieldBoundaries.AddEdge(a, b);
var deadEnds = city.fieldBoundaries.Vertices.Select((_, i) => i).Where(i => city.fieldBoundaries.Neighbours(i).Count() == 1);
foreach (var deadEnd in deadEnds)
{
var neighbour = city.fieldBoundaries.Neighbours(deadEnd).First();
var closest = city.fieldBoundaries.Vertices
.Select((_, i) => i)
.OrderBy(i => Point.Dist(city.fieldBoundaries[i], city.fieldBoundaries[deadEnd]))
.Skip(1)
.First(c => c != neighbour);
city.fieldBoundaries.AddEdge(deadEnd, closest);
city.roads.AddEdge(deadEnd, closest);
}
}
private void FixRoadsDensity(City city, double angle = 0.25f)
{
// dla każdego punktu w grafie dróg
// chyba że ma 2 to pomiń?
// wyznacz punkt 0
// oblicz odległości kątowe do wszystkich punktów
// posortuj je
// między wszystkimiu parami oblicz kąt
// potem według jakiegoś parametru usuń te, które są za bliskie
for (int i = 0; i < city.roads.Vertices.Count(); i++)
{
var p = city.roads[i];
if (city.roads.Neighbours(i).Count() <= 2)
continue;
var reference = new Point(p.x, p.y + 30);
var orderedNeighours = city.roads.Neighbours(i)
.Select(n => (Vertex: n, Point: city.roads[n]))
.Select(x => (Vertex: x.Vertex, Angle: PointUtils.AngleBetween(p, reference, x.Point)))
.OrderBy(x => x.Angle)
.Select(x => x.Vertex);
foreach (var (a, b) in orderedNeighours.RotateRight(1).Zip(orderedNeighours, (a, b) => (a, b)))
{
if( PointUtils.AngleBetween(p, city.roads[a], city.roads[b]) < angle)
{
city.roads.DeleteEdge(i, a);
}
}
}
}
void CreateWorldRoadGraph()
{
roads.Vertices = verticesForCitites.Select(i => _basicGraph.Vertices[i]).ToList();
VoronoiGenerator generator = new VoronoiGenerator(roads.Vertices.Select(s => s.Center).ToList());
generator.Generate();
roads.Edges = generator.Delaunay.Edges;
}
void AddLanesToRoads()
{
// ergo dodaj randomowe połączenia xd
}
public void Annotate(Map map)
{
_basicGraph = map.Sites.Clone() as Graph<MapSite>;
_voronoiGraph = map.Boundaries;
_locationGraph = map.Metadata.GetProperty<Graph<Location>>(LandmassPass.MapLocationsProperty);
verticesForCitites = LocateCities();
foreach (var index in verticesForCitites)
{
cities.Add(CreateCity(index, _random.Next(0, 10)));
}
CreateWorldRoadGraph();
mainRoads = roads.Morph(s => s.Center);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d612532edd124c75a746b1d74faa42f8
timeCreated: 1573422504

View File

@ -5,7 +5,7 @@ using Assets.Common;
namespace Assets.AnnotationPass
{
public class LocationPass : IAnnotationPass
public class LandmassPass : IAnnotationPass
{
public const string MapLocationsProperty = "Locations";
public const string SiteLocationProperty = "Location";
@ -19,7 +19,7 @@ namespace Assets.AnnotationPass
private Random _random;
public LocationPass(IEnumerable<Location> locations, Random random = null)
public LandmassPass(IEnumerable<Location> locations, Random random = null)
{
_locations = new Graph<Location> { Vertices = new List<Location>(locations) };
_random = random ?? new Random();

View File

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Assets.Cities;
using Assets.Common;
namespace Assets.AnnotationPass
{
public class LocateCitiesPass : IAnnotationPass
{
public const string CitiesProperty = "Cities";
public const string CityProperty = "City";
private Graph<Location> _locationGraph;
private Graph<MapSite> _basicGraph;
private Random _random;
public LocateCitiesPass(Random random = null)
{
_random = random ?? new Random();
}
IEnumerable<int> LocateCities()
{
// var verticesForCitites = CountProbablitityOfCity(ChoosePoints(20));
// verticesForCitites.Sort();
// return verticesForCitites.GetRange(0, 10);
return ChoosePoints(20);
}
City CreateCity(int vertex, int size)
{
City newCity = new City(_basicGraph);
var site = _basicGraph.Vertices[vertex];
var sites = new List<MapSite> { site };
var location = site.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty);
for (int i = 0; i < size - 1; i++)
{
var neighbours = _basicGraph.Neighbours(site.Index).Select(j => _basicGraph.Vertices[j]).Where(s => s.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty) == location).ToList();
site = neighbours[_random.Next(neighbours.Count)];
sites.Add(site);
}
foreach (var s in sites.Distinct())
{
newCity.AddSite(s);
s.Metadata.SetProperty(CityProperty, newCity);
}
return newCity;
}
List<int> ChoosePoints(int number)
{
var vertices = new List<int>();
for (int i = 0; i < number; i++)
{
var randomLocation = _locationGraph.Vertices[_random.Next(1, _locationGraph.Vertices.Count())];
var count = randomLocation.Sites.Count();
var randomPoint = randomLocation.Sites[_random.Next(0, count)];
vertices.Add(randomPoint.Index);
}
return vertices;
}
public void Annotate(Map map)
{
_basicGraph = map.Sites.Clone() as Graph<MapSite>;
_locationGraph = map.Metadata.GetProperty<Graph<Location>>(LandmassPass.MapLocationsProperty);
var cities = new List<City>();
var locations = LocateCities();
foreach (var index in locations)
cities.Add(CreateCity(index, _random.Next(0, 10)));
map.Metadata.SetProperty(CitiesProperty, cities);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a5fc9d4f539a45d9af0661c60fbc1bb8
timeCreated: 1573418593

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3890d890d2b20cd08920cac7a9706272
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,60 @@
using System.Collections.Generic;
using System.Linq;
using Assets.Common;
using Assets.Voronoi;
namespace Assets.Cities
{
public class City
{
public Graph<MapSite> startGraph;
public List<MapSite> sites;
public Graph<Point> roads = new Graph<Point>();
public Graph<Point> fieldBoundaries = new Graph<Point>();
public List<CityField> fields = new List<CityField>();
public List<(int, int)> edges;
public City(Graph<MapSite> startGraph)
{
this.startGraph = startGraph;
this.sites = new List<MapSite>();
this.edges = new List<(int, int)>();
}
public City(Graph<MapSite> startGraph, List<MapSite> sitesList) : this(startGraph)
{
this.sites = sitesList;
}
public void AddSite(MapSite site)
{
sites.Add(site);
FixBoundaryEdges(site);
}
private void FixBoundaryEdges(MapSite site)
{
var a = edges;
var b = site.Edges.Select(x => x.Item1 < x.Item2 ? x : (x.Item2, x.Item1));
edges = a.Union(b).Except(a.Intersect(b)).ToList();
}
public void CreateRoadGraph(IList<Point> points)
{
var pointsForRoads = sites.SelectMany(site => site.Boundary.Select(i => (i, points[i])).Append((-1, site.Center))).Distinct().ToList();
var mapping = pointsForRoads.Select((x, i) => x.Item1 == -1 ? (-1, -1) : (i, x.Item1)).Where(x => x.Item1 != -1).ToDictionary(x => x.Item2, x => x.Item1);
VoronoiGenerator generator = new VoronoiGenerator(pointsForRoads.Select(x => x.Item2));
generator.Generate();
roads = generator.Delaunay.Morph(s => s.Point);
fieldBoundaries = new Graph<Point> { Vertices = roads.Vertices, Edges = edges.Select(e => (mapping[e.Item1], mapping[e.Item2])) };
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ea278043ef9644c6992b3269f26b1f61
timeCreated: 1573418494

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
using Assets.Common;
namespace Assets.Cities
{
public class CityField
{
public List<Point> boundary;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d5245590d0aa431a880e2b98e127d5f0
timeCreated: 1573418463

View File

@ -1,437 +0,0 @@
using Assets.Common;
using Assets.Voronoi;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
//namespace Assets.Scripts
//{
// public class PointProximityComparer : IEqualityComparer<Point>
// {
// double _threshold;
//
// public PointProximityComparer(double threshold = 0.2)
// {
// _threshold = threshold;
// }
//
// public bool Equals(Point x, Point y)
// {
// return Point.Dist(x, y) < _threshold;
// }
//
// public int GetHashCode(Point obj)
// {
// return obj.GetHashCode();
// }
// }
//
// public class CityField
// {
// public List<Point> boundary;
// }
//
// public class City
// {
// public Graph<Voronoi.Site> startGraph;
// public List<Voronoi.Site> sites;
//
// public Graph<Point> roads = new Graph<Point>();
// public Graph<Point> fieldBoundaries = new Graph<Point>();
//
// public List<CityField> fields = new List<CityField>();
//
// public List<(int, int)> edges;
//
// public City(Graph<Site> startGraph)
// {
// this.startGraph = startGraph;
//
// this.sites = new List<Voronoi.Site>();
// this.edges = new List<(int, int)>();
// }
//
// public City(Graph<Site> startGraph, List<Site> sitesList) : this(startGraph)
// {
// this.sites = sitesList;
// }
//
// public void AddSite(Site site)
// {
// sites.Add(site);
// FixBoundaryEdges(site);
// }
//
// private void FixBoundaryEdges(Site site)
// {
// var a = edges;
// var b = site.Edges.Select(x => x.Item1 < x.Item2 ? x : (x.Item2, x.Item1));
//
// edges = a.Union(b).Except(a.Intersect(b)).ToList();
// }
//
// public void CreateRoadGraph(IList<Point> points)
// {
// var pointsForRoads = sites.SelectMany(site => site.Vertices.Select(i => (i, points[i])).Append((-1, site.Point))).Distinct().ToList();
// var mapping = pointsForRoads.Select((x, i) => x.Item1 == -1 ? (-1, -1) : (i, x.Item1)).Where(x => x.Item1 != -1).ToDictionary(x => x.Item2, x => x.Item1);
//
// VoronoiGenerator generator = new VoronoiGenerator(pointsForRoads.Select(x => x.Item2));
// generator.Generate();
//
// roads = generator.Delaunay.Morph(s => s.Point);
//
// fieldBoundaries = new Graph<Point> { Vertices = roads.Vertices, Edges = edges.Select(e => (mapping[e.Item1], mapping[e.Item2])) };
// }
// }
//
// [Serializable]
// public class GraphGeneratorDebug
// {
// public bool displayVertices = false;
// public bool displayCrossroads = true;
// public bool displayEdges = false;
// public bool displayCities = true;
// public bool displayCityRoads = true;
// public bool displayFieldBoundaries = true;
// public bool displayWorldRoads = false;
// }
//
// [RequireComponent(typeof(LandmassGenerator))]
public class CityGenerator : MonoBehaviour
{
// private System.Random _random;
// private Graph<Point> _voronoiGraph;
// private Graph<Location> _locationGraph;
// private Graph<Site> _basicGraph;
// private List<int> verticesForRoads;
// private List<int> verticesForCitites;
//
// public GraphGeneratorDebug debug;
// public double minimumAngle = 0.25;
//
// public List<City> cities = new List<City>();
//
// Graph<Site> roads = new Graph<Site>();
//
// Graph<Point> mainRoads = new Graph<Point>();
//
// List<int> CountProbablitityOfCity(List<int> vertices)
// {
// List<int> probabilities = new List<int>();
// vertices.ForEach(v => probabilities.Add((v % 2 == 0 ? _random.Next(0, 50) : _random.Next(50, 100))));
// return probabilities;
// }
//
// List<int> LocateCities()
// {
// // var verticesForCitites = CountProbablitityOfCity(ChoosePoints(20));
// // verticesForCitites.Sort();
// // return verticesForCitites.GetRange(0, 10);
// return ChoosePoints(20);
// }
//
// public bool IsPointInsideCity(City city, Point point)
// {
// return city.sites.Any(s => PointUtils.IsPointInside(point, s.Vertices.Select(i => _voronoiGraph[i]).ToArray()));
// }
//
// City CreateCity(int vertex, int size)
// {
// City newCity = new City(_basicGraph);
// var site = _basicGraph.Vertices[vertex];
// var sites = new List<Site>() { site };
// var location = site.Location;
//
// for (int i = 0; i < size - 1; i++)
// {
// location = site.Location;
// var neighbours = _basicGraph.Neighbours(site.Index).Select(j => _basicGraph.Vertices[j]).Where(s => s.Location == location).ToList();
// site = neighbours[_random.Next(neighbours.Count)];
// sites.Add(site);
// }
//
// foreach (var s in sites.Distinct())
// {
// newCity.AddSite(s);
// }
//
// newCity.CreateRoadGraph(_voronoiGraph.Vertices);
//
// var edges = newCity.roads.Edges.ToList();
// foreach (var (a, b) in edges)
// {
// var (va, vb) = (newCity.roads[a], newCity.roads[b]);
// var center = (va + vb) / 2;
//
// if (!IsPointInsideCity(newCity, center))
// newCity.roads.DeleteEdge(a, b);
// }
//
// ConnectPointsIntoRoads(newCity);
// FixRoadsDensity(newCity, minimumAngle);
// CreateFieldBoundaries(newCity);
//
// return newCity;
// }
//
// List<int> ChoosePoints(int number)
// {
// var vertices = new List<int>();
// for (int i = 0; i < number; i++)
// {
// var randomLocation = _locationGraph.Vertices[_random.Next(1, _locationGraph.Vertices.Count())];
// var count = randomLocation.Sites.Count();
// var randomPoint = randomLocation.Sites[_random.Next(0, count)];
// vertices.Add(randomPoint.Index);
// }
// return vertices;
// }
//
// void ConnectPointsIntoRoads(City city)
// {
// var original = city.roads.Morph(s => s, e => Point.Dist(city.roads[e.Item1], city.roads[e.Item2]));
//
// //1.Sort all the edges in non - decreasing order of their weight.
// //2.Pick the smallest edge.Check if it forms a cycle with the spanning tree formed so far. If cycle is not formed, include this edge.Else, discard it.
// //3.Repeat step#2 until there are (V-1) edges in the spanning tree.
//
// var edges = original.Edges.OrderByDescending(e => original.GetEdgeData(e));
//
// Graph<Point> roads = new Graph<Point>() { Vertices = city.roads.Vertices };
//
// foreach (var edge in original.Edges)
// {
// roads.AddEdge(edge.Item1, edge.Item2);
//
// if (Graph<Point>.HasCycle(roads))
// roads.DeleteEdge(edge.Item1, edge.Item2);
// if (roads.Edges.Count() == roads.Vertices.Count() - 1)
// break;
// }
//
// city.roads = roads;
// }
//
// private void CreateFieldBoundaries(City city)
// {
// foreach (var (a, b) in city.roads.Edges)
// city.fieldBoundaries.AddEdge(a, b);
//
// var deadEnds = city.fieldBoundaries.Vertices.Select((_, i) => i).Where(i => city.fieldBoundaries.Neighbours(i).Count() == 1);
//
// foreach (var deadEnd in deadEnds)
// {
// var neighbour = city.fieldBoundaries.Neighbours(deadEnd).First();
// var closest = city.fieldBoundaries.Vertices
// .Select((_, i) => i)
// .OrderBy(i => Point.Dist(city.fieldBoundaries[i], city.fieldBoundaries[deadEnd]))
// .Skip(1)
// .First(c => c != neighbour);
//
// city.fieldBoundaries.AddEdge(deadEnd, closest);
// city.roads.AddEdge(deadEnd, closest);
// }
// }
//
//
// private void FixRoadsDensity(City city, double angle = 0.25f)
// {
// // dla każdego punktu w grafie dróg
// // chyba że ma 2 to pomiń?
// // wyznacz punkt 0
// // oblicz odległości kątowe do wszystkich punktów
// // posortuj je
// // między wszystkimiu parami oblicz kąt
// // potem według jakiegoś parametru usuń te, które są za bliskie
//
//
// for (int i = 0; i < city.roads.Vertices.Count(); i++)
// {
// var p = city.roads[i];
// if (city.roads.Neighbours(i).Count() <= 2)
// continue;
//
// var reference = new Point(p.x, p.y + 30);
//
// var orderedNeighours = city.roads.Neighbours(i)
// .Select(n => (Vertex: n, Point: city.roads[n]))
// .Select(x => (Vertex: x.Vertex, Angle: PointUtils.AngleBetween(p, reference, x.Point)))
// .OrderBy(x => x.Angle)
// .Select(x => x.Vertex);
//
// foreach (var (a, b) in orderedNeighours.RotateRight(1).Zip(orderedNeighours, (a, b) => (a, b)))
// {
// if( PointUtils.AngleBetween(p, city.roads[a], city.roads[b]) < angle)
// {
// city.roads.DeleteEdge(i, a);
// }
// }
// }
// }
//
//
//
//
//
//
// void CreateWorldRoadGraph()
// {
// roads.Vertices = verticesForCitites.Select(i => _basicGraph.Vertices[i]).ToList();
//
// VoronoiGenerator generator = new VoronoiGenerator(roads.Vertices.Select(s => s.Point).ToList());
// generator.Generate();
//
// roads.Edges = generator.Delaunay.Edges;
// }
//
//
// void AddLanesToRoads()
// {
// // ergo dodaj randomowe połączenia xd
// }
//
//
//
//
// // UI Methods
//
//
// public void Start()
// {
// Reset();
// }
//
// public void Reset()
// {
//
// var graphGenerator = GetComponent<LandmassGenerator>();
// _random = new System.Random(graphGenerator.seed);
// cities = new List<City>();
// }
//
// public void NewCity()
// {
// cities.Add(CreateCity(LocateCities()[_random.Next(0, 10)], _random.Next(0, 10)));
// }
//
// public void Generate()
// {
// var graphGenerator = GetComponent<LandmassGenerator>();
// graphGenerator.Generate();
// _basicGraph = graphGenerator.VoronoiGenerator.Delaunay.Morph(l => l);
// _voronoiGraph = graphGenerator.VoronoiGenerator.Voronoi;
// _locationGraph = graphGenerator.LocationGenerator.Result;
//
// verticesForCitites = LocateCities();
// foreach (var index in verticesForCitites)
// {
// cities.Add(CreateCity(index, _random.Next(0, 10)));
// }
//
// CreateWorldRoadGraph();
// mainRoads = roads.Morph(s => s.Point);
//
// }
//
// private void DisplayGraphVertices(Graph<Point> graph)
// {
// var vertices = graph.Vertices.Select(p => p.ToVector3());
// var offset = Vector3.right;
//
// foreach (var (v, i) in vertices.Select((x, i) => (x, i)))
// {
// Gizmos.DrawSphere(v, 1);
// }
// }
//
// private void DisplayGraphCrossroads(Graph<Point> graph, List<int> vertices)
// {
// //foreach (var v in vertices.Select(i => graph.Vertices[i].ToVector3()))
// //{
// // Gizmos.DrawSphere(v, 1);
// //}
// }
//
//
// private void DisplayGraphCities(List<City> cities)
// {
// foreach (City city in cities)
// {
// Gizmos.color = Color.magenta;
// foreach (var (a, b) in city.edges)
// {
// Gizmos.DrawLine(_voronoiGraph.Vertices[a].ToVector3(), _voronoiGraph.Vertices[b].ToVector3());
// }
//
// foreach (var a in city.sites)
// Gizmos.DrawSphere(a.Point.ToVector3(), 1);
// }
// }
//
//
// private void DisplayGraphEdges(Graph<Point> graph)
// {
// var edges = graph.Edges
// .Select(edge => (graph.Vertices[edge.Item1], graph.Vertices[edge.Item2]))
// .Select(edge => (edge.Item1.ToVector3(), edge.Item2.ToVector3()));
//
// foreach (var (s, e) in edges) Gizmos.DrawLine(s, e);
// }
//
// private void OnDrawGizmos()
// {
//
// if (debug.displayVertices)
// {
// Gizmos.color = Color.white;
// DisplayGraphVertices(_basicGraph.Morph(l => l.Point));
// }
//
// if (debug.displayEdges)
// {
// Gizmos.color = Color.white;
// DisplayGraphEdges(_basicGraph.Morph(l => l.Point));
// }
//
// if (debug.displayCrossroads)
// {
// Gizmos.color = Color.magenta;
// DisplayGraphCrossroads(_basicGraph.Morph(l => l.Point), verticesForRoads);
// }
//
// if (debug.displayCities)
// {
// Gizmos.color = Color.magenta;
// DisplayGraphCities(cities);
// }
//
// if (debug.displayFieldBoundaries)
// {
// Gizmos.color = Color.white;
//
// foreach (var city in cities)
// DisplayGraphEdges(city.fieldBoundaries);
// }
//
// if (debug.displayCityRoads)
// {
// Gizmos.color = Color.green;
//
// foreach (var city in cities)
// {
// DisplayGraphEdges(city.roads);
// DisplayGraphVertices(city.roads);
// }
// }
//
//
// if (debug.displayWorldRoads)
// {
// // Gizmos.color = new Color(0.254f, 0.127f, 0.156f);
// Gizmos.color = Color.blue;
// DisplayGraphEdges(mainRoads);
// }
// }
}
//}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: ec8bb5e8662a03f4bb9224a34ef8db2b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,15 +0,0 @@
using Assets.Voronoi;
namespace Assets.Common
{
public class LocationSite
{
public readonly Site Site;
public Location Location;
public LocationSite(Site site)
{
Site = site;
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: ae1606ff46e64c2a9dc080c61bbd74b8
timeCreated: 1573304795

View File

@ -17,8 +17,12 @@ namespace Assets.Common
set
{
_sites = value;
int i = 0;
foreach (var site in _sites.Vertices)
{
site.Map = this;
site.Index = i++;
}
}
}

View File

@ -16,6 +16,7 @@ namespace Assets.Common
Boundary = boundary;
}
public int Index { get; internal set; }
public Point Center { get; set; }
public bool IsOuter { get; set; } = false;
public IEnumerable<int> Boundary { get; set; }

View File

@ -1,9 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Assets.AnnotationPass;
using Assets.Cities;
using Assets.Common;
using Assets.GridGenerator;
using Assets.PointDistribution;
@ -28,6 +30,7 @@ namespace Assets
public bool displayLocations = true;
public bool displayLocationCells = true;
public bool displayLocationEdges = true;
public bool displayCities = true;
public bool displayLocationPoints = true;
[NonSerialized] public float generationTime = 0.0f;
@ -58,7 +61,7 @@ namespace Assets
public Graph<MapSite> SitesGraph => Map?.Sites;
public Graph<Point> BoundariesGraph => Map?.Boundaries;
public Graph<Location> LocationGraph => Map?.Metadata.GetProperty<Graph<Location>>(LocationPass.MapLocationsProperty);
public Graph<Location> LocationGraph => Map?.Metadata.GetProperty<Graph<Location>>(LandmassPass.MapLocationsProperty);
public void Generate()
{
@ -86,7 +89,8 @@ namespace Assets
{
var generator = new MapGenerator(new VoronoiGridGenerator(seed, new PoissonDiskSampler(radius) { Generator = new Random(seed) }));
generator.AddAnnotationPass(new LocationPass(types.Prepend(new LocationType { name = "Ocean", height = -1 }).Select(t => new Location { Type = t }), new Random(seed)));
generator.AddAnnotationPass(new LandmassPass(types.Prepend(new LocationType { name = "Ocean", height = -1 }).Select(t => new Location { Type = t }), new Random(seed)));
generator.AddAnnotationPass(new LocateCitiesPass(new Random(seed)));
return generator;
}
@ -95,6 +99,20 @@ namespace Assets
{
GenerationThread?.Abort();
}
private void DisplayGraphCities(IEnumerable<City> cities)
{
foreach (City city in cities)
{
foreach (var (a, b) in city.edges)
{
Gizmos.DrawLine(Map.Boundaries[a].ToVector3(), Map.Boundaries[b].ToVector3());
}
foreach (var a in city.sites)
Gizmos.DrawSphere(a.Center.ToVector3(), 1);
}
}
void OnDrawGizmos()
{
@ -136,19 +154,19 @@ namespace Assets
Gizmos.color = Color.blue;
if (!Map.Metadata.HasProperty(LocationPass.MapLocationsProperty)) return;
if (!Map.Metadata.HasProperty(LandmassPass.MapLocationsProperty)) return;
var locations = Map.Metadata.GetProperty<Graph<Location>>(LocationPass.MapLocationsProperty);
var locations = Map.Metadata.GetProperty<Graph<Location>>(LandmassPass.MapLocationsProperty);
if (debug.displayLocationCells)
{
var cells = Map.Sites.Vertices
.Where(s => s.Metadata.HasProperty(LocationPass.SiteLocationProperty))
.Where(s => s.Metadata.GetProperty<Location>(LocationPass.SiteLocationProperty).Type.name != "Ocean");
.Where(s => s.Metadata.HasProperty(LandmassPass.SiteLocationProperty))
.Where(s => s.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty).Type.name != "Ocean");
foreach (var site in cells)
{
var location = site.Metadata.GetProperty<Location>(LocationPass.SiteLocationProperty);
var location = site.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty);
Gizmos.color = location.Type.color;
Gizmos.DrawSphere(site.Center.ToVector3(), 2);
@ -177,7 +195,7 @@ namespace Assets
//
if (debug.displayLocationEdges)
{
foreach (var location in Map.Metadata.GetProperty<Graph<Location>>(LocationPass.MapLocationsProperty).Vertices)
foreach (var location in Map.Metadata.GetProperty<Graph<Location>>(LandmassPass.MapLocationsProperty).Vertices)
{
Gizmos.color = location.Type.color;
foreach (var (a, b) in location.BoundaryEdges)
@ -186,6 +204,12 @@ namespace Assets
}
}
}
if (debug.displayCities && Map.Metadata.HasProperty(LocateCitiesPass.CitiesProperty))
{
Gizmos.color = Color.magenta;
DisplayGraphCities(Map.Metadata.GetProperty<IEnumerable<City>>(LocateCitiesPass.CitiesProperty));
}
}
}
}

View File

@ -0,0 +1,25 @@
using System.Collections.Generic;
using Assets.Common;
namespace Assets.Utils
{
public class PointProximityComparer : IEqualityComparer<Point>
{
double _threshold;
public PointProximityComparer(double threshold = 0.2)
{
_threshold = threshold;
}
public bool Equals(Point x, Point y)
{
return Point.Dist(x, y) < _threshold;
}
public int GetHashCode(Point obj)
{
return obj.GetHashCode();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 765daf76a463490ba0a1e186f5c82fdf
timeCreated: 1573418560