Removed support for triangle attributes,

Added triangle region marker

git-svn-id: https://triangle.svn.codeplex.com/svn@71645 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
SND\wo80_cp
2013-01-21 14:59:13 +00:00
parent 99d2202fad
commit c19681b2dd
21 changed files with 396 additions and 251 deletions
+11 -3
View File
@@ -63,10 +63,17 @@ namespace MeshExplorer
{
if (currentGenerator != null && InputGenerated != null)
{
InputGeometry input = currentGenerator.Generate(sliderParam1.Value,
sliderParam2.Value, sliderParam3.Value);
try
{
InputGeometry input = currentGenerator.Generate(sliderParam1.Value,
sliderParam2.Value, sliderParam3.Value);
InputGenerated(input, EventArgs.Empty);
InputGenerated(input, EventArgs.Empty);
}
catch (Exception ex)
{
DarkMessageBox.Show("Exception", ex.Message);
}
}
}
@@ -135,6 +142,7 @@ namespace MeshExplorer
darkListBox1.Items.Add(new StarInBox());
darkListBox1.Items.Add(new RingPolygon());
darkListBox1.Items.Add(new BoxWithHole());
darkListBox1.Items.Add(new CircleWithHole());
darkListBox1.SelectedIndex = 0;
}
@@ -0,0 +1,139 @@
// -----------------------------------------------------------------------
// <copyright file="RingPolygon.cs" company="">
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace MeshExplorer.Generators
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TriangleNet.Geometry;
/// <summary>
/// Generates a ring polygon.
/// </summary>
public class CircleWithHole : IGenerator
{
// Parameters range
double[] range1 = { 100, 250 };
double[] range2 = { 2, 15 };
public string Name
{
get { return "Circle with Hole"; }
}
public string Description
{
get { return ""; }
}
public int ParameterCount
{
get { return 2; }
}
public string ParameterDescription(int paramIndex)
{
if (paramIndex == 1)
{
return "Number of points:";
}
if (paramIndex == 2)
{
return "Outer radius:";
}
return "";
}
public string ParameterDescription(int paramIndex, double paramValue)
{
if (paramIndex == 1)
{
int num = (int)((range1[1] - range1[0]) / 100.0 * paramValue + range1[0]);
return num.ToString();
}
if (paramIndex == 2)
{
int radius = (int)((range2[1] - range2[0]) / 100.0 * paramValue + range2[0]);
return radius.ToString();
}
return "";
}
public InputGeometry Generate(double param1, double param2, double param3)
{
// Number of points on the outer circle
int n = (int)((range1[1] - range1[0]) / 100.0 * param1 + range1[0]);
int count, npoints;
double radius = (int)((range2[1] - range2[0]) / 100.0 * param2 + range2[0]);
// Step size on the outer circle
double h = 2 * Math.PI * radius / n;
// Current radius and step size
double r, dphi;
InputGeometry input = new InputGeometry(n + 1);
// Inner cirlce (radius = 1)
r = 1;
npoints = (int)(2 * Math.PI * r / h);
dphi = 2 * Math.PI / npoints;
for (int i = 0; i < npoints; i++)
{
input.AddPoint(r * Math.Cos(i * dphi), r * Math.Sin(i * dphi), 1);
input.AddSegment(i, (i + 1) % npoints, 1);
}
count = input.Count;
// Center cirlce
r = (radius + 1) / 2.0;
npoints = (int)(2 * Math.PI * r / h);
dphi = 2 * Math.PI / npoints;
for (int i = 0; i < npoints; i++)
{
input.AddPoint(r * Math.Cos(i * dphi), r * Math.Sin(i * dphi), 2);
input.AddSegment(count + i, count + (i + 1) % npoints, 2);
}
count = input.Count;
// Outer cirlce
r = radius;
npoints = (int)(2 * Math.PI * r / h);
dphi = 2 * Math.PI / npoints;
for (int i = 0; i < npoints; i++)
{
input.AddPoint(r * Math.Cos(i * dphi), r * Math.Sin(i * dphi), 3);
input.AddSegment(count + i, count + (i + 1) % npoints, 3);
}
input.AddHole(0, 0);
// Regions: |------|------|---|
// r 1 0
input.AddRegion((r + 3.0) / 4.0, 0, 1);
input.AddRegion((3 * r + 1.0) / 4.0, 0, 2);
return input;
}
public override string ToString()
{
return this.Name;
}
}
}
@@ -97,6 +97,7 @@
<DependentUpon>FormMain.cs</DependentUpon>
</Compile>
<Compile Include="Generators\BoxWithHole.cs" />
<Compile Include="Generators\CircleWithHole.cs" />
<Compile Include="Generators\IGenerator.cs" />
<Compile Include="Generators\RandomPoints.cs" />
<Compile Include="Generators\RandomPointsCircle.cs" />
+1 -1
View File
@@ -79,7 +79,7 @@
this.label19.Name = "label19";
this.label19.Size = new System.Drawing.Size(134, 40);
this.label19.TabIndex = 6;
this.label19.Text = "Beta 3 (2012-10-30)\r\nChristian Woltering\r\nMIT";
this.label19.Text = "Beta 3 (2013-01-20)\r\nChristian Woltering\r\nMIT";
//
// label18
//
-1
View File
@@ -599,7 +599,6 @@ namespace TriangleNet.Algorithm
/// <summary>
/// Recursively form a Delaunay triangulation by the divide-and-conquer method.
/// </summary>
/// <param name="sortarray"></param>
/// <param name="left"></param>
/// <param name="right"></param>
/// <param name="axis"></param>
+3 -3
View File
@@ -24,7 +24,7 @@ namespace TriangleNet
VarArea = false;
FixedArea = false;
Usertest = false;
RegionAttrib = false;
UseRegions = false;
Convex = false;
Jettison = false;
UseBoundaryMarkers = true;
@@ -84,9 +84,9 @@ namespace TriangleNet
/// </summary>
public bool Usertest { get; set; }
/// <summary>
/// Apply attributes to identify triangles in certain regions.
/// Identify triangles in certain regions.
/// </summary>
public bool RegionAttrib { get; set; }
public bool UseRegions { get; set; }
/// <summary>
/// Enclose the convex hull with segments.
/// </summary>
+22 -124
View File
@@ -11,6 +11,7 @@ namespace TriangleNet
using System;
using TriangleNet.Geometry;
using System.Collections.Generic;
using TriangleNet.Tools;
/// <summary>
/// Carves holes into the triangulation.
@@ -18,10 +19,12 @@ namespace TriangleNet
class Carver
{
Mesh mesh;
List<Triangle> viri;
public Carver(Mesh mesh)
{
this.mesh = mesh;
this.viri = new List<Triangle>();
}
/// <summary>
@@ -57,7 +60,7 @@ namespace TriangleNet
if (!hulltri.IsInfected())
{
hulltri.Infect();
mesh.viri.Add(hulltri.triangle);
viri.Add(hulltri.triangle);
}
}
else
@@ -118,11 +121,11 @@ namespace TriangleNet
// Loop through all the infected triangles, spreading the virus to
// their neighbors, then to their neighbors' neighbors.
for (int i = 0; i < mesh.viri.Count; i++)
for (int i = 0; i < viri.Count; i++)
{
// WARNING: Don't use foreach, mesh.viri list may get modified.
testtri.triangle = mesh.viri[i];
testtri.triangle = viri[i];
// A triangle is marked as infected by messing with one of its pointers
// to subsegments, setting it to an illegal value. Hence, we have to
// temporarily uninfect this triangle so that we can examine its
@@ -164,7 +167,7 @@ namespace TriangleNet
// the neighbor becomes infected.
neighbor.Infect();
// Ensure that the neighbor's neighbors will be infected.
mesh.viri.Add(neighbor.triangle);
viri.Add(neighbor.triangle);
}
else
{
@@ -194,7 +197,7 @@ namespace TriangleNet
testtri.Infect();
}
foreach (var virus in mesh.viri)
foreach (var virus in viri)
{
testtri.triangle = virus;
@@ -286,90 +289,9 @@ namespace TriangleNet
}
// Empty the virus pool.
mesh.viri.Clear();
viri.Clear();
}
/// <summary>
/// Spread regional attributes and/or area constraints (from a .poly file)
/// throughout the mesh.
/// </summary>
/// <param name="attribute"></param>
/// <param name="area"></param>
/// <remarks>
/// This procedure operates in two phases. The first phase spreads an
/// attribute and/or an area constraint through a (segment-bounded) region.
/// The triangles are marked to ensure that each triangle is added to the
/// virus pool only once, so the procedure will terminate.
///
/// The second phase uninfects all infected triangles, returning them to
/// normal.
/// </remarks>
void RegionPlague(double attribute, double area)
{
Otri testtri = default(Otri);
Otri neighbor = default(Otri);
Osub neighborsubseg = default(Osub);
Behavior behavior = mesh.behavior;
// Loop through all the infected triangles, spreading the attribute
// and/or area constraint to their neighbors, then to their neighbors'
// neighbors.
for (int i = 0; i < mesh.viri.Count; i++)
{
// WARNING: Don't use foreach, mesh.viri list may get modified.
testtri.triangle = mesh.viri[i];
// A triangle is marked as infected by messing with one of its pointers
// to subsegments, setting it to an illegal value. Hence, we have to
// temporarily uninfect this triangle so that we can examine its
// adjacent subsegments.
// TODO: Not true in the C# version (so we could skip this).
testtri.Uninfect();
if (behavior.RegionAttrib)
{
// Set an attribute (Note: the attributes array was resized before).
testtri.triangle.attributes[mesh.eextras] = attribute;
}
if (behavior.VarArea)
{
// Set an area constraint.
testtri.triangle.area = area;
}
// Check each of the triangle's three neighbors.
for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
{
// Find the neighbor.
testtri.Sym(ref neighbor);
// Check for a subsegment between the triangle and its neighbor.
testtri.SegPivot(ref neighborsubseg);
// Make sure the neighbor exists, is not already infected, and
// isn't protected by a subsegment.
if ((neighbor.triangle != Mesh.dummytri) && !neighbor.IsInfected()
&& (neighborsubseg.seg == Mesh.dummysub))
{
// Infect the neighbor.
neighbor.Infect();
// Ensure that the neighbor's neighbors will be infected.
mesh.viri.Add(neighbor.triangle);
}
}
// Remark the triangle as infected, so it doesn't get added to the
// virus pool again.
testtri.Infect();
}
// Uninfect all triangles.
foreach (var virus in mesh.viri)
{
testtri.triangle = virus;
testtri.Uninfect();
}
// Empty the virus pool.
mesh.viri.Clear();
}
/// <summary>
/// Find the holes and infect them. Find the area constraints and infect
/// them. Infect the convex hull. Spread the infection and kill triangles.
@@ -378,11 +300,10 @@ namespace TriangleNet
public void CarveHoles()
{
Otri searchtri = default(Otri);
Otri tri = default(Otri);
Vertex searchorg, searchdest;
LocateResult intersect;
Otri[] regionTris = null;
Triangle[] regionTris = null;
if (!mesh.behavior.Convex)
{
@@ -417,7 +338,7 @@ namespace TriangleNet
// Infect the triangle. This is done by marking the triangle
// as infected and including the triangle in the virus pool.
searchtri.Infect();
mesh.viri.Add(searchtri.triangle);
viri.Add(searchtri.triangle);
}
}
}
@@ -430,14 +351,14 @@ namespace TriangleNet
// which might not be convex; they can only be used with a freshly triangulated PSLG.)
if (mesh.regions.Count > 0)
{
regionTris = new Otri[mesh.regions.Count];
int i = 0;
regionTris = new Triangle[mesh.regions.Count];
// Find the starting triangle for each region.
foreach (var region in mesh.regions)
{
regionTris[i].triangle = Mesh.dummytri;
regionTris[i] = Mesh.dummytri;
// Ignore region points that aren't within the bounds of the mesh.
if (mesh.bounds.Contains(region.point))
{
@@ -458,7 +379,8 @@ namespace TriangleNet
{
// Record the triangle for processing after the
// holes have been carved.
searchtri.Copy(ref regionTris[i]);
regionTris[i] = searchtri.triangle;
regionTris[i].region = region.id;
}
}
}
@@ -467,57 +389,33 @@ namespace TriangleNet
}
}
if (mesh.viri.Count > 0)
if (viri.Count > 0)
{
// Carve the holes and concavities.
Plague();
}
// The virus pool should be empty now.
if (regionTris != null)
{
if (mesh.behavior.RegionAttrib)
{
// Make the triangle's attributes larger.
double[] attributes = new double[mesh.eextras + 1];
// Assign every triangle a regional attribute of zero.
tri.orient = 0;
foreach (var t in mesh.triangles.Values)
{
Array.Copy(tri.triangle.attributes, attributes, mesh.eextras);
tri.triangle = t;
tri.triangle.attributes = attributes;
}
}
var iterator = new RegionIterator(mesh);
for (int i = 0; i < regionTris.Length; i++)
{
if (regionTris[i].triangle != Mesh.dummytri)
if (regionTris[i] != Mesh.dummytri)
{
// Make sure the triangle under consideration still exists.
// It may have been eaten by the virus.
if (!Otri.IsDead(regionTris[i].triangle))
if (!Otri.IsDead(regionTris[i]))
{
// Put one triangle in the virus pool.
regionTris[i].Infect();
mesh.viri.Add(regionTris[i].triangle);
// Apply one region's attribute and/or area constraint.
RegionPlague(mesh.regions[i].Attribute, mesh.regions[i].Area);
// The virus pool should be empty now.
iterator.Process(regionTris[i]);
}
}
}
if (mesh.behavior.RegionAttrib)
{
// Note the fact that each triangle has an additional attribute.
mesh.eextras++;
}
}
// Free up memory (virus pool should be empty anyway).
mesh.viri.Clear();
viri.Clear();
}
}
}
+5 -11
View File
@@ -33,11 +33,11 @@ namespace TriangleNet.Data
internal Otri[] neighbors;
internal Vertex[] vertices;
internal Osub[] subsegs;
internal double[] attributes;
internal int region;
internal double area;
internal bool infected;
public Triangle(int numAttributes)
public Triangle()
{
// Initialize the three adjoining triangles to be "outer space".
neighbors = new Otri[3];
@@ -58,11 +58,6 @@ namespace TriangleNet.Data
subsegs[2].seg = Mesh.dummysub;
}
if (numAttributes > 0)
{
attributes = new double[numAttributes];
}
// TODO:
//if (Behavior.VarArea)
//{
@@ -70,7 +65,6 @@ namespace TriangleNet.Data
//}
}
#region Public properties
/// <summary>
@@ -171,11 +165,11 @@ namespace TriangleNet.Data
}
/// <summary>
/// Gets the triangle attributes.
/// Region ID the triangle belongs to.
/// </summary>
public double[] Attributes
public int Region
{
get { return this.attributes; }
get { return this.region; }
}
#endregion
+2 -2
View File
@@ -80,8 +80,8 @@ namespace TriangleNet.Geometry
double Area { get; }
/// <summary>
/// Triangle atributes.
/// Region ID the triangle belongs to.
/// </summary>
double[] Attributes { get; }
int Region { get; }
}
}
@@ -197,11 +197,10 @@ namespace TriangleNet.Geometry
/// </summary>
/// <param name="x">X coordinate of the hole.</param>
/// <param name="y">Y coordinate of the hole.</param>
/// <param name="area">The regions area constraint.</param>
/// <param name="attribute">Region attribute.</param>
public void AddRegion(double x, double y, double area, double attribute)
/// <param name="id">The region id.</param>
public void AddRegion(double x, double y, int id)
{
regions.Add(new RegionPointer(x, y, area, attribute));
regions.Add(new RegionPointer(x, y, id));
}
/// <summary>
@@ -16,45 +16,18 @@ namespace TriangleNet.Geometry
public class RegionPointer
{
internal Point point;
internal double area;
internal double attribute;
internal int id;
/// <summary>
/// Initializes a new instance of the <see cref="RegionPointer" /> class.
/// </summary>
/// <param name="x">X coordinate of the region.</param>
/// <param name="y">Y coordinate of the region.</param>
/// <param name="area">Area constraint.</param>
/// <param name="attribute">Region attribute.</param>
public RegionPointer(double x, double y, double area, double attribute)
/// <param name="id">Region id.</param>
public RegionPointer(double x, double y, int id)
{
this.point = new Point(x, y);
this.area = area;
this.attribute = attribute;
}
/// <summary>
/// Gets the location of the region.
/// </summary>
internal Point Point
{
get { return point; }
}
/// <summary>
/// Gets the area constraint.
/// </summary>
internal double Area
{
get { return area; }
}
/// <summary>
/// Gets the region attribute.
/// </summary>
internal double Attribute
{
get { return attribute; }
this.id = id;
}
}
}
+2 -3
View File
@@ -75,7 +75,6 @@ namespace TriangleNet.IO
int numberofsegments = input.segments.Count;
mesh.inelements = elements;
mesh.eextras = triangles[0].Attributes != null ? triangles[0].Attributes.Length : 0;
// Create the triangles.
for (i = 0; i < mesh.inelements; i++)
@@ -134,9 +133,9 @@ namespace TriangleNet.IO
}
// Read the triangle's attributes.
tri.triangle.attributes = triangles[i].Attributes;
tri.triangle.region = triangles[i].Region;
// TODO
// TODO: VarArea
if (mesh.behavior.VarArea)
{
tri.triangle.area = triangles[i].Area;
+18 -19
View File
@@ -447,19 +447,17 @@ namespace TriangleNet.IO
throw new Exception("Can't read input file (region).");
}
if (line.Length < 5)
if (line.Length < 4)
{
throw new Exception("Invalid region.");
throw new Exception("Invalid region attributes.");
}
data.AddRegion(
// Region x and y
double.Parse(line[1]),
double.Parse(line[2]),
// Region attribute
double.Parse(line[3]),
// Region area constraint
double.Parse(line[4]));
double.Parse(line[1], nfi),
double.Parse(line[2], nfi),
// Region id
int.Parse(line[3]));
}
}
}
@@ -504,6 +502,7 @@ namespace TriangleNet.IO
{
// Read number of elements and number of attributes.
string[] line;
bool validRegion = false;
if (!TryReadLine(reader, out line))
{
@@ -517,6 +516,12 @@ namespace TriangleNet.IO
if (line.Length > 2)
{
attributes = int.Parse(line[2]);
validRegion = true;
}
if (attributes > 1)
{
SimpleLog.Instance.Warning("Triangle attributes not supported.", "FileReader.Read");
}
triangles = new List<ITriangle>(intriangles);
@@ -542,18 +547,12 @@ namespace TriangleNet.IO
int.Parse(line[2]) - startIndex,
int.Parse(line[3]) - startIndex);
// Read triangle attributes
if (attributes > 0)
// Read triangle region
if (attributes > 0 && validRegion)
{
for (int j = 0; j < attributes; j++)
{
tri.attributes = new double[attributes];
if (line.Length > 4 + j)
{
tri.attributes[j] = double.Parse(line[4 + j]);
}
}
int region = 0;
validRegion = int.TryParse(line[4], out region);
tri.region = region;
}
triangles.Add(tri);
+6 -6
View File
@@ -142,6 +142,7 @@ namespace TriangleNet.IO
{
Otri tri = default(Otri);
Vertex p1, p2, p3;
bool regions = mesh.behavior.UseRegions;
int j = 0;
@@ -150,7 +151,7 @@ namespace TriangleNet.IO
using (StreamWriter writer = new StreamWriter(filename))
{
// Number of triangles, vertices per triangle, attributes per triangle.
writer.WriteLine("{0} 3 {1}", mesh.triangles.Count, mesh.eextras);
writer.WriteLine("{0} 3 {1}", mesh.triangles.Count, regions ? 1 : 0);
foreach (var item in mesh.triangles.Values)
{
@@ -163,9 +164,9 @@ namespace TriangleNet.IO
// Triangle number, indices for three vertices.
writer.Write("{0} {1} {2} {3}", j, p1.id, p2.id, p3.id);
for (int i = 0; i < mesh.eextras; i++)
if (regions)
{
writer.Write(" {0}", tri.triangle.attributes[i].ToString(nfi));
writer.Write(" {0}", tri.triangle.region);
}
writer.WriteLine();
@@ -260,9 +261,8 @@ namespace TriangleNet.IO
writer.WriteLine("{0}", mesh.regions.Count);
foreach (var region in mesh.regions)
{
writer.WriteLine("{0} {1} {2} {3} {4}", j, region.point.X.ToString(nfi),
region.point.Y.ToString(nfi), region.attribute.ToString(nfi),
region.area.ToString(nfi));
writer.WriteLine("{0} {1} {2} {3}", j, region.point.X.ToString(nfi),
region.point.Y.ToString(nfi), region.id);
j++;
}
+5 -4
View File
@@ -17,7 +17,7 @@ namespace TriangleNet.IO
public class InputTriangle : ITriangle
{
internal int[] vertices;
internal double[] attributes;
internal int region;
internal double area;
public InputTriangle(int p0, int p1, int p2)
@@ -106,11 +106,12 @@ namespace TriangleNet.IO
}
/// <summary>
/// Gets the triangle attributes.
/// Region ID the triangle belongs to.
/// </summary>
public double[] Attributes
public int Region
{
get { return null; }
get { return region; }
set { region = value; }
}
#endregion
+26 -37
View File
@@ -48,8 +48,6 @@ namespace TriangleNet
internal List<Point> holes;
internal List<RegionPointer> regions;
internal List<Triangle> viri;
// Other variables.
internal BoundingBox bounds; // x and y bounds.
internal int invertices; // Number of input vertices.
@@ -59,7 +57,7 @@ namespace TriangleNet
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.
//internal int eextras; // Number of attributes per triangle.
internal int hullsize; // Number of edges in convex hull.
internal int steinerleft; // Number of Steiner points not yet used.
internal bool checksegments; // Are there segments in the triangulation yet?
@@ -182,7 +180,6 @@ namespace TriangleNet
triangles = new Dictionary<int, Triangle>();
subsegs = new Dictionary<int, Segment>();
viri = new List<Triangle>();
flipstack = new Stack<Otri>();
holes = new List<Point>();
@@ -247,6 +244,7 @@ namespace TriangleNet
// behavior.VarArea = true;
//}
// TODO: remove
if (!behavior.Poly)
{
// Be careful not to allocate space for element area constraints that
@@ -255,9 +253,11 @@ namespace TriangleNet
// 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.RegionAttrib = false;
behavior.UseRegions = false;
}
behavior.UseRegions = input.Regions.Count > 0;
TransferNodes(input);
// Read and reconstruct a mesh.
@@ -296,6 +296,7 @@ namespace TriangleNet
// behavior.UseBoundaryMarkers = true;
//}
// TODO: remove
if (!behavior.Poly)
{
// Be careful not to allocate space for element area constraints that
@@ -304,9 +305,11 @@ namespace TriangleNet
// 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.RegionAttrib = false;
behavior.UseRegions = false;
}
behavior.UseRegions = input.Regions.Count > 0;
steinerleft = behavior.Steiner;
TransferNodes(input);
@@ -706,8 +709,6 @@ namespace TriangleNet
{
int hulledges = 0;
eextras = 0;
if (behavior.Algorithm == TriangulationAlgorithm.Dwyer)
{
Dwyer alg = new Dwyer();
@@ -746,7 +747,6 @@ namespace TriangleNet
this.hash_seg = 0;
this.hash_tri = 0;
viri.Clear();
flipstack.Clear();
hullsize = 0;
@@ -771,6 +771,8 @@ namespace TriangleNet
Statistic.InCircleCount = 0;
Statistic.CounterClockwiseCount = 0;
Statistic.InCircleCountDecimal = 0;
Statistic.CounterClockwiseCountDecimal = 0;
Statistic.Orient3dCount = 0;
Statistic.HyperbolaCount = 0;
Statistic.CircleTopCount = 0;
@@ -805,7 +807,7 @@ namespace TriangleNet
private void DummyInit()
{
// Set up 'dummytri', the 'triangle' that occupies "outer space."
dummytri = new Triangle(0);
dummytri = new Triangle();
dummytri.hash = -1;
dummytri.id = -1;
@@ -880,7 +882,7 @@ namespace TriangleNet
/// <param name="newotri">Reference to the new triangle.</param>
internal void MakeTriangle(ref Otri newotri)
{
Triangle tri = new Triangle(eextras);
Triangle tri = new Triangle();
tri.hash = this.hash_tri++;
tri.id = tri.hash;
@@ -981,14 +983,13 @@ namespace TriangleNet
Vertex first;
Vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
Vertex segmentorg, segmentdest;
double attrib;
int region;
double area;
InsertVertexResult success;
LocateResult intersect;
bool doflip;
bool mirrorflag;
bool enq;
int i;
if (splitseg.seg == null)
{
@@ -1094,11 +1095,8 @@ namespace TriangleNet
newbotright.SetApex(newvertex);
horiz.SetOrg(newvertex);
for (i = 0; i < eextras; i++)
{
// Set the element attributes of a new triangle.
newbotright.triangle.attributes[i] = botright.triangle.attributes[i];
}
// Set the region of a new triangle.
newbotright.triangle.region = botright.triangle.region;
if (behavior.VarArea)
{
@@ -1114,11 +1112,8 @@ namespace TriangleNet
newtopright.SetApex(newvertex);
topright.SetOrg(newvertex);
for (i = 0; i < eextras; i++)
{
// Set the element attributes of another new triangle.
newtopright.triangle.attributes[i] = topright.triangle.attributes[i];
}
// Set the region of another new triangle.
newtopright.triangle.region = topright.triangle.region;
if (behavior.VarArea)
{
@@ -1223,13 +1218,9 @@ namespace TriangleNet
newbotright.SetApex(newvertex);
horiz.SetApex(newvertex);
for (i = 0; i < eextras; i++)
{
// Set the element attributes of the new triangles.
attrib = horiz.triangle.attributes[i];
newbotleft.triangle.attributes[i] = attrib;
newbotright.triangle.attributes[i] = attrib;
}
// Set the region of the new triangles.
newbotleft.triangle.region = horiz.triangle.region;
newbotright.triangle.region = horiz.triangle.region;
if (behavior.VarArea)
{
@@ -1426,13 +1417,11 @@ namespace TriangleNet
top.SetDest(farvertex);
top.SetApex(leftvertex);
for (i = 0; i < eextras; i++)
{
// Take the average of the two triangles' attributes.
attrib = 0.5 * (top.triangle.attributes[i] + horiz.triangle.attributes[i]);
top.triangle.attributes[i] = attrib;
horiz.triangle.attributes[i] = attrib;
}
// Assign region.
// TODO: check region ok (no Math.Min necessary)
region = Math.Min(top.triangle.region, horiz.triangle.region);
top.triangle.region = region;
horiz.triangle.region = region;
if (behavior.VarArea)
{
+4
View File
@@ -152,6 +152,8 @@ namespace TriangleNet
private static decimal CounterClockwiseDecimal(Point pa, Point pb, Point pc)
{
Statistic.CounterClockwiseCountDecimal++;
decimal detleft, detright, det, detsum;
detleft = ((decimal)pa.x - (decimal)pc.x) * ((decimal)pb.y - (decimal)pc.y);
@@ -258,6 +260,8 @@ namespace TriangleNet
private static decimal InCircleDecimal(Point pa, Point pb, Point pc, Point pd)
{
Statistic.InCircleCountDecimal++;
decimal adx, bdx, cdx, ady, bdy, cdy;
decimal bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
decimal alift, blift, clift;
+2 -2
View File
@@ -724,7 +724,7 @@ namespace TriangleNet
split = 0.5;
}
// Create the new vertex.
// Create the new vertex (interpolate coordinates).
newvertex = new Vertex(
eorg.x + split * (edest.x - eorg.x),
eorg.y + split * (edest.y - eorg.y),
@@ -738,7 +738,7 @@ namespace TriangleNet
mesh.vertices.Add(newvertex.hash, newvertex);
// Interpolate its coordinate and attributes.
// Interpolate attributes.
for (int i = 0; i < mesh.nextras; i++)
{
newvertex.attributes[i] = eorg.attributes[i]
@@ -0,0 +1,139 @@
// -----------------------------------------------------------------------
// <copyright file="RegionIterator.cs" company="">
// Original Matlab code by John Burkardt, Florida State University
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace TriangleNet.Tools
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TriangleNet.Data;
/// <summary>
/// Iterates the region a given triangle belongs to and applies an action
/// to each connected trianlge in that region. Default action is to set the
/// region id.
/// </summary>
public class RegionIterator
{
Mesh mesh;
List<Triangle> viri;
public RegionIterator(Mesh mesh)
{
this.mesh = mesh;
this.viri = new List<Triangle>();
}
/// <summary>
/// Spread regional attributes and/or area constraints (from a .poly file)
/// throughout the mesh.
/// </summary>
/// <param name="attribute"></param>
/// <param name="area"></param>
/// <remarks>
/// This procedure operates in two phases. The first phase spreads an
/// attribute and/or an area constraint through a (segment-bounded) region.
/// The triangles are marked to ensure that each triangle is added to the
/// virus pool only once, so the procedure will terminate.
///
/// The second phase uninfects all infected triangles, returning them to
/// normal.
/// </remarks>
void ProcessRegion(Action<Triangle> func)
{
Otri testtri = default(Otri);
Otri neighbor = default(Otri);
Osub neighborsubseg = default(Osub);
Behavior behavior = mesh.behavior;
// Loop through all the infected triangles, spreading the attribute
// and/or area constraint to their neighbors, then to their neighbors'
// neighbors.
for (int i = 0; i < viri.Count; i++)
{
// WARNING: Don't use foreach, viri list gets modified.
testtri.triangle = viri[i];
// A triangle is marked as infected by messing with one of its pointers
// to subsegments, setting it to an illegal value. Hence, we have to
// temporarily uninfect this triangle so that we can examine its
// adjacent subsegments.
// TODO: Not true in the C# version (so we could skip this).
testtri.Uninfect();
// Apply function.
func(testtri.triangle);
// Check each of the triangle's three neighbors.
for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
{
// Find the neighbor.
testtri.Sym(ref neighbor);
// Check for a subsegment between the triangle and its neighbor.
testtri.SegPivot(ref neighborsubseg);
// Make sure the neighbor exists, is not already infected, and
// isn't protected by a subsegment.
if ((neighbor.triangle != Mesh.dummytri) && !neighbor.IsInfected()
&& (neighborsubseg.seg == Mesh.dummysub))
{
// Infect the neighbor.
neighbor.Infect();
// Ensure that the neighbor's neighbors will be infected.
viri.Add(neighbor.triangle);
}
}
// Remark the triangle as infected, so it doesn't get added to the
// virus pool again.
testtri.Infect();
}
// Uninfect all triangles.
foreach (var virus in viri)
{
virus.infected = false;
}
// Empty the virus pool.
viri.Clear();
}
/// <summary>
/// Set the region attribute of all trianlges connected to given triangle.
/// </summary>
public void Process(Triangle triangle)
{
// Default action is to just set the region id for all trianlges.
this.Process(triangle, (tri) => { tri.region = triangle.region; });
}
/// <summary>
/// Process all trianlges connected to given triangle and apply given action.
/// </summary>
public void Process(Triangle triangle, Action<Triangle> func)
{
if (triangle != Mesh.dummytri)
{
// Make sure the triangle under consideration still exists.
// It may have been eaten by the virus.
if (!Otri.IsDead(triangle))
{
// Put one triangle in the virus pool.
triangle.infected = true;
viri.Add(triangle);
// Apply one region's attribute and/or area constraint.
ProcessRegion(func);
// The virus pool should be empty now.
}
}
// Free up memory (virus pool should be empty anyway).
viri.Clear();
}
}
}
+2
View File
@@ -23,11 +23,13 @@ namespace TriangleNet.Tools
/// Number of incircle tests performed.
/// </summary>
public static long InCircleCount = 0;
public static long InCircleCountDecimal = 0;
/// <summary>
/// Number of counterclockwise tests performed.
/// </summary>
public static long CounterClockwiseCount = 0;
public static long CounterClockwiseCountDecimal = 0;
/// <summary>
/// Number of 3D orientation tests performed.
+1
View File
@@ -87,6 +87,7 @@
<Compile Include="Tools\CuthillMcKee.cs" />
<Compile Include="Tools\IVoronoi.cs" />
<Compile Include="Tools\QualityMeasure.cs" />
<Compile Include="Tools\RegionIterator.cs" />
<Compile Include="Tools\Statistic.cs" />
<Compile Include="Algorithm\SweepLine.cs" />
<Compile Include="Tools\Voronoi.cs" />