using System; using System.Collections.Generic; using System.Linq; using Assets.Generators; 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; } [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 (debug.displayLabels) Handles.Label(point, $"({point.x:F1}, {point.y:F1})"); } } if (generator is null) return; if (debug.displayNeighbours) { Gizmos.color = Color.yellow; foreach (var site in generator.Sites) { var vecStart = new Vector3((float)site.Point.x, (float)site.Point.y); foreach (var neighbour in site.Neighbours) { var vecEnd = new Vector3((float)neighbour.Point.x, (float)neighbour.Point.y); Gizmos.DrawLine(vecStart, vecEnd); } } } Gizmos.color = Color.green; foreach (var edge in generator.Edges) { 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); } 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.displayVertices) { foreach (var vertex in generator.Vertices) { var point = new Vector3((float)vertex.x, (float)vertex.y); Gizmos.DrawSphere(point, 1); if (debug.displayLabels) Handles.Label(point, $"({point.x:F1}, {point.y:F1})"); } } 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(); } } } }