96 lines
3.1 KiB
C#
96 lines
3.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Assets.Cities;
|
|
using Assets.Common;
|
|
|
|
namespace Assets.AnnotationPass
|
|
{
|
|
public class LocateCitiesPass : IAnnotationPass
|
|
{
|
|
public const string CitiesProperty = "Cities";
|
|
public const string CityProperty = "City";
|
|
public int MaxCitiesCount { get; set; } = 20;
|
|
public int MaxPlacementTries { get; set; } = 30;
|
|
public float RangeOfInfluence { get; set; } = .5f;
|
|
public float CitiesSize { get; set; } = .5f;
|
|
|
|
|
|
private Graph<Location> _locationGraph;
|
|
private Graph<MapSite> _basicGraph;
|
|
private Random _random;
|
|
|
|
public LocateCitiesPass(Random random = null)
|
|
{
|
|
_random = random ?? new Random();
|
|
}
|
|
|
|
City CreateCity(int vertex, int size)
|
|
{
|
|
City newCity = new City();
|
|
|
|
var site = _basicGraph.Vertices[vertex];
|
|
newCity.Center = site.Center.Clone() as Point;
|
|
site.Tags.Add("City.Center");
|
|
|
|
var sites = new List<MapSite> { site };
|
|
var location = site.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty);
|
|
|
|
for (int i = 0; i < size - 1; i++)
|
|
{
|
|
var neighbours = _basicGraph.Neighbours(site.Index).Select(j => _basicGraph.Vertices[j]).Where(s => s.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty) == location).ToList();
|
|
site = neighbours[_random.Next(neighbours.Count)];
|
|
sites.Add(site);
|
|
}
|
|
|
|
foreach (var s in sites.Distinct())
|
|
{
|
|
newCity.AddSite(s);
|
|
s.Metadata.SetProperty(CityProperty, newCity);
|
|
}
|
|
|
|
newCity.RangeOfInfluence = GetCityRangeOfInfluence(newCity);
|
|
return newCity;
|
|
}
|
|
|
|
List<City> CreateCities()
|
|
{
|
|
List<City> cities = new List<City>();
|
|
var vertices = new List<int>();
|
|
|
|
int guard = MaxPlacementTries;
|
|
int createdCitiesCount = 0;
|
|
|
|
while (createdCitiesCount < MaxCitiesCount && guard-- > 0)
|
|
{
|
|
var randomLocation = _locationGraph.Vertices.Skip(1).RandomElement(_random);
|
|
var randomSite = randomLocation.Sites.RandomElement(_random);
|
|
|
|
if (cities.Any(c => Point.Dist(PointUtils.Mean(c.Sites.Select(s => s.Center)), randomSite.Center) < c.RangeOfInfluence))
|
|
continue;
|
|
|
|
cities.Add(CreateCity(randomSite.Index, (int)Math.Ceiling(CitiesSize * _random.Next(0, 30))));
|
|
guard = MaxPlacementTries;
|
|
createdCitiesCount++;
|
|
}
|
|
|
|
return cities;
|
|
|
|
}
|
|
|
|
public float GetCityRangeOfInfluence(City city)
|
|
{
|
|
return RangeOfInfluence*city.Sites.Count;
|
|
}
|
|
|
|
public void Annotate(Map map)
|
|
{
|
|
_basicGraph = map.Sites.Clone() as Graph<MapSite>;
|
|
_locationGraph = map.Metadata.GetProperty<Graph<Location>>(LandmassPass.MapLocationsProperty);
|
|
|
|
var cities = CreateCities();
|
|
|
|
map.Metadata.SetProperty(CitiesProperty, cities);
|
|
}
|
|
}
|
|
} |