using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Numerics;
namespace NaturalNeighbor
{
using Internal;
///
/// Performs planar subdivision
///
public class SubDivision2d
{
///
/// Constructs a new subdivision including the specified points
///
/// XY coordinates
/// Margin for the bounding box
public SubDivision2d(Vector2[] points, double margin)
{
Bounds bounds = Utils.CalculateBounds(points, (float)margin, null, null);
_impl = new SubDiv2D_Mutable(bounds);
_searchContext = new SearchContext();
InsertRange(points);
}
internal int NumberOfSamples { get; private set; }
private SearchContext _searchContext;
///
/// Constructs a new subdivision including the specified points
///
/// XY coordinates
public SubDivision2d(Vector2[] points):this(points, 0.0)
{
}
///
/// Constructs an empty subdivision with the specified boundaries
///
/// the bottom left corner
/// the top right corner
public SubDivision2d(Vector2 min, Vector2 max)
{
_impl = new SubDiv2D_Mutable(new Bounds(min, max));
_searchContext = new SearchContext();
}
internal SubDiv2D_Mutable _impl;
///
/// The bottom left corner of the bounding box
///
public Vector2 MinValue => _impl.Bounds.MinValue;
///
/// The top right corner of the bounding box
///
public Vector2 MaxValue => _impl.Bounds.MaxValue;
///
/// Inserts a node into Delaunay graph
///
/// xy coordinate
/// node Id
public NodeId Insert(Vector2 point)
{
return _impl.Insert(point, _searchContext);
}
///
/// Inserts a node into Delaunay graph
///
/// x coordinate
/// y coordinate
/// node Id
public NodeId Insert(float x, float y)
{
var result = _impl.Insert(new Vector2(x, y), _searchContext);
if (_searchContext.Vertex == 0)
{
NumberOfSamples++;
}
return result;
}
///
/// Inserts a sequence of nodes into Delaunay graph
///
/// xy coordinates
public void InsertRange(IEnumerable points)
{
foreach (var p in points)
{
_impl.Insert(p, _searchContext);
if (_searchContext.Vertex == 0)
{
NumberOfSamples++;
}
}
}
///
/// Clears the graph retaining the bounding box
///
public void Clear()
{
var bounds = _impl.Bounds;
_impl = new SubDiv2D_Mutable(bounds);
_searchContext.Clear();
NumberOfSamples = 0;
}
///
/// Reads delaunay triangles in the current node set
///
/// list of triangles
public IEnumerable GetDelaunayTriangles()
{
return _impl.GetTriangles();
}
///
/// Reads all edges of graph
///
/// A list of endpoints forming an edge
public IEnumerable<(Vector2, Vector2)> GetEdges()
{
return _impl.GetEdges();
}
///
/// Finds a node closest to the specified location
///
/// Location xy coordinate
/// Closest node location
/// Found node Id, null if point is out of bounds
public NodeId? FindNearest(Vector2 point, out Vector2 result)
{
return _impl.FindNearest(point, _searchContext, out result);
}
///
/// Finds a node closest to the specified location
///
/// Location X coordinate
/// Location Y coordinate
/// Closest node location
/// Id of the found node or null if point is out of bounds
public NodeId? FindNearest(float x, float y, out Vector2 result)
{
return _impl.FindNearest(new Vector2(x, y), _searchContext, out result);
}
///
/// Reads all voronoi facets
///
/// A list of facets
public IEnumerable GetVoronoiFacets()
{
return _impl.GetVoronoiFacets();
}
///
/// Reads specific voronoi facets
///
/// node ids
/// A list of requested facets
public IEnumerable GetVoronoiFacets(IReadOnlyList vertices)
{
return _impl.GetVoronoiFacets(vertices);
}
}
}