Code/comments cleanup
git-svn-id: https://triangle.svn.codeplex.com/svn@75046 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
@@ -75,9 +75,9 @@ namespace MeshExplorer.Views
|
||||
public void HandleMeshChange(Mesh mesh)
|
||||
{
|
||||
// New mesh stats
|
||||
lbNumVert.Text = statistic.Vertices.ToString();
|
||||
lbNumSeg.Text = statistic.ConstrainedEdges.ToString();
|
||||
lbNumTri.Text = statistic.Triangles.ToString();
|
||||
lbNumVert.Text = mesh.Vertices.Count.ToString();
|
||||
lbNumSeg.Text = mesh.Segments.Count.ToString();
|
||||
lbNumTri.Text = mesh.Triangles.Count.ToString();
|
||||
|
||||
// Update statistics tab
|
||||
angleHistogram1.SetData(statistic.MinAngleHistogram, statistic.MaxAngleHistogram);
|
||||
|
||||
@@ -34,8 +34,6 @@ namespace TriangleNet.Data
|
||||
|
||||
public BadTriQueue()
|
||||
{
|
||||
//badtriangles = new List<BadTriangle>();
|
||||
|
||||
queuefront = new BadTriangle[4096];
|
||||
queuetail = new BadTriangle[4096];
|
||||
nextnonemptyq = new int[4096];
|
||||
@@ -147,19 +145,19 @@ namespace TriangleNet.Data
|
||||
/// </summary>
|
||||
/// <param name="enqtri"></param>
|
||||
/// <param name="minedge"></param>
|
||||
/// <param name="enqapex"></param>
|
||||
/// <param name="enqorg"></param>
|
||||
/// <param name="enqdest"></param>
|
||||
public void Enqueue(ref Otri enqtri, double minedge, Vertex enqapex, Vertex enqorg, Vertex enqdest)
|
||||
/// <param name="apex"></param>
|
||||
/// <param name="org"></param>
|
||||
/// <param name="dest"></param>
|
||||
public void Enqueue(ref Otri enqtri, double minedge, Vertex apex, Vertex org, Vertex dest)
|
||||
{
|
||||
// Allocate space for the bad triangle.
|
||||
BadTriangle newbad = new BadTriangle();
|
||||
|
||||
newbad.poortri = enqtri;
|
||||
newbad.key = minedge;
|
||||
newbad.apex = enqapex;
|
||||
newbad.org = enqorg;
|
||||
newbad.dest = enqdest;
|
||||
newbad.apex = apex;
|
||||
newbad.org = org;
|
||||
newbad.dest = dest;
|
||||
|
||||
Enqueue(newbad);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace TriangleNet.Data
|
||||
class BadTriangle
|
||||
{
|
||||
public Otri poortri; // A skinny or too-large triangle.
|
||||
public double key; // cos^2 of smallest (apical) angle.
|
||||
public double key; // cos^2 of smallest (apical) angle.
|
||||
public Vertex org, dest, apex; // Its three vertices.
|
||||
public BadTriangle next; // Pointer to next bad triangle.
|
||||
|
||||
|
||||
@@ -14,10 +14,9 @@ namespace TriangleNet.Data
|
||||
/// An oriented subsegment.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Iincludes a pointer to a subsegment and an orientation. The orientation
|
||||
/// denotes a side of the edge. Hence, there are two possible orientations.
|
||||
/// By convention, the edge is always directed so that the "side" denoted
|
||||
/// is the right side of the edge.
|
||||
/// Includes a pointer to a subsegment and an orientation. The orientation denotes a
|
||||
/// side of the edge. Hence, there are two possible orientations. By convention, the
|
||||
/// edge is always directed so that the "side" denoted is the right side of the edge.
|
||||
/// </remarks>
|
||||
struct Osub
|
||||
{
|
||||
|
||||
@@ -14,10 +14,9 @@ namespace TriangleNet.Data
|
||||
/// An oriented triangle.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Includes a pointer to a triangle and orientation.
|
||||
/// The orientation denotes an edge of the triangle. Hence, there are
|
||||
/// three possible orientations. By convention, each edge always points
|
||||
/// counterclockwise about the corresponding triangle.
|
||||
/// Includes a pointer to a triangle and orientation. The orientation denotes an edge
|
||||
/// of the triangle. Hence, there are three possible orientations. By convention, each
|
||||
/// edge always points counterclockwise about the corresponding triangle.
|
||||
/// </remarks>
|
||||
struct Otri
|
||||
{
|
||||
|
||||
@@ -13,11 +13,6 @@ namespace TriangleNet.Data
|
||||
/// <summary>
|
||||
/// The subsegment data structure.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Each subsegment contains two pointers to adjoining subsegments, plus
|
||||
/// four pointers to vertices, plus two pointers to adjoining triangles,
|
||||
/// plus one boundary marker.
|
||||
/// </remarks>
|
||||
public class Segment : ISegment
|
||||
{
|
||||
// Hash for dictionary. Will be set by mesh instance.
|
||||
|
||||
@@ -13,12 +13,6 @@ namespace TriangleNet.Data
|
||||
/// <summary>
|
||||
/// The triangle data structure.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Each triangle contains three pointers to adjoining triangles, plus three
|
||||
/// pointers to vertices, plus three pointers to subsegments (declared below;
|
||||
/// these pointers are usually 'dummysub'). It may or may not also contain
|
||||
/// user-defined attributes and/or a floating-point "area constraint".
|
||||
/// </remarks>
|
||||
public class Triangle : ITriangle
|
||||
{
|
||||
// Hash for dictionary. Will be set by mesh instance.
|
||||
|
||||
@@ -4,21 +4,62 @@ namespace TriangleNet.Geometry
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Polygon interface.
|
||||
/// </summary>
|
||||
public interface IPolygon
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the vertices of the polygon.
|
||||
/// </summary>
|
||||
List<Vertex> Points { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the segments of the polygon.
|
||||
/// </summary>
|
||||
List<IEdge> Segments { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of points defining the holes of the polygon.
|
||||
/// </summary>
|
||||
List<Point> Holes { get; }
|
||||
//List<Point> Regions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of pointers defining the regions of the polygon.
|
||||
/// </summary>
|
||||
List<RegionPointer> Regions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value indicating wether the vertices have marks or not.
|
||||
/// </summary>
|
||||
bool HasPointMarkers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value indicating wether the segments have marks or not.
|
||||
/// </summary>
|
||||
bool HasSegmentMarkers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a contour to the polygon.
|
||||
/// </summary>
|
||||
/// <param name="points">Points making up the contour.</param>
|
||||
/// <param name="marker">Contour marker.</param>
|
||||
/// <param name="hole">Treat contour as a hole (interior boundary).</param>
|
||||
/// <param name="convex">The hole is convex.</param>
|
||||
void AddContour(IEnumerable<Vertex> points, int marker, bool hole, bool convex);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a contour to the polygon.
|
||||
/// </summary>
|
||||
/// <param name="points">Points making up the contour.</param>
|
||||
/// <param name="marker">Contour marker.</param>
|
||||
/// <param name="hole">Point inside the contour, making it a hole.</param>
|
||||
void AddContour(IEnumerable<Vertex> points, int marker, Point hole);
|
||||
|
||||
/// <summary>
|
||||
/// Compute the bounds of the polygon.
|
||||
/// </summary>
|
||||
/// <returns>Rectangle defining an axis-aligned bounding box.</returns>
|
||||
Rectangle Bounds();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ namespace TriangleNet.Geometry
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Data;
|
||||
|
||||
/// <summary>
|
||||
/// A polygon represented as a planar straight line graph.
|
||||
/// </summary>
|
||||
public class Polygon : IPolygon
|
||||
{
|
||||
List<Vertex> points;
|
||||
@@ -13,30 +16,37 @@ namespace TriangleNet.Geometry
|
||||
|
||||
List<IEdge> segments;
|
||||
|
||||
/// <inherit />
|
||||
public List<Vertex> Points
|
||||
{
|
||||
get { return points; }
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
public List<Point> Holes
|
||||
{
|
||||
get { return holes; }
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
public List<RegionPointer> Regions
|
||||
{
|
||||
get { return regions; }
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
public List<IEdge> Segments
|
||||
{
|
||||
get { return segments; }
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
public bool HasPointMarkers { get; set; }
|
||||
|
||||
/// <inherit />
|
||||
public bool HasSegmentMarkers { get; set; }
|
||||
|
||||
/// <inherit />
|
||||
public int Count
|
||||
{
|
||||
get { return points.Count; }
|
||||
@@ -59,6 +69,7 @@ namespace TriangleNet.Geometry
|
||||
HasSegmentMarkers = false;
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
public void AddContour(IEnumerable<Vertex> points, int marker = 0,
|
||||
bool hole = false, bool convex = false)
|
||||
{
|
||||
@@ -106,6 +117,7 @@ namespace TriangleNet.Geometry
|
||||
}
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
public void AddContour(IEnumerable<Vertex> points, int marker, Point hole)
|
||||
{
|
||||
// Copy input to list.
|
||||
@@ -130,9 +142,11 @@ namespace TriangleNet.Geometry
|
||||
this.segments.Add(new Edge(offset + i, offset + ((i + 1) % count), marker));
|
||||
}
|
||||
|
||||
// TODO: check if hole is actually inside contour?
|
||||
this.holes.Add(hole);
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
public Rectangle Bounds()
|
||||
{
|
||||
var bounds = new Rectangle();
|
||||
@@ -141,11 +155,17 @@ namespace TriangleNet.Geometry
|
||||
return bounds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a vertex to the polygon.
|
||||
/// </summary>
|
||||
public void Add(Vertex vertex)
|
||||
{
|
||||
this.points.Add(vertex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a vertex to the polygon.
|
||||
/// </summary>
|
||||
public void Add(Vertex vertex, double[] attributes)
|
||||
{
|
||||
// TODO: check attibutes
|
||||
@@ -155,6 +175,9 @@ namespace TriangleNet.Geometry
|
||||
this.points.Add(vertex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a segment to the polygon.
|
||||
/// </summary>
|
||||
public void Add(Edge edge)
|
||||
{
|
||||
this.segments.Add(edge);
|
||||
|
||||
@@ -199,6 +199,7 @@ namespace TriangleNet
|
||||
behavior.MaxAngle = quality.MaximumAngle;
|
||||
|
||||
behavior.MaxArea = quality.MaximumArea;
|
||||
// TODO: behavior.VarArea = quality.VariableArea;
|
||||
|
||||
this.Refine();
|
||||
}
|
||||
|
||||
@@ -1,33 +1,31 @@
|
||||
|
||||
namespace TriangleNet.Meshing
|
||||
{
|
||||
/// <summary>
|
||||
/// Mesh constraint options for polygon triangulation.
|
||||
/// </summary>
|
||||
public class ConstraintOptions
|
||||
{
|
||||
public static ConstraintOptions Empty
|
||||
{
|
||||
get { return new ConstraintOptions(); }
|
||||
}
|
||||
|
||||
#region Public properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating wether to use regions.
|
||||
/// Gets or sets a value indicating whether to use regions.
|
||||
/// </summary>
|
||||
public bool UseRegions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating wether to create a Conforming
|
||||
/// Gets or sets a value indicating whether to create a Conforming
|
||||
/// Delaunay triangulation.
|
||||
/// </summary>
|
||||
public bool ConformingDelaunay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enclose the convex hull with segments.
|
||||
/// Gets or sets a value indicating whether to enclose the convex
|
||||
/// hull with segments.
|
||||
/// </summary>
|
||||
public bool Convex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Suppresses boundary segment splitting.
|
||||
/// Gets or sets a flag indicating whether to suppress boundary
|
||||
/// segment splitting.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 0 = split segments (default)
|
||||
@@ -35,7 +33,5 @@ namespace TriangleNet.Meshing
|
||||
/// 2 = prevent all segment splitting, including internal boundaries
|
||||
/// </remarks>
|
||||
public int SegmentSplitting { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,13 @@ namespace TriangleNet.Meshing
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// The DataReader class provides methods for mesh reconstruction.
|
||||
/// The Converter class provides methods for mesh reconstruction.
|
||||
/// </summary>
|
||||
public class Converter
|
||||
{
|
||||
/// <summary>
|
||||
/// Reconstruct a triangulation from its raw data representation.
|
||||
/// </summary>
|
||||
public Mesh ToMesh(Polygon polygon, IList<ITriangle> triangles)
|
||||
{
|
||||
return ToMesh(polygon, triangles.ToArray());
|
||||
@@ -26,25 +29,6 @@ namespace TriangleNet.Meshing
|
||||
/// <summary>
|
||||
/// Reconstruct a triangulation from its raw data representation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Reads an .ele file and reconstructs the original mesh. If the -p switch
|
||||
/// is used, this procedure will also read a .poly file and reconstruct the
|
||||
/// subsegments of the original mesh. If the -a switch is used, this
|
||||
/// procedure will also read an .area file and set a maximum area constraint
|
||||
/// on each triangle.
|
||||
///
|
||||
/// Vertices that are not corners of triangles, such as nodes on edges of
|
||||
/// subparametric elements, are discarded.
|
||||
///
|
||||
/// This routine finds the adjacencies between triangles (and subsegments)
|
||||
/// by forming one stack of triangles for each vertex. Each triangle is on
|
||||
/// three different stacks simultaneously. Each triangle's subsegment
|
||||
/// pointers are used to link the items in each stack. This memory-saving
|
||||
/// feature makes the code harder to read. The most important thing to keep
|
||||
/// in mind is that each triangle is removed from a stack precisely when
|
||||
/// the corresponding pointer is adjusted to refer to a subsegment rather
|
||||
/// than the next triangle of the stack.
|
||||
/// </remarks>
|
||||
public Mesh ToMesh(Polygon polygon, ITriangle[] triangles)
|
||||
{
|
||||
Otri tri = default(Otri);
|
||||
@@ -93,8 +77,8 @@ namespace TriangleNet.Meshing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the adjacencies between triangles by forming a stack of triangles
|
||||
/// for each vertex.
|
||||
/// Finds the adjacencies between triangles by forming a stack of triangles for
|
||||
/// each vertex. Each triangle is on three different stacks simultaneously.
|
||||
/// </summary>
|
||||
private static List<Otri>[] SetNeighbors(Mesh mesh, ITriangle[] triangles)
|
||||
{
|
||||
@@ -102,15 +86,14 @@ namespace TriangleNet.Meshing
|
||||
Otri triangleleft = default(Otri);
|
||||
Otri checktri = default(Otri);
|
||||
Otri checkleft = default(Otri);
|
||||
Otri nexttri; // Triangle
|
||||
Otri nexttri;
|
||||
Vertex tdest, tapex;
|
||||
Vertex checkdest, checkapex;
|
||||
int[] corner = new int[3];
|
||||
int aroundvertex;
|
||||
int i;
|
||||
|
||||
// Allocate a temporary array that maps each vertex to some adjacent
|
||||
// triangle.
|
||||
// Allocate a temporary array that maps each vertex to some adjacent triangle.
|
||||
var vertexarray = new List<Otri>[mesh.vertices.Count];
|
||||
|
||||
// Each vertex is initially unrepresented.
|
||||
@@ -164,11 +147,12 @@ namespace TriangleNet.Meshing
|
||||
{
|
||||
// Take the number for the origin of triangleloop.
|
||||
aroundvertex = corner[tri.orient];
|
||||
|
||||
int index = vertexarray[aroundvertex].Count - 1;
|
||||
|
||||
// Look for other triangles having this vertex.
|
||||
nexttri = vertexarray[aroundvertex][index];
|
||||
// Link the current triangle to the next one in the stack.
|
||||
//tri.triangle.neighbors[tri.orient] = nexttri;
|
||||
|
||||
// Push the current triangle onto the stack.
|
||||
vertexarray[aroundvertex].Add(tri);
|
||||
|
||||
@@ -212,6 +196,9 @@ namespace TriangleNet.Meshing
|
||||
return vertexarray;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the adjacencies between triangles and subsegments.
|
||||
/// </summary>
|
||||
private static void SetSegments(Mesh mesh, Polygon polygon, List<Otri>[] vertexarray)
|
||||
{
|
||||
Otri checktri = default(Otri);
|
||||
|
||||
@@ -7,6 +7,9 @@ namespace TriangleNet.Meshing
|
||||
using TriangleNet.IO;
|
||||
using TriangleNet.Meshing.Algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Create meshes of point sets or polygons.
|
||||
/// </summary>
|
||||
public class GenericMesher : ITriangulator, IConstraintMesher, IQualityMesher
|
||||
{
|
||||
ITriangulator triangulator;
|
||||
@@ -21,55 +24,31 @@ namespace TriangleNet.Meshing
|
||||
this.triangulator = triangulator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triangulates a point set.
|
||||
/// </summary>
|
||||
/// <param name="points">Collection of points.</param>
|
||||
/// <returns>Mesh</returns>
|
||||
/// <inherit />
|
||||
public IMesh Triangulate(ICollection<Vertex> points)
|
||||
{
|
||||
return triangulator.Triangulate(points);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triangulates a polygon.
|
||||
/// </summary>
|
||||
/// <param name="polygon">The polygon.</param>
|
||||
/// <returns>Mesh</returns>
|
||||
/// <inherit />
|
||||
public IMesh Triangulate(IPolygon polygon)
|
||||
{
|
||||
return Triangulate(polygon, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triangulates a polygon, applying constraint options.
|
||||
/// </summary>
|
||||
/// <param name="polygon">The polygon.</param>
|
||||
/// <param name="options">Constraint options.</param>
|
||||
/// <returns>Mesh</returns>
|
||||
/// <inherit />
|
||||
public IMesh Triangulate(IPolygon polygon, ConstraintOptions options)
|
||||
{
|
||||
return Triangulate(polygon, options, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triangulates a polygon, applying quality options.
|
||||
/// </summary>
|
||||
/// <param name="polygon">The polygon.</param>
|
||||
/// <param name="quality">Quality options.</param>
|
||||
/// <returns>Mesh</returns>
|
||||
/// <inherit />
|
||||
public IMesh Triangulate(IPolygon polygon, QualityOptions quality)
|
||||
{
|
||||
return Triangulate(polygon, null, quality);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triangulates a polygon, applying quality and constraint options.
|
||||
/// </summary>
|
||||
/// <param name="polygon">The polygon.</param>
|
||||
/// <param name="options">Constraint options.</param>
|
||||
/// <param name="quality">Quality options.</param>
|
||||
/// <returns>Mesh</returns>
|
||||
/// <inherit />
|
||||
public IMesh Triangulate(IPolygon polygon, ConstraintOptions options, QualityOptions quality)
|
||||
{
|
||||
var mesh = (Mesh)triangulator.Triangulate(polygon.Points);
|
||||
@@ -80,7 +59,7 @@ namespace TriangleNet.Meshing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a structured mesh with bounds (0, 0, width, height).
|
||||
/// Generates a structured mesh with bounds [0, 0, width, height].
|
||||
/// </summary>
|
||||
/// <param name="width">Width of the mesh (must be > 0).</param>
|
||||
/// <param name="height">Height of the mesh (must be > 0).</param>
|
||||
|
||||
@@ -3,9 +3,24 @@ namespace TriangleNet.Meshing
|
||||
{
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for polygon triangulation.
|
||||
/// </summary>
|
||||
public interface IConstraintMesher
|
||||
{
|
||||
/// <summary>
|
||||
/// Triangulates a polygon.
|
||||
/// </summary>
|
||||
/// <param name="polygon">The polygon.</param>
|
||||
/// <returns>Mesh</returns>
|
||||
IMesh Triangulate(IPolygon polygon);
|
||||
|
||||
/// <summary>
|
||||
/// Triangulates a polygon, applying constraint options.
|
||||
/// </summary>
|
||||
/// <param name="polygon">The polygon.</param>
|
||||
/// <param name="options">Constraint options.</param>
|
||||
/// <returns>Mesh</returns>
|
||||
IMesh Triangulate(IPolygon polygon, ConstraintOptions options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,17 +5,49 @@ namespace TriangleNet.Meshing
|
||||
using TriangleNet.Data;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Mesh interface.
|
||||
/// </summary>
|
||||
public interface IMesh
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the vertices of the mesh.
|
||||
/// </summary>
|
||||
ICollection<Vertex> Vertices { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the edges of the mesh.
|
||||
/// </summary>
|
||||
IEnumerable<Edge> Edges { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the segments (constraint edges) of the mesh.
|
||||
/// </summary>
|
||||
ICollection<Segment> Segments { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the triangles of the mesh.
|
||||
/// </summary>
|
||||
ICollection<Triangle> Triangles { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the holes of the mesh.
|
||||
/// </summary>
|
||||
IList<Point> Holes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bounds of the mesh.
|
||||
/// </summary>
|
||||
Rectangle Bounds { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Renumber mesh vertices and triangles.
|
||||
/// </summary>
|
||||
void Renumber();
|
||||
|
||||
/// <summary>
|
||||
/// Refine the mesh.
|
||||
/// </summary>
|
||||
void Refine(QualityOptions quality);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,26 @@ namespace TriangleNet.Meshing
|
||||
{
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for polygon triangulation with quality constraints.
|
||||
/// </summary>
|
||||
public interface IQualityMesher
|
||||
{
|
||||
/// <summary>
|
||||
/// Triangulates a polygon, applying quality options.
|
||||
/// </summary>
|
||||
/// <param name="polygon">The polygon.</param>
|
||||
/// <param name="quality">Quality options.</param>
|
||||
/// <returns>Mesh</returns>
|
||||
IMesh Triangulate(IPolygon polygon, QualityOptions quality);
|
||||
|
||||
/// <summary>
|
||||
/// Triangulates a polygon, applying quality and constraint options.
|
||||
/// </summary>
|
||||
/// <param name="polygon">The polygon.</param>
|
||||
/// <param name="options">Constraint options.</param>
|
||||
/// <param name="quality">Quality options.</param>
|
||||
/// <returns>Mesh</returns>
|
||||
IMesh Triangulate(IPolygon polygon, ConstraintOptions options, QualityOptions quality);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,15 @@ namespace TriangleNet.Meshing
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Update summary.
|
||||
/// Interface for point set triangulation.
|
||||
/// </summary>
|
||||
public interface ITriangulator
|
||||
{
|
||||
/// <summary>
|
||||
/// Triangulates a point set.
|
||||
/// </summary>
|
||||
/// <param name="points">Collection of points.</param>
|
||||
/// <returns>Mesh</returns>
|
||||
IMesh Triangulate(ICollection<Vertex> points);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,11 @@ namespace TriangleNet.Meshing
|
||||
using System;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Mesh constraint options for quality triangulation.
|
||||
/// </summary>
|
||||
public class QualityOptions
|
||||
{
|
||||
public static QualityOptions Empty
|
||||
{
|
||||
get { return new QualityOptions(); }
|
||||
}
|
||||
|
||||
#region Public properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a maximum angle constraint.
|
||||
/// </summary>
|
||||
@@ -29,10 +25,22 @@ namespace TriangleNet.Meshing
|
||||
public double MaximumArea { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Apply a user-defined triangle constraint.
|
||||
/// Gets or sets a user-defined triangle constraint.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The test function will be called for each triangle in the mesh. The
|
||||
/// second argument is the area of the triangle tested. If the function
|
||||
/// returns true, the triangle is considered bad and will be refined.
|
||||
/// </remarks>
|
||||
public Func<ITriangle, double, bool> UserTest { get; set; }
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Gets or sets a area constraint per triangle.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this flag is set to true, the <see cref="ITriangle.Area"/> value will
|
||||
/// be used to check if a triangle needs refinement.
|
||||
/// </remarks>
|
||||
public bool VariableArea { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,14 @@ namespace TriangleNet
|
||||
using TriangleNet.Tools;
|
||||
|
||||
/// <summary>
|
||||
/// Adaptive exact arithmetic geometric predicates.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The adaptive exact arithmetic geometric predicates implemented herein are described in
|
||||
/// detail in the paper "Adaptive Precision Floating-Point Arithmetic and Fast Robust
|
||||
/// Geometric Predicates." by Jonathan Richard Shewchuk, see
|
||||
/// http://www.cs.cmu.edu/~quake/robust.html
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///
|
||||
/// The macros of the original C code were automatically expanded using the Visual Studio
|
||||
/// command prompt with the command "CL /P /C EXACT.C", see
|
||||
/// http://msdn.microsoft.com/en-us/library/8z9z0bx6.aspx
|
||||
@@ -28,7 +30,7 @@ namespace TriangleNet
|
||||
private static double epsilon, splitter, resulterrbound;
|
||||
private static double ccwerrboundA, ccwerrboundB, ccwerrboundC;
|
||||
private static double iccerrboundA, iccerrboundB, iccerrboundC;
|
||||
private static double o3derrboundA, o3derrboundB, o3derrboundC;
|
||||
//private static double o3derrboundA, o3derrboundB, o3derrboundC;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the variables used for exact arithmetic.
|
||||
@@ -82,9 +84,9 @@ namespace TriangleNet
|
||||
iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
|
||||
iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
|
||||
iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
|
||||
o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
|
||||
o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
|
||||
o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
|
||||
//o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
|
||||
//o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
|
||||
//o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -237,15 +239,15 @@ namespace TriangleNet
|
||||
/// <summary>
|
||||
/// Find the circumcenter of a triangle.
|
||||
/// </summary>
|
||||
/// <param name="torg">Triangle point.</param>
|
||||
/// <param name="tdest">Triangle point.</param>
|
||||
/// <param name="tapex">Triangle point.</param>
|
||||
/// <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>
|
||||
public static Point FindCircumcenter(Point torg, Point tdest, Point tapex,
|
||||
ref double xi, ref double eta, double offconstant)
|
||||
public static Point FindCircumcenter(Point org, Point dest, Point apex,
|
||||
ref double xi, ref double eta, double offconstant)
|
||||
{
|
||||
double xdo, ydo, xao, yao;
|
||||
double dodist, aodist, dadist;
|
||||
@@ -255,14 +257,14 @@ namespace TriangleNet
|
||||
Statistic.CircumcenterCount++;
|
||||
|
||||
// Compute the circumcenter of the triangle.
|
||||
xdo = tdest.x - torg.x;
|
||||
ydo = tdest.y - torg.y;
|
||||
xao = tapex.x - torg.x;
|
||||
yao = tapex.y - torg.y;
|
||||
xdo = dest.x - org.x;
|
||||
ydo = dest.y - org.y;
|
||||
xao = apex.x - org.x;
|
||||
yao = apex.y - org.y;
|
||||
dodist = xdo * xdo + ydo * ydo;
|
||||
aodist = xao * xao + yao * yao;
|
||||
dadist = (tdest.x - tapex.x) * (tdest.x - tapex.x) +
|
||||
(tdest.y - tapex.y) * (tdest.y - tapex.y);
|
||||
dadist = (dest.x - apex.x) * (dest.x - apex.x) +
|
||||
(dest.y - apex.y) * (dest.y - apex.y);
|
||||
|
||||
if (Behavior.NoExact)
|
||||
{
|
||||
@@ -273,7 +275,7 @@ namespace TriangleNet
|
||||
// Use the counterclockwise() routine to ensure a positive (and
|
||||
// reasonably accurate) result, avoiding any possibility of
|
||||
// division by zero.
|
||||
denominator = 0.5 / CounterClockwise(tdest, tapex, torg);
|
||||
denominator = 0.5 / CounterClockwise(dest, apex, org);
|
||||
// Don't count the above as an orientation test.
|
||||
Statistic.CounterClockwiseCount--;
|
||||
}
|
||||
@@ -321,8 +323,8 @@ namespace TriangleNet
|
||||
{
|
||||
if (offconstant > 0.0)
|
||||
{
|
||||
dxoff = 0.5 * (tapex.x - tdest.x) - offconstant * (tapex.y - tdest.y);
|
||||
dyoff = 0.5 * (tapex.y - tdest.y) + offconstant * (tapex.x - tdest.x);
|
||||
dxoff = 0.5 * (apex.x - dest.x) - offconstant * (apex.y - dest.y);
|
||||
dyoff = 0.5 * (apex.y - dest.y) + offconstant * (apex.x - dest.x);
|
||||
// If the off-center is closer to the destination than the
|
||||
// circumcenter, use the off-center instead.
|
||||
if (dxoff * dxoff + dyoff * dyoff <
|
||||
@@ -342,15 +344,15 @@ namespace TriangleNet
|
||||
xi = (yao * dx - xao * dy) * (2.0 * denominator);
|
||||
eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
|
||||
|
||||
return new Point(torg.x + dx, torg.y + dy);
|
||||
return new Point(org.x + dx, org.y + dy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the circumcenter of a triangle.
|
||||
/// </summary>
|
||||
/// <param name="torg">Triangle point.</param>
|
||||
/// <param name="tdest">Triangle point.</param>
|
||||
/// <param name="tapex">Triangle point.</param>
|
||||
/// <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>
|
||||
@@ -363,8 +365,8 @@ namespace TriangleNet
|
||||
/// This procedure also returns the square of the length of the triangle's
|
||||
/// shortest edge.
|
||||
/// </remarks>
|
||||
public static Point FindCircumcenter(Point torg, Point tdest, Point tapex,
|
||||
ref double xi, ref double eta)
|
||||
public static Point FindCircumcenter(Point org, Point dest, Point apex,
|
||||
ref double xi, ref double eta)
|
||||
{
|
||||
double xdo, ydo, xao, yao;
|
||||
double dodist, aodist;
|
||||
@@ -374,10 +376,10 @@ namespace TriangleNet
|
||||
Statistic.CircumcenterCount++;
|
||||
|
||||
// Compute the circumcenter of the triangle.
|
||||
xdo = tdest.x - torg.x;
|
||||
ydo = tdest.y - torg.y;
|
||||
xao = tapex.x - torg.x;
|
||||
yao = tapex.y - torg.y;
|
||||
xdo = dest.x - org.x;
|
||||
ydo = dest.y - org.y;
|
||||
xao = apex.x - org.x;
|
||||
yao = apex.y - org.y;
|
||||
dodist = xdo * xdo + ydo * ydo;
|
||||
aodist = xao * xao + yao * yao;
|
||||
|
||||
@@ -390,7 +392,7 @@ namespace TriangleNet
|
||||
// Use the counterclockwise() routine to ensure a positive (and
|
||||
// reasonably accurate) result, avoiding any possibility of
|
||||
// division by zero.
|
||||
denominator = 0.5 / CounterClockwise(tdest, tapex, torg);
|
||||
denominator = 0.5 / CounterClockwise(dest, apex, org);
|
||||
// Don't count the above as an orientation test.
|
||||
Statistic.CounterClockwiseCount--;
|
||||
}
|
||||
@@ -406,7 +408,7 @@ namespace TriangleNet
|
||||
xi = (yao * dx - xao * dy) * (2.0 * denominator);
|
||||
eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
|
||||
|
||||
return new Point(torg.x + dx, torg.y + dy);
|
||||
return new Point(org.x + dx, org.y + dy);
|
||||
}
|
||||
|
||||
#region Exact arithmetics
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Sampler.cs">
|
||||
// Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
@@ -11,7 +12,7 @@ namespace TriangleNet
|
||||
using System.Linq;
|
||||
|
||||
/// <summary>
|
||||
/// Used for triangle sampling in the Mesh.Locate method.
|
||||
/// Used for triangle sampling in the <see cref="TriangleLocator"/> class.
|
||||
/// </summary>
|
||||
class Sampler
|
||||
{
|
||||
|
||||
@@ -315,7 +315,7 @@ namespace TriangleNet.Tools
|
||||
sfn.seg = subsegMap[f_next.triangle.hash];
|
||||
|
||||
// Insert point Lf,f_next /\ Sf_next into P
|
||||
if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
|
||||
if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
|
||||
{
|
||||
p.id = n + segIndex++;
|
||||
segPoints.Add(p);
|
||||
@@ -332,7 +332,7 @@ namespace TriangleNet.Tools
|
||||
if (!f_next.triangle.infected)
|
||||
{
|
||||
// Insert point Lf,f_next /\ Sf into P
|
||||
if (SegmentsIntersect(sf.SegOrg(), sf.SegDest(), cc_f, cc_f_next, out p, true))
|
||||
if (SegmentsIntersect(sf.Org(), sf.Dest(), cc_f, cc_f_next, out p, true))
|
||||
{
|
||||
p.id = n + segIndex++;
|
||||
segPoints.Add(p);
|
||||
@@ -348,14 +348,14 @@ namespace TriangleNet.Tools
|
||||
if (!sf.Equal(sfn))
|
||||
{
|
||||
// Insert Lf,fnext /\ Sf and Lf,fnext /\ Sfnext into P
|
||||
if (SegmentsIntersect(sf.SegOrg(), sf.SegDest(), cc_f, cc_f_next, out p, true))
|
||||
if (SegmentsIntersect(sf.Org(), sf.Dest(), cc_f, cc_f_next, out p, true))
|
||||
{
|
||||
p.id = n + segIndex++;
|
||||
segPoints.Add(p);
|
||||
vpoints.Add(p);
|
||||
}
|
||||
|
||||
if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
|
||||
if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
|
||||
{
|
||||
p.id = n + segIndex++;
|
||||
segPoints.Add(p);
|
||||
@@ -486,7 +486,7 @@ namespace TriangleNet.Tools
|
||||
sfn.seg = subsegMap[f_next.triangle.hash];
|
||||
|
||||
// Insert point Lf,f_next /\ Sf_next into P
|
||||
if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
|
||||
if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
|
||||
{
|
||||
p.id = n + segIndex++;
|
||||
segPoints.Add(p);
|
||||
@@ -499,8 +499,8 @@ namespace TriangleNet.Tools
|
||||
// Call Sf the constrained edge blinding f
|
||||
sf.seg = subsegMap[f.triangle.hash];
|
||||
|
||||
sorg = sf.SegOrg();
|
||||
sdest = sf.SegDest();
|
||||
sorg = sf.Org();
|
||||
sdest = sf.Dest();
|
||||
|
||||
// if f_next is tagged non-blind then
|
||||
if (!f_next.triangle.infected)
|
||||
@@ -546,7 +546,7 @@ namespace TriangleNet.Tools
|
||||
vpoints.Add(p);
|
||||
}
|
||||
|
||||
if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
|
||||
if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
|
||||
{
|
||||
p.id = n + segIndex++;
|
||||
segPoints.Add(p);
|
||||
|
||||
@@ -55,20 +55,17 @@ namespace TriangleNet.Tools
|
||||
var point = new Point(x, y);
|
||||
var indices = root.FindTriangles(point);
|
||||
|
||||
var result = new List<ITriangle>();
|
||||
|
||||
foreach (var i in indices)
|
||||
{
|
||||
var tri = this.triangles[i];
|
||||
|
||||
if (IsPointInTriangle(point, tri.GetVertex(0), tri.GetVertex(1), tri.GetVertex(2)))
|
||||
{
|
||||
result.Add(tri);
|
||||
break;
|
||||
return tri;
|
||||
}
|
||||
}
|
||||
|
||||
return result.FirstOrDefault();
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
namespace TriangleNet.Tools
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
using TriangleNet.Data;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
@@ -109,66 +108,6 @@ namespace TriangleNet.Tools
|
||||
/// </summary>
|
||||
public double LargestAngle { get { return maxAngle; } }
|
||||
|
||||
int inVetrices = 0;
|
||||
/// <summary>
|
||||
/// Gets the number of input vertices.
|
||||
/// </summary>
|
||||
public int InputVertices { get { return inVetrices; } }
|
||||
|
||||
int inTriangles = 0;
|
||||
/// <summary>
|
||||
/// Gets the number of input triangles.
|
||||
/// </summary>
|
||||
public int InputTriangles { get { return inTriangles; } }
|
||||
|
||||
int inSegments = 0;
|
||||
/// <summary>
|
||||
/// Gets the number of input segments.
|
||||
/// </summary>
|
||||
public int InputSegments { get { return inSegments; } }
|
||||
|
||||
int inHoles = 0;
|
||||
/// <summary>
|
||||
/// Gets the number of input holes.
|
||||
/// </summary>
|
||||
public int InputHoles { get { return inHoles; } }
|
||||
|
||||
int outVertices = 0;
|
||||
/// <summary>
|
||||
/// Gets the number of mesh vertices.
|
||||
/// </summary>
|
||||
public int Vertices { get { return outVertices; } }
|
||||
|
||||
int outTriangles = 0;
|
||||
/// <summary>
|
||||
/// Gets the number of mesh triangles.
|
||||
/// </summary>
|
||||
public int Triangles { get { return outTriangles; } }
|
||||
|
||||
int outEdges = 0;
|
||||
/// <summary>
|
||||
/// Gets the number of mesh edges.
|
||||
/// </summary>
|
||||
public int Edges { get { return outEdges; } }
|
||||
|
||||
int boundaryEdges = 0;
|
||||
/// <summary>
|
||||
/// Gets the number of exterior boundary edges.
|
||||
/// </summary>
|
||||
public int BoundaryEdges { get { return boundaryEdges; } }
|
||||
|
||||
int intBoundaryEdges = 0;
|
||||
/// <summary>
|
||||
/// Gets the number of interior boundary edges.
|
||||
/// </summary>
|
||||
public int InteriorBoundaryEdges { get { return intBoundaryEdges; } }
|
||||
|
||||
int constrainedEdges = 0;
|
||||
/// <summary>
|
||||
/// Gets the number of constrained edges.
|
||||
/// </summary>
|
||||
public int ConstrainedEdges { get { return constrainedEdges; } }
|
||||
|
||||
int[] angleTable;
|
||||
/// <summary>
|
||||
/// Gets the angle histogram.
|
||||
@@ -264,17 +203,6 @@ namespace TriangleNet.Tools
|
||||
/// <param name="mesh"></param>
|
||||
public void Update(Mesh mesh, int sampleDegrees)
|
||||
{
|
||||
inVetrices = mesh.invertices;
|
||||
inTriangles = mesh.inelements;
|
||||
inSegments = mesh.insegments;
|
||||
inHoles = mesh.holes.Count;
|
||||
outVertices = mesh.vertices.Count - mesh.undeads;
|
||||
outTriangles = mesh.triangles.Count;
|
||||
outEdges = (int)mesh.edges;
|
||||
boundaryEdges = (int)mesh.hullsize;
|
||||
intBoundaryEdges = mesh.subsegs.Count - (int)mesh.hullsize;
|
||||
constrainedEdges = mesh.subsegs.Count;
|
||||
|
||||
Point[] p = new Point[3];
|
||||
|
||||
int k1, k2;
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Data;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
namespace TriangleNet.Tools
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Data;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// The Voronoi Diagram is the dual of a pointset triangulation.
|
||||
/// </summary>
|
||||
@@ -103,7 +103,7 @@ namespace TriangleNet.Tools
|
||||
{
|
||||
//if (item.Boundary == 0)
|
||||
{
|
||||
ConstructVoronoiRegion(region);
|
||||
ConstructCell(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,9 +134,8 @@ namespace TriangleNet.Tools
|
||||
/// <summary>
|
||||
/// Construct Voronoi region for given vertex.
|
||||
/// </summary>
|
||||
/// <param name="vertex"></param>
|
||||
/// <returns>The circumcenter indices which make up the cell.</returns>
|
||||
private void ConstructVoronoiRegion(VoronoiRegion region)
|
||||
/// <param name="region"></param>
|
||||
private void ConstructCell(VoronoiRegion region)
|
||||
{
|
||||
var vertex = region.Generator as Vertex;
|
||||
|
||||
|
||||
@@ -11,8 +11,12 @@ namespace TriangleNet
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Update summary.
|
||||
/// Locate triangles in a mesh.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// WARNING: This routine is designed for convex triangulations, and will
|
||||
/// not generally work after the holes and concavities have been carved.
|
||||
/// </remarks>
|
||||
class TriangleLocator
|
||||
{
|
||||
Sampler sampler;
|
||||
|
||||
Reference in New Issue
Block a user