Added 'TriangleNet.Voronoi' namespace,
Added new Voronoi code (edge based construction), Moved old Voronoi code to 'Legacy' namespace git-svn-id: https://triangle.svn.codeplex.com/svn@75112 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
@@ -12,6 +12,7 @@ using TriangleNet.Meshing.Algorithm;
|
||||
using TriangleNet.Tools;
|
||||
using TriangleNet.Smoothing;
|
||||
using TriangleNet.Rendering;
|
||||
using TriangleNet.Voronoi.Legacy;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
@@ -611,7 +612,7 @@ namespace MeshExplorer
|
||||
|
||||
if (mesh.IsPolygon)
|
||||
{
|
||||
this.voronoi = new BoundedVoronoi(mesh);
|
||||
this.voronoi = new BoundedVoronoiLegacy(mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace TriangleNet.Rendering
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Tools;
|
||||
using TriangleNet.Voronoi.Legacy;
|
||||
|
||||
public interface IRenderContext
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace TriangleNet.Rendering
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Rendering.Buffer;
|
||||
using TriangleNet.Rendering.Util;
|
||||
using TriangleNet.Tools;
|
||||
using TriangleNet.Voronoi.Legacy;
|
||||
|
||||
public interface IRenderLayer
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace TriangleNet.Rendering
|
||||
using System.Linq;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Tools;
|
||||
using TriangleNet.Voronoi.Legacy;
|
||||
|
||||
/// <summary>
|
||||
/// The RenderContext class brings all the rendering parts together.
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace TriangleNet.Rendering
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Rendering.Buffer;
|
||||
using TriangleNet.Rendering.Util;
|
||||
using TriangleNet.Tools;
|
||||
using TriangleNet.Voronoi.Legacy;
|
||||
|
||||
public class RenderLayer : IRenderLayer
|
||||
{
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Rendering.GDI;
|
||||
using TriangleNet.Tools;
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Rendering.Util;
|
||||
using TriangleNet.Voronoi.Legacy;
|
||||
|
||||
public class RenderManager
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace TriangleNet.Smoothing
|
||||
{
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Tools;
|
||||
using TriangleNet.Voronoi.Legacy;
|
||||
|
||||
/// <summary>
|
||||
/// Simple mesh smoother implementation.
|
||||
@@ -54,7 +54,7 @@ namespace TriangleNet.Smoothing
|
||||
/// </summary>
|
||||
private void Step(Mesh mesh)
|
||||
{
|
||||
BoundedVoronoi voronoi = new BoundedVoronoi(mesh, false);
|
||||
BoundedVoronoiLegacy voronoi = new BoundedVoronoiLegacy(mesh, false);
|
||||
|
||||
var cells = voronoi.Regions;
|
||||
|
||||
|
||||
@@ -96,17 +96,23 @@
|
||||
<Compile Include="Smoothing\ISmoother.cs" />
|
||||
<Compile Include="Smoothing\SimpleSmoother.cs" />
|
||||
<Compile Include="Tools\AdjacencyMatrix.cs" />
|
||||
<Compile Include="Tools\BoundedVoronoi.cs" />
|
||||
<Compile Include="Voronoi\Legacy\BoundedVoronoiLegacy.cs" />
|
||||
<Compile Include="Tools\CuthillMcKee.cs" />
|
||||
<Compile Include="Tools\IVoronoi.cs" />
|
||||
<Compile Include="Voronoi\Legacy\IVoronoi.cs" />
|
||||
<Compile Include="Tools\QuadTree.cs" />
|
||||
<Compile Include="Tools\QualityMeasure.cs" />
|
||||
<Compile Include="Meshing\Iterators\RegionIterator.cs" />
|
||||
<Compile Include="Tools\Statistic.cs" />
|
||||
<Compile Include="Meshing\Algorithm\SweepLine.cs" />
|
||||
<Compile Include="Tools\Voronoi.cs" />
|
||||
<Compile Include="Tools\VoronoiRegion.cs" />
|
||||
<Compile Include="Voronoi\Legacy\Voronoi.cs" />
|
||||
<Compile Include="Voronoi\Legacy\VoronoiRegion.cs" />
|
||||
<Compile Include="TriangleLocator.cs" />
|
||||
<Compile Include="Voronoi\BoundedVoronoi.cs" />
|
||||
<Compile Include="Voronoi\DCEL\Face.cs" />
|
||||
<Compile Include="Voronoi\DCEL\HalfEdge.cs" />
|
||||
<Compile Include="Voronoi\DCEL\Vertex.cs" />
|
||||
<Compile Include="Voronoi\StandardVoronoi.cs" />
|
||||
<Compile Include="Voronoi\VoronoiBase.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="BoundedVoronoi.cs">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Voronoi
|
||||
{
|
||||
public class BoundedVoronoi : VoronoiBase
|
||||
{
|
||||
public BoundedVoronoi(Mesh mesh)
|
||||
: base(mesh, true)
|
||||
{
|
||||
// We explicitly told the base constructor to call the Generate method, so
|
||||
// at this point the basic Voronoi diagram is already created.
|
||||
PostProcess();
|
||||
}
|
||||
|
||||
private void PostProcess()
|
||||
{
|
||||
// Compute edge intersections with mesh boundary edges.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Face.cs">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Voronoi.DCEL
|
||||
{
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// A face of DCEL mesh.
|
||||
/// </summary>
|
||||
public class Face
|
||||
{
|
||||
internal Point generator;
|
||||
|
||||
internal HalfEdge edge;
|
||||
internal bool bounded;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a half-edge connected to the face.
|
||||
/// </summary>
|
||||
public HalfEdge Edge
|
||||
{
|
||||
get { return edge; }
|
||||
set { edge = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value, indicating if the face is bounded (for Voronoi diagram).
|
||||
/// </summary>
|
||||
public bool Bounded
|
||||
{
|
||||
get { return bounded; }
|
||||
set { bounded = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Face" /> class.
|
||||
/// </summary>
|
||||
/// <param name="generator">The generator of this face (for Voronoi diagram)</param>
|
||||
public Face(Point generator)
|
||||
: this(generator, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Face" /> class.
|
||||
/// </summary>
|
||||
/// <param name="generator">The generator of this face (for Voronoi diagram)</param>
|
||||
/// <param name="edge">The half-edge connected to this face.</param>
|
||||
public Face(Point generator, HalfEdge edge)
|
||||
{
|
||||
this.generator = generator;
|
||||
this.edge = edge;
|
||||
this.bounded = true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("F-ID {0}", generator.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="HalfEdge.cs">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Voronoi.DCEL
|
||||
{
|
||||
public class HalfEdge
|
||||
{
|
||||
internal int id;
|
||||
|
||||
internal Vertex origin;
|
||||
internal Face face;
|
||||
internal HalfEdge twin;
|
||||
internal HalfEdge next;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the origin of the half-edge.
|
||||
/// </summary>
|
||||
public Vertex Origin
|
||||
{
|
||||
get { return origin; }
|
||||
set { origin = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the face connected to the half-edge.
|
||||
/// </summary>
|
||||
public Face Face
|
||||
{
|
||||
get { return face; }
|
||||
set { face = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the twin of the half-edge.
|
||||
/// </summary>
|
||||
public HalfEdge Twin
|
||||
{
|
||||
get { return twin; }
|
||||
set { twin = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the next pointer of the half-edge.
|
||||
/// </summary>
|
||||
public HalfEdge Next
|
||||
{
|
||||
get { return next; }
|
||||
set { next = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HalfEdge" /> class.
|
||||
/// </summary>
|
||||
/// <param name="origin">The origin of this half-edge.</param>
|
||||
public HalfEdge(Vertex origin)
|
||||
{
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HalfEdge" /> class.
|
||||
/// </summary>
|
||||
/// <param name="origin">The origin of this half-edge.</param>
|
||||
/// <param name="face">The face connected to this half-edge.</param>
|
||||
public HalfEdge(Vertex origin, Face face)
|
||||
{
|
||||
this.origin = origin;
|
||||
this.face = face;
|
||||
|
||||
// IMPORTANT: do not remove the (this.face == null) check!
|
||||
if (face != null && this.face.edge == null)
|
||||
{
|
||||
face.edge = this;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("HE-ID {0} (Origin = VID-{1})", id, origin.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Vertex.cs">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Voronoi.DCEL
|
||||
{
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
public class Vertex : Point
|
||||
{
|
||||
internal HalfEdge leaving;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a half-edge leaving the vertex.
|
||||
/// </summary>
|
||||
public HalfEdge Leaving
|
||||
{
|
||||
get { return leaving; }
|
||||
set { leaving = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Vertex" /> class.
|
||||
/// </summary>
|
||||
/// <param name="x">The x coordinate.</param>
|
||||
/// <param name="y">The y coordinate.</param>
|
||||
public Vertex(double x, double y)
|
||||
: base(x, y)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Vertex" /> class.
|
||||
/// </summary>
|
||||
/// <param name="x">The x coordinate.</param>
|
||||
/// <param name="y">The y coordinate.</param>
|
||||
/// <param name="leaving">A half-edge leaving this vertex.</param>
|
||||
public Vertex(double x, double y, HalfEdge leaving)
|
||||
: base(x, y)
|
||||
{
|
||||
this.leaving = leaving;
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -4,7 +4,7 @@
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Tools
|
||||
namespace TriangleNet.Voronoi.Legacy
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -18,7 +18,7 @@ namespace TriangleNet.Tools
|
||||
/// 2D Centroidal Voronoi Tessellations with Constraints, 2010,
|
||||
/// Jane Tournois, Pierre Alliez and Olivier Devillers
|
||||
/// </remarks>
|
||||
public class BoundedVoronoi : IVoronoi
|
||||
public class BoundedVoronoiLegacy : IVoronoi
|
||||
{
|
||||
Mesh mesh;
|
||||
|
||||
@@ -34,19 +34,19 @@ namespace TriangleNet.Tools
|
||||
bool includeBoundary = true;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BoundedVoronoi" /> class.
|
||||
/// Initializes a new instance of the <see cref="BoundedVoronoiLegacy" /> class.
|
||||
/// </summary>
|
||||
/// <param name="mesh">Mesh instance.</param>
|
||||
public BoundedVoronoi(Mesh mesh)
|
||||
public BoundedVoronoiLegacy(Mesh mesh)
|
||||
: this(mesh, true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BoundedVoronoi" /> class.
|
||||
/// Initializes a new instance of the <see cref="BoundedVoronoiLegacy" /> class.
|
||||
/// </summary>
|
||||
/// <param name="mesh">Mesh instance.</param>
|
||||
public BoundedVoronoi(Mesh mesh, bool includeBoundary)
|
||||
public BoundedVoronoiLegacy(Mesh mesh, bool includeBoundary)
|
||||
{
|
||||
this.mesh = mesh;
|
||||
this.includeBoundary = includeBoundary;
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Tools
|
||||
namespace TriangleNet.Voronoi.Legacy
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Tools
|
||||
namespace TriangleNet.Voronoi.Legacy
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Tools
|
||||
namespace TriangleNet.Voronoi.Legacy
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -0,0 +1,31 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="StandardVoronoi.cs">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Voronoi
|
||||
{
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
public class StandardVoronoi : VoronoiBase
|
||||
{
|
||||
public StandardVoronoi(Mesh mesh)
|
||||
: this(mesh, mesh.bounds)
|
||||
{
|
||||
}
|
||||
|
||||
public StandardVoronoi(Mesh mesh, Rectangle box)
|
||||
: base(mesh, true)
|
||||
{
|
||||
// We explicitly told the base constructor to call the Generate method, so
|
||||
// at this point the basic Voronoi diagram is already created.
|
||||
PostProcess(box);
|
||||
}
|
||||
|
||||
private void PostProcess(Rectangle box)
|
||||
{
|
||||
// Compute edge intersections with bounding box.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="VoronoiBase.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>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Voronoi
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
using TriangleNet.Data;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Voronoi.DCEL;
|
||||
|
||||
using Vertex = TriangleNet.Voronoi.DCEL.Vertex;
|
||||
|
||||
/// <summary>
|
||||
/// The Voronoi diagram is the dual of a pointset triangulation.
|
||||
/// </summary>
|
||||
public abstract class VoronoiBase
|
||||
{
|
||||
protected Vertex[] vertices;
|
||||
protected List<HalfEdge> edges;
|
||||
protected Face[] faces;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vertices of the Voronoi diagram.
|
||||
/// </summary>
|
||||
public Vertex[] Vertices
|
||||
{
|
||||
get { return vertices; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of half-edges specify the Voronoi diagram topology.
|
||||
/// </summary>
|
||||
public List<HalfEdge> HalfEdges
|
||||
{
|
||||
get { return edges; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the faces of the Voronoi diagram.
|
||||
/// </summary>
|
||||
public Face[] Faces
|
||||
{
|
||||
get { return faces; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of edges of the Voronoi diagram.
|
||||
/// </summary>
|
||||
public IEnumerable<IEdge> Edges
|
||||
{
|
||||
get { return EnumerateEdges(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="VoronoiBase" /> class.
|
||||
/// </summary>
|
||||
/// <param name="mesh">Triangle mesh.</param>
|
||||
/// <param name="generate">If set to true, the constuctor will call the Generate
|
||||
/// method, which builds the Voronoi diagram.</param>
|
||||
protected VoronoiBase(Mesh mesh, bool generate)
|
||||
{
|
||||
if (generate)
|
||||
{
|
||||
Generate(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the Voronoi diagram from given triangle mesh..
|
||||
/// </summary>
|
||||
/// <param name="mesh"></param>
|
||||
protected void Generate(Mesh mesh)
|
||||
{
|
||||
mesh.Renumber();
|
||||
mesh.MakeVertexMap();
|
||||
|
||||
// Allocate space for voronoi diagram
|
||||
this.vertices = new Vertex[mesh.triangles.Count + mesh.hullsize];
|
||||
this.faces = new Face[mesh.vertices.Count];
|
||||
this.edges = new List<HalfEdge>();
|
||||
|
||||
// Compute triangles circumcenters and setup bounding box
|
||||
var map = ComputeVertices(mesh);
|
||||
|
||||
// Create all Voronoi faces.
|
||||
foreach (var vertex in mesh.vertices.Values)
|
||||
{
|
||||
faces[vertex.id] = new Face(vertex);
|
||||
}
|
||||
|
||||
ComputeEdges(mesh, map);
|
||||
|
||||
// At this point all edges are computed, but the (edge.next) pointers aren't set.
|
||||
ConnectEdges(map);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the Voronoi vertices (the circumcenters of the triangles).
|
||||
/// </summary>
|
||||
/// <returns>An empty map, which will map all vertices to a list of leaving edges.</returns>
|
||||
protected List<HalfEdge>[] ComputeVertices(Mesh mesh)
|
||||
{
|
||||
Otri tri = default(Otri);
|
||||
double xi = 0, eta = 0;
|
||||
Vertex vertex;
|
||||
Point pt;
|
||||
int id;
|
||||
|
||||
// Maps all vertices to a list of leaving edges.
|
||||
var map = new List<HalfEdge>[mesh.triangles.Count];
|
||||
|
||||
// Compue triangle circumcenters
|
||||
foreach (var t in mesh.triangles.Values)
|
||||
{
|
||||
id = t.id;
|
||||
tri.triangle = t;
|
||||
|
||||
pt = RobustPredicates.FindCircumcenter(tri.Org(), tri.Dest(), tri.Apex(), ref xi, ref eta);
|
||||
|
||||
vertex = new Vertex(pt.x, pt.y);
|
||||
vertex.id = id;
|
||||
|
||||
vertices[id] = vertex;
|
||||
map[id] = new List<HalfEdge>();
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the edges of the Voronoi diagram.
|
||||
/// </summary>
|
||||
/// <param name="map">Empty vertex map.</param>
|
||||
protected void ComputeEdges(Mesh mesh, List<HalfEdge>[] map)
|
||||
{
|
||||
Otri tri, neighbor = default(Otri);
|
||||
TriangleNet.Geometry.Vertex org, dest;
|
||||
|
||||
double px, py;
|
||||
int id, nid, count = mesh.triangles.Count;
|
||||
|
||||
Face face, neighborFace;
|
||||
HalfEdge edge, twin;
|
||||
Vertex vertex, end;
|
||||
|
||||
// Count infinte edges (vertex id for their endpoints).
|
||||
int j = 0;
|
||||
|
||||
// Count half-edges (edge ids).
|
||||
int k = 0;
|
||||
|
||||
// To loop over the set of edges, loop over all triangles, and look at the
|
||||
// three edges of each triangle. If there isn't another triangle adjacent
|
||||
// to the edge, operate on the edge. If there is another adjacent triangle,
|
||||
// operate on the edge only if the current triangle has a smaller id than
|
||||
// its neighbor. This way, each edge is considered only once.
|
||||
foreach (var t in mesh.triangles.Values)
|
||||
{
|
||||
id = t.id;
|
||||
|
||||
tri.triangle = t;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
tri.orient = i;
|
||||
tri.Sym(ref neighbor);
|
||||
|
||||
nid = neighbor.triangle.id;
|
||||
|
||||
if (id < nid || nid < 0)
|
||||
{
|
||||
// Get the endpoints of the current triangle edge.
|
||||
org = tri.Org();
|
||||
dest = tri.Dest();
|
||||
|
||||
face = faces[org.id];
|
||||
neighborFace = faces[dest.id];
|
||||
|
||||
vertex = vertices[id];
|
||||
|
||||
// For each edge in the triangle mesh, there's a corresponding edge
|
||||
// in the Voronoi diagram, i.e. two half-edges will be created.
|
||||
if (nid < 0)
|
||||
{
|
||||
// Undounded edge, direction perpendicular to the boundary edge,
|
||||
// pointing outwards.
|
||||
px = dest.y - org.y;
|
||||
py = org.x - dest.x;
|
||||
|
||||
end = new Vertex(vertex.x + px, vertex.y + py);
|
||||
end.id = count + j++;
|
||||
|
||||
vertices[end.id] = end;
|
||||
|
||||
edge = new HalfEdge(end, face);
|
||||
twin = new HalfEdge(vertex, neighborFace);
|
||||
|
||||
end.leaving = edge;
|
||||
|
||||
// Make (face.edge) always point to an edge that starts at an infinite
|
||||
// vertex. This will allow traversing of unbounded faces.
|
||||
face.edge = edge;
|
||||
face.bounded = false;
|
||||
|
||||
map[id].Add(twin);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create half-edges.
|
||||
edge = new HalfEdge(vertices[nid], face);
|
||||
twin = new HalfEdge(vertex, neighborFace);
|
||||
|
||||
// Set leaving edges.
|
||||
vertices[nid].leaving = edge;
|
||||
vertex.leaving = twin;
|
||||
|
||||
// Add to vertex map.
|
||||
map[nid].Add(edge);
|
||||
map[id].Add(twin);
|
||||
}
|
||||
|
||||
// Setup twin edges.
|
||||
edge.twin = twin;
|
||||
twin.twin = edge;
|
||||
|
||||
edge.id = k++;
|
||||
twin.id = k++;
|
||||
|
||||
this.edges.Add(edge);
|
||||
this.edges.Add(twin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connect all edges of the Voronoi diagram.
|
||||
/// </summary>
|
||||
/// <param name="map">Maps all vertices to a list of leaving edges.</param>
|
||||
protected void ConnectEdges(List<HalfEdge>[] map)
|
||||
{
|
||||
int length = map.Length;
|
||||
|
||||
// For each halfe-edge, find its successor in the connected face.
|
||||
foreach (var edge in this.edges)
|
||||
{
|
||||
var face = edge.face.generator.id;
|
||||
|
||||
// The id of the dest vertex of current edge.
|
||||
int id = edge.twin.origin.id;
|
||||
|
||||
if (id < length)
|
||||
{
|
||||
// Look for the edge that is connected to the current face. Each
|
||||
// Voronoi vertex has degree 3, so this loop is actually O(1).
|
||||
foreach (var next in map[id])
|
||||
{
|
||||
if (next.face.generator.id == face)
|
||||
{
|
||||
edge.next = next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<IEdge> EnumerateEdges()
|
||||
{
|
||||
var edges = new List<IEdge>(this.edges.Count / 2);
|
||||
|
||||
foreach (var edge in this.edges)
|
||||
{
|
||||
var twin = edge.twin;
|
||||
|
||||
// Report edge only once.
|
||||
if (edge.id < twin.id)
|
||||
{
|
||||
edges.Add(new Edge(edge.origin.id, twin.origin.id));
|
||||
}
|
||||
}
|
||||
|
||||
return edges;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user