From 8bfcb28a304bc36933ae131ddf10a6c10c48ba06 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sat, 17 Aug 2019 14:08:41 +0200 Subject: [PATCH] Compute location neighbours --- Assets/Map/LocationGenerator.cs | 61 ++++++++++++++++++-------------- Assets/Scripts/GraphGenerator.cs | 57 +++++++++++++++++++++++------ 2 files changed, 81 insertions(+), 37 deletions(-) diff --git a/Assets/Map/LocationGenerator.cs b/Assets/Map/LocationGenerator.cs index c327ff8..f5e86d6 100644 --- a/Assets/Map/LocationGenerator.cs +++ b/Assets/Map/LocationGenerator.cs @@ -1,31 +1,51 @@ using System; using System.Collections.Generic; using System.Linq; -using UnityEngine; +using Assets.Voronoi; using Random = System.Random; namespace Assets.Map { public class LocationGenerator { - private Graph _graph; + private readonly Graph _sites; + private readonly Graph _locations; + private readonly List<(int, Location)> _queue = new List<(int, Location)>(); - private Random _random; - + private readonly Dictionary> _blacklist = new Dictionary>(); + + private readonly Random _random; + + public Graph Sites => _sites; + public Graph Result => _locations; + public bool Done => _queue.Count == 0; - public Graph Result => _graph; - private Dictionary> _blacklist = new Dictionary>(); + - public LocationGenerator(Graph graph, Random random = null) + public LocationGenerator(List locations, Graph sites, Random random = null) { - _graph = graph; + _sites = sites.Morph(s => new LocationSite(s)); + _locations = new Graph { Vertices = new List(locations) }; + _random = random ?? new Random(); } - public void Init(params (int, Location)[] start) + public void SetLocation(int vertex, Location location) { - foreach (var (vertex, location) in start) - SetLocation(vertex, location); + _sites.Vertices[vertex].Location = location; + location.Sites.Add(_sites.Vertices[vertex]); + + FixBoundaryPoints(vertex, location); + FixBoundaryEdges(vertex, location); + + foreach (var neighbour in _sites.Neighbours(vertex)) + if (_sites.Vertices[neighbour].Location == null) + _queue.Add((neighbour, location)); + else if (location != _sites.Vertices[neighbour].Location) + _locations.AddEdge( + _locations.Vertices.IndexOf(location), + _locations.Vertices.IndexOf(_sites.Vertices[neighbour].Location) + ); } private (int, Location) Dequeue() @@ -37,7 +57,7 @@ namespace Assets.Map _queue.RemoveAt(index); - if (_graph.Vertices[pair.Item1].Location == null) return pair; + if (_sites.Vertices[pair.Item1].Location == null) return pair; } throw new Exception("No more elements."); @@ -56,23 +76,10 @@ namespace Assets.Map } } - private void SetLocation(int vertex, Location location) - { - _graph.Vertices[vertex].Location = location; - location.Sites.Add(_graph.Vertices[vertex]); - - FixBoundaryPoints(vertex, location); - FixBoundaryEdges(vertex, location); - - foreach (var neighbour in _graph.Neighbours(vertex)) - if (_graph.Vertices[neighbour].Location == null) - _queue.Add((neighbour, location)); - } - private void FixBoundaryPoints(int vertex, Location location) { var a = location.BoundaryPoints; - var b = _graph.Vertices[vertex].Site.Vertices; + var b = _sites.Vertices[vertex].Site.Vertices; if (!_blacklist.ContainsKey(location)) _blacklist[location] = new List(); _blacklist[location].AddRange(a.Intersect(b)); @@ -83,7 +90,7 @@ namespace Assets.Map private void FixBoundaryEdges(int vertex, Location location) { var a = location.BoundaryEdges; - var b = _graph.Vertices[vertex].Site.Edges; + var b = _sites.Vertices[vertex].Site.Edges; location.BoundaryEdges = a.Union(b).Except(a.Intersect(b)).ToList(); } diff --git a/Assets/Scripts/GraphGenerator.cs b/Assets/Scripts/GraphGenerator.cs index 1bf45ea..dd716f6 100644 --- a/Assets/Scripts/GraphGenerator.cs +++ b/Assets/Scripts/GraphGenerator.cs @@ -24,6 +24,7 @@ namespace Assets public bool displayHalfEdges = false; public bool displayEdges = true; public bool displayLocations = true; + public bool displayLocationCells = true; public bool displayLocationEdges = true; public bool displayLocationPoints = true; } @@ -69,6 +70,7 @@ namespace Assets public float radius = 8; private double _directrix = 0.0f; + private Graph<(Point, Location)> _locationGraph; void Start() { @@ -94,6 +96,7 @@ namespace Assets _voronoiGenerator = new VoronoiGenerator(_points.Select(x => new Point(x.x, x.y)).ToList()); _locationGenerator = null; + _locationGraph = null; _locations = new List() { new Location() { Type = new LocationType() { color = Color.clear, name = "Ocean" } } }; _locations.AddRange(types.Select(type => new Location { Type = type })); @@ -118,19 +121,27 @@ namespace Assets { Stage = GenerationStage.Location; - _locationGenerator = new LocationGenerator(_voronoiGenerator.Delaunay.Morph(site => new LocationSite(site)), _random); - _locationGenerator.Init( - _locations.Select(location => (_random.Next(_voronoiGenerator.Delaunay.Vertices.Count), location)) - .Concat(new List { 0, 1, 2, 3 }.Select(i => (i, _locations[0]))) // borders should be water - .ToArray() - ); + _locationGenerator = new LocationGenerator(_locations, _voronoiGenerator.Delaunay, _random); + + var initial = + from location in _locations + select (_random.Next(_voronoiGenerator.Delaunay.Vertices.Count), location); + + initial = initial.Concat(new List { 0, 1, 2, 3 }.Select(i => (i, _locations[0]))); + + foreach (var (vertex, location) in initial) + _locationGenerator.SetLocation(vertex, location); } } else if (Stage == GenerationStage.Location) { _locationGenerator.Step(); - - if (_locationGenerator.Done) Stage = GenerationStage.Done; + + if (_locationGenerator.Done) + { + Stage = GenerationStage.Done; + RecalculateLocationGraph(); + } } } @@ -208,15 +219,20 @@ namespace Assets if (LocationGenerator == null) return; - if (debug.displayLocations) + if (debug.displayLocationCells) { - foreach (var location in LocationGenerator.Result.Vertices.Where(l => l.Location != null && l.Location != _locations[0])) + foreach (var location in LocationGenerator.Sites.Vertices.Where(l => l.Location != null && l.Location != _locations[0])) { Gizmos.color = location.Location.Type.color; Gizmos.DrawSphere(location.Site.Point.ToVector3(), 2); } } + if (debug.displayLocations && _locationGraph != null) + { + DisplayGraphEdges(_locationGraph.Morph(a => a.Item1)); + } + if (debug.displayLocationPoints) { foreach (var location in _locations.Skip(1)) @@ -270,6 +286,27 @@ namespace Assets foreach (var (s, e) in edges) Gizmos.DrawLine(s, e); } + + private void RecalculateLocationGraph() + { + Point Mean(IEnumerable points) + { + var result = new Point(0, 0); + var i = 0; + + foreach (var point in points) + { + result.x = (result.x * i + point.x) / (i + 1); + result.y = (result.y * i + point.y) / (i + 1); + + i++; + } + + return result; + } + + _locationGraph = LocationGenerator.Result.Morph(location => (Mean(location.Sites.Select(s => s.Site.Point)), location)); + } } } \ No newline at end of file