Compute location neighbours
This commit is contained in:
parent
8a9adbd28f
commit
8bfcb28a30
@ -1,31 +1,51 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using Assets.Voronoi;
|
||||||
using Random = System.Random;
|
using Random = System.Random;
|
||||||
|
|
||||||
namespace Assets.Map
|
namespace Assets.Map
|
||||||
{
|
{
|
||||||
public class LocationGenerator
|
public class LocationGenerator
|
||||||
{
|
{
|
||||||
private Graph<LocationSite> _graph;
|
private readonly Graph<LocationSite> _sites;
|
||||||
|
private readonly Graph<Location> _locations;
|
||||||
|
|
||||||
private readonly List<(int, Location)> _queue = new List<(int, Location)>();
|
private readonly List<(int, Location)> _queue = new List<(int, Location)>();
|
||||||
private Random _random;
|
private readonly Dictionary<Location, List<int>> _blacklist = new Dictionary<Location, List<int>>();
|
||||||
|
|
||||||
|
private readonly Random _random;
|
||||||
|
|
||||||
|
public Graph<LocationSite> Sites => _sites;
|
||||||
|
public Graph<Location> Result => _locations;
|
||||||
|
|
||||||
public bool Done => _queue.Count == 0;
|
public bool Done => _queue.Count == 0;
|
||||||
public Graph<LocationSite> Result => _graph;
|
|
||||||
private Dictionary<Location, List<int>> _blacklist = new Dictionary<Location, List<int>>();
|
|
||||||
|
|
||||||
public LocationGenerator(Graph<LocationSite> graph, Random random = null)
|
public LocationGenerator(List<Location> locations, Graph<Site> sites, Random random = null)
|
||||||
{
|
{
|
||||||
_graph = graph;
|
_sites = sites.Morph(s => new LocationSite(s));
|
||||||
|
_locations = new Graph<Location> { Vertices = new List<Location>(locations) };
|
||||||
|
|
||||||
_random = random ?? new Random();
|
_random = random ?? new Random();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(params (int, Location)[] start)
|
public void SetLocation(int vertex, Location location)
|
||||||
{
|
{
|
||||||
foreach (var (vertex, location) in start)
|
_sites.Vertices[vertex].Location = location;
|
||||||
SetLocation(vertex, 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()
|
private (int, Location) Dequeue()
|
||||||
@ -37,7 +57,7 @@ namespace Assets.Map
|
|||||||
|
|
||||||
_queue.RemoveAt(index);
|
_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.");
|
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)
|
private void FixBoundaryPoints(int vertex, Location location)
|
||||||
{
|
{
|
||||||
var a = location.BoundaryPoints;
|
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<int>();
|
if (!_blacklist.ContainsKey(location)) _blacklist[location] = new List<int>();
|
||||||
_blacklist[location].AddRange(a.Intersect(b));
|
_blacklist[location].AddRange(a.Intersect(b));
|
||||||
@ -83,7 +90,7 @@ namespace Assets.Map
|
|||||||
private void FixBoundaryEdges(int vertex, Location location)
|
private void FixBoundaryEdges(int vertex, Location location)
|
||||||
{
|
{
|
||||||
var a = location.BoundaryEdges;
|
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();
|
location.BoundaryEdges = a.Union(b).Except(a.Intersect(b)).ToList();
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ namespace Assets
|
|||||||
public bool displayHalfEdges = false;
|
public bool displayHalfEdges = false;
|
||||||
public bool displayEdges = true;
|
public bool displayEdges = true;
|
||||||
public bool displayLocations = true;
|
public bool displayLocations = true;
|
||||||
|
public bool displayLocationCells = true;
|
||||||
public bool displayLocationEdges = true;
|
public bool displayLocationEdges = true;
|
||||||
public bool displayLocationPoints = true;
|
public bool displayLocationPoints = true;
|
||||||
}
|
}
|
||||||
@ -69,6 +70,7 @@ namespace Assets
|
|||||||
public float radius = 8;
|
public float radius = 8;
|
||||||
|
|
||||||
private double _directrix = 0.0f;
|
private double _directrix = 0.0f;
|
||||||
|
private Graph<(Point, Location)> _locationGraph;
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
@ -94,6 +96,7 @@ namespace Assets
|
|||||||
|
|
||||||
_voronoiGenerator = new VoronoiGenerator(_points.Select(x => new Point(x.x, x.y)).ToList());
|
_voronoiGenerator = new VoronoiGenerator(_points.Select(x => new Point(x.x, x.y)).ToList());
|
||||||
_locationGenerator = null;
|
_locationGenerator = null;
|
||||||
|
_locationGraph = null;
|
||||||
|
|
||||||
_locations = new List<Location>() { new Location() { Type = new LocationType() { color = Color.clear, name = "Ocean" } } };
|
_locations = new List<Location>() { new Location() { Type = new LocationType() { color = Color.clear, name = "Ocean" } } };
|
||||||
_locations.AddRange(types.Select(type => new Location { Type = type }));
|
_locations.AddRange(types.Select(type => new Location { Type = type }));
|
||||||
@ -118,19 +121,27 @@ namespace Assets
|
|||||||
{
|
{
|
||||||
Stage = GenerationStage.Location;
|
Stage = GenerationStage.Location;
|
||||||
|
|
||||||
_locationGenerator = new LocationGenerator(_voronoiGenerator.Delaunay.Morph(site => new LocationSite(site)), _random);
|
_locationGenerator = new LocationGenerator(_locations, _voronoiGenerator.Delaunay, _random);
|
||||||
_locationGenerator.Init(
|
|
||||||
_locations.Select(location => (_random.Next(_voronoiGenerator.Delaunay.Vertices.Count), location))
|
var initial =
|
||||||
.Concat(new List<int> { 0, 1, 2, 3 }.Select(i => (i, _locations[0]))) // borders should be water
|
from location in _locations
|
||||||
.ToArray()
|
select (_random.Next(_voronoiGenerator.Delaunay.Vertices.Count), location);
|
||||||
);
|
|
||||||
|
initial = initial.Concat(new List<int> { 0, 1, 2, 3 }.Select(i => (i, _locations[0])));
|
||||||
|
|
||||||
|
foreach (var (vertex, location) in initial)
|
||||||
|
_locationGenerator.SetLocation(vertex, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Stage == GenerationStage.Location)
|
else if (Stage == GenerationStage.Location)
|
||||||
{
|
{
|
||||||
_locationGenerator.Step();
|
_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 (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.color = location.Location.Type.color;
|
||||||
Gizmos.DrawSphere(location.Site.Point.ToVector3(), 2);
|
Gizmos.DrawSphere(location.Site.Point.ToVector3(), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debug.displayLocations && _locationGraph != null)
|
||||||
|
{
|
||||||
|
DisplayGraphEdges(_locationGraph.Morph(a => a.Item1));
|
||||||
|
}
|
||||||
|
|
||||||
if (debug.displayLocationPoints)
|
if (debug.displayLocationPoints)
|
||||||
{
|
{
|
||||||
foreach (var location in _locations.Skip(1))
|
foreach (var location in _locations.Skip(1))
|
||||||
@ -270,6 +286,27 @@ namespace Assets
|
|||||||
|
|
||||||
foreach (var (s, e) in edges) Gizmos.DrawLine(s, e);
|
foreach (var (s, e) in edges) Gizmos.DrawLine(s, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RecalculateLocationGraph()
|
||||||
|
{
|
||||||
|
Point Mean(IEnumerable<Point> 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user