437 lines
14 KiB
C#
437 lines
14 KiB
C#
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);
|
|
// }
|
|
// }
|
|
}
|
|
//} |