using System; using System.Collections.Generic; using System.Linq; using Assets.Generators; using Assets.Map; using Assets.Voronoi; using UnityEditor; using UnityEngine; using Random = System.Random; namespace Assets { [Serializable] public class GraphGeneratorDebug { public bool enabled = true; public bool displayPoints = true; public bool displayBeachLine = true; public bool displayParabolas = false; public bool displayVertices = true; public bool displayNeighbours = false; public bool displayLabels = false; public bool displayHalfEdges = false; public bool displayEdges = true; } [RequireComponent(typeof(MeshRenderer), typeof(MeshFilter)), ExecuteInEditMode] public class GraphGenerator : MonoBehaviour { MeshFilter _filter; private PoissonDiskSampler _sampler; IList _points = new List(); public VoronoiGenerator generator; public int seed = Environment.TickCount; public Vector2 size = new Vector2(); public GraphGeneratorDebug debug; [Range(2.0f, 64.0f)] public float radius = 8; private double _directrix = 0.0f; private Random _random; private Dictionary _colors; void Start() { _filter = GetComponent(); Reset(); } public Vector3 RandomPoint() { return _points[_random.Next(_points.Count)]; } public void Reset() { _colors = new Dictionary(); _random = new System.Random(seed); _sampler = new PoissonDiskSampler(radius); _sampler.Generator = _random; _points = new List(_sampler.Generate(size.x, size.y)); for (int i = 0; i < 10; i++) { _colors[RandomPoint()] = Color.yellow; } // points = new List() // { // new Vector3(15.7f, 5.9f), // new Vector3(37.9f, 10.3f), // new Vector3(24.6f, 18.1f), // new Vector3(53.5f, 8.0f), // }; generator = new VoronoiGenerator(_points.Select(x => new Point(x.x, x.y)).ToList()); } public void Generate() { generator.Generate(); } public void Step() { generator.Step(); _directrix = generator.Line.Directrix; } void OnDrawGizmos() { if (!debug.enabled) return; if (debug.displayPoints) { foreach (var point in _points) { Gizmos.color = _colors.ContainsKey(point) ? _colors[point] : Color.white; Gizmos.DrawSphere(point, 1); } } if (generator is null) return; if (debug.displayNeighbours) { Gizmos.color = Color.yellow; DisplayGraphEdges(generator.Delaunay); } if (debug.displayVertices) { Gizmos.color = Color.blue; DisplayGraphVertices(generator.Voronoi); } if (debug.displayHalfEdges) { Gizmos.color = Color.green; foreach (var edge in generator.HalfEdges) { var vecStart = new Vector3((float)edge.Start.x, (float)edge.Start.y); var vecEnd = new Vector3((float)edge.End.x, (float)edge.End.y); Gizmos.DrawLine(vecStart, vecEnd); } } if (debug.displayEdges) { Gizmos.color = Color.white; DisplayGraphEdges(generator.Voronoi); } Gizmos.color = Color.red; Gizmos.DrawLine(new Vector3(0, (float)generator.Line.Directrix), new Vector3(size.x, (float)generator.Line.Directrix)); Gizmos.color = Color.blue; Vector3 start; if (debug.displayParabolas) { foreach (var parabola in generator.Line.Parabolas) { start = new Vector3(-size.x, (float)generator.Line.EvalParabola(parabola.Site.Point, -size.x)); for (var x = -size.x + 0.1f; x < size.x * 2; x += 0.1f) { var point = new Vector3(x, (float)generator.Line.EvalParabola(parabola.Site.Point, x)); Gizmos.DrawLine(start, point); start = point; } } } if (debug.displayBeachLine) { Gizmos.color = Color.white; start = new Vector3(-size.x, (float)generator.Line.Eval(-size.x)); for (var x = -size.x + 0.1f; x < size.x * 2; x += 0.1f) { var point = new Vector3(x, (float)generator.Line.Eval(x)); Gizmos.DrawLine(start, point); start = point; } } } public void Rewind(float y) { while (generator.Line.Directrix < y && !generator.Done) { generator.Step(); } } private void DisplayGraphVertices(Graph graph) { var vertices = graph.Vertices.Select(p => new Vector3((float) p.x, (float) p.y)); foreach (var v in vertices) { Gizmos.DrawSphere(v, 1); if (debug.displayLabels) Handles.Label(v, $"({v.x:F2}, {v.y:F2})"); } } private void DisplayGraphEdges(Graph graph) { var edges = graph.Edges .Select(edge => (graph.Vertices[edge.Item1], graph.Vertices[edge.Item2])) .Select(edge => (new Vector3((float)edge.Item1.x, (float)edge.Item1.y), new Vector3((float)edge.Item2.x, (float)edge.Item2.y))); foreach (var (s, e) in edges) Gizmos.DrawLine(s, e); } } }