Code cleanup
git-svn-id: https://triangle.svn.codeplex.com/svn@77330 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
@@ -27,7 +27,6 @@ namespace TriangleNet
|
||||
Func<ITriangle, double, bool> usertest;
|
||||
|
||||
int noBisect = 0;
|
||||
int steiner = -1;
|
||||
|
||||
double minAngle = 0.0;
|
||||
double maxAngle = 0.0;
|
||||
@@ -217,15 +216,6 @@ namespace TriangleNet
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use maximum number of Steiner points.
|
||||
/// </summary>
|
||||
public int SteinerPoints
|
||||
{
|
||||
get { return steiner; }
|
||||
set { steiner = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute boundary information.
|
||||
/// </summary>
|
||||
|
||||
@@ -12,9 +12,7 @@ namespace TriangleNet.Geometry
|
||||
/// </summary>
|
||||
public static IMesh Triangulate(this IPolygon polygon)
|
||||
{
|
||||
var mesher = new GenericMesher();
|
||||
|
||||
return mesher.Triangulate(polygon, null, null);
|
||||
return (new GenericMesher()).Triangulate(polygon, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -23,9 +21,7 @@ namespace TriangleNet.Geometry
|
||||
/// <param name="options">Constraint options.</param>
|
||||
public static IMesh Triangulate(this IPolygon polygon, ConstraintOptions options)
|
||||
{
|
||||
var mesher = new GenericMesher();
|
||||
|
||||
return mesher.Triangulate(polygon, options, null);
|
||||
return (new GenericMesher()).Triangulate(polygon, options, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -34,9 +30,7 @@ namespace TriangleNet.Geometry
|
||||
/// <param name="quality">Quality options.</param>
|
||||
public static IMesh Triangulate(this IPolygon polygon, QualityOptions quality)
|
||||
{
|
||||
var mesher = new GenericMesher();
|
||||
|
||||
return mesher.Triangulate(polygon, null, quality);
|
||||
return (new GenericMesher()).Triangulate(polygon, null, quality);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -46,13 +40,7 @@ namespace TriangleNet.Geometry
|
||||
/// <param name="quality">Quality options.</param>
|
||||
public static IMesh Triangulate(this IPolygon polygon, ConstraintOptions options, QualityOptions quality)
|
||||
{
|
||||
var mesher = new GenericMesher();
|
||||
|
||||
var mesh = (Mesh)mesher.Triangulate(polygon.Points);
|
||||
|
||||
mesh.ApplyConstraints(polygon, options, quality);
|
||||
|
||||
return mesh;
|
||||
return (new GenericMesher()).Triangulate(polygon, options, quality);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -64,80 +52,7 @@ namespace TriangleNet.Geometry
|
||||
public static IMesh Triangulate(this IPolygon polygon, ConstraintOptions options, QualityOptions quality,
|
||||
ITriangulator triangulator)
|
||||
{
|
||||
var mesher = new GenericMesher(triangulator);
|
||||
|
||||
var mesh = (Mesh)mesher.Triangulate(polygon.Points);
|
||||
|
||||
mesh.ApplyConstraints(polygon, options, quality);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rectangle extensions
|
||||
|
||||
/// <summary>
|
||||
/// Find intersection of a rectangle with a segment.
|
||||
/// </summary>
|
||||
/// <param name="rect">The rectangle.</param>
|
||||
/// <param name="p0">Segment start point.</param>
|
||||
/// <param name="p1">Segment end point.</param>
|
||||
/// <param name="c0">Intersection associated to start point.</param>
|
||||
/// <param name="c1">Intersection associated to end point.</param>
|
||||
/// <returns>Returns true, if segment intersects or lies completely in rectangle, otherwise false.</returns>
|
||||
/// <remarks>
|
||||
/// Liang-Barsky function by Daniel White, http://www.skytopia.com/project/articles/compsci/clipping.html
|
||||
/// </remarks>
|
||||
public static bool Intersect(this Rectangle rect, Point p0, Point p1, ref Point c0, ref Point c1)
|
||||
{
|
||||
// Define the x/y clipping values for the border.
|
||||
double xmin = rect.Left;
|
||||
double xmax = rect.Right;
|
||||
double ymin = rect.Bottom;
|
||||
double ymax = rect.Top;
|
||||
|
||||
// Define the start and end points of the line.
|
||||
double x0 = p0.X;
|
||||
double y0 = p0.Y;
|
||||
double x1 = p1.X;
|
||||
double y1 = p1.Y;
|
||||
|
||||
double t0 = 0.0;
|
||||
double t1 = 1.0;
|
||||
|
||||
double dx = x1 - x0;
|
||||
double dy = y1 - y0;
|
||||
|
||||
double p = 0.0, q = 0.0, r;
|
||||
|
||||
for (int edge = 0; edge < 4; edge++)
|
||||
{
|
||||
// Traverse through left, right, bottom, top edges.
|
||||
if (edge == 0) { p = -dx; q = -(xmin - x0); }
|
||||
if (edge == 1) { p = dx; q = (xmax - x0); }
|
||||
if (edge == 2) { p = -dy; q = -(ymin - y0); }
|
||||
if (edge == 3) { p = dy; q = (ymax - y0); }
|
||||
r = q / p;
|
||||
if (p == 0 && q < 0) return false; // Don't draw line at all. (parallel line outside)
|
||||
if (p < 0)
|
||||
{
|
||||
if (r > t1) return false; // Don't draw line at all.
|
||||
else if (r > t0) t0 = r; // Line is clipped!
|
||||
}
|
||||
else if (p > 0)
|
||||
{
|
||||
if (r < t0) return false; // Don't draw line at all.
|
||||
else if (r < t1) t1 = r; // Line is clipped!
|
||||
}
|
||||
}
|
||||
|
||||
c0.x = x0 + t0 * dx;
|
||||
c0.y = y0 + t0 * dy;
|
||||
c1.x = x0 + t1 * dx;
|
||||
c1.y = y0 + t1 * dy;
|
||||
|
||||
return true; // (clipped) line is drawn
|
||||
return (new GenericMesher(triangulator)).Triangulate(polygon, options, quality);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace TriangleNet.Geometry
|
||||
/// <returns>Return true, if bounding box contains given point.</returns>
|
||||
public bool Contains(Point pt)
|
||||
{
|
||||
return ((pt.X >= xmin) && (pt.X <= xmax) && (pt.Y >= ymin) && (pt.Y <= ymax));
|
||||
return ((pt.x >= xmin) && (pt.x <= xmax) && (pt.y >= ymin) && (pt.y <= ymax));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -356,7 +356,7 @@ namespace TriangleNet.IO
|
||||
using (StreamWriter writer = new StreamWriter(filename))
|
||||
{
|
||||
// Number of edges, number of boundary markers (zero or one).
|
||||
writer.WriteLine("{0} {1}", mesh.edges, behavior.UseBoundaryMarkers ? "1" : "0");
|
||||
writer.WriteLine("{0} {1}", mesh.NumberOfEdges, behavior.UseBoundaryMarkers ? "1" : "0");
|
||||
|
||||
long index = 0;
|
||||
// To loop over the set of edges, loop over all triangles, and look at
|
||||
|
||||
@@ -54,7 +54,6 @@ namespace TriangleNet
|
||||
internal int inelements; // Number of input triangles.
|
||||
internal int insegments; // Number of input segments.
|
||||
internal int undeads; // Number of input vertices that don't appear in the mesh.
|
||||
internal int edges; // Number of output edges.
|
||||
internal int mesh_dim; // Dimension (ought to be 2).
|
||||
internal int nextras; // Number of attributes per vertex.
|
||||
//internal int eextras; // Number of attributes per triangle.
|
||||
@@ -136,17 +135,26 @@ namespace TriangleNet
|
||||
/// <summary>
|
||||
/// Gets the number of input vertices.
|
||||
/// </summary>
|
||||
public int NumberOfInputPoints { get { return invertices; } }
|
||||
public int NumberOfInputPoints
|
||||
{
|
||||
get { return invertices; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of mesh edges.
|
||||
/// </summary>
|
||||
public int NumberOfEdges { get { return this.edges; } }
|
||||
public int NumberOfEdges
|
||||
{
|
||||
get { return (3 * triangles.Count + hullsize) / 2; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the input is a PSLG or a point set.
|
||||
/// </summary>
|
||||
public bool IsPolygon { get { return this.insegments > 0; } }
|
||||
public bool IsPolygon
|
||||
{
|
||||
get { return this.insegments > 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current node numbering.
|
||||
@@ -240,6 +248,8 @@ namespace TriangleNet
|
||||
holes = new List<Point>();
|
||||
regions = new List<RegionPointer>();
|
||||
|
||||
steinerleft = -1;
|
||||
|
||||
this.predicates = predicates;
|
||||
|
||||
this.qualityMesher = new QualityMesher(this, predicates);
|
||||
@@ -311,78 +321,7 @@ namespace TriangleNet
|
||||
}
|
||||
|
||||
#region Misc
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Load a mesh from file (.node/poly and .ele).
|
||||
/// </summary>
|
||||
public void Load(string filename)
|
||||
{
|
||||
List<ITriangle> triangles;
|
||||
InputGeometry geometry;
|
||||
|
||||
FileReader.Read(filename, out geometry, out triangles);
|
||||
|
||||
if (geometry != null && triangles != null)
|
||||
{
|
||||
Load(geometry, triangles);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reconstructs a mesh from raw input data.
|
||||
/// </summary>
|
||||
public void Load(InputGeometry input, List<ITriangle> triangles)
|
||||
{
|
||||
if (input == null || triangles == null)
|
||||
{
|
||||
throw new ArgumentException("Invalid input (argument is null).");
|
||||
}
|
||||
|
||||
// Clear all data structures / reset hash seeds
|
||||
this.ResetData();
|
||||
|
||||
if (input.HasSegments)
|
||||
{
|
||||
behavior.Poly = true;
|
||||
|
||||
this.holes.AddRange(input.Holes);
|
||||
}
|
||||
|
||||
//if (input.EdgeMarkers != null)
|
||||
//{
|
||||
// behavior.UseBoundaryMarkers = true;
|
||||
//}
|
||||
|
||||
//if (input.TriangleAreas != null)
|
||||
//{
|
||||
// behavior.VarArea = true;
|
||||
//}
|
||||
|
||||
// TODO: remove
|
||||
if (!behavior.Poly)
|
||||
{
|
||||
// Be careful not to allocate space for element area constraints that
|
||||
// will never be assigned any value (other than the default -1.0).
|
||||
behavior.VarArea = false;
|
||||
|
||||
// Be careful not to add an extra attribute to each element unless the
|
||||
// input supports it (PSLG in, but not refining a preexisting mesh).
|
||||
behavior.useRegions = false;
|
||||
}
|
||||
|
||||
behavior.useRegions = input.Regions.Count > 0;
|
||||
|
||||
TransferNodes(input.points);
|
||||
|
||||
// Read and reconstruct a mesh.
|
||||
hullsize = DataReader.Reconstruct(this, input, triangles.ToArray());
|
||||
|
||||
// Calculate the number of edges.
|
||||
edges = (3 * triangles.Count + hullsize) / 2;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Triangulate given input data.
|
||||
/// </summary>
|
||||
@@ -407,14 +346,14 @@ namespace TriangleNet
|
||||
// Copy quality options
|
||||
if (quality != null)
|
||||
{
|
||||
behavior.Quality = true;
|
||||
|
||||
behavior.MinAngle = quality.MinimumAngle;
|
||||
behavior.MaxAngle = quality.MaximumAngle;
|
||||
behavior.MaxArea = quality.MaximumArea;
|
||||
behavior.UserTest = quality.UserTest;
|
||||
|
||||
behavior.SteinerPoints = quality.SteinerPoints == 0 ? -1 : quality.SteinerPoints;
|
||||
|
||||
behavior.Quality = true;
|
||||
steinerleft = quality.SteinerPoints == 0 ? -1 : quality.SteinerPoints;
|
||||
}
|
||||
|
||||
//if (input.EdgeMarkers != null)
|
||||
@@ -431,9 +370,7 @@ namespace TriangleNet
|
||||
}
|
||||
|
||||
behavior.useRegions = input.Regions.Count > 0;
|
||||
|
||||
steinerleft = behavior.SteinerPoints;
|
||||
|
||||
|
||||
// Ensure that no vertex can be mistaken for a triangular bounding
|
||||
// box vertex in insertvertex().
|
||||
infvertex1 = null;
|
||||
@@ -475,9 +412,6 @@ namespace TriangleNet
|
||||
// Enforce angle and area constraints.
|
||||
qualityMesher.EnforceQuality();
|
||||
}
|
||||
|
||||
// Calculate the number of edges.
|
||||
edges = (3 * triangles.Count + hullsize) / 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -497,8 +431,6 @@ namespace TriangleNet
|
||||
|
||||
Reset();
|
||||
|
||||
steinerleft = behavior.SteinerPoints;
|
||||
|
||||
// Ensure that no vertex can be mistaken for a triangular bounding
|
||||
// box vertex in insertvertex().
|
||||
infvertex1 = infvertex2 = infvertex3 = null;
|
||||
@@ -513,9 +445,6 @@ namespace TriangleNet
|
||||
// Enforce angle and area constraints.
|
||||
qualityMesher.EnforceQuality();
|
||||
}
|
||||
|
||||
// Calculate the number of edges.
|
||||
edges = (3 * triangles.Count + hullsize) / 2;
|
||||
}
|
||||
|
||||
internal void CopyTo(Mesh target)
|
||||
@@ -533,7 +462,6 @@ namespace TriangleNet
|
||||
|
||||
target.numbering = this.numbering;
|
||||
target.hullsize = this.hullsize;
|
||||
target.edges = this.edges;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -556,7 +484,6 @@ namespace TriangleNet
|
||||
flipstack.Clear();
|
||||
|
||||
hullsize = 0;
|
||||
edges = 0;
|
||||
|
||||
Reset();
|
||||
|
||||
|
||||
@@ -341,7 +341,6 @@ namespace TriangleNet.Meshing
|
||||
}
|
||||
|
||||
mesh.hullsize = hullsize;
|
||||
mesh.edges = (3 * mesh.triangles.Count + hullsize) / 2;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -355,7 +354,7 @@ namespace TriangleNet.Meshing
|
||||
var vertices = new HVertex[mesh.vertices.Count];
|
||||
var faces = new Face[mesh.triangles.Count];
|
||||
|
||||
dcel.HalfEdges.Capacity = 2 * mesh.edges;
|
||||
dcel.HalfEdges.Capacity = 2 * mesh.NumberOfEdges;
|
||||
|
||||
mesh.Renumber();
|
||||
|
||||
|
||||
@@ -38,31 +38,31 @@ namespace TriangleNet.Meshing
|
||||
this.triangulator = triangulator;
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
/// <inheritdoc />
|
||||
public IMesh Triangulate(IList<Vertex> points)
|
||||
{
|
||||
return triangulator.Triangulate(points);
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
/// <inheritdoc />
|
||||
public IMesh Triangulate(IPolygon polygon)
|
||||
{
|
||||
return Triangulate(polygon, null, null);
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
/// <inheritdoc />
|
||||
public IMesh Triangulate(IPolygon polygon, ConstraintOptions options)
|
||||
{
|
||||
return Triangulate(polygon, options, null);
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
/// <inheritdoc />
|
||||
public IMesh Triangulate(IPolygon polygon, QualityOptions quality)
|
||||
{
|
||||
return Triangulate(polygon, null, quality);
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
/// <inheritdoc />
|
||||
public IMesh Triangulate(IPolygon polygon, ConstraintOptions options, QualityOptions quality)
|
||||
{
|
||||
var mesh = (Mesh)triangulator.Triangulate(polygon.Points);
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
namespace TriangleNet
|
||||
{
|
||||
using System;
|
||||
using TriangleNet.Topology;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Tools;
|
||||
|
||||
@@ -701,10 +700,10 @@ namespace TriangleNet
|
||||
double _i, _j;
|
||||
double _0;
|
||||
|
||||
acx = (double)(pa.X - pc.X);
|
||||
bcx = (double)(pb.X - pc.X);
|
||||
acy = (double)(pa.Y - pc.Y);
|
||||
bcy = (double)(pb.Y - pc.Y);
|
||||
acx = (double)(pa.x - pc.x);
|
||||
bcx = (double)(pb.x - pc.x);
|
||||
acy = (double)(pa.y - pc.y);
|
||||
bcy = (double)(pb.y - pc.y);
|
||||
|
||||
detleft = (double)(acx * bcy); c = (double)(splitter * acx); abig = (double)(c - acx); ahi = c - abig; alo = acx - ahi; c = (double)(splitter * bcy); abig = (double)(c - bcy); bhi = c - abig; blo = bcy - bhi; err1 = detleft - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); detlefttail = (alo * blo) - err3;
|
||||
detright = (double)(acy * bcx); c = (double)(splitter * acy); abig = (double)(c - acy); ahi = c - abig; alo = acy - ahi; c = (double)(splitter * bcx); abig = (double)(c - bcx); bhi = c - abig; blo = bcx - bhi; err1 = detright - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); detrighttail = (alo * blo) - err3;
|
||||
@@ -720,10 +719,10 @@ namespace TriangleNet
|
||||
return det;
|
||||
}
|
||||
|
||||
bvirt = (double)(pa.X - acx); avirt = acx + bvirt; bround = bvirt - pc.X; around = pa.X - avirt; acxtail = around + bround;
|
||||
bvirt = (double)(pb.X - bcx); avirt = bcx + bvirt; bround = bvirt - pc.X; around = pb.X - avirt; bcxtail = around + bround;
|
||||
bvirt = (double)(pa.Y - acy); avirt = acy + bvirt; bround = bvirt - pc.Y; around = pa.Y - avirt; acytail = around + bround;
|
||||
bvirt = (double)(pb.Y - bcy); avirt = bcy + bvirt; bround = bvirt - pc.Y; around = pb.Y - avirt; bcytail = around + bround;
|
||||
bvirt = (double)(pa.x - acx); avirt = acx + bvirt; bround = bvirt - pc.x; around = pa.x - avirt; acxtail = around + bround;
|
||||
bvirt = (double)(pb.x - bcx); avirt = bcx + bvirt; bround = bvirt - pc.x; around = pb.x - avirt; bcxtail = around + bround;
|
||||
bvirt = (double)(pa.y - acy); avirt = acy + bvirt; bround = bvirt - pc.y; around = pa.y - avirt; acytail = around + bround;
|
||||
bvirt = (double)(pb.y - bcy); avirt = bcy + bvirt; bround = bvirt - pc.y; around = pb.y - avirt; bcytail = around + bround;
|
||||
|
||||
if ((acxtail == 0.0) && (acytail == 0.0)
|
||||
&& (bcxtail == 0.0) && (bcytail == 0.0))
|
||||
@@ -837,19 +836,19 @@ namespace TriangleNet
|
||||
double _i, _j;
|
||||
double _0;
|
||||
|
||||
adx = (double)(pa.X - pd.X);
|
||||
bdx = (double)(pb.X - pd.X);
|
||||
cdx = (double)(pc.X - pd.X);
|
||||
ady = (double)(pa.Y - pd.Y);
|
||||
bdy = (double)(pb.Y - pd.Y);
|
||||
cdy = (double)(pc.Y - pd.Y);
|
||||
adx = (double)(pa.x - pd.x);
|
||||
bdx = (double)(pb.x - pd.x);
|
||||
cdx = (double)(pc.x - pd.x);
|
||||
ady = (double)(pa.y - pd.y);
|
||||
bdy = (double)(pb.y - pd.y);
|
||||
cdy = (double)(pc.y - pd.y);
|
||||
|
||||
adx = (double)(pa.X - pd.X);
|
||||
bdx = (double)(pb.X - pd.X);
|
||||
cdx = (double)(pc.X - pd.X);
|
||||
ady = (double)(pa.Y - pd.Y);
|
||||
bdy = (double)(pb.Y - pd.Y);
|
||||
cdy = (double)(pc.Y - pd.Y);
|
||||
adx = (double)(pa.x - pd.x);
|
||||
bdx = (double)(pb.x - pd.x);
|
||||
cdx = (double)(pc.x - pd.x);
|
||||
ady = (double)(pa.y - pd.y);
|
||||
bdy = (double)(pb.y - pd.y);
|
||||
cdy = (double)(pc.y - pd.y);
|
||||
|
||||
bdxcdy1 = (double)(bdx * cdy); c = (double)(splitter * bdx); abig = (double)(c - bdx); ahi = c - abig; alo = bdx - ahi; c = (double)(splitter * cdy); abig = (double)(c - cdy); bhi = c - abig; blo = cdy - bhi; err1 = bdxcdy1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); bdxcdy0 = (alo * blo) - err3;
|
||||
cdxbdy1 = (double)(cdx * bdy); c = (double)(splitter * cdx); abig = (double)(c - cdx); ahi = c - abig; alo = cdx - ahi; c = (double)(splitter * bdy); abig = (double)(c - bdy); bhi = c - abig; blo = bdy - bhi; err1 = cdxbdy1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); cdxbdy0 = (alo * blo) - err3;
|
||||
@@ -891,12 +890,12 @@ namespace TriangleNet
|
||||
return det;
|
||||
}
|
||||
|
||||
bvirt = (double)(pa.X - adx); avirt = adx + bvirt; bround = bvirt - pd.X; around = pa.X - avirt; adxtail = around + bround;
|
||||
bvirt = (double)(pa.Y - ady); avirt = ady + bvirt; bround = bvirt - pd.Y; around = pa.Y - avirt; adytail = around + bround;
|
||||
bvirt = (double)(pb.X - bdx); avirt = bdx + bvirt; bround = bvirt - pd.X; around = pb.X - avirt; bdxtail = around + bround;
|
||||
bvirt = (double)(pb.Y - bdy); avirt = bdy + bvirt; bround = bvirt - pd.Y; around = pb.Y - avirt; bdytail = around + bround;
|
||||
bvirt = (double)(pc.X - cdx); avirt = cdx + bvirt; bround = bvirt - pd.X; around = pc.X - avirt; cdxtail = around + bround;
|
||||
bvirt = (double)(pc.Y - cdy); avirt = cdy + bvirt; bround = bvirt - pd.Y; around = pc.Y - avirt; cdytail = around + bround;
|
||||
bvirt = (double)(pa.x - adx); avirt = adx + bvirt; bround = bvirt - pd.x; around = pa.x - avirt; adxtail = around + bround;
|
||||
bvirt = (double)(pa.y - ady); avirt = ady + bvirt; bround = bvirt - pd.y; around = pa.y - avirt; adytail = around + bround;
|
||||
bvirt = (double)(pb.x - bdx); avirt = bdx + bvirt; bround = bvirt - pd.x; around = pb.x - avirt; bdxtail = around + bround;
|
||||
bvirt = (double)(pb.y - bdy); avirt = bdy + bvirt; bround = bvirt - pd.y; around = pb.y - avirt; bdytail = around + bround;
|
||||
bvirt = (double)(pc.x - cdx); avirt = cdx + bvirt; bround = bvirt - pd.x; around = pc.x - avirt; cdxtail = around + bround;
|
||||
bvirt = (double)(pc.y - cdy); avirt = cdy + bvirt; bround = bvirt - pd.y; around = pc.y - avirt; cdytail = around + bround;
|
||||
if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
|
||||
&& (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0))
|
||||
{
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace TriangleNet.Tools
|
||||
{
|
||||
var a = array[i];
|
||||
int j = i - 1;
|
||||
while (j >= left && (array[j].X > a.X || (array[j].X == a.X && array[j].Y > a.Y)))
|
||||
while (j >= left && (array[j].x > a.x || (array[j].x == a.x && array[j].y > a.y)))
|
||||
{
|
||||
array[j + 1] = array[j];
|
||||
j--;
|
||||
@@ -66,8 +66,8 @@ namespace TriangleNet.Tools
|
||||
|
||||
// Choose a random pivot to split the array.
|
||||
pivot = rand.Next(left, right);
|
||||
pivotx = array[pivot].X;
|
||||
pivoty = array[pivot].Y;
|
||||
pivotx = array[pivot].x;
|
||||
pivoty = array[pivot].y;
|
||||
// Split the array.
|
||||
left--;
|
||||
right++;
|
||||
@@ -78,15 +78,15 @@ namespace TriangleNet.Tools
|
||||
{
|
||||
left++;
|
||||
}
|
||||
while ((left <= right) && ((array[left].X < pivotx) ||
|
||||
((array[left].X == pivotx) && (array[left].Y < pivoty))));
|
||||
while ((left <= right) && ((array[left].x < pivotx) ||
|
||||
((array[left].x == pivotx) && (array[left].y < pivoty))));
|
||||
// Search for a vertex whose x-coordinate is too small for the right.
|
||||
do
|
||||
{
|
||||
right--;
|
||||
}
|
||||
while ((left <= right) && ((array[right].X > pivotx) ||
|
||||
((array[right].X == pivotx) && (array[right].Y > pivoty))));
|
||||
while ((left <= right) && ((array[right].x > pivotx) ||
|
||||
((array[right].x == pivotx) && (array[right].y > pivoty))));
|
||||
|
||||
if (left < right)
|
||||
{
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace TriangleNet.Tools
|
||||
i++;
|
||||
}
|
||||
|
||||
if (points[0].ID == points[1].ID)
|
||||
if (points[0].id == points[1].id)
|
||||
{
|
||||
horrors += CheckVertexIDs(poly, count);
|
||||
}
|
||||
@@ -114,13 +114,15 @@ namespace TriangleNet.Tools
|
||||
}
|
||||
}
|
||||
|
||||
return horrors == 0;
|
||||
return horrors > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the polygon for 360 degree angles.
|
||||
/// </summary>
|
||||
public static bool HasBadAngles(IPolygon poly)
|
||||
/// <param name="poly">The polygon.</param>
|
||||
/// <param name="threshold">The angle threshold.</param>
|
||||
public static bool HasBadAngles(IPolygon poly, double threshold = 2e-12)
|
||||
{
|
||||
var logger = Log.Instance;
|
||||
|
||||
@@ -134,18 +136,24 @@ namespace TriangleNet.Tools
|
||||
|
||||
foreach (var seg in poly.Segments)
|
||||
{
|
||||
q0 = p0;
|
||||
q1 = p1;
|
||||
q0 = p0; // Previous segment start point.
|
||||
q1 = p1; // Previous segment end point.
|
||||
|
||||
p0 = seg.GetVertex(0);
|
||||
p1 = seg.GetVertex(1);
|
||||
p0 = seg.GetVertex(0); // Current segment start point.
|
||||
p1 = seg.GetVertex(1); // Current segment end point.
|
||||
|
||||
if (p0 == p1 || q0 == q1)
|
||||
{
|
||||
// Ignore zero-length segments.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (q0 != null && q1 != null)
|
||||
{
|
||||
// The two segments are connected.
|
||||
if (p0 == q1 && p1 != null)
|
||||
{
|
||||
if (IsBadAngle(q0, p0, p1))
|
||||
if (IsBadAngle(q0, p0, p1,threshold))
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Bad segment angle found at index {0}.", i),
|
||||
@@ -157,29 +165,29 @@ namespace TriangleNet.Tools
|
||||
i++;
|
||||
}
|
||||
|
||||
return horrors == 0;
|
||||
return horrors > 0;
|
||||
}
|
||||
|
||||
private static bool IsBadAngle(Point a, Point b, Point c, double eps = 0.0)
|
||||
private static bool IsBadAngle(Point a, Point b, Point c, double threshold = 0.0)
|
||||
{
|
||||
double x = DotProduct(a, b, c);
|
||||
double y = CrossProductLength(a, b, c);
|
||||
|
||||
return Math.Abs(Math.Atan2(y, x)) <= eps;
|
||||
return Math.Abs(Math.Atan2(y, x)) <= threshold;
|
||||
}
|
||||
|
||||
// Returns the dot product <AB, BC>.
|
||||
private static double DotProduct(Point a, Point b, Point c)
|
||||
{
|
||||
// Calculate the dot product.
|
||||
return (a.X - b.X) * (c.X - b.X) + (a.Y - b.Y) * (c.Y - b.Y);
|
||||
return (a.x - b.x) * (c.x - b.x) + (a.y - b.y) * (c.y - b.y);
|
||||
}
|
||||
|
||||
// Returns the length of cross product AB x BC.
|
||||
private static double CrossProductLength(Point a, Point b, Point c)
|
||||
{
|
||||
// Calculate the Z coordinate of the cross product.
|
||||
return (a.X - b.X) * (c.Y - b.Y) - (a.Y - b.Y) * (c.X - b.X);
|
||||
return (a.x - b.x) * (c.y - b.y) - (a.y - b.y) * (c.x - b.x);
|
||||
}
|
||||
|
||||
private static int CheckVertexIDs(IPolygon poly, int count)
|
||||
@@ -197,14 +205,14 @@ namespace TriangleNet.Tools
|
||||
p = seg.GetVertex(0);
|
||||
q = seg.GetVertex(1);
|
||||
|
||||
if (p.ID < 0 || p.ID >= count)
|
||||
if (p.id < 0 || p.id >= count)
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Segment {0} has invalid startpoint.", i),
|
||||
"PolygonValidator.IsConsistent()");
|
||||
}
|
||||
|
||||
if (q.ID < 0 || q.ID >= count)
|
||||
if (q.id < 0 || q.id >= count)
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Segment {0} has invalid endpoint.", i),
|
||||
@@ -224,7 +232,7 @@ namespace TriangleNet.Tools
|
||||
// Check for duplicate ids.
|
||||
foreach (var p in poly.Points)
|
||||
{
|
||||
if (!ids.Add(p.ID))
|
||||
if (!ids.Add(p.id))
|
||||
{
|
||||
Log.Instance.Warning("Found duplicate vertex ids.", "PolygonValidator.IsConsistent()");
|
||||
return 1;
|
||||
|
||||
@@ -272,8 +272,8 @@ namespace TriangleNet.Tools
|
||||
k1 = plus1Mod3[i];
|
||||
k2 = minus1Mod3[i];
|
||||
|
||||
dx[i] = p[k1].X - p[k2].X;
|
||||
dy[i] = p[k1].Y - p[k2].Y;
|
||||
dx[i] = p[k1].x - p[k2].x;
|
||||
dy[i] = p[k1].y - p[k2].y;
|
||||
|
||||
edgeLength[i] = dx[i] * dx[i] + dy[i] * dy[i];
|
||||
|
||||
@@ -294,8 +294,8 @@ namespace TriangleNet.Tools
|
||||
}
|
||||
|
||||
//triarea = Primitives.CounterClockwise(p[0], p[1], p[2]);
|
||||
triArea = Math.Abs((p[2].X - p[0].X) * (p[1].Y - p[0].Y) -
|
||||
(p[1].X - p[0].X) * (p[2].Y - p[0].Y));
|
||||
triArea = Math.Abs((p[2].x - p[0].x) * (p[1].y - p[0].y) -
|
||||
(p[1].x - p[0].x) * (p[2].y - p[0].y));
|
||||
|
||||
if (triArea < minArea)
|
||||
{
|
||||
|
||||
@@ -79,15 +79,15 @@ namespace TriangleNet.Tools
|
||||
internal static bool IsPointInTriangle(Point p, Point t0, Point t1, Point t2)
|
||||
{
|
||||
// TODO: no need to create new Point instances here
|
||||
Point d0 = new Point(t1.X - t0.X, t1.Y - t0.Y);
|
||||
Point d1 = new Point(t2.X - t0.X, t2.Y - t0.Y);
|
||||
Point d2 = new Point(p.X - t0.X, p.Y - t0.Y);
|
||||
Point d0 = new Point(t1.x - t0.x, t1.y - t0.y);
|
||||
Point d1 = new Point(t2.x - t0.x, t2.y - t0.y);
|
||||
Point d2 = new Point(p.x - t0.x, p.y - t0.y);
|
||||
|
||||
// crossproduct of (0, 0, 1) and d0
|
||||
Point c0 = new Point(-d0.Y, d0.X);
|
||||
Point c0 = new Point(-d0.y, d0.x);
|
||||
|
||||
// crossproduct of (0, 0, 1) and d1
|
||||
Point c1 = new Point(-d1.Y, d1.X);
|
||||
Point c1 = new Point(-d1.y, d1.x);
|
||||
|
||||
// Linear combination d2 = s * d0 + v * d1.
|
||||
//
|
||||
@@ -111,7 +111,7 @@ namespace TriangleNet.Tools
|
||||
|
||||
internal static double DotProduct(Point p, Point q)
|
||||
{
|
||||
return p.X * q.X + p.Y * q.Y;
|
||||
return p.x * q.x + p.y * q.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -187,23 +187,23 @@ namespace TriangleNet.Tools
|
||||
// +--------------+
|
||||
Rectangle box;
|
||||
|
||||
var width = bounds.Right - pivot.X;
|
||||
var height = bounds.Top - pivot.Y;
|
||||
var width = bounds.Right - pivot.x;
|
||||
var height = bounds.Top - pivot.y;
|
||||
|
||||
// 1. region south west
|
||||
box = new Rectangle(bounds.Left, bounds.Bottom, width, height);
|
||||
regions[0] = new QuadNode(box, tree);
|
||||
|
||||
// 2. region south east
|
||||
box = new Rectangle(pivot.X, bounds.Bottom, width, height);
|
||||
box = new Rectangle(pivot.x, bounds.Bottom, width, height);
|
||||
regions[1] = new QuadNode(box, tree);
|
||||
|
||||
// 3. region north west
|
||||
box = new Rectangle(bounds.Left, pivot.Y, width, height);
|
||||
box = new Rectangle(bounds.Left, pivot.y, width, height);
|
||||
regions[2] = new QuadNode(box, tree);
|
||||
|
||||
// 4. region north east
|
||||
box = new Rectangle(pivot.X, pivot.Y, width, height);
|
||||
box = new Rectangle(pivot.x, pivot.y, width, height);
|
||||
regions[3] = new QuadNode(box, tree);
|
||||
|
||||
Point[] triangle = new Point[3];
|
||||
@@ -268,8 +268,8 @@ namespace TriangleNet.Tools
|
||||
// Iterate through all triangle laterals and find bounding box intersections
|
||||
for (int i = 0; i < 3; k = i++)
|
||||
{
|
||||
dx = triangle[i].X - triangle[k].X;
|
||||
dy = triangle[i].Y - triangle[k].Y;
|
||||
dx = triangle[i].x - triangle[k].x;
|
||||
dy = triangle[i].y - triangle[k].y;
|
||||
|
||||
if (dx != 0.0)
|
||||
{
|
||||
@@ -287,13 +287,13 @@ namespace TriangleNet.Tools
|
||||
double t;
|
||||
|
||||
// find intersection with plane x = m_pivot.dX
|
||||
t = (pivot.X - triangle[k].X) / dx;
|
||||
t = (pivot.x - triangle[k].x) / dx;
|
||||
if (t < (1 + EPS) && t > -EPS)
|
||||
{
|
||||
// we have an intersection
|
||||
double yComponent = triangle[k].Y + t * dy;
|
||||
double yComponent = triangle[k].y + t * dy;
|
||||
|
||||
if (yComponent < pivot.Y && yComponent >= bounds.Bottom)
|
||||
if (yComponent < pivot.y && yComponent >= bounds.Bottom)
|
||||
{
|
||||
AddToRegion(index, SW);
|
||||
AddToRegion(index, SE);
|
||||
@@ -306,13 +306,13 @@ namespace TriangleNet.Tools
|
||||
}
|
||||
|
||||
// find intersection with plane x = m_boundingBox[0].dX
|
||||
t = (bounds.Left - triangle[k].X) / dx;
|
||||
t = (bounds.Left - triangle[k].x) / dx;
|
||||
if (t < (1 + EPS) && t > -EPS)
|
||||
{
|
||||
// we have an intersection
|
||||
double yComponent = triangle[k].Y + t * dy;
|
||||
double yComponent = triangle[k].y + t * dy;
|
||||
|
||||
if (yComponent < pivot.Y && yComponent >= bounds.Bottom)
|
||||
if (yComponent < pivot.y && yComponent >= bounds.Bottom)
|
||||
{
|
||||
AddToRegion(index, SW);
|
||||
}
|
||||
@@ -323,13 +323,13 @@ namespace TriangleNet.Tools
|
||||
}
|
||||
|
||||
// find intersection with plane x = m_boundingBox[1].dX
|
||||
t = (bounds.Right - triangle[k].X) / dx;
|
||||
t = (bounds.Right - triangle[k].x) / dx;
|
||||
if (t < (1 + EPS) && t > -EPS)
|
||||
{
|
||||
// we have an intersection
|
||||
double yComponent = triangle[k].Y + t * dy;
|
||||
double yComponent = triangle[k].y + t * dy;
|
||||
|
||||
if (yComponent < pivot.Y && yComponent >= bounds.Bottom)
|
||||
if (yComponent < pivot.y && yComponent >= bounds.Bottom)
|
||||
{
|
||||
AddToRegion(index, SE);
|
||||
}
|
||||
@@ -345,13 +345,13 @@ namespace TriangleNet.Tools
|
||||
double t, xComponent;
|
||||
|
||||
// find intersection with plane y = m_pivot.dY
|
||||
t = (pivot.Y - triangle[k].Y) / dy;
|
||||
t = (pivot.y - triangle[k].y) / dy;
|
||||
if (t < (1 + EPS) && t > -EPS)
|
||||
{
|
||||
// we have an intersection
|
||||
xComponent = triangle[k].X + t * dx;
|
||||
xComponent = triangle[k].x + t * dx;
|
||||
|
||||
if (xComponent > pivot.X && xComponent <= bounds.Right)
|
||||
if (xComponent > pivot.x && xComponent <= bounds.Right)
|
||||
{
|
||||
AddToRegion(index, SE);
|
||||
AddToRegion(index, NE);
|
||||
@@ -364,13 +364,13 @@ namespace TriangleNet.Tools
|
||||
}
|
||||
|
||||
// find intersection with plane y = m_boundingBox[0].dY
|
||||
t = (bounds.Bottom - triangle[k].Y) / dy;
|
||||
t = (bounds.Bottom - triangle[k].y) / dy;
|
||||
if (t < (1 + EPS) && t > -EPS)
|
||||
{
|
||||
// we have an intersection
|
||||
xComponent = triangle[k].X + t * dx;
|
||||
xComponent = triangle[k].x + t * dx;
|
||||
|
||||
if (xComponent > pivot.X && xComponent <= bounds.Right)
|
||||
if (xComponent > pivot.x && xComponent <= bounds.Right)
|
||||
{
|
||||
AddToRegion(index, SE);
|
||||
}
|
||||
@@ -381,13 +381,13 @@ namespace TriangleNet.Tools
|
||||
}
|
||||
|
||||
// find intersection with plane y = m_boundingBox[1].dY
|
||||
t = (bounds.Top - triangle[k].Y) / dy;
|
||||
t = (bounds.Top - triangle[k].y) / dy;
|
||||
if (t < (1 + EPS) && t > -EPS)
|
||||
{
|
||||
// we have an intersection
|
||||
xComponent = triangle[k].X + t * dx;
|
||||
xComponent = triangle[k].x + t * dx;
|
||||
|
||||
if (xComponent > pivot.X && xComponent <= bounds.Right)
|
||||
if (xComponent > pivot.x && xComponent <= bounds.Right)
|
||||
{
|
||||
AddToRegion(index, NE);
|
||||
}
|
||||
@@ -401,11 +401,11 @@ namespace TriangleNet.Tools
|
||||
int FindRegion(Point point)
|
||||
{
|
||||
int b = 2;
|
||||
if (point.Y < pivot.Y)
|
||||
if (point.y < pivot.y)
|
||||
{
|
||||
b = 0;
|
||||
}
|
||||
if (point.X > pivot.X)
|
||||
if (point.x > pivot.x)
|
||||
{
|
||||
b++;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace TriangleNet
|
||||
while (true)
|
||||
{
|
||||
// Check whether the apex is the point we seek.
|
||||
if ((fapex.x == searchpoint.X) && (fapex.y == searchpoint.Y))
|
||||
if ((fapex.x == searchpoint.x) && (fapex.y == searchpoint.y))
|
||||
{
|
||||
searchtri.Lprev();
|
||||
return LocateResult.OnVertex;
|
||||
@@ -149,8 +149,8 @@ namespace TriangleNet
|
||||
// a line perpendicular to the line (forg, fdest) and passing
|
||||
// through 'fapex', and determining which side of this line
|
||||
// 'searchpoint' falls on.
|
||||
moveleft = (fapex.x - searchpoint.X) * (fdest.x - forg.x) +
|
||||
(fapex.y - searchpoint.Y) * (fdest.y - forg.y) > 0.0;
|
||||
moveleft = (fapex.x - searchpoint.x) * (fdest.x - forg.x) +
|
||||
(fapex.y - searchpoint.y) * (fdest.y - forg.y) > 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -266,8 +266,8 @@ namespace TriangleNet
|
||||
// Record the distance from the suggested starting triangle to the
|
||||
// point we seek.
|
||||
torg = searchtri.Org();
|
||||
searchdist = (searchpoint.X - torg.x) * (searchpoint.X - torg.x) +
|
||||
(searchpoint.Y - torg.y) * (searchpoint.Y - torg.y);
|
||||
searchdist = (searchpoint.x - torg.x) * (searchpoint.x - torg.x) +
|
||||
(searchpoint.y - torg.y) * (searchpoint.y - torg.y);
|
||||
|
||||
// If a recently encountered triangle has been recorded and has not been
|
||||
// deallocated, test it as a good starting point.
|
||||
@@ -276,13 +276,13 @@ namespace TriangleNet
|
||||
if (!Otri.IsDead(recenttri.tri))
|
||||
{
|
||||
torg = recenttri.Org();
|
||||
if ((torg.x == searchpoint.X) && (torg.y == searchpoint.Y))
|
||||
if ((torg.x == searchpoint.x) && (torg.y == searchpoint.y))
|
||||
{
|
||||
recenttri.Copy(ref searchtri);
|
||||
return LocateResult.OnVertex;
|
||||
}
|
||||
dist = (searchpoint.X - torg.x) * (searchpoint.X - torg.x) +
|
||||
(searchpoint.Y - torg.y) * (searchpoint.Y - torg.y);
|
||||
dist = (searchpoint.x - torg.x) * (searchpoint.x - torg.x) +
|
||||
(searchpoint.y - torg.y) * (searchpoint.y - torg.y);
|
||||
if (dist < searchdist)
|
||||
{
|
||||
recenttri.Copy(ref searchtri);
|
||||
@@ -301,8 +301,8 @@ namespace TriangleNet
|
||||
if (!Otri.IsDead(sampletri.tri))
|
||||
{
|
||||
torg = sampletri.Org();
|
||||
dist = (searchpoint.X - torg.x) * (searchpoint.X - torg.x) +
|
||||
(searchpoint.Y - torg.y) * (searchpoint.Y - torg.y);
|
||||
dist = (searchpoint.x - torg.x) * (searchpoint.x - torg.x) +
|
||||
(searchpoint.y - torg.y) * (searchpoint.y - torg.y);
|
||||
if (dist < searchdist)
|
||||
{
|
||||
sampletri.Copy(ref searchtri);
|
||||
@@ -315,11 +315,11 @@ namespace TriangleNet
|
||||
torg = searchtri.Org();
|
||||
tdest = searchtri.Dest();
|
||||
// Check the starting triangle's vertices.
|
||||
if ((torg.x == searchpoint.X) && (torg.y == searchpoint.Y))
|
||||
if ((torg.x == searchpoint.x) && (torg.y == searchpoint.y))
|
||||
{
|
||||
return LocateResult.OnVertex;
|
||||
}
|
||||
if ((tdest.x == searchpoint.X) && (tdest.y == searchpoint.Y))
|
||||
if ((tdest.x == searchpoint.x) && (tdest.y == searchpoint.y))
|
||||
{
|
||||
searchtri.Lnext();
|
||||
return LocateResult.OnVertex;
|
||||
@@ -335,8 +335,8 @@ namespace TriangleNet
|
||||
else if (ahead == 0.0)
|
||||
{
|
||||
// Check if 'searchpoint' is between 'torg' and 'tdest'.
|
||||
if (((torg.x < searchpoint.X) == (searchpoint.X < tdest.x)) &&
|
||||
((torg.y < searchpoint.Y) == (searchpoint.Y < tdest.y)))
|
||||
if (((torg.x < searchpoint.x) == (searchpoint.x < tdest.x)) &&
|
||||
((torg.y < searchpoint.y) == (searchpoint.y < tdest.y)))
|
||||
{
|
||||
return LocateResult.OnEdge;
|
||||
}
|
||||
|
||||
@@ -270,8 +270,8 @@ namespace TriangleNet.Voronoi.Legacy
|
||||
|
||||
private bool BoxRayIntersection(Point pt, double dx, double dy, out Point intersect)
|
||||
{
|
||||
double x = pt.X;
|
||||
double y = pt.Y;
|
||||
double x = pt.x;
|
||||
double y = pt.y;
|
||||
|
||||
double t1, x1, y1, t2, x2, y2;
|
||||
|
||||
@@ -365,7 +365,7 @@ namespace TriangleNet.Voronoi.Legacy
|
||||
}
|
||||
else
|
||||
{
|
||||
edges.Add(new Edge(last.ID, pt.ID));
|
||||
edges.Add(new Edge(last.id, pt.id));
|
||||
|
||||
last = pt;
|
||||
}
|
||||
@@ -373,7 +373,7 @@ namespace TriangleNet.Voronoi.Legacy
|
||||
|
||||
if (region.Bounded && first != null)
|
||||
{
|
||||
edges.Add(new Edge(last.ID, first.ID));
|
||||
edges.Add(new Edge(last.id, first.id));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace TriangleNet.Voronoi
|
||||
factory = new DefaultVoronoiFactory();
|
||||
}
|
||||
|
||||
factory.Initialize(vertices.Length, 2 * mesh.edges, faces.Length);
|
||||
factory.Initialize(vertices.Length, 2 * mesh.NumberOfEdges, faces.Length);
|
||||
|
||||
// Compute triangles circumcenters.
|
||||
var map = ComputeVertices(mesh, vertices);
|
||||
|
||||
Reference in New Issue
Block a user