private void BuildPatches() { var points = GetVoronoiPoints(NumPatches, Center).ToList(); var v = Voronoi.Build(points); for (var i = 0; i < 3; i++) { var toRelax = v.Points.Take(3).ToList(); toRelax.Add(v.Points[NumPatches]); v = Voronoi.Relax(v, toRelax); } v = Voronoi.Relax(v); var comparer = new Vector2LengthComparer(); v.Points.Sort(comparer); var regions = v.Partitioning(); Patches.Clear(); foreach (var region in regions) { Patches.Add(Patch.FromRegion(this, region)); } var patchesInTown = Patches.OrderBy(p => (Center - p.Center).magnitude).Take(NumPatches).ToList(); // Find random patch at the outside of town to place water if (Options.Water) { var firstWaterPatch = patchesInTown.Where(p => p.GetAllNeighbours().Any(n => !n.WithinCity)) .OrderBy(p => Random.value).First(); firstWaterPatch.Water = true; Vector2 waterDirection = (firstWaterPatch.Center - Center).normalized; var toCheck = new List <Patch> { firstWaterPatch }; while (toCheck.Any()) { var checking = toCheck[0]; toCheck.RemoveAt(0); var waterPatches = checking.GetAllNeighbours().Except(patchesInTown) .Where(n => Math.Abs(GeometryHelpers.AngleComparedTo(Center - n.Center, waterDirection)) < Math.PI / 4) .Where(n => !n.Water).ToList(); foreach (var waterPatch in waterPatches) { waterPatch.Water = true; toCheck.Add(waterPatch); } } } patchesInTown = Patches.Where(p => !p.Water).OrderBy(p => (Center - p.Center).magnitude).Take(NumPatches) .ToList(); foreach (var patch in patchesInTown) { patch.WithinCity = true; patch.WithinWalls = true; } Castle = new Castle(patchesInTown.Last()); Market = patchesInTown.First(); Market.IsCityCenter = true; var circumference = FindCircumference(patchesInTown); var smoothAmount = Math.Min(1f, 40f / circumference.Vertices.Count); if (Options.Walls) { SmoothPatches(circumference, smoothAmount); } if (Options.Water) { var waterCircumference = FindCircumference(Patches.Where(p => p.Water)); SmoothPatches(waterCircumference, 0.2f); WaterBorder.Clear(); WaterBorder.AddRange(waterCircumference.Vertices); } }