private void MathTesting() { //Setup var cell = new Cell(); cell.SitePoint = new Point(400, 400); cell.AddPoint(new Point(250, 100)); cell.AddPoint(new Point(700, 300)); cell.AddPoint(new Point(400, 500)); cell.AddPoint(new Point(150, 300)); cell.AddPoint(new Point(100, 200)); var newCell = cell.Inset(50); // _drawService.DrawCell(cell,Color.FromArgb(255,100, 100, 100),true,true); // _drawService.DrawCell(newCell, Color.FromArgb(255, 180, 180, 180), true, true); var triangles = new BowyerWatsonGenerator().DelaunayTriangulation(newCell.Points); foreach (var t in triangles) { //_drawService.DrawTriangle(t, Colors.CornflowerBlue); } foreach (var p in newCell.GenerateRandomPoints(20)) { //_drawService.DrawPoint(p, 5, Colors.Red); } }
/// <summary> /// Generate random points insidea cell /// </summary> public static List <Point> GenerateRandomPoints(this Cell cell, int amount) { //Do an inset to avoid spawning points on the edges //Easier to take random points inside a triangle than a cell, so first triangulate the cell var triangles = new BowyerWatsonGenerator().DelaunayTriangulation(cell.Points); var points = new List <Point>(); if (triangles.Count < 1) { return(points); } var perTriangle = amount / triangles.Count; //for every triangle take the amount of points for (int i = 0; i < perTriangle; i++) { foreach (var t in triangles) { var p = t.RandomPointInTriangle(); points.Add(p); } } return(points); }
/// <summary> /// Create a Voronoi Diagram using a list of points and a specified algorithm to use /// </summary> public static VoronoiDiagram CreateVoronoi(List <Point> points, GenerationSettings settings) { VoronoiDiagram voronoi; var startX = settings.StartX; var startY = settings.StartX; var width = settings.Width; var length = settings.Length; //Select algorithm to use switch (settings.VoronoiAlgorithm) { // Voronoi according to Boywer-Watson Algorithm // http://paulbourke.net/papers/triangulate/ case VoronoiAlgorithm.BoywerWatson: { voronoi = new BowyerWatsonGenerator().GetVoronoi(points); break; } // Voronoi according to Fortunes Algorithm // http://blog.ivank.net/fortunes-algorithm-and-implementation.html case VoronoiAlgorithm.Fortune: { voronoi = new FortuneGenerator().GetVoronoi(points); break; } default: throw new ArgumentOutOfRangeException(nameof(settings.VoronoiAlgorithm), settings.VoronoiAlgorithm, null); } voronoi.Bounds = new Rectangle(startX, startY, width, length); voronoi.Sites = points; voronoi.FinishVoronoi(); return(voronoi);; }
/// <summary> /// Convert the Voronoi Diagram into a city with roads and building zones /// </summary> private void GenerateCity() { if (_voronoiDiagram == null) { //GenerateVoronoi(); return; } //Settings for generation _citySettings.DistrictSettings = DistrictSettings.ToList(); _citySettings.GenerateInnerRoads = GenerateInnerRoads; _citySettings.RoadSubdivision = RoadSubdivisions; _citySettings.DebugMode = DebugMode.Value; //generate city var timer = Stopwatch.StartNew(); _cityData = CityBuilder.GenerateCity(_citySettings, _voronoiDiagram); timer.Stop(); //update timer var time = timer.ElapsedMilliseconds / 1000.0; GenerationTimeText = $"City generated in {time} seconds."; //update canvas RefreshCanvas(); //InsetTesting var insetCells = new List <Cell>(); var points = new List <Point>(); foreach (var d in _cityData.Districts) { foreach (var c in d.Cells) { var cInset = c.Inset(20); insetCells.Add(cInset); //_drawService.DrawCell(c, Color.FromArgb(255, 120, 120, 120), true, true); points.AddRange(cInset.GenerateRandomPoints(9)); } } ////Draw foreach (var c in insetCells) { //_drawService.DrawCell(c, Color.FromArgb(255, 188, 188, 188), true, true); //Draw Triangulation var triangles = new BowyerWatsonGenerator().DelaunayTriangulation(c.Points); foreach (var t in triangles) { //_drawService.DrawTriangle(t, Colors.CornflowerBlue); } } foreach (var p in points) { _drawService.DrawPoint(p, 4, Colors.OrangeRed); } }