Compute location neighbours
This commit is contained in:
parent
8a9adbd28f
commit
8bfcb28a30
@ -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<LocationSite> _graph;
|
||||
private readonly Graph<LocationSite> _sites;
|
||||
private readonly Graph<Location> _locations;
|
||||
|
||||
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 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();
|
||||
}
|
||||
|
||||
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<int>();
|
||||
_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();
|
||||
}
|
||||
|
@ -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<Location>() { 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<int> { 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<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)
|
||||
{
|
||||
_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<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