inz-00/Assets/Scripts/GraphGenerator.cs

204 lines
6.2 KiB
C#

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<Vector3> _points = new List<Vector3>();
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<Vector3, Color> _colors;
void Start()
{
_filter = GetComponent<MeshFilter>();
Reset();
}
public Vector3 RandomPoint()
{
return _points[_random.Next(_points.Count)];
}
public void Reset()
{
_colors = new Dictionary<Vector3, Color>();
_random = new System.Random(seed);
_sampler = new PoissonDiskSampler(radius);
_sampler.Generator = _random;
_points = new List<Vector3>(_sampler.Generate(size.x, size.y));
for (int i = 0; i < 10; i++)
{
_colors[RandomPoint()] = Color.yellow;
}
// points = new List<Vector3>()
// {
// 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<Point> 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<Point> 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);
}
}
}