98 lines
3.2 KiB
C#
98 lines
3.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Assets.Voronoi;
|
|
using Random = System.Random;
|
|
|
|
namespace Assets.Map
|
|
{
|
|
public class LocationGenerator
|
|
{
|
|
private readonly Graph<LocationSite> _sites;
|
|
private readonly Graph<Location> _locations;
|
|
|
|
private readonly List<(int, Location)> _queue = new List<(int, Location)>();
|
|
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 LocationGenerator(List<Location> locations, Graph<Site> sites, Random random = null)
|
|
{
|
|
_sites = sites.Morph(s => new LocationSite(s));
|
|
_locations = new Graph<Location> { Vertices = new List<Location>(locations) };
|
|
|
|
_random = random ?? new Random();
|
|
}
|
|
|
|
public void SetLocation(int vertex, Location 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()
|
|
{
|
|
while (_queue.Count > 0)
|
|
{
|
|
var index = _random.Next(_queue.Count);
|
|
var pair = _queue[index];
|
|
|
|
_queue.RemoveAt(index);
|
|
|
|
if (_sites.Vertices[pair.Item1].Location == null) return pair;
|
|
}
|
|
|
|
throw new Exception("No more elements.");
|
|
}
|
|
|
|
public void Step()
|
|
{
|
|
try
|
|
{
|
|
var (vertex, location) = Dequeue();
|
|
|
|
SetLocation(vertex, location);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
}
|
|
}
|
|
|
|
private void FixBoundaryPoints(int vertex, Location location)
|
|
{
|
|
var a = location.BoundaryPoints;
|
|
var b = _sites.Vertices[vertex].Site.Vertices;
|
|
|
|
if (!_blacklist.ContainsKey(location)) _blacklist[location] = new List<int>();
|
|
_blacklist[location].AddRange(a.Intersect(b));
|
|
|
|
location.BoundaryPoints = a.Union(b).Except(_blacklist[location]).ToList();
|
|
}
|
|
|
|
private void FixBoundaryEdges(int vertex, Location location)
|
|
{
|
|
var a = location.BoundaryEdges;
|
|
var b = _sites.Vertices[vertex].Site.Edges;
|
|
|
|
location.BoundaryEdges = a.Union(b).Except(a.Intersect(b)).ToList();
|
|
}
|
|
}
|
|
} |