git-svn-id: https://triangle.svn.codeplex.com/svn@78017 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
@@ -76,8 +76,8 @@ namespace TriangleNet.Geometry
|
||||
/// <summary>
|
||||
/// Try to find a point inside the contour.
|
||||
/// </summary>
|
||||
/// <param name="limit">The number of iterations on each segment (default = 8).</param>
|
||||
/// <param name="eps">Threshold for co-linear points (default = 2e-6).</param>
|
||||
/// <param name="limit">The number of iterations on each segment (default = 5).</param>
|
||||
/// <param name="eps">Threshold for co-linear points (default = 2e-5).</param>
|
||||
/// <returns>Point inside the contour</returns>
|
||||
/// <exception cref="Exception">Throws if no point could be found.</exception>
|
||||
/// <remarks>
|
||||
@@ -86,16 +86,16 @@ namespace TriangleNet.Geometry
|
||||
/// on the bisecting line, or, if <see cref="IPredicates.CounterClockwise"/> is less than
|
||||
/// eps, on the perpendicular line.
|
||||
/// A given number of points will be tested (limit), while the distance to the contour
|
||||
/// boundary will be reduced in each iteration (with a factor of 1/2^i, i = 1 ... limit).
|
||||
/// boundary will be reduced in each iteration (with a factor 1 / 2^i, i = 1 ... limit).
|
||||
/// </remarks>
|
||||
public Point FindInteriorPoint(int limit = 8, double eps = 2e-6)
|
||||
public Point FindInteriorPoint(int limit = 5, double eps = 2e-5)
|
||||
{
|
||||
var point = new Point(0.0, 0.0);
|
||||
|
||||
if (convex)
|
||||
{
|
||||
int count = this.Points.Count;
|
||||
|
||||
var point = new Point(0.0, 0.0);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
point.x += this.Points[i].x;
|
||||
@@ -152,8 +152,8 @@ namespace TriangleNet.Geometry
|
||||
c = contour[(i + 2) % length];
|
||||
|
||||
// Corner point.
|
||||
bx = b.X;
|
||||
by = b.Y;
|
||||
bx = b.x;
|
||||
by = b.y;
|
||||
|
||||
// NOTE: if we knew the contour points were in counterclockwise order, we
|
||||
// could skip concave corners and search only in one direction.
|
||||
@@ -163,14 +163,14 @@ namespace TriangleNet.Geometry
|
||||
if (Math.Abs(h) < eps)
|
||||
{
|
||||
// Points are nearly co-linear. Use perpendicular direction.
|
||||
dx = (c.Y - a.Y) / 2;
|
||||
dy = (a.X - c.X) / 2;
|
||||
dx = (c.y - a.y) / 2;
|
||||
dy = (a.x - c.x) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Direction [midpoint(a-c) -> corner point]
|
||||
dx = (a.X + c.X) / 2 - bx;
|
||||
dy = (a.Y + c.Y) / 2 - by;
|
||||
dx = (a.x + c.x) / 2 - bx;
|
||||
dy = (a.y + c.y) / 2 - by;
|
||||
}
|
||||
|
||||
// Move around the contour.
|
||||
@@ -182,8 +182,8 @@ namespace TriangleNet.Geometry
|
||||
for (int j = 0; j < limit; j++)
|
||||
{
|
||||
// Search in direction.
|
||||
test.X = bx + dx / h;
|
||||
test.Y = by + dy / h;
|
||||
test.x = bx + dx * h;
|
||||
test.y = by + dy * h;
|
||||
|
||||
if (bounds.Contains(test) && IsPointInPolygon(test, contour))
|
||||
{
|
||||
@@ -191,15 +191,15 @@ namespace TriangleNet.Geometry
|
||||
}
|
||||
|
||||
// Search in opposite direction (see NOTE above).
|
||||
test.X = bx - dx / h;
|
||||
test.Y = by - dy / h;
|
||||
test.x = bx - dx * h;
|
||||
test.y = by - dy * h;
|
||||
|
||||
if (bounds.Contains(test) && IsPointInPolygon(test, contour))
|
||||
{
|
||||
return test;
|
||||
}
|
||||
|
||||
h = 2.0 * h;
|
||||
h = h / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace TriangleNet.Geometry
|
||||
#endif
|
||||
|
||||
public Point()
|
||||
: this(0, 0, 0)
|
||||
: this(0.0, 0.0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,30 @@ namespace TriangleNet.Geometry
|
||||
|
||||
int label;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the segments boundary mark.
|
||||
/// </summary>
|
||||
public int Label
|
||||
{
|
||||
get { return label; }
|
||||
set { label = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the first endpoints index.
|
||||
/// </summary>
|
||||
public int P0
|
||||
{
|
||||
get { return v0.id; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the second endpoints index.
|
||||
/// </summary>
|
||||
public int P1
|
||||
{
|
||||
get { return v1.id; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Segment" /> class.
|
||||
/// </summary>
|
||||
@@ -64,30 +88,5 @@ namespace TriangleNet.Geometry
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first endpoints index.
|
||||
/// </summary>
|
||||
public int P0
|
||||
{
|
||||
get { return v0.id; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the second endpoints index.
|
||||
/// </summary>
|
||||
public int P1
|
||||
{
|
||||
get { return v1.id; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the segments boundary mark.
|
||||
/// </summary>
|
||||
public int Label
|
||||
{
|
||||
get { return label; }
|
||||
set { label = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace TriangleNet.IO
|
||||
{
|
||||
public bool IsSupported(string file)
|
||||
{
|
||||
string ext = Path.GetExtension(file);
|
||||
string ext = Path.GetExtension(file).ToLower();
|
||||
|
||||
if (ext == ".node" || ext == ".poly" || ext == ".ele")
|
||||
{
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
|
||||
namespace TriangleNet.Meshing.Iterators
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Topology;
|
||||
|
||||
public class VertexCirculator
|
||||
{
|
||||
List<Otri> cache = new List<Otri>();
|
||||
|
||||
Mesh mesh;
|
||||
|
||||
public VertexCirculator(Mesh mesh)
|
||||
{
|
||||
this.mesh = mesh;
|
||||
|
||||
mesh.MakeVertexMap();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerate all vertices adjacent to given vertex.
|
||||
/// </summary>
|
||||
/// <param name="vertex">The center vertex.</param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<Vertex> EnumerateVertices(Vertex vertex)
|
||||
{
|
||||
BuildCache(vertex, true);
|
||||
|
||||
foreach (var item in cache)
|
||||
{
|
||||
yield return item.Dest();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerate all triangles adjacent to given vertex.
|
||||
/// </summary>
|
||||
/// <param name="vertex">The center vertex.</param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<ITriangle> EnumerateTriangles(Vertex vertex)
|
||||
{
|
||||
BuildCache(vertex, false);
|
||||
|
||||
foreach (var item in cache)
|
||||
{
|
||||
yield return item.tri;
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildCache(Vertex vertex, bool vertices)
|
||||
{
|
||||
cache.Clear();
|
||||
|
||||
Otri init = vertex.tri;
|
||||
Otri next = default(Otri);
|
||||
Otri prev = default(Otri);
|
||||
|
||||
init.Copy(ref next);
|
||||
|
||||
// Move counter-clockwise around the vertex.
|
||||
while (next.tri.id != Mesh.DUMMY)
|
||||
{
|
||||
cache.Add(next);
|
||||
|
||||
next.Copy(ref prev);
|
||||
next.Onext();
|
||||
|
||||
if (next.Equals(init))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (next.tri.id == Mesh.DUMMY)
|
||||
{
|
||||
// We reached the boundary. To get all adjacent triangles, start
|
||||
// again at init triangle and now move clockwise.
|
||||
init.Copy(ref next);
|
||||
|
||||
if (vertices)
|
||||
{
|
||||
// Don't forget to add the vertex lying on the boundary.
|
||||
prev.Lnext();
|
||||
cache.Add(prev);
|
||||
}
|
||||
|
||||
next.Oprev();
|
||||
|
||||
while (next.tri.id != Mesh.DUMMY)
|
||||
{
|
||||
cache.Insert(0, next);
|
||||
|
||||
next.Oprev();
|
||||
|
||||
if (next.Equals(init))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,8 @@ namespace TriangleNet.Smoothing
|
||||
/// </remarks>
|
||||
public class SimpleSmoother : ISmoother
|
||||
{
|
||||
IPredicates predicates;
|
||||
TrianglePool pool;
|
||||
Configuration config;
|
||||
|
||||
IVoronoiFactory factory;
|
||||
|
||||
@@ -30,19 +31,34 @@ namespace TriangleNet.Smoothing
|
||||
/// Initializes a new instance of the <see cref="SimpleSmoother" /> class.
|
||||
/// </summary>
|
||||
public SimpleSmoother()
|
||||
: this(new VoronoiFactory(), RobustPredicates.Default)
|
||||
: this(new VoronoiFactory())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SimpleSmoother" /> class.
|
||||
/// </summary>
|
||||
/// <param name="factory">Voronoi object factory.</param>
|
||||
/// <param name="predicates">Geometric predicates implementation.</param>
|
||||
public SimpleSmoother(IVoronoiFactory factory, IPredicates predicates)
|
||||
public SimpleSmoother(IVoronoiFactory factory)
|
||||
{
|
||||
this.factory = factory;
|
||||
this.predicates = predicates;
|
||||
this.pool = new TrianglePool();
|
||||
|
||||
this.config = new Configuration(
|
||||
() => RobustPredicates.Default,
|
||||
() => pool.Restart());
|
||||
|
||||
this.options = new ConstraintOptions() { ConformingDelaunay = true };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SimpleSmoother" /> class.
|
||||
/// </summary>
|
||||
/// <param name="factory">Voronoi object factory.</param>
|
||||
/// <param name="config">Configuration.</param>
|
||||
public SimpleSmoother(IVoronoiFactory factory, Configuration config)
|
||||
{
|
||||
this.factory = factory;
|
||||
this.config = config;
|
||||
|
||||
this.options = new ConstraintOptions() { ConformingDelaunay = true };
|
||||
}
|
||||
@@ -56,18 +72,21 @@ namespace TriangleNet.Smoothing
|
||||
{
|
||||
var smoothedMesh = (Mesh)mesh;
|
||||
|
||||
var mesher = new GenericMesher(config);
|
||||
var predicates = config.Predicates();
|
||||
|
||||
// The smoother should respect the mesh segment splitting behavior.
|
||||
this.options.SegmentSplitting = smoothedMesh.behavior.NoBisect;
|
||||
|
||||
// Take a few smoothing rounds (Lloyd's algorithm).
|
||||
for (int i = 0; i < limit; i++)
|
||||
{
|
||||
Step(smoothedMesh, factory);
|
||||
Step(smoothedMesh, factory, predicates);
|
||||
|
||||
// Actually, we only want to rebuild, if mesh is no longer
|
||||
// Actually, we only want to rebuild, if the mesh is no longer
|
||||
// Delaunay. Flipping edges could be the right choice instead
|
||||
// of re-triangulating...
|
||||
smoothedMesh = (Mesh)Rebuild(smoothedMesh).Triangulate(options);
|
||||
smoothedMesh = (Mesh)mesher.Triangulate(Rebuild(smoothedMesh), options);
|
||||
|
||||
factory.Reset();
|
||||
}
|
||||
@@ -75,7 +94,7 @@ namespace TriangleNet.Smoothing
|
||||
smoothedMesh.CopyTo((Mesh)mesh);
|
||||
}
|
||||
|
||||
private void Step(Mesh mesh, IVoronoiFactory factory)
|
||||
private void Step(Mesh mesh, IVoronoiFactory factory, IPredicates predicates)
|
||||
{
|
||||
var voronoi = new BoundedVoronoi(mesh, factory, predicates);
|
||||
|
||||
|
||||
@@ -40,11 +40,10 @@ namespace TriangleNet.Tools
|
||||
dx = vertex.x - org.x;
|
||||
dy = vertex.y - org.y;
|
||||
|
||||
// To interpolate vertex attributes for the new vertex inserted at
|
||||
// the circumcenter, define a coordinate system with a xi-axis,
|
||||
// directed from the triangle's origin to its destination, and
|
||||
// an eta-axis, directed from its origin to its apex.
|
||||
// Calculate the xi and eta coordinates of the circumcenter.
|
||||
// To interpolate vertex attributes for the new vertex, define a
|
||||
// coordinate system with a xi-axis directed from the triangle's
|
||||
// origin to its destination, and an eta-axis, directed from its
|
||||
// origin to its apex.
|
||||
xi = (yao * dx - xao * dy) * (2.0 * denominator);
|
||||
eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
<Compile Include="Meshing\IConstraintMesher.cs" />
|
||||
<Compile Include="Meshing\IMesh.cs" />
|
||||
<Compile Include="Meshing\IQualityMesher.cs" />
|
||||
<Compile Include="Meshing\Iterators\VertexCirculator.cs" />
|
||||
<Compile Include="Meshing\ITriangulator.cs" />
|
||||
<Compile Include="Meshing\QualityOptions.cs" />
|
||||
<Compile Include="Meshing\QualityMesher.cs" />
|
||||
|
||||
@@ -298,7 +298,7 @@ namespace TriangleNet
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
index = 0;
|
||||
index = offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user