Code documentation updates.

This commit is contained in:
wo80
2022-05-24 12:17:39 +02:00
parent cd22e5e82c
commit ea8ad5f272
51 changed files with 724 additions and 415 deletions
+12
View File
@@ -13,16 +13,28 @@ namespace TriangleNet
/// </summary>
public class Configuration
{
/// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary>
public Configuration()
: this(() => RobustPredicates.Default, () => new TrianglePool())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary>
/// <param name="predicates">Factory method for <see cref="IPredicates" />.</param>
public Configuration(Func<IPredicates> predicates)
: this(predicates, () => new TrianglePool())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary>
/// <param name="predicates">Factory method for <see cref="IPredicates" />.</param>
/// <param name="trianglePool">Factory method for <see cref="TrianglePool" />.</param>
public Configuration(Func<IPredicates> predicates, Func<TrianglePool> trianglePool)
{
Predicates = predicates;
+7
View File
@@ -10,6 +10,9 @@ namespace TriangleNet.Geometry
using System.Collections.Generic;
using TriangleNet.Tools;
/// <summary>
/// Represents a contour of a polygon (outer boundary or internal holes).
/// </summary>
public class Contour
{
int marker;
@@ -54,6 +57,10 @@ namespace TriangleNet.Geometry
this.convex = convex;
}
/// <summary>
/// Gets the list of segments of the contour.
/// </summary>
/// <returns></returns>
public List<ISegment> GetSegments()
{
var segments = new List<ISegment>();
+14
View File
@@ -4,6 +4,9 @@ namespace TriangleNet.Geometry
using System;
using TriangleNet.Meshing;
/// <summary>
/// Extension methods.
/// </summary>
public static class ExtensionMethods
{
#region IPolygon extensions
@@ -19,6 +22,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Triangulates a polygon, applying constraint options.
/// </summary>
/// <param name="polygon">Polygon instance.</param>
/// <param name="options">Constraint options.</param>
public static IMesh Triangulate(this IPolygon polygon, ConstraintOptions options)
{
@@ -28,6 +32,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Triangulates a polygon, applying quality options.
/// </summary>
/// <param name="polygon">Polygon instance.</param>
/// <param name="quality">Quality options.</param>
public static IMesh Triangulate(this IPolygon polygon, QualityOptions quality)
{
@@ -37,6 +42,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Triangulates a polygon, applying quality and constraint options.
/// </summary>
/// <param name="polygon">Polygon instance.</param>
/// <param name="options">Constraint options.</param>
/// <param name="quality">Quality options.</param>
public static IMesh Triangulate(this IPolygon polygon, ConstraintOptions options, QualityOptions quality)
@@ -47,6 +53,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Triangulates a polygon, applying quality and constraint options.
/// </summary>
/// <param name="polygon">Polygon instance.</param>
/// <param name="options">Constraint options.</param>
/// <param name="quality">Quality options.</param>
/// <param name="triangulator">The triangulation algorithm.</param>
@@ -67,6 +74,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Test whether a given point lies inside a triangle or not.
/// </summary>
/// <param name="triangle">Triangle instance.</param>
/// <param name="p">Point to locate.</param>
/// <returns>True, if point is inside or on the edge of this triangle.</returns>
public static bool Contains(this ITriangle triangle, Point p)
@@ -77,6 +85,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Test whether a given point lies inside a triangle or not.
/// </summary>
/// <param name="triangle">Triangle instance.</param>
/// <param name="x">Point to locate.</param>
/// <param name="y">Point to locate.</param>
/// <returns>True, if point is inside or on the edge of this triangle.</returns>
@@ -117,6 +126,11 @@ namespace TriangleNet.Geometry
return false;
}
/// <summary>
/// Returns the bounding box of the triangle.
/// </summary>
/// <param name="triangle">Triangle instance.</param>
/// <returns></returns>
public static Rectangle Bounds(this ITriangle triangle)
{
var bounds = new Rectangle();
+3
View File
@@ -6,6 +6,9 @@
namespace TriangleNet.Geometry
{
/// <summary>
/// Simple edge interface.
/// </summary>
public interface IEdge
{
/// <summary>
+20
View File
@@ -28,16 +28,30 @@ namespace TriangleNet.Geometry
internal double z;
#endif
/// <summary>
/// Initializes a new instance of the <see cref="Point" /> class.
/// </summary>
public Point()
: this(0.0, 0.0, 0)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Point" /> class.
/// </summary>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
public Point(double x, double y)
: this(x, y, 0)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Point" /> class.
/// </summary>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <param name="label">The point label.</param>
public Point(double x, double y, int label)
{
this.x = x;
@@ -101,6 +115,7 @@ namespace TriangleNet.Geometry
#region Overriding Equals() and == Operator
/// <inheritdoc />
public static bool operator ==(Point a, Point b)
{
if (a is null)
@@ -118,13 +133,16 @@ namespace TriangleNet.Geometry
return a.Equals(b);
}
/// <inheritdoc />
public static bool operator !=(Point a, Point b)
{
return !(a == b);
}
/// <inheritdoc />
public override bool Equals(object obj) => Equals(obj as Point);
/// <inheritdoc />
public bool Equals(Point p)
{
// If object is null return false.
@@ -139,6 +157,7 @@ namespace TriangleNet.Geometry
#endregion
/// <inheritdoc />
public int CompareTo(Point other)
{
if (x == other.x && y == other.y)
@@ -149,6 +168,7 @@ namespace TriangleNet.Geometry
return (x < other.x || (x == other.x && y < other.y)) ? -1 : 1;
}
/// <inheritdoc />
public override int GetHashCode()
{
int hash = 19;
+5 -2
View File
@@ -25,6 +25,10 @@ namespace TriangleNet.Geometry
xmax = ymax = -double.MaxValue;
}
/// <summary>
/// Initializes a new instance of the <see cref="Rectangle" /> class.
/// </summary>
/// <param name="other"></param>
public Rectangle(Rectangle other)
: this(other.Left, other.Bottom, other.Right, other.Top)
{
@@ -125,8 +129,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Expand rectangle to include given rectangle.
/// </summary>
/// <param name="x">X coordinate.</param>
/// <param name="y">Y coordinate.</param>
/// <param name="other">The other rectangle.</param>
public void Expand(Rectangle other)
{
xmin = Math.Min(xmin, other.xmin);
+1
View File
@@ -106,6 +106,7 @@ namespace TriangleNet.Geometry
#endregion
/// <inheritdoc />
public override int GetHashCode() => hash;
}
}
+1 -1
View File
@@ -64,7 +64,7 @@ namespace TriangleNet.IO
/// <summary>
/// Save a polygon geometry to disk.
/// </summary>
/// <param name="mesh">An instance of the <see cref="IPolygon" /> class.</param>
/// <param name="polygon">An instance of the <see cref="IPolygon" /> class.</param>
/// <param name="filename">The path of the file to save.</param>
public static void Write(IPolygon polygon, string filename)
{
+3
View File
@@ -18,6 +18,9 @@ namespace TriangleNet.IO
internal int label;
internal double area;
/// <summary>
/// Initializes a new instance of the <see cref="InputTriangle" /> class.
/// </summary>
public InputTriangle(int p0, int p1, int p2)
{
vertices = new int[] { p0, p1, p2 };
+11
View File
@@ -17,6 +17,11 @@ namespace TriangleNet.IO
/// </summary>
public class TriangleFormat : IPolygonFormat, IMeshFormat
{
/// <summary>
/// Returns a value indicating whether the given file is supported by this format.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public bool IsSupported(string file)
{
string ext = Path.GetExtension(file).ToLower();
@@ -29,6 +34,7 @@ namespace TriangleNet.IO
return false;
}
/// <inheritdoc />
public IMesh Import(string filename)
{
string ext = Path.GetExtension(filename);
@@ -49,6 +55,7 @@ namespace TriangleNet.IO
throw new NotSupportedException("Could not load '" + filename + "' file.");
}
/// <inheritdoc />
public void Write(IMesh mesh, string filename)
{
var writer = new TriangleWriter();
@@ -57,11 +64,13 @@ namespace TriangleNet.IO
writer.WriteElements((Mesh)mesh, Path.ChangeExtension(filename, ".ele"));
}
/// <inheritdoc />
public void Write(IMesh mesh, Stream stream)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public IPolygon Read(string filename)
{
string ext = Path.GetExtension(filename);
@@ -79,11 +88,13 @@ namespace TriangleNet.IO
}
/// <inheritdoc />
public void Write(IPolygon polygon, string filename)
{
(new TriangleWriter()).WritePoly(polygon, filename);
}
/// <inheritdoc />
public void Write(IPolygon polygon, Stream stream)
{
throw new NotImplementedException();
+1 -2
View File
@@ -267,7 +267,7 @@ namespace TriangleNet.IO
/// </summary>
/// <param name="polyfilename"></param>
/// <param name="readElements">If true, look for an associated .ele file.</param>
/// <param name="readElements">If true, look for an associated .area file.</param>
/// <param name="readArea">If true, look for an associated .area file.</param>
public Polygon ReadPolyFile(string polyfilename, bool readElements, bool readArea)
{
// Read poly file
@@ -603,7 +603,6 @@ namespace TriangleNet.IO
/// </summary>
/// <param name="areafilename"></param>
/// <param name="intriangles"></param>
/// <param name="data"></param>
private double[] ReadAreaFile(string areafilename, int intriangles)
{
double[] data = null;
+4 -1
View File
@@ -100,8 +100,11 @@ namespace TriangleNet.IO
/// <summary>
/// Write the vertices to a stream.
/// </summary>
/// <param name="nodes"></param>
/// <param name="writer"></param>
/// <param name="nodes"></param>
/// <param name="markers"></param>
/// <param name="attribs"></param>
/// <param name="jettison"></param>
private void WriteNodes(StreamWriter writer, IEnumerable<Vertex> nodes, bool markers,
int attribs, bool jettison)
{
+54
View File
@@ -3,14 +3,68 @@ namespace TriangleNet
{
using TriangleNet.Geometry;
/// <summary>
/// Geometric predicates interface.
/// </summary>
public interface IPredicates
{
/// <summary>
/// Check, if the three points appear in counterclockwise order. The result is
/// also a rough approximation of twice the signed area of the triangle defined
/// by the three points.
/// </summary>
/// <param name="a">Point a.</param>
/// <param name="b">Point b.</param>
/// <param name="c">Point c.</param>
/// <returns>Return a positive value if the points pa, pb, and pc occur in
/// counterclockwise order; a negative value if they occur in clockwise order;
/// and zero if they are collinear.</returns>
double CounterClockwise(Point a, Point b, Point c);
/// <summary>
/// Check if the point pd lies inside the circle passing through pa, pb, and pc. The
/// points pa, pb, and pc must be in counterclockwise order, or the sign of the result
/// will be reversed.
/// </summary>
/// <param name="a">Point a.</param>
/// <param name="b">Point b.</param>
/// <param name="c">Point c.</param>
/// <param name="p">Point d.</param>
/// <returns>Return a positive value if the point pd lies inside the circle passing through
/// pa, pb, and pc; a negative value if it lies outside; and zero if the four points
/// are cocircular.</returns>
double InCircle(Point a, Point b, Point c, Point p);
/// <summary>
/// Find the circumcenter of a triangle.
/// </summary>
/// <param name="org">Triangle point.</param>
/// <param name="dest">Triangle point.</param>
/// <param name="apex">Triangle point.</param>
/// <param name="xi">Relative coordinate of new location.</param>
/// <param name="eta">Relative coordinate of new location.</param>
/// <returns>Coordinates of the circumcenter</returns>
/// <remarks>
/// The result is returned both in terms of x-y coordinates and xi-eta
/// (barycentric) coordinates. The xi-eta coordinate system is defined in
/// terms of the triangle: the origin of the triangle is the origin of the
/// coordinate system; the destination of the triangle is one unit along the
/// xi axis; and the apex of the triangle is one unit along the eta axis.
/// This procedure also returns the square of the length of the triangle's
/// shortest edge.
/// </remarks>
Point FindCircumcenter(Point org, Point dest, Point apex, ref double xi, ref double eta);
/// <summary>
/// Find the circumcenter of a triangle.
/// </summary>
/// <param name="org">Triangle point.</param>
/// <param name="dest">Triangle point.</param>
/// <param name="apex">Triangle point.</param>
/// <param name="xi">Relative coordinate of new location.</param>
/// <param name="eta">Relative coordinate of new location.</param>
/// <param name="offconstant">Off-center constant.</param>
/// <returns>Coordinates of the circumcenter (or off-center)</returns>
Point FindCircumcenter(Point org, Point dest, Point apex, ref double xi, ref double eta,
double offconstant);
}
+8 -7
View File
@@ -9,6 +9,9 @@ namespace TriangleNet
using System;
using System.Collections.Generic;
/// <summary>
/// The log level.
/// </summary>
public enum LogLevel { Info, Warning, Error }
/// <summary>
@@ -68,6 +71,7 @@ namespace TriangleNet
/// <summary>
/// A simple logger, which logs messages to a List.
/// </summary>
public sealed class Log
{
/// <summary>
@@ -95,13 +99,10 @@ namespace TriangleNet
private Log() { }
public static Log Instance
{
get
{
return instance;
}
}
/// <summary>
/// Gets the <see cref="Log"/> instance.
/// </summary>
public static Log Instance => instance;
#endregion
+57 -54
View File
@@ -219,6 +219,11 @@ namespace TriangleNet
TransferNodes(points);
}
/// <summary>
/// Refine the mesh to match given quality options.
/// </summary>
/// <param name="quality">The quality constraints.</param>
/// <param name="delaunay">A value indicating, whether the refined mesh should be Conforming Delaunay.</param>
public void Refine(QualityOptions quality, bool delaunay = false)
{
invertices = vertices.Count;
@@ -319,10 +324,8 @@ namespace TriangleNet
target.hullsize = this.hullsize;
}
/// <summary>
/// Reset all the mesh data. This method will also wipe
/// out all mesh data.
/// </summary>
// TODO: Remove unused method.
private void ResetData()
{
vertices.Clear();
@@ -369,7 +372,7 @@ namespace TriangleNet
/// <summary>
/// Read the vertices from memory.
/// </summary>
/// <param name="data">The input data.</param>
/// <param name="points">The input data.</param>
private void TransferNodes(IList<Vertex> points)
{
invertices = points.Count;
@@ -1392,55 +1395,55 @@ namespace TriangleNet
/// <param name="triflaws">A flag that determines whether the new triangles should
/// be tested for quality, and enqueued if they are bad.</param>
/// <remarks>
// This is a conceptually difficult routine. The starting assumption is
// that we have a polygon with n sides. n - 1 of these sides are currently
// represented as edges in the mesh. One side, called the "base", need not
// be.
//
// Inside the polygon is a structure I call a "fan", consisting of n - 1
// triangles that share a common origin. For each of these triangles, the
// edge opposite the origin is one of the sides of the polygon. The
// primary edge of each triangle is the edge directed from the origin to
// the destination; note that this is not the same edge that is a side of
// the polygon. 'firstedge' is the primary edge of the first triangle.
// From there, the triangles follow in counterclockwise order about the
// polygon, until 'lastedge', the primary edge of the last triangle.
// 'firstedge' and 'lastedge' are probably connected to other triangles
// beyond the extremes of the fan, but their identity is not important, as
// long as the fan remains connected to them.
//
// Imagine the polygon oriented so that its base is at the bottom. This
// puts 'firstedge' on the far right, and 'lastedge' on the far left.
// The right vertex of the base is the destination of 'firstedge', and the
// left vertex of the base is the apex of 'lastedge'.
//
// The challenge now is to find the right sequence of edge flips to
// transform the fan into a Delaunay triangulation of the polygon. Each
// edge flip effectively removes one triangle from the fan, committing it
// to the polygon. The resulting polygon has one fewer edge. If 'doflip'
// is set, the final flip will be performed, resulting in a fan of one
// (useless?) triangle. If 'doflip' is not set, the final flip is not
// performed, resulting in a fan of two triangles, and an unfinished
// triangular polygon that is not yet filled out with a single triangle.
// On completion of the routine, 'lastedge' is the last remaining triangle,
// or the leftmost of the last two.
//
// Although the flips are performed in the order described above, the
// decisions about what flips to perform are made in precisely the reverse
// order. The recursive triangulatepolygon() procedure makes a decision,
// uses up to two recursive calls to triangulate the "subproblems"
// (polygons with fewer edges), and then performs an edge flip.
//
// The "decision" it makes is which vertex of the polygon should be
// connected to the base. This decision is made by testing every possible
// vertex. Once the best vertex is found, the two edges that connect this
// vertex to the base become the bases for two smaller polygons. These
// are triangulated recursively. Unfortunately, this approach can take
// O(n^2) time not only in the worst case, but in many common cases. It's
// rarely a big deal for vertex deletion, where n is rarely larger than
// ten, but it could be a big deal for segment insertion, especially if
// there's a lot of long segments that each cut many triangles. I ought to
// code a faster algorithm some day.
/// This is a conceptually difficult routine. The starting assumption is
/// that we have a polygon with n sides. n - 1 of these sides are currently
/// represented as edges in the mesh. One side, called the "base", need not
/// be.
///
/// Inside the polygon is a structure I call a "fan", consisting of n - 1
/// triangles that share a common origin. For each of these triangles, the
/// edge opposite the origin is one of the sides of the polygon. The
/// primary edge of each triangle is the edge directed from the origin to
/// the destination; note that this is not the same edge that is a side of
/// the polygon. 'firstedge' is the primary edge of the first triangle.
/// From there, the triangles follow in counterclockwise order about the
/// polygon, until 'lastedge', the primary edge of the last triangle.
/// 'firstedge' and 'lastedge' are probably connected to other triangles
/// beyond the extremes of the fan, but their identity is not important, as
/// long as the fan remains connected to them.
///
/// Imagine the polygon oriented so that its base is at the bottom. This
/// puts 'firstedge' on the far right, and 'lastedge' on the far left.
/// The right vertex of the base is the destination of 'firstedge', and the
/// left vertex of the base is the apex of 'lastedge'.
///
/// The challenge now is to find the right sequence of edge flips to
/// transform the fan into a Delaunay triangulation of the polygon. Each
/// edge flip effectively removes one triangle from the fan, committing it
/// to the polygon. The resulting polygon has one fewer edge. If 'doflip'
/// is set, the final flip will be performed, resulting in a fan of one
/// (useless?) triangle. If 'doflip' is not set, the final flip is not
/// performed, resulting in a fan of two triangles, and an unfinished
/// triangular polygon that is not yet filled out with a single triangle.
/// On completion of the routine, 'lastedge' is the last remaining triangle,
/// or the leftmost of the last two.
///
/// Although the flips are performed in the order described above, the
/// decisions about what flips to perform are made in precisely the reverse
/// order. The recursive triangulatepolygon() procedure makes a decision,
/// uses up to two recursive calls to triangulate the "subproblems"
/// (polygons with fewer edges), and then performs an edge flip.
///
/// The "decision" it makes is which vertex of the polygon should be
/// connected to the base. This decision is made by testing every possible
/// vertex. Once the best vertex is found, the two edges that connect this
/// vertex to the base become the bases for two smaller polygons. These
/// are triangulated recursively. Unfortunately, this approach can take
/// O(n^2) time not only in the worst case, but in many common cases. It's
/// rarely a big deal for vertex deletion, where n is rarely larger than
/// ten, but it could be a big deal for segment insertion, especially if
/// there's a lot of long segments that each cut many triangles. I ought to
/// code a faster algorithm some day.
/// </remarks>
private void TriangulatePolygon(Otri firstedge, Otri lastedge,
int edgecount, bool doflip, bool triflaws)
+3
View File
@@ -14,6 +14,9 @@ namespace TriangleNet
using TriangleNet.Tools;
using TriangleNet.Topology;
/// <summary>
/// Mesh validation helper.
/// </summary>
public static class MeshValidator
{
private static RobustPredicates predicates = RobustPredicates.Default;
+1 -1
View File
@@ -57,7 +57,7 @@ namespace TriangleNet.Meshing.Algorithm
Mesh mesh;
/// <summary>
/// Form a Delaunay triangulation by the divide-and-conquer method.
/// Compute a Delaunay triangulation by the divide-and-conquer method.
/// </summary>
/// <returns></returns>
/// <remarks>
@@ -19,10 +19,9 @@ namespace TriangleNet.Meshing.Algorithm
Mesh mesh;
/// <summary>
/// Form a Delaunay triangulation by incrementally inserting vertices.
/// Compute a Delaunay triangulation by incrementally inserting vertices.
/// </summary>
/// <returns>Returns the number of edges on the convex hull of the
/// triangulation.</returns>
/// <returns></returns>
public IMesh Triangulate(IList<Vertex> points, Configuration config)
{
mesh = new Mesh(config, points);
@@ -33,6 +33,9 @@ namespace TriangleNet.Meshing.Algorithm
double xminextreme; // Nonexistent x value used as a flag in sweepline.
List<SplayNode> splaynodes;
/// <summary>
/// Compute a Delaunay triangulation by the sweepline method.
/// </summary>
public IMesh Triangulate(IList<Vertex> points, Configuration config)
{
predicates = config.Predicates();
+5
View File
@@ -351,6 +351,11 @@ namespace TriangleNet.Meshing
#region DCEL conversion
/// <summary>
/// Convert the triangle mesh topology to DCEL.
/// </summary>
/// <param name="mesh"></param>
/// <returns></returns>
public DcelMesh ToDCEL(Mesh mesh)
{
var dcel = new DcelMesh();
+3 -3
View File
@@ -14,9 +14,9 @@ namespace TriangleNet.Meshing.Data
/// A (priority) queue for bad triangles.
/// </summary>
/// <remarks>
// The queue is actually a set of 4096 queues. I use multiple queues to
// give priority to smaller angles. I originally implemented a heap, but
// the queues are faster by a larger margin than I'd suspected.
/// The queue is actually a set of 4096 queues. I use multiple queues to
/// give priority to smaller angles. I originally implemented a heap, but
/// the queues are faster by a larger margin than I'd suspected.
/// </remarks>
class BadTriQueue
{
+19
View File
@@ -15,26 +15,45 @@ namespace TriangleNet.Meshing
/// <summary>
/// Create meshes of point sets or polygons.
/// </summary>
/// <remarks>
/// If not specified otherwise, the default triangulation algorithm used is <see cref="Dwyer" />.
/// </remarks>
public class GenericMesher
{
Configuration config;
ITriangulator triangulator;
/// <summary>
/// Initializes a new instance of the <see cref="GenericMesher" /> class.
/// </summary>
public GenericMesher()
: this(new Dwyer(), new Configuration())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericMesher" /> class.
/// </summary>
/// <param name="triangulator">The <see cref="ITriangulator" /> algorithm implementation.</param>
public GenericMesher(ITriangulator triangulator)
: this(triangulator, new Configuration())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericMesher" /> class.
/// </summary>
/// <param name="config">The <see cref="Configuration" />.</param>
public GenericMesher(Configuration config)
: this(new Dwyer(), config)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GenericMesher" /> class.
/// </summary>
/// <param name="triangulator">The <see cref="ITriangulator" /> algorithm implementation.</param>
/// <param name="config">The <see cref="Configuration" />.</param>
public GenericMesher(ITriangulator triangulator, Configuration config)
{
this.config = config;
+1 -1
View File
@@ -49,7 +49,7 @@ namespace TriangleNet.Meshing
/// Refine the mesh.
/// </summary>
/// <param name="quality">The quality constraints.</param>
/// <param name="conforming">
/// <param name="delaunay">
/// A value indicating, if the refined mesh should be Conforming Delaunay.
/// </param>
void Refine(QualityOptions quality, bool delaunay);
@@ -15,6 +15,11 @@ namespace TriangleNet.Meshing.Iterators
/// </summary>
public class EdgeIterator
{
/// <summary>
/// Enumerate all edges of the given mesh.
/// </summary>
/// <param name="mesh"></param>
/// <returns></returns>
public IEnumerable<Edge> EnumerateEdges(IMesh mesh)
{
Otri tri = default;
@@ -51,7 +56,7 @@ namespace TriangleNet.Meshing.Iterators
}
/// <summary>
/// Enumerate the edges of the mesh.
/// Enumerate all edges of the given mesh.
/// </summary>
/// <param name="mesh"></param>
/// <param name="skipSegments"></param>
@@ -22,6 +22,9 @@ namespace TriangleNet.Meshing.Iterators
{
List<Triangle> region;
/// <summary>
/// Initializes a new instance of the <see cref="RegionIterator" /> class.
/// </summary>
public RegionIterator(Mesh mesh)
{
this.region = new List<Triangle>();
@@ -10,10 +10,16 @@ namespace TriangleNet.Meshing.Iterators
using TriangleNet.Geometry;
using TriangleNet.Topology;
/// <summary>
/// Vertex circulator to enumerate the vertices connected to a mesh vertex.
/// </summary>
public class VertexCirculator
{
List<Otri> cache = new List<Otri>();
/// <summary>
/// Initializes a new instance of the <see cref="VertexCirculator" /> class.
/// </summary>
public VertexCirculator(Mesh mesh)
{
mesh.MakeVertexMap();
+1 -1
View File
@@ -52,7 +52,7 @@ namespace TriangleNet.Meshing
/// Apply quality constraints to a mesh.
/// </summary>
/// <param name="quality">The quality constraints.</param>
/// <param name="delaunay">A value indicating, if the refined mesh should be Conforming Delaunay.</param>
/// <param name="delaunay">A value indicating, whether the refined mesh should be Conforming Delaunay.</param>
public void Apply(QualityOptions quality, bool delaunay = false)
{
// Copy quality options
File diff suppressed because it is too large Load Diff
+7 -51
View File
@@ -121,22 +121,15 @@ namespace TriangleNet
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="RobustPredicates" /> class.
/// </summary>
public RobustPredicates()
{
AllocateWorkspace();
}
/// <summary>
/// Check, if the three points appear in counterclockwise order. The result is
/// also a rough approximation of twice the signed area of the triangle defined
/// by the three points.
/// </summary>
/// <param name="pa">Point a.</param>
/// <param name="pb">Point b.</param>
/// <param name="pc">Point c.</param>
/// <returns>Return a positive value if the points pa, pb, and pc occur in
/// counterclockwise order; a negative value if they occur in clockwise order;
/// and zero if they are collinear.</returns>
/// <inheritdoc/>
public double CounterClockwise(Point pa, Point pb, Point pc)
{
double detleft, detright, det;
@@ -190,18 +183,7 @@ namespace TriangleNet
return CounterClockwiseAdapt(pa, pb, pc, detsum);
}
/// <summary>
/// Check if the point pd lies inside the circle passing through pa, pb, and pc. The
/// points pa, pb, and pc must be in counterclockwise order, or the sign of the result
/// will be reversed.
/// </summary>
/// <param name="pa">Point a.</param>
/// <param name="pb">Point b.</param>
/// <param name="pc">Point c.</param>
/// <param name="pd">Point d.</param>
/// <returns>Return a positive value if the point pd lies inside the circle passing through
/// pa, pb, and pc; a negative value if it lies outside; and zero if the four points
/// are cocircular.</returns>
/// <inheritdoc/>
public double InCircle(Point pa, Point pb, Point pc, Point pd)
{
double adx, bdx, cdx, ady, bdy, cdy;
@@ -273,16 +255,7 @@ namespace TriangleNet
return InCircle(pa, pb, pc, pd);
}
/// <summary>
/// Find the circumcenter of a triangle.
/// </summary>
/// <param name="org">Triangle point.</param>
/// <param name="dest">Triangle point.</param>
/// <param name="apex">Triangle point.</param>
/// <param name="xi">Relative coordinate of new location.</param>
/// <param name="eta">Relative coordinate of new location.</param>
/// <param name="offconstant">Off-center constant.</param>
/// <returns>Coordinates of the circumcenter (or off-center)</returns>
/// <inheritdoc/>
public Point FindCircumcenter(Point org, Point dest, Point apex,
ref double xi, ref double eta, double offconstant)
{
@@ -384,24 +357,7 @@ namespace TriangleNet
return new Point(org.x + dx, org.y + dy);
}
/// <summary>
/// Find the circumcenter of a triangle.
/// </summary>
/// <param name="org">Triangle point.</param>
/// <param name="dest">Triangle point.</param>
/// <param name="apex">Triangle point.</param>
/// <param name="xi">Relative coordinate of new location.</param>
/// <param name="eta">Relative coordinate of new location.</param>
/// <returns>Coordinates of the circumcenter</returns>
/// <remarks>
/// The result is returned both in terms of x-y coordinates and xi-eta
/// (barycentric) coordinates. The xi-eta coordinate system is defined in
/// terms of the triangle: the origin of the triangle is the origin of the
/// coordinate system; the destination of the triangle is one unit along the
/// xi axis; and the apex of the triangle is one unit along the eta axis.
/// This procedure also returns the square of the length of the triangle's
/// shortest edge.
/// </remarks>
/// <inheritdoc/>
public Point FindCircumcenter(Point org, Point dest, Point apex,
ref double xi, ref double eta)
{
+13
View File
@@ -46,6 +46,10 @@ namespace TriangleNet.Tools
get { return irow; }
}
/// <summary>
/// Initializes a new instance of the <see cref="AdjacencyMatrix" /> class.
/// </summary>
/// <param name="mesh">The mesh.</param>
public AdjacencyMatrix(Mesh mesh)
{
this.N = mesh.vertices.Count;
@@ -60,6 +64,12 @@ namespace TriangleNet.Tools
SortIndices();
}
/// <summary>
/// Initializes a new instance of the <see cref="AdjacencyMatrix" /> class.
/// </summary>
/// <param name="pcol">The column pointers.</param>
/// <param name="irow">The row indices.</param>
/// <exception cref="ArgumentException"></exception>
public AdjacencyMatrix(int[] pcol, int[] irow)
{
this.N = pcol.Length - 1;
@@ -265,6 +275,9 @@ namespace TriangleNet.Tools
return list;
}
/// <summary>
/// Sort indices.
/// </summary>
public void SortIndices()
{
int k1, k2, n = N;
+11 -11
View File
@@ -34,7 +34,7 @@ namespace TriangleNet.Tools
/// <summary>
/// Gets the permutation vector for the Reverse Cuthill-McKee numbering.
/// </summary>
/// <param name="mesh">The mesh.</param>
/// <param name="matrix">The adjacency matrix.</param>
/// <returns>Permutation vector.</returns>
public int[] Renumber(AdjacencyMatrix matrix)
{
@@ -89,11 +89,11 @@ namespace TriangleNet.Tools
int iccsze = 0;
int level_num = 0;
/// Index vector for a level structure. The level structure is stored in the
/// currently unused spaces in the permutation vector PERM.
// Index vector for a level structure. The level structure is stored in the
// currently unused spaces in the permutation vector PERM.
int[] level_row = new int[n + 1];
/// Marks variables that have been numbered.
// Marks variables that have been numbered.
int[] mask = new int[n];
for (i = 0; i < n; i++)
@@ -139,8 +139,8 @@ namespace TriangleNet.Tools
/// nonzero input mask values are considered by the routine. The nodes numbered by RCM will have
/// their mask values set to zero.</param>
/// <param name="perm">Output, int PERM(NODE_NUM), the RCM ordering.</param>
/// <param name="offset">Internal array offset.</param>
/// <param name="iccsze">Output, int ICCSZE, the size of the connected component that has been numbered.</param>
/// <param name="node_num">the number of nodes.</param>
/// <remarks>
/// The connected component is specified by a node ROOT and a mask.
/// The numbering starts at the root node.
@@ -169,8 +169,8 @@ namespace TriangleNet.Tools
// Number of nodes in the mesh.
int n = matrix.N;
/// Workspace, int DEG[NODE_NUM], a temporary vector used to hold
/// the degree of the nodes in the section graph specified by mask and root.
// Workspace, int DEG[NODE_NUM], a temporary vector used to hold
// the degree of the nodes in the section graph specified by mask and root.
int[] deg = new int[n];
// Find the degrees of the nodes in the component specified by MASK and ROOT.
@@ -269,7 +269,7 @@ namespace TriangleNet.Tools
/// containing the level structure found.</param>
/// <param name="level">Output, int LEVEL(NODE_NUM), the level structure array pair
/// containing the level structure found.</param>
/// <param name="node_num">the number of nodes.</param>
/// <param name="offset">Internal array offset.</param>
/// <remarks>
/// The diameter of a graph is the maximum distance (number of edges)
/// between any two nodes of the graph.
@@ -409,7 +409,7 @@ namespace TriangleNet.Tools
/// in level 1. The neighbors of ROOT are in level 2, and so on.</param>
/// <param name="level_row">Output, int LEVEL_ROW[NODE_NUM+1], the rooted level structure.</param>
/// <param name="level">Output, int LEVEL[NODE_NUM], the rooted level structure.</param>
/// <param name="node_num">the number of nodes.</param>
/// <param name="offset">Internal array offset.</param>
/// <remarks>
/// Only nodes for which MASK is nonzero will be considered.
///
@@ -502,7 +502,7 @@ namespace TriangleNet.Tools
/// <param name="iccsze">Output, int ICCSIZE, the number of nodes in the connected component.</param>
/// <param name="ls">Output, int LS[NODE_NUM], stores in entries 1 through ICCSIZE the nodes in the
/// connected component, starting with ROOT, and proceeding by levels.</param>
/// <param name="node_num">the number of nodes.</param>
/// <param name="offset">Internal array offset.</param>
/// <remarks>
/// The connected component is specified by MASK and ROOT.
/// Nodes for which MASK is zero are ignored.
@@ -621,7 +621,6 @@ namespace TriangleNet.Tools
/// <summary>
/// Produces the inverse of a given permutation.
/// </summary>
/// <param name="n">Number of items permuted.</param>
/// <param name="perm">PERM[N], a permutation.</param>
/// <returns>The inverse permutation.</returns>
int[] PermInverse(int[] perm)
@@ -642,6 +641,7 @@ namespace TriangleNet.Tools
/// Reverses the elements of an integer vector.
/// </summary>
/// <param name="size">number of entries in the array.</param>
/// <param name="offset">Internal array offset.</param>
/// <param name="a">the array to be reversed.</param>
/// <example>
/// Input:
+3
View File
@@ -9,6 +9,9 @@ namespace TriangleNet.Tools
{
using TriangleNet.Geometry;
/// <summary>
/// Interpolation helper.
/// </summary>
public static class Interpolation
{
/// <summary>
+3
View File
@@ -9,6 +9,9 @@ namespace TriangleNet.Tools
using System;
using TriangleNet.Geometry;
/// <summary>
/// Segment intersection helper.
/// </summary>
public static class IntersectionHelper
{
/// <summary>
+3
View File
@@ -10,6 +10,9 @@ namespace TriangleNet.Tools
using System.Collections.Generic;
using TriangleNet.Geometry;
/// <summary>
/// Polygon validation helper.
/// </summary>
public static class PolygonValidator
{
/// <summary>
+6
View File
@@ -59,6 +59,9 @@ namespace TriangleNet.Tools
Mesh mesh;
/// <summary>
/// Initializes a new instance of the <see cref="QualityMeasure" /> class.
/// </summary>
public QualityMeasure()
{
areaMeasure = new AreaMeasure();
@@ -158,6 +161,9 @@ namespace TriangleNet.Tools
#endregion
/// <summary>
/// Update all quality measures.
/// </summary>
public void Update(Mesh mesh)
{
this.mesh = mesh;
+10
View File
@@ -22,12 +22,20 @@ namespace TriangleNet.Tools
/// Number of incircle tests performed.
/// </summary>
public static long InCircleCount = 0;
/// <summary>
/// Number of adaptive incircle tests performed.
/// </summary>
public static long InCircleAdaptCount = 0;
/// <summary>
/// Number of counterclockwise tests performed.
/// </summary>
public static long CounterClockwiseCount = 0;
/// <summary>
/// Number of adaptive counterclockwise tests performed.
/// </summary>
public static long CounterClockwiseAdaptCount = 0;
/// <summary>
@@ -201,6 +209,8 @@ namespace TriangleNet.Tools
/// Update statistics about the quality of the mesh.
/// </summary>
/// <param name="mesh"></param>
/// <param name="sampleDegrees">Number of degrees to sample
/// (currently fixed to 60 = sample every 3 degrees).</param>
public void Update(Mesh mesh, int sampleDegrees)
{
Point[] p = new Point[3];
+6
View File
@@ -50,6 +50,12 @@ namespace TriangleNet.Tools
root.CreateSubRegion(++currentDepth);
}
/// <summary>
/// Query the quadtree a given point.
/// </summary>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <returns></returns>
public ITriangle Query(double x, double y)
{
var point = new Point(x, y);
+9 -1
View File
@@ -9,10 +9,18 @@ namespace TriangleNet.Topology.DCEL
using System.Collections.Generic;
using TriangleNet.Geometry;
/// <summary>
/// DCEL mesh.
/// </summary>
public class DcelMesh
{
/// <summary>List of vertices.</summary>
protected List<Vertex> vertices;
/// <summary>List of half-edges.</summary>
protected List<HalfEdge> edges;
/// <summary>List of faces.</summary>
protected List<Face> faces;
/// <summary>
@@ -24,7 +32,7 @@ namespace TriangleNet.Topology.DCEL
}
/// <summary>
/// Initializes a new instance of the <see cref="" /> class.
/// Initializes a new instance of the <see cref="DcelMesh" /> class.
/// </summary>
/// <param name="initialize">If false, lists will not be initialized.</param>
protected DcelMesh(bool initialize)
+5 -1
View File
@@ -10,12 +10,15 @@ namespace TriangleNet.Topology.DCEL
using TriangleNet.Geometry;
/// <summary>
/// A face of DCEL mesh.
/// A face of the DCEL datastructure.
/// </summary>
public class Face
{
#region Static initialization of "Outer Space" face
/// <summary>
/// A face representing "outer space".
/// </summary>
public static readonly Face Empty;
static Face()
@@ -105,6 +108,7 @@ namespace TriangleNet.Topology.DCEL
} while (edge.ID != first);
}
/// <inheritdoc />
public override string ToString()
{
return string.Format("F-ID {0}", id);
+7
View File
@@ -6,6 +6,9 @@
namespace TriangleNet.Topology.DCEL
{
/// <summary>
/// A half-edge of the DCEL datastructure.
/// </summary>
public class HalfEdge
{
internal int id;
@@ -25,6 +28,9 @@ namespace TriangleNet.Topology.DCEL
set { id = value; }
}
/// <summary>
/// Gets or sets a boundary marker.
/// </summary>
public int Boundary
{
get { return mark; }
@@ -93,6 +99,7 @@ namespace TriangleNet.Topology.DCEL
}
}
/// <inheritdoc />
public override string ToString()
{
return string.Format("HE-ID {0} (Origin = VID-{1})", id, origin.id);
+4
View File
@@ -8,6 +8,9 @@ namespace TriangleNet.Topology.DCEL
{
using System.Collections.Generic;
/// <summary>
/// A vertex of the DCEL datastructure.
/// </summary>
public class Vertex : TriangleNet.Geometry.Point
{
internal HalfEdge leaving;
@@ -60,6 +63,7 @@ namespace TriangleNet.Topology.DCEL
} while (edge.ID != first);
}
/// <inheritdoc />
public override string ToString()
{
return string.Format("V-ID {0}", base.id);
+5 -4
View File
@@ -23,11 +23,12 @@ namespace TriangleNet.Topology
internal SubSegment seg;
internal int orient; // Ranges from 0 to 1.
public SubSegment Segment
{
get { return seg; }
}
/// <summary>
/// Gets the subsegment.
/// </summary>
public SubSegment Segment => seg;
/// <inheritdoc />
public override string ToString()
{
if (seg == null)
+5
View File
@@ -23,12 +23,16 @@ namespace TriangleNet.Topology
internal Triangle tri;
internal int orient; // Ranges from 0 to 2.
/// <summary>
/// Gets or sets the triangle.
/// </summary>
public Triangle Triangle
{
get { return tri; }
set { tri = value; }
}
/// <inheritdoc />
public override string ToString()
{
if (tri == null)
@@ -77,6 +81,7 @@ namespace TriangleNet.Topology
/// <summary>
/// Find the abutting triangle; same edge. [sym(abc) -> ba*]
/// </summary>
/// <remarks>
/// Note that the edge direction is necessarily reversed, because the handle specified
/// by an oriented triangle is directed counterclockwise around the triangle.
/// </remarks>
+5
View File
@@ -23,6 +23,9 @@ namespace TriangleNet.Topology
internal Otri[] triangles;
internal int boundary;
/// <summary>
/// Initializes a new instance of the <see cref="SubSegment" /> class.
/// </summary>
public SubSegment()
{
// Four NULL vertices.
@@ -83,11 +86,13 @@ namespace TriangleNet.Topology
return triangles[index].tri.hash == Mesh.DUMMY ? null : triangles[index].tri;
}
/// <inheritdoc />
public override int GetHashCode()
{
return this.hash;
}
/// <inheritdoc />
public override string ToString()
{
return String.Format("SID {0}", hash);
+9
View File
@@ -77,11 +77,18 @@ namespace TriangleNet.Topology
/// <summary>
/// Gets the specified corners vertex.
/// </summary>
/// <param name="index">The corner index (0, 1 or 2).</param>
/// <returns></returns>
public Vertex GetVertex(int index)
{
return this.vertices[index]; // TODO: Check range?
}
/// <summary>
/// Gets the specified corners vertex id.
/// </summary>
/// <param name="index">The corner index (0, 1 or 2).</param>
/// <returns></returns>
public int GetVertexID(int index)
{
return this.vertices[index].id;
@@ -115,11 +122,13 @@ namespace TriangleNet.Topology
#endregion
/// <inheritdoc />
public override int GetHashCode()
{
return this.hash;
}
/// <inheritdoc />
public override string ToString()
{
return String.Format("TID {0}", hash);
+12 -2
View File
@@ -32,12 +32,21 @@ namespace TriangleNet
// Pointer to a recently visited triangle. Improves point location if
// proximate vertices are inserted sequentially.
internal Otri recenttri;
/// <summary>
/// Initializes a new instance of the <see cref="TriangleLocator" /> class.
/// </summary>
/// <param name="mesh">The mesh.</param>
public TriangleLocator(Mesh mesh)
: this(mesh, RobustPredicates.Default)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TriangleLocator" /> class.
/// </summary>
/// <param name="mesh">The mesh.</param>
/// <param name="predicates">The predicates.</param>
public TriangleLocator(Mesh mesh, IPredicates predicates)
{
this.mesh = mesh;
@@ -55,7 +64,8 @@ namespace TriangleNet
otri.Copy(ref recenttri);
}
public void Reset()
// TODO: Remove unused method.
internal void Reset()
{
sampler.Reset();
recenttri.tri = null; // No triangle has been visited yet.
+24 -9
View File
@@ -10,6 +10,9 @@ namespace TriangleNet
using System.Collections.Generic;
using TriangleNet.Topology;
/// <summary>
/// Pool datastructure storing triangles of a <see cref="Mesh" />.
/// </summary>
public class TrianglePool : ICollection<Triangle>
{
// Determines the size of each block in the pool.
@@ -32,6 +35,9 @@ namespace TriangleNet
/// </summary>
public int Capacity => size;
/// <summary>
/// Initializes a new instance of the <see cref="TrianglePool" /> class.
/// </summary>
public TrianglePool()
{
size = 0;
@@ -97,6 +103,9 @@ namespace TriangleNet
return triangle;
}
/// <summary>
/// Release triangle (making it a free triangle).
/// </summary>
public void Release(Triangle triangle)
{
stack.Push(triangle);
@@ -172,11 +181,17 @@ namespace TriangleNet
}
}
/// <summary>
/// Not supported for this <see cref="ICollection{Triangle}" />.
/// </summary>
public void Add(Triangle item)
{
throw new NotImplementedException();
throw new NotSupportedException();
}
/// <summary>
/// Clear the pool.
/// </summary>
public void Clear()
{
stack.Clear();
@@ -199,6 +214,7 @@ namespace TriangleNet
size = count = 0;
}
/// <inheritdoc />
public bool Contains(Triangle item)
{
int i = item.hash;
@@ -211,6 +227,7 @@ namespace TriangleNet
return pool[i / BLOCKSIZE][i % BLOCKSIZE].hash >= 0;
}
/// <inheritdoc />
public void CopyTo(Triangle[] array, int index)
{
var enumerator = GetEnumerator();
@@ -222,21 +239,19 @@ namespace TriangleNet
}
}
public int Count
{
get { return count - stack.Count; }
}
/// <inheritdoc />
public int Count => count - stack.Count;
public bool IsReadOnly
{
get { return true; }
}
/// <inheritdoc />
public bool IsReadOnly => true;
/// <inheritdoc />
public bool Remove(Triangle item)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public IEnumerator<Triangle> GetEnumerator()
{
return new Enumerator(this);
+13
View File
@@ -12,15 +12,28 @@ namespace TriangleNet.Voronoi
using TVertex = TriangleNet.Geometry.Vertex;
/// <summary>
/// Computing the bounded Voronoi diagram of a constrained and conforming Delaunay triangulation.
/// </summary>
public class BoundedVoronoi : VoronoiBase
{
int offset;
/// <summary>
/// Initializes a new instance of the <see cref="StandardVoronoi" /> class.
/// </summary>
/// <param name="mesh">The mesh.</param>
public BoundedVoronoi(Mesh mesh)
: this(mesh, new DefaultVoronoiFactory(), RobustPredicates.Default)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="StandardVoronoi" /> class.
/// </summary>
/// <param name="mesh">The mesh.</param>
/// <param name="factory"></param>
/// <param name="predicates"></param>
public BoundedVoronoi(Mesh mesh, IVoronoiFactory factory, IPredicates predicates)
: base(mesh, factory, predicates, true)
{
@@ -9,24 +9,29 @@ namespace TriangleNet.Voronoi
/// </summary>
public class DefaultVoronoiFactory : IVoronoiFactory
{
/// <inheritdoc />
public void Initialize(int vertexCount, int edgeCount, int faceCount)
{
}
/// <inheritdoc />
public void Reset()
{
}
/// <inheritdoc />
public Vertex CreateVertex(double x, double y)
{
return new Vertex(x, y);
}
/// <inheritdoc />
public HalfEdge CreateHalfEdge(Vertex origin, Face face)
{
return new HalfEdge(origin, face);
}
/// <inheritdoc />
public Face CreateFace(Geometry.Vertex vertex)
{
return new Face(vertex);
+29
View File
@@ -3,16 +3,45 @@ namespace TriangleNet.Voronoi
{
using TriangleNet.Topology.DCEL;
/// <summary>
/// Factory for Voronoi DCEL datastructure.
/// </summary>
public interface IVoronoiFactory
{
/// <summary>
/// Initialize object pool.
/// </summary>
/// <param name="vertexCount"></param>
/// <param name="edgeCount"></param>
/// <param name="faceCount"></param>
void Initialize(int vertexCount, int edgeCount, int faceCount);
/// <summary>
/// Reset object pool.
/// </summary>
void Reset();
/// <summary>
/// Return a <see cref="Vertex" />.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
Vertex CreateVertex(double x, double y);
/// <summary>
/// Return a <see cref="HalfEdge" />.
/// </summary>
/// <param name="origin"></param>
/// <param name="face"></param>
/// <returns></returns>
HalfEdge CreateHalfEdge(Vertex origin, Face face);
/// <summary>
/// Return a <see cref="Face" />.
/// </summary>
/// <param name="vertex"></param>
/// <returns></returns>
Face CreateFace(Geometry.Vertex vertex);
}
}
+19
View File
@@ -11,18 +11,37 @@ namespace TriangleNet.Voronoi
using TriangleNet.Tools;
using TriangleNet.Topology.DCEL;
/// <summary>
/// Computing the standard Voronoi diagram of a Delaunay triangulation.
/// </summary>
public class StandardVoronoi : VoronoiBase
{
/// <summary>
/// Initializes a new instance of the <see cref="StandardVoronoi" /> class.
/// </summary>
/// <param name="mesh">The mesh.</param>
public StandardVoronoi(Mesh mesh)
: this(mesh, mesh.bounds, new DefaultVoronoiFactory(), RobustPredicates.Default)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="StandardVoronoi" /> class.
/// </summary>
/// <param name="mesh">The mesh.</param>
/// <param name="box">The bounding box used to clip infinite Voronoi edges.</param>
public StandardVoronoi(Mesh mesh, Rectangle box)
: this(mesh, box, new DefaultVoronoiFactory(), RobustPredicates.Default)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="StandardVoronoi" /> class.
/// </summary>
/// <param name="mesh">The mesh.</param>
/// <param name="box">The bounding box used for clipping (not implemented.)</param>
/// <param name="factory"></param>
/// <param name="predicates"></param>
public StandardVoronoi(Mesh mesh, Rectangle box, IVoronoiFactory factory, IPredicates predicates)
: base(mesh, factory, predicates, true)
{