Changed Behavoir class to non-static
git-svn-id: https://triangle.svn.codeplex.com/svn@67992 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
@@ -73,7 +73,8 @@ namespace MeshExplorer.Controls
|
||||
|
||||
timer = new Timer();
|
||||
timer.Interval = 3000;
|
||||
timer.Tick += (sender, e) => {
|
||||
timer.Tick += (sender, e) =>
|
||||
{
|
||||
timer.Stop();
|
||||
coordinate = String.Empty;
|
||||
this.Invalidate();
|
||||
@@ -90,13 +91,6 @@ namespace MeshExplorer.Controls
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
public void ShowQuality(int measure)
|
||||
{
|
||||
//Tuple<int, byte>[] q = TriangleQuality.Measure(data, measure);
|
||||
|
||||
//this.RenderQualities(q);
|
||||
}
|
||||
|
||||
public void SetData(InputGeometry mesh)
|
||||
{
|
||||
data.SetData(mesh);
|
||||
@@ -202,66 +196,20 @@ namespace MeshExplorer.Controls
|
||||
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
|
||||
if (meshRenderer != null)
|
||||
if (voronoiRenderer != null && this.showVoronoi)
|
||||
{
|
||||
meshRenderer.RenderMesh(g, zoom, renderColors);
|
||||
voronoiRenderer.Render(g, zoom, renderColors);
|
||||
meshRenderer.RenderGeometry(g, zoom, renderColors);
|
||||
}
|
||||
else if (meshRenderer != null)
|
||||
{
|
||||
meshRenderer.Render(g, zoom, renderColors);
|
||||
}
|
||||
|
||||
if (voronoiRenderer != null && this.showVoronoi)
|
||||
{
|
||||
voronoiRenderer.Render(g, zoom, renderColors);
|
||||
}
|
||||
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
/*
|
||||
private void RenderQualitiesX(Tuple<int, byte>[] q)
|
||||
{
|
||||
PointF[] p = new PointF[3];
|
||||
PointF[] pts = data.Points;
|
||||
|
||||
int[] tri;
|
||||
|
||||
Brush q1 = new SolidBrush(Color.FromArgb(50, Color.Orange));
|
||||
Brush q2 = new SolidBrush(Color.FromArgb(50, Color.Red));
|
||||
|
||||
Graphics g = buffer.Graphics;
|
||||
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
|
||||
int n = q.Length;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
tri = data.Triangles[q[i].Item1];
|
||||
|
||||
if (zoom.ViewportContains(pts[tri[0]]) ||
|
||||
zoom.ViewportContains(pts[tri[1]]) ||
|
||||
zoom.ViewportContains(pts[tri[2]]))
|
||||
{
|
||||
p[0] = zoom.WorldToScreen(pts[tri[0]]);
|
||||
p[1] = zoom.WorldToScreen(pts[tri[1]]);
|
||||
p[2] = zoom.WorldToScreen(pts[tri[2]]);
|
||||
|
||||
// Fill
|
||||
g.FillPolygon(q[i].Item2 > 1 ? q2 : q1, p);
|
||||
|
||||
// Outline
|
||||
g.DrawLine(lines, p[0], p[1]);
|
||||
g.DrawLine(lines, p[1], p[2]);
|
||||
g.DrawLine(lines, p[2], p[0]);
|
||||
|
||||
// Points
|
||||
g.FillEllipse(Brushes.Green, p[0].X - 1.5f, p[0].Y - 1.5f, 3, 3);
|
||||
g.FillEllipse(Brushes.Green, p[1].X - 1.5f, p[1].Y - 1.5f, 3, 3);
|
||||
g.FillEllipse(Brushes.Green, p[2].X - 1.5f, p[2].Y - 1.5f, 3, 3);
|
||||
}
|
||||
}
|
||||
|
||||
this.Invalidate();
|
||||
}*/
|
||||
|
||||
#region Control overrides
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pe)
|
||||
@@ -297,8 +245,8 @@ namespace MeshExplorer.Controls
|
||||
timer.Stop();
|
||||
|
||||
PointF c = zoom.ScreenToWorld((float)e.X / this.Width, (float)e.Y / this.Height);
|
||||
coordinate = String.Format("X:{0} Y:{1}",
|
||||
c.X.ToString(Util.Nfi),
|
||||
coordinate = String.Format("X:{0} Y:{1}",
|
||||
c.X.ToString(Util.Nfi),
|
||||
c.Y.ToString(Util.Nfi));
|
||||
|
||||
this.Invalidate();
|
||||
|
||||
@@ -146,5 +146,42 @@ namespace MeshExplorer.Rendering
|
||||
this.RenderPoints(g);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders only the mesh edges (no points or segments).
|
||||
/// </summary>
|
||||
public void RenderMesh(Graphics g, Zoom zoom, RenderColors renderColors)
|
||||
{
|
||||
this.renderColors = renderColors;
|
||||
this.zoom = zoom;
|
||||
|
||||
if (data.Edges != null)
|
||||
{
|
||||
this.RenderEdges(g);
|
||||
}
|
||||
else if (data.Triangles != null)
|
||||
{
|
||||
this.RenderTriangles(g);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders only points and segments (no mesh triangles).
|
||||
/// </summary>
|
||||
public void RenderGeometry(Graphics g, Zoom zoom, RenderColors renderColors)
|
||||
{
|
||||
this.renderColors = renderColors;
|
||||
this.zoom = zoom;
|
||||
|
||||
if (data.Segments != null)
|
||||
{
|
||||
this.RenderSegments(g);
|
||||
}
|
||||
|
||||
if (data.Points != null)
|
||||
{
|
||||
this.RenderPoints(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,8 +781,11 @@ namespace TriangleNet.Algorithm
|
||||
Otri dissolveedge = default(Otri);
|
||||
Otri deadtriangle = default(Otri);
|
||||
Vertex markorg;
|
||||
|
||||
int hullsize;
|
||||
|
||||
bool noPoly = !mesh.behavior.Poly;
|
||||
|
||||
// Find an edge on the convex hull to start point location from.
|
||||
startghost.Lprev(ref searchedge);
|
||||
searchedge.SymSelf();
|
||||
@@ -799,7 +802,7 @@ namespace TriangleNet.Algorithm
|
||||
|
||||
// If no PSLG is involved, set the boundary markers of all the vertices
|
||||
// on the convex hull. If a PSLG is used, this step is done later.
|
||||
if (!Behavior.Poly)
|
||||
if (noPoly)
|
||||
{
|
||||
// Watch out for the case where all the input vertices are collinear.
|
||||
if (dissolveedge.triangle != Mesh.dummytri)
|
||||
|
||||
@@ -75,6 +75,8 @@ namespace TriangleNet.Algorithm
|
||||
Vertex markorg;
|
||||
int hullsize;
|
||||
|
||||
bool noPoly = !mesh.behavior.Poly;
|
||||
|
||||
// Find a boundary triangle.
|
||||
nextedge.triangle = Mesh.dummytri;
|
||||
nextedge.orient = 0;
|
||||
@@ -110,7 +112,7 @@ namespace TriangleNet.Algorithm
|
||||
dissolveedge.SymSelf();
|
||||
// If not using a PSLG, the vertices should be marked now.
|
||||
// (If using a PSLG, markhull() will do the job.)
|
||||
if (!Behavior.Poly)
|
||||
if (noPoly)
|
||||
{
|
||||
// Be careful! One must check for the case where all the input
|
||||
// vertices are collinear, and thus all the triangles are part of
|
||||
|
||||
@@ -480,6 +480,8 @@ namespace TriangleNet.Algorithm
|
||||
Vertex markorg;
|
||||
int hullsize;
|
||||
|
||||
bool noPoly = !mesh.behavior.Poly;
|
||||
|
||||
// Find an edge on the convex hull to start point location from.
|
||||
startghost.Lprev(ref searchedge);
|
||||
searchedge.SymSelf();
|
||||
@@ -496,7 +498,7 @@ namespace TriangleNet.Algorithm
|
||||
|
||||
// If no PSLG is involved, set the boundary markers of all the vertices
|
||||
// on the convex hull. If a PSLG is used, this step is done later.
|
||||
if (!Behavior.Poly)
|
||||
if (noPoly)
|
||||
{
|
||||
// Watch out for the case where all the input vertices are collinear.
|
||||
if (dissolveedge.triangle != Mesh.dummytri)
|
||||
|
||||
+111
-101
@@ -5,115 +5,19 @@
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
namespace TriangleNet
|
||||
{
|
||||
// TODO: Make Behavior non-static and an instance member of mesh class.
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Controls the behavior of the meshing software.
|
||||
/// </summary>
|
||||
static class Behavior
|
||||
class Behavior
|
||||
{
|
||||
/// <summary>
|
||||
/// Input is a Planar Straight Line Graph.
|
||||
/// </summary>
|
||||
public static bool Poly { get; set; }
|
||||
/// <summary>
|
||||
/// Quality mesh generation.
|
||||
/// </summary>
|
||||
public static bool Quality { get; set; }
|
||||
/// <summary>
|
||||
/// Apply a maximum triangle area constraint.
|
||||
/// </summary>
|
||||
public static bool VarArea { get; set; }
|
||||
/// <summary>
|
||||
/// Apply a maximum triangle area constraint.
|
||||
/// </summary>
|
||||
public static bool FixedArea { get; set; }
|
||||
/// <summary>
|
||||
/// Apply a user-defined triangle constraint.
|
||||
/// </summary>
|
||||
public static bool Usertest { get; set; }
|
||||
/// <summary>
|
||||
/// Apply attributes to identify triangles in certain regions.
|
||||
/// </summary>
|
||||
public static bool RegionAttrib { get; set; }
|
||||
/// <summary>
|
||||
/// Enclose the convex hull with segments.
|
||||
/// </summary>
|
||||
public static bool Convex { get; set; }
|
||||
/// <summary>
|
||||
/// Jettison unused vertices from output.
|
||||
/// </summary>
|
||||
public static bool Jettison { get; set; }
|
||||
/// <summary>
|
||||
/// Compute boundary information.
|
||||
/// </summary>
|
||||
public static bool UseBoundaryMarkers { get; set; }
|
||||
/// <summary>
|
||||
/// Ignores holes in polygons.
|
||||
/// </summary>
|
||||
public static bool NoHoles { get; set; }
|
||||
/// <summary>
|
||||
/// No exact arithmetic.
|
||||
/// </summary>
|
||||
public static bool NoExact { get; set; }
|
||||
/// <summary>
|
||||
/// Conforming Delaunay (all triangles are truly Delaunay).
|
||||
/// </summary>
|
||||
public static bool ConformDel { get; set; }
|
||||
/// <summary>
|
||||
/// Algorithm to use for triangulation.
|
||||
/// </summary>
|
||||
public static TriangulationAlgorithm Algorithm { get; set; }
|
||||
/// <summary>
|
||||
/// Log detailed information.
|
||||
/// </summary>
|
||||
public static bool Verbose { get; set; }
|
||||
/// <summary>
|
||||
/// Use segments (should not be set manually)
|
||||
/// </summary>
|
||||
public static bool UseSegments { get; set; } // TODO: internal set
|
||||
|
||||
/// <summary>
|
||||
/// Suppresses boundary segment splitting.
|
||||
/// </summary>
|
||||
public static int NoBisect { get; set; } // <- int !
|
||||
/// <summary>
|
||||
/// Use maximum number of added Steiner points.
|
||||
/// </summary>
|
||||
public static int Steiner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Minimum angle constraint.
|
||||
/// </summary>
|
||||
public static double MinAngle { get; set; }
|
||||
/// <summary>
|
||||
/// (should not be set manually)
|
||||
/// </summary>
|
||||
public static double GoodAngle { get; set; }
|
||||
/// <summary>
|
||||
/// (should not be set manually)
|
||||
/// </summary>
|
||||
public static double Offconstant { get; set; }
|
||||
/// <summary>
|
||||
/// Maximum area constraint.
|
||||
/// </summary>
|
||||
public static double MaxArea { get; set; }
|
||||
/// <summary>
|
||||
/// Maximum angle constraint.
|
||||
/// </summary>
|
||||
public static double MaxAngle { get; set; }
|
||||
/// <summary>
|
||||
/// (should not be set manually)
|
||||
/// </summary>
|
||||
public static double MaxGoodAngle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Load behavior defaults.
|
||||
/// </summary>
|
||||
public static void Init()
|
||||
public Behavior()
|
||||
{
|
||||
Poly = false;
|
||||
Quality = false;
|
||||
@@ -125,10 +29,8 @@ namespace TriangleNet
|
||||
Jettison = false;
|
||||
UseBoundaryMarkers = true;
|
||||
NoHoles = false;
|
||||
NoExact = false;
|
||||
ConformDel = false;
|
||||
Algorithm = TriangulationAlgorithm.Dwyer;
|
||||
Verbose = true;
|
||||
UseSegments = true;
|
||||
|
||||
NoBisect = 0;
|
||||
@@ -140,6 +42,114 @@ namespace TriangleNet
|
||||
MaxGoodAngle = 0.0;
|
||||
MaxArea = -1.0;
|
||||
Offconstant = 0.0;
|
||||
|
||||
Verbose = true;
|
||||
NoExact = false;
|
||||
}
|
||||
|
||||
#region Static properties
|
||||
|
||||
/// <summary>
|
||||
/// No exact arithmetic.
|
||||
/// </summary>
|
||||
public static bool NoExact { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Log detailed information.
|
||||
/// </summary>
|
||||
public static bool Verbose { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public properties
|
||||
|
||||
/// <summary>
|
||||
/// Input is a Planar Straight Line Graph.
|
||||
/// </summary>
|
||||
public bool Poly { get; set; }
|
||||
/// <summary>
|
||||
/// Quality mesh generation.
|
||||
/// </summary>
|
||||
public bool Quality { get; set; }
|
||||
/// <summary>
|
||||
/// Apply a maximum triangle area constraint.
|
||||
/// </summary>
|
||||
public bool VarArea { get; set; }
|
||||
/// <summary>
|
||||
/// Apply a maximum triangle area constraint.
|
||||
/// </summary>
|
||||
public bool FixedArea { get; set; }
|
||||
/// <summary>
|
||||
/// Apply a user-defined triangle constraint.
|
||||
/// </summary>
|
||||
public bool Usertest { get; set; }
|
||||
/// <summary>
|
||||
/// Apply attributes to identify triangles in certain regions.
|
||||
/// </summary>
|
||||
public bool RegionAttrib { get; set; }
|
||||
/// <summary>
|
||||
/// Enclose the convex hull with segments.
|
||||
/// </summary>
|
||||
public bool Convex { get; set; }
|
||||
/// <summary>
|
||||
/// Jettison unused vertices from output.
|
||||
/// </summary>
|
||||
public bool Jettison { get; set; }
|
||||
/// <summary>
|
||||
/// Compute boundary information.
|
||||
/// </summary>
|
||||
public bool UseBoundaryMarkers { get; set; }
|
||||
/// <summary>
|
||||
/// Ignores holes in polygons.
|
||||
/// </summary>
|
||||
public bool NoHoles { get; set; }
|
||||
/// <summary>
|
||||
/// Conforming Delaunay (all triangles are truly Delaunay).
|
||||
/// </summary>
|
||||
public bool ConformDel { get; set; }
|
||||
/// <summary>
|
||||
/// Algorithm to use for triangulation.
|
||||
/// </summary>
|
||||
public TriangulationAlgorithm Algorithm { get; set; }
|
||||
/// <summary>
|
||||
/// Use segments (should not be set manually)
|
||||
/// </summary>
|
||||
public bool UseSegments { get; set; } // TODO: internal set
|
||||
|
||||
/// <summary>
|
||||
/// Suppresses boundary segment splitting.
|
||||
/// </summary>
|
||||
public int NoBisect { get; set; } // <- int !
|
||||
/// <summary>
|
||||
/// Use maximum number of added Steiner points.
|
||||
/// </summary>
|
||||
public int Steiner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Minimum angle constraint.
|
||||
/// </summary>
|
||||
public double MinAngle { get; set; }
|
||||
/// <summary>
|
||||
/// (should not be set manually)
|
||||
/// </summary>
|
||||
public double GoodAngle { get; set; }
|
||||
/// <summary>
|
||||
/// (should not be set manually)
|
||||
/// </summary>
|
||||
public double Offconstant { get; set; }
|
||||
/// <summary>
|
||||
/// Maximum area constraint.
|
||||
/// </summary>
|
||||
public double MaxArea { get; set; }
|
||||
/// <summary>
|
||||
/// Maximum angle constraint.
|
||||
/// </summary>
|
||||
public double MaxAngle { get; set; }
|
||||
/// <summary>
|
||||
/// (should not be set manually)
|
||||
/// </summary>
|
||||
public double MaxGoodAngle { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace TriangleNet
|
||||
{
|
||||
Mesh mesh;
|
||||
|
||||
|
||||
public Carver(Mesh mesh)
|
||||
{
|
||||
this.mesh = mesh;
|
||||
@@ -311,6 +310,8 @@ namespace TriangleNet
|
||||
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.
|
||||
@@ -325,12 +326,12 @@ namespace TriangleNet
|
||||
// adjacent subsegments.
|
||||
// TODO: Not true in the C# version (so we could skip this).
|
||||
testtri.Uninfect();
|
||||
if (Behavior.RegionAttrib)
|
||||
if (behavior.RegionAttrib)
|
||||
{
|
||||
// Set an attribute (Note: the attributes array was resized before).
|
||||
testtri.triangle.attributes[mesh.eextras] = attribute;
|
||||
}
|
||||
if (Behavior.VarArea)
|
||||
if (behavior.VarArea)
|
||||
{
|
||||
// Set an area constraint.
|
||||
testtri.triangle.area = area;
|
||||
@@ -383,14 +384,14 @@ namespace TriangleNet
|
||||
|
||||
Otri[] regionTris = null;
|
||||
|
||||
if (!Behavior.Convex)
|
||||
if (!mesh.behavior.Convex)
|
||||
{
|
||||
// Mark as infected any unprotected triangles on the boundary.
|
||||
// This is one way by which concavities are created.
|
||||
InfectHull();
|
||||
}
|
||||
|
||||
if (!Behavior.NoHoles)
|
||||
if (!mesh.behavior.NoHoles)
|
||||
{
|
||||
// Infect each triangle in which a hole lies.
|
||||
foreach (var hole in mesh.holes)
|
||||
@@ -475,7 +476,7 @@ namespace TriangleNet
|
||||
|
||||
if (regionTris != null)
|
||||
{
|
||||
if (Behavior.RegionAttrib)
|
||||
if (mesh.behavior.RegionAttrib)
|
||||
{
|
||||
// Make the triangle's attributes larger.
|
||||
double[] attributes = new double[mesh.eextras + 1];
|
||||
@@ -508,7 +509,7 @@ namespace TriangleNet
|
||||
}
|
||||
}
|
||||
|
||||
if (Behavior.RegionAttrib)
|
||||
if (mesh.behavior.RegionAttrib)
|
||||
{
|
||||
// Note the fact that each triangle has an additional attribute.
|
||||
mesh.eextras++;
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace TriangleNet.Data
|
||||
// Three NULL vertices.
|
||||
vertices = new Vertex[3];
|
||||
|
||||
if (Behavior.UseSegments)
|
||||
// TODO: if (Behavior.UseSegments)
|
||||
{
|
||||
// Initialize the three adjoining subsegments to be the
|
||||
// omnipresent subsegment.
|
||||
@@ -63,10 +63,11 @@ namespace TriangleNet.Data
|
||||
attributes = new double[numAttributes];
|
||||
}
|
||||
|
||||
if (Behavior.VarArea)
|
||||
{
|
||||
area = -1.0;
|
||||
}
|
||||
// TODO:
|
||||
//if (Behavior.VarArea)
|
||||
//{
|
||||
// area = -1.0;
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace TriangleNet.IO
|
||||
//tri.triangle.neighbors[0].triangle = tri.triangle;
|
||||
}
|
||||
|
||||
if (Behavior.Poly)
|
||||
if (mesh.behavior.Poly)
|
||||
{
|
||||
mesh.insegments = numberofsegments;
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace TriangleNet.IO
|
||||
tri.triangle.attributes = triangles[i].Attributes;
|
||||
|
||||
// TODO
|
||||
if (Behavior.VarArea)
|
||||
if (mesh.behavior.VarArea)
|
||||
{
|
||||
tri.triangle.area = triangles[i].Area;
|
||||
}
|
||||
@@ -197,7 +197,7 @@ namespace TriangleNet.IO
|
||||
|
||||
// Prepare to count the boundary edges.
|
||||
hullsize = 0;
|
||||
if (Behavior.Poly)
|
||||
if (mesh.behavior.Poly)
|
||||
{
|
||||
// Read the segments from the .poly file, and link them
|
||||
// to their neighboring triangles.
|
||||
|
||||
@@ -43,7 +43,9 @@ namespace TriangleNet.IO
|
||||
Vertex vertex;
|
||||
long outvertices = mesh.vertices.Count;
|
||||
|
||||
if (Behavior.Jettison)
|
||||
Behavior behavior = mesh.behavior;
|
||||
|
||||
if (behavior.Jettison)
|
||||
{
|
||||
outvertices = mesh.vertices.Count - mesh.undeads;
|
||||
}
|
||||
@@ -55,13 +57,13 @@ namespace TriangleNet.IO
|
||||
// Number of vertices, number of dimensions, number of vertex attributes,
|
||||
// and number of boundary markers (zero or one).
|
||||
writer.WriteLine("{0} {1} {2} {3}", outvertices, mesh.mesh_dim, mesh.nextras,
|
||||
Behavior.UseBoundaryMarkers ? "1" : "0");
|
||||
behavior.UseBoundaryMarkers ? "1" : "0");
|
||||
|
||||
foreach (var item in mesh.vertices.Values)
|
||||
{
|
||||
vertex = item;
|
||||
|
||||
if (!Behavior.Jettison || vertex.type != VertexType.UndeadVertex)
|
||||
if (!behavior.Jettison || vertex.type != VertexType.UndeadVertex)
|
||||
{
|
||||
// Vertex number, x and y coordinates.
|
||||
writer.Write("{0} {1} {2}", index, vertex.x.ToString(nfi), vertex.y.ToString(nfi));
|
||||
@@ -72,7 +74,7 @@ namespace TriangleNet.IO
|
||||
writer.Write(" {0}", vertex.attributes[j].ToString(nfi));
|
||||
}
|
||||
|
||||
if (Behavior.UseBoundaryMarkers)
|
||||
if (behavior.UseBoundaryMarkers)
|
||||
{
|
||||
// Write the boundary marker.
|
||||
writer.Write(" {0}", vertex.mark);
|
||||
@@ -154,6 +156,8 @@ namespace TriangleNet.IO
|
||||
Osub subseg = default(Osub);
|
||||
Vertex pt1, pt2;
|
||||
|
||||
bool useBoundaryMarkers = mesh.behavior.UseBoundaryMarkers;
|
||||
|
||||
using (StreamWriter writer = new StreamWriter(filename))
|
||||
{
|
||||
if (writeNodes)
|
||||
@@ -167,12 +171,12 @@ namespace TriangleNet.IO
|
||||
// Followed by number of dimensions, number of vertex attributes,
|
||||
// and number of boundary markers (zero or one).
|
||||
writer.WriteLine("0 {0} {1} {2}", mesh.mesh_dim, mesh.nextras,
|
||||
Behavior.UseBoundaryMarkers ? "1" : "0");
|
||||
useBoundaryMarkers ? "1" : "0");
|
||||
}
|
||||
|
||||
// Number of segments, number of boundary markers (zero or one).
|
||||
writer.WriteLine("{0} {1}", mesh.subsegs.Count,
|
||||
Behavior.UseBoundaryMarkers ? "1" : "0");
|
||||
useBoundaryMarkers ? "1" : "0");
|
||||
|
||||
subseg.orient = 0;
|
||||
|
||||
@@ -185,7 +189,7 @@ namespace TriangleNet.IO
|
||||
pt2 = subseg.Dest();
|
||||
|
||||
// Segment number, indices of its two endpoints, and possibly a marker.
|
||||
if (Behavior.UseBoundaryMarkers)
|
||||
if (useBoundaryMarkers)
|
||||
{
|
||||
writer.WriteLine("{0} {1} {2} {3}", j, pt1.id, pt2.id, subseg.seg.boundary);
|
||||
}
|
||||
@@ -232,10 +236,12 @@ namespace TriangleNet.IO
|
||||
Osub checkmark = default(Osub);
|
||||
Vertex p1, p2;
|
||||
|
||||
Behavior behavior = mesh.behavior;
|
||||
|
||||
using (StreamWriter writer = new StreamWriter(filename))
|
||||
{
|
||||
// Number of edges, number of boundary markers (zero or one).
|
||||
writer.WriteLine("{0} {1}", mesh.edges, Behavior.UseBoundaryMarkers ? "1" : "0");
|
||||
writer.WriteLine("{0} {1}", mesh.edges, behavior.UseBoundaryMarkers ? "1" : "0");
|
||||
|
||||
long index = 0;
|
||||
// To loop over the set of edges, loop over all triangles, and look at
|
||||
@@ -256,11 +262,11 @@ namespace TriangleNet.IO
|
||||
p1 = tri.Org();
|
||||
p2 = tri.Dest();
|
||||
|
||||
if (Behavior.UseBoundaryMarkers)
|
||||
if (behavior.UseBoundaryMarkers)
|
||||
{
|
||||
// Edge number, indices of two endpoints, and a boundary marker.
|
||||
// If there's no subsegment, the boundary marker is zero.
|
||||
if (Behavior.UseSegments)
|
||||
if (behavior.UseSegments)
|
||||
{
|
||||
tri.SegPivot(ref checkmark);
|
||||
|
||||
@@ -371,7 +377,7 @@ namespace TriangleNet.IO
|
||||
torg = tri.Org();
|
||||
tdest = tri.Dest();
|
||||
tapex = tri.Apex();
|
||||
circumcenter = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta, false);
|
||||
circumcenter = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta);
|
||||
|
||||
// X and y coordinates.
|
||||
writer.Write("{0} {1} {2}", index, circumcenter.X.ToString(nfi),
|
||||
@@ -456,7 +462,7 @@ namespace TriangleNet.IO
|
||||
|
||||
long outvertices = mesh.vertices.Count;
|
||||
|
||||
if (Behavior.Jettison)
|
||||
if (mesh.behavior.Jettison)
|
||||
{
|
||||
outvertices = mesh.vertices.Count - mesh.undeads;
|
||||
}
|
||||
@@ -472,7 +478,7 @@ namespace TriangleNet.IO
|
||||
{
|
||||
p1 = item;
|
||||
|
||||
if (!Behavior.Jettison || p1.type != VertexType.UndeadVertex)
|
||||
if (!mesh.behavior.Jettison || p1.type != VertexType.UndeadVertex)
|
||||
{
|
||||
// The "0.0" is here because the OFF format uses 3D coordinates.
|
||||
writer.WriteLine(" {0} {1} 0.0", p1[0].ToString(nfi), p1[1].ToString(nfi));
|
||||
|
||||
@@ -81,7 +81,8 @@ namespace TriangleNet
|
||||
// proximate vertices are inserted sequentially.
|
||||
internal Otri recenttri;
|
||||
|
||||
//static FlipStacker dummyflip;
|
||||
// Controls the behavior of the mesh instance.
|
||||
internal Behavior behavior;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -166,7 +167,7 @@ namespace TriangleNet
|
||||
{
|
||||
logger = SimpleLog.Instance;
|
||||
|
||||
Behavior.Init();
|
||||
behavior = new Behavior();
|
||||
|
||||
vertices = new Dictionary<int, Vertex>();
|
||||
triangles = new Dictionary<int, Triangle>();
|
||||
@@ -222,28 +223,28 @@ namespace TriangleNet
|
||||
|
||||
if (input.HasSegments)
|
||||
{
|
||||
Behavior.Poly = true;
|
||||
behavior.Poly = true;
|
||||
}
|
||||
|
||||
//if (input.EdgeMarkers != null)
|
||||
//{
|
||||
// Behavior.UseBoundaryMarkers = true;
|
||||
// behavior.UseBoundaryMarkers = true;
|
||||
//}
|
||||
|
||||
//if (input.TriangleAreas != null)
|
||||
//{
|
||||
// Behavior.VarArea = true;
|
||||
// behavior.VarArea = true;
|
||||
//}
|
||||
|
||||
if (!Behavior.Poly)
|
||||
if (!behavior.Poly)
|
||||
{
|
||||
// Be careful not to allocate space for element area constraints that
|
||||
// will never be assigned any value (other than the default -1.0).
|
||||
Behavior.VarArea = false;
|
||||
behavior.VarArea = false;
|
||||
|
||||
// Be careful not to add an extra attribute to each element unless the
|
||||
// input supports it (PSLG in, but not refining a preexisting mesh).
|
||||
Behavior.RegionAttrib = false;
|
||||
behavior.RegionAttrib = false;
|
||||
}
|
||||
|
||||
TransferNodes(input);
|
||||
@@ -277,26 +278,26 @@ namespace TriangleNet
|
||||
|
||||
if (input.HasSegments)
|
||||
{
|
||||
Behavior.Poly = true;
|
||||
behavior.Poly = true;
|
||||
}
|
||||
|
||||
//if (input.EdgeMarkers != null)
|
||||
//{
|
||||
// Behavior.UseBoundaryMarkers = true;
|
||||
// behavior.UseBoundaryMarkers = true;
|
||||
//}
|
||||
|
||||
if (!Behavior.Poly)
|
||||
if (!behavior.Poly)
|
||||
{
|
||||
// Be careful not to allocate space for element area constraints that
|
||||
// will never be assigned any value (other than the default -1.0).
|
||||
Behavior.VarArea = false;
|
||||
behavior.VarArea = false;
|
||||
|
||||
// Be careful not to add an extra attribute to each element unless the
|
||||
// input supports it (PSLG in, but not refining a preexisting mesh).
|
||||
Behavior.RegionAttrib = false;
|
||||
behavior.RegionAttrib = false;
|
||||
}
|
||||
|
||||
steinerleft = Behavior.Steiner;
|
||||
steinerleft = behavior.Steiner;
|
||||
|
||||
TransferNodes(input);
|
||||
|
||||
@@ -308,7 +309,7 @@ namespace TriangleNet
|
||||
infvertex2 = null;
|
||||
infvertex3 = null;
|
||||
|
||||
if (Behavior.UseSegments)
|
||||
if (behavior.UseSegments)
|
||||
{
|
||||
// Segments will be introduced next.
|
||||
checksegments = true;
|
||||
@@ -317,7 +318,7 @@ namespace TriangleNet
|
||||
FormSkeleton(input);
|
||||
}
|
||||
|
||||
if (Behavior.Poly && (triangles.Count > 0))
|
||||
if (behavior.Poly && (triangles.Count > 0))
|
||||
{
|
||||
// Copy holes
|
||||
foreach (var item in input.holes)
|
||||
@@ -348,7 +349,7 @@ namespace TriangleNet
|
||||
regions.Clear();
|
||||
}
|
||||
|
||||
if (Behavior.Quality && (triangles.Count > 0))
|
||||
if (behavior.Quality && (triangles.Count > 0))
|
||||
{
|
||||
quality.EnforceQuality(); // Enforce angle and area constraints.
|
||||
}
|
||||
@@ -394,14 +395,14 @@ namespace TriangleNet
|
||||
/// <param name="areaConstraint">Global area constraint.</param>
|
||||
public void Refine(double areaConstraint)
|
||||
{
|
||||
Behavior.FixedArea = true;
|
||||
Behavior.MaxArea = areaConstraint;
|
||||
behavior.FixedArea = true;
|
||||
behavior.MaxArea = areaConstraint;
|
||||
|
||||
this.Refine();
|
||||
|
||||
// Reset option for sanity
|
||||
Behavior.FixedArea = false;
|
||||
Behavior.MaxArea = -1.0;
|
||||
behavior.FixedArea = false;
|
||||
behavior.MaxArea = -1.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -414,9 +415,9 @@ namespace TriangleNet
|
||||
|
||||
// TODO: Set all vertex types to input (i.e. NOT free)?
|
||||
|
||||
if (Behavior.Poly)
|
||||
if (behavior.Poly)
|
||||
{
|
||||
if (Behavior.UseSegments)
|
||||
if (behavior.UseSegments)
|
||||
{
|
||||
insegments = subsegs.Count;
|
||||
}
|
||||
@@ -428,7 +429,7 @@ namespace TriangleNet
|
||||
|
||||
Reset();
|
||||
|
||||
steinerleft = Behavior.Steiner;
|
||||
steinerleft = behavior.Steiner;
|
||||
|
||||
// Ensure that no vertex can be mistaken for a triangular bounding
|
||||
// box vertex in insertvertex().
|
||||
@@ -436,7 +437,7 @@ namespace TriangleNet
|
||||
infvertex2 = null;
|
||||
infvertex3 = null;
|
||||
|
||||
if (Behavior.UseSegments)
|
||||
if (behavior.UseSegments)
|
||||
{
|
||||
checksegments = true;
|
||||
}
|
||||
@@ -502,23 +503,23 @@ namespace TriangleNet
|
||||
{
|
||||
if (option == Options.ConformingDelaunay)
|
||||
{
|
||||
Behavior.ConformDel = value;
|
||||
Behavior.Quality = value; // TODO: ok?
|
||||
behavior.ConformDel = value;
|
||||
behavior.Quality = value; // TODO: ok?
|
||||
return;
|
||||
}
|
||||
else if (option == Options.BoundaryMarkers)
|
||||
{
|
||||
Behavior.UseBoundaryMarkers = value;
|
||||
behavior.UseBoundaryMarkers = value;
|
||||
return;
|
||||
}
|
||||
else if (option == Options.Quality)
|
||||
{
|
||||
Behavior.Quality = value;
|
||||
behavior.Quality = value;
|
||||
|
||||
if (value)
|
||||
{
|
||||
Behavior.MinAngle = 20.0;
|
||||
Behavior.MaxAngle = 140.0;
|
||||
behavior.MinAngle = 20.0;
|
||||
behavior.MaxAngle = 140.0;
|
||||
UpdateOptions();
|
||||
}
|
||||
|
||||
@@ -526,7 +527,7 @@ namespace TriangleNet
|
||||
}
|
||||
else if (option == Options.Convex)
|
||||
{
|
||||
Behavior.Convex = value;
|
||||
behavior.Convex = value;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -543,23 +544,23 @@ namespace TriangleNet
|
||||
|
||||
if (option == Options.MinAngle)
|
||||
{
|
||||
Behavior.MinAngle = value;
|
||||
Behavior.Quality = (value >= 0); // TODO: ok?
|
||||
behavior.MinAngle = value;
|
||||
behavior.Quality = (value >= 0); // TODO: ok?
|
||||
UpdateOptions();
|
||||
return;
|
||||
}
|
||||
else if (option == Options.MaxAngle)
|
||||
{
|
||||
Behavior.MaxAngle = value;
|
||||
Behavior.Quality = (value >= 0); // TODO: ok?
|
||||
behavior.MaxAngle = value;
|
||||
behavior.Quality = (value >= 0); // TODO: ok?
|
||||
UpdateOptions();
|
||||
return;
|
||||
}
|
||||
else if (option == Options.MaxArea)
|
||||
{
|
||||
Behavior.MaxArea = value;
|
||||
Behavior.FixedArea = true;
|
||||
Behavior.Quality = (value >= 0); // TODO: ok?
|
||||
behavior.MaxArea = value;
|
||||
behavior.FixedArea = true;
|
||||
behavior.Quality = (value >= 0); // TODO: ok?
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -575,33 +576,33 @@ namespace TriangleNet
|
||||
{
|
||||
if (option == Options.NoBisect)
|
||||
{
|
||||
Behavior.NoBisect = value;
|
||||
behavior.NoBisect = value;
|
||||
return;
|
||||
}
|
||||
else if (option == Options.SteinerPoints)
|
||||
{
|
||||
Behavior.Steiner = value;
|
||||
behavior.Steiner = value;
|
||||
return;
|
||||
}
|
||||
else if (option == Options.MinAngle)
|
||||
{
|
||||
Behavior.MinAngle = value;
|
||||
Behavior.Quality = (value >= 0); // TODO: ok?
|
||||
behavior.MinAngle = value;
|
||||
behavior.Quality = (value >= 0); // TODO: ok?
|
||||
UpdateOptions();
|
||||
return;
|
||||
}
|
||||
else if (option == Options.MaxAngle)
|
||||
{
|
||||
Behavior.MaxAngle = value;
|
||||
Behavior.Quality = (value >= 0); // TODO: ok?
|
||||
behavior.MaxAngle = value;
|
||||
behavior.Quality = (value >= 0); // TODO: ok?
|
||||
UpdateOptions();
|
||||
return;
|
||||
}
|
||||
else if (option == Options.MaxArea)
|
||||
{
|
||||
Behavior.MaxArea = value;
|
||||
Behavior.Quality = (value >= 0); // TODO: ok?
|
||||
Behavior.FixedArea = true;
|
||||
behavior.MaxArea = value;
|
||||
behavior.Quality = (value >= 0); // TODO: ok?
|
||||
behavior.FixedArea = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -613,20 +614,20 @@ namespace TriangleNet
|
||||
/// </summary>
|
||||
private void UpdateOptions()
|
||||
{
|
||||
Behavior.UseSegments = Behavior.Poly || Behavior.Quality || Behavior.Convex;
|
||||
Behavior.GoodAngle = Math.Cos(Behavior.MinAngle * Math.PI / 180.0);
|
||||
Behavior.MaxGoodAngle = Math.Cos(Behavior.MaxAngle * Math.PI / 180.0);
|
||||
behavior.UseSegments = behavior.Poly || behavior.Quality || behavior.Convex;
|
||||
behavior.GoodAngle = Math.Cos(behavior.MinAngle * Math.PI / 180.0);
|
||||
behavior.MaxGoodAngle = Math.Cos(behavior.MaxAngle * Math.PI / 180.0);
|
||||
|
||||
if (Behavior.GoodAngle == 1.0)
|
||||
if (behavior.GoodAngle == 1.0)
|
||||
{
|
||||
Behavior.Offconstant = 0.0;
|
||||
behavior.Offconstant = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Behavior.Offconstant = 0.475 * Math.Sqrt((1.0 + Behavior.GoodAngle) / (1.0 - Behavior.GoodAngle));
|
||||
behavior.Offconstant = 0.475 * Math.Sqrt((1.0 + behavior.GoodAngle) / (1.0 - behavior.GoodAngle));
|
||||
}
|
||||
|
||||
Behavior.GoodAngle *= Behavior.GoodAngle;
|
||||
behavior.GoodAngle *= behavior.GoodAngle;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -643,12 +644,12 @@ namespace TriangleNet
|
||||
|
||||
eextras = 0;
|
||||
|
||||
if (Behavior.Algorithm == TriangulationAlgorithm.Dwyer)
|
||||
if (behavior.Algorithm == TriangulationAlgorithm.Dwyer)
|
||||
{
|
||||
Dwyer alg = new Dwyer();
|
||||
hulledges = alg.Triangulate(this);
|
||||
}
|
||||
else if (Behavior.Algorithm == TriangulationAlgorithm.SweepLine)
|
||||
else if (behavior.Algorithm == TriangulationAlgorithm.SweepLine)
|
||||
{
|
||||
SweepLine alg = new SweepLine();
|
||||
hulledges = alg.Triangulate(this);
|
||||
@@ -750,7 +751,7 @@ namespace TriangleNet
|
||||
dummytri.neighbors[1].triangle = dummytri;
|
||||
dummytri.neighbors[2].triangle = dummytri;
|
||||
|
||||
if (Behavior.UseSegments)
|
||||
if (behavior.UseSegments)
|
||||
{
|
||||
// Set up 'dummysub', the omnipresent subsegment pointed to by any
|
||||
// triangle side or subsegment end that isn't attached to a real
|
||||
@@ -973,8 +974,8 @@ namespace TriangleNet
|
||||
// The vertex falls on a subsegment, and hence will not be inserted.
|
||||
if (segmentflaws)
|
||||
{
|
||||
enq = Behavior.NoBisect != 2;
|
||||
if (enq && (Behavior.NoBisect == 1))
|
||||
enq = behavior.NoBisect != 2;
|
||||
if (enq && (behavior.NoBisect == 1))
|
||||
{
|
||||
// This subsegment may be split only if it is an
|
||||
// internal boundary.
|
||||
@@ -1035,7 +1036,7 @@ namespace TriangleNet
|
||||
newbotright.triangle.attributes[i] = botright.triangle.attributes[i];
|
||||
}
|
||||
|
||||
if (Behavior.VarArea)
|
||||
if (behavior.VarArea)
|
||||
{
|
||||
// Set the area constraint of a new triangle.
|
||||
newbotright.triangle.area = botright.triangle.area;
|
||||
@@ -1055,7 +1056,7 @@ namespace TriangleNet
|
||||
newtopright.triangle.attributes[i] = topright.triangle.attributes[i];
|
||||
}
|
||||
|
||||
if (Behavior.VarArea)
|
||||
if (behavior.VarArea)
|
||||
{
|
||||
// Set the area constraint of another new triangle.
|
||||
newtopright.triangle.area = topright.triangle.area;
|
||||
@@ -1166,7 +1167,7 @@ namespace TriangleNet
|
||||
newbotright.triangle.attributes[i] = attrib;
|
||||
}
|
||||
|
||||
if (Behavior.VarArea)
|
||||
if (behavior.VarArea)
|
||||
{
|
||||
// Set the area constraint of the new triangles.
|
||||
area = horiz.triangle.area;
|
||||
@@ -1369,7 +1370,7 @@ namespace TriangleNet
|
||||
horiz.triangle.attributes[i] = attrib;
|
||||
}
|
||||
|
||||
if (Behavior.VarArea)
|
||||
if (behavior.VarArea)
|
||||
{
|
||||
if ((top.triangle.area <= 0.0) || (horiz.triangle.area <= 0.0))
|
||||
{
|
||||
@@ -1904,7 +1905,7 @@ namespace TriangleNet
|
||||
// the resulting triangles.
|
||||
deltri.Onext(ref firstedge);
|
||||
deltri.Oprev(ref lastedge);
|
||||
TriangulatePolygon(firstedge, lastedge, edgecount, false, Behavior.NoBisect == 0);
|
||||
TriangulatePolygon(firstedge, lastedge, edgecount, false, behavior.NoBisect == 0);
|
||||
}
|
||||
// Splice out two triangles.
|
||||
deltri.Lprev(ref deltriright);
|
||||
@@ -1928,7 +1929,7 @@ namespace TriangleNet
|
||||
// Set the new origin of 'deltri' and check its quality.
|
||||
neworg = lefttri.Org();
|
||||
deltri.SetOrg(neworg);
|
||||
if (Behavior.NoBisect == 0)
|
||||
if (behavior.NoBisect == 0)
|
||||
{
|
||||
quality.TestTriangle(ref deltri);
|
||||
}
|
||||
@@ -3028,7 +3029,7 @@ namespace TriangleNet
|
||||
|
||||
this.insegments = 0;
|
||||
|
||||
if (Behavior.Poly)
|
||||
if (behavior.Poly)
|
||||
{
|
||||
// If the input vertices are collinear, there is no triangulation,
|
||||
// so don't try to insert segments.
|
||||
@@ -3092,7 +3093,7 @@ namespace TriangleNet
|
||||
}
|
||||
}
|
||||
|
||||
if (Behavior.Convex || !Behavior.Poly)
|
||||
if (behavior.Convex || !behavior.Poly)
|
||||
{
|
||||
// Enclose the convex hull with subsegments.
|
||||
MarkHull();
|
||||
|
||||
@@ -18,14 +18,23 @@ namespace TriangleNet
|
||||
/// <remarks>
|
||||
/// http://www.cise.ufl.edu/~ungor/aCute/index.html
|
||||
/// </remarks>
|
||||
static class NewLocation
|
||||
class NewLocation
|
||||
{
|
||||
const double EPS = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;
|
||||
|
||||
Mesh mesh;
|
||||
Behavior behavior;
|
||||
|
||||
public NewLocation(Mesh mesh)
|
||||
{
|
||||
this.mesh = mesh;
|
||||
this.behavior = mesh.behavior;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a new location for a Steiner point.
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <param name="mesh"></param>
|
||||
/// <param name="torg"></param>
|
||||
/// <param name="tdest"></param>
|
||||
/// <param name="tapex"></param>
|
||||
@@ -34,17 +43,17 @@ namespace TriangleNet
|
||||
/// <param name="eta"></param>
|
||||
/// <param name="offcenter"></param>
|
||||
/// <param name="badotri"></param>
|
||||
public static void FindLocation(Mesh m, Vertex torg, Vertex tdest, Vertex tapex,
|
||||
public void FindLocation(Vertex torg, Vertex tdest, Vertex tapex,
|
||||
Vertex circumcenter, ref double xi, ref double eta, bool offcenter, Otri badotri) // TODO: ref circumcenter???
|
||||
{
|
||||
// Based on using -U switch, call the corresponding function
|
||||
if (Behavior.MaxAngle == 0.0)
|
||||
if (behavior.MaxAngle == 0.0)
|
||||
{
|
||||
FindNewLocationWithoutMaxAngle(m, torg, tdest, tapex, circumcenter, ref xi, ref eta, true, badotri);
|
||||
FindNewLocationWithoutMaxAngle(torg, tdest, tapex, circumcenter, ref xi, ref eta, true, badotri);
|
||||
}
|
||||
else
|
||||
{
|
||||
FindNewLocation(m, torg, tdest, tapex, circumcenter, ref xi, ref eta, true, badotri);
|
||||
FindNewLocation(torg, tdest, tapex, circumcenter, ref xi, ref eta, true, badotri);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -52,7 +61,6 @@ namespace TriangleNet
|
||||
/// <summary>
|
||||
/// Find a new location for a Steiner point.
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <param name="torg"></param>
|
||||
/// <param name="tdest"></param>
|
||||
/// <param name="tapex"></param>
|
||||
@@ -61,9 +69,10 @@ namespace TriangleNet
|
||||
/// <param name="eta"></param>
|
||||
/// <param name="offcenter"></param>
|
||||
/// <param name="badotri"></param>
|
||||
static void FindNewLocationWithoutMaxAngle(Mesh m, Vertex torg, Vertex tdest, Vertex tapex,
|
||||
private void FindNewLocationWithoutMaxAngle(Vertex torg, Vertex tdest, Vertex tapex,
|
||||
Vertex circumcenter, ref double xi, ref double eta, bool offcenter, Otri badotri)
|
||||
{
|
||||
double offconstant = behavior.Offconstant;
|
||||
|
||||
// for calculating the distances of the edges
|
||||
double xdo, ydo, xao, yao, xda, yda;
|
||||
@@ -284,14 +293,14 @@ namespace TriangleNet
|
||||
|
||||
}// end of switch
|
||||
// check for offcenter condition
|
||||
if (offcenter && (Behavior.Offconstant > 0.0))
|
||||
if (offcenter && (offconstant > 0.0))
|
||||
{
|
||||
// origin has the smallest angle
|
||||
if (orientation == 213 || orientation == 231)
|
||||
{
|
||||
// Find the position of the off-center, as described by Alper Ungor.
|
||||
dxoff = 0.5 * xShortestEdge - Behavior.Offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge + Behavior.Offconstant * xShortestEdge;
|
||||
dxoff = 0.5 * xShortestEdge - offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge + offconstant * xShortestEdge;
|
||||
// If the off-center is closer to destination than the
|
||||
// circumcenter, use the off-center instead.
|
||||
/// doubleLY BAD CASE ///
|
||||
@@ -311,8 +320,8 @@ namespace TriangleNet
|
||||
else if (orientation == 123 || orientation == 132)
|
||||
{
|
||||
// Find the position of the off-center, as described by Alper Ungor.
|
||||
dxoff = 0.5 * xShortestEdge + Behavior.Offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge - Behavior.Offconstant * xShortestEdge;
|
||||
dxoff = 0.5 * xShortestEdge + offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge - offconstant * xShortestEdge;
|
||||
// If the off-center is closer to the origin than the
|
||||
// circumcenter, use the off-center instead.
|
||||
/// doubleLY BAD CASE ///
|
||||
@@ -331,8 +340,8 @@ namespace TriangleNet
|
||||
else
|
||||
{//orientation == 312 || orientation == 321
|
||||
// Find the position of the off-center, as described by Alper Ungor.
|
||||
dxoff = 0.5 * xShortestEdge - Behavior.Offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge + Behavior.Offconstant * xShortestEdge;
|
||||
dxoff = 0.5 * xShortestEdge - offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge + offconstant * xShortestEdge;
|
||||
// If the off-center is closer to the origin than the
|
||||
// circumcenter, use the off-center instead.
|
||||
/// doubleLY BAD CASE ///
|
||||
@@ -371,7 +380,7 @@ namespace TriangleNet
|
||||
}
|
||||
/// RELOCATION (LOCAL SMOOTHING) ///
|
||||
/// check for possible relocation of one of triangle's points ///
|
||||
relocated = DoSmoothing(m, delotri, torg, tdest, tapex, ref newloc);
|
||||
relocated = DoSmoothing(delotri, torg, tdest, tapex, ref newloc);
|
||||
/// if relocation is possible, delete that vertex and insert a vertex at the new location ///
|
||||
if (relocated > 0)
|
||||
{
|
||||
@@ -385,17 +394,17 @@ namespace TriangleNet
|
||||
{
|
||||
case 1:
|
||||
//printf("Relocate: (%f,%f)\n", torg[0],torg[1]);
|
||||
m.DeleteVertex(ref delotri);
|
||||
mesh.DeleteVertex(ref delotri);
|
||||
break;
|
||||
case 2:
|
||||
//printf("Relocate: (%f,%f)\n", tdest[0],tdest[1]);
|
||||
delotri.LnextSelf();
|
||||
m.DeleteVertex(ref delotri);
|
||||
mesh.DeleteVertex(ref delotri);
|
||||
break;
|
||||
case 3:
|
||||
//printf("Relocate: (%f,%f)\n", tapex[0],tapex[1]);
|
||||
delotri.LprevSelf();
|
||||
m.DeleteVertex(ref delotri);
|
||||
mesh.DeleteVertex(ref delotri);
|
||||
break;
|
||||
|
||||
}
|
||||
@@ -405,7 +414,7 @@ namespace TriangleNet
|
||||
// calculate radius of the petal according to angle constraint
|
||||
// first find the visible region, PETAL
|
||||
// find the center of the circle and radius
|
||||
petalRadius = Math.Sqrt(shortestEdgeDist) / (2 * Math.Sin(Behavior.MinAngle * Math.PI / 180.0));
|
||||
petalRadius = Math.Sqrt(shortestEdgeDist) / (2 * Math.Sin(behavior.MinAngle * Math.PI / 180.0));
|
||||
/// compute two possible centers of the petal ///
|
||||
// finding the center
|
||||
// first find the middle point of smallest edge
|
||||
@@ -439,7 +448,7 @@ namespace TriangleNet
|
||||
}
|
||||
|
||||
/// find the third point of the neighbor triangle ///
|
||||
neighborNotFound = GetNeighborsVertex(m, badotri, middleAngleCorner.x, middleAngleCorner.y,
|
||||
neighborNotFound = GetNeighborsVertex(badotri, middleAngleCorner.x, middleAngleCorner.y,
|
||||
smallestAngleCorner.x, smallestAngleCorner.y, ref thirdPoint, ref neighborotri);
|
||||
/// find the circumcenter of the neighbor triangle ///
|
||||
dxFirstSuggestion = dx; // if we cannot find any appropriate suggestion, we use circumcenter
|
||||
@@ -451,7 +460,9 @@ namespace TriangleNet
|
||||
neighborvertex_2 = neighborotri.Dest();
|
||||
neighborvertex_3 = neighborotri.Apex();
|
||||
// now calculate neighbor's circumcenter which is the voronoi site
|
||||
neighborCircumcenter = Primitives.FindCircumcenter(neighborvertex_1, neighborvertex_2, neighborvertex_3, ref xi_tmp, ref eta_tmp, false);
|
||||
neighborCircumcenter = Primitives.FindCircumcenter(neighborvertex_1, neighborvertex_2, neighborvertex_3,
|
||||
ref xi_tmp, ref eta_tmp);
|
||||
|
||||
/// compute petal and Voronoi edge intersection ///
|
||||
// in order to avoid degenerate cases, we need to do a vector based calculation for line
|
||||
vector_x = (middleAngleCorner.y - smallestAngleCorner.y);//(-y, x)
|
||||
@@ -568,7 +579,7 @@ namespace TriangleNet
|
||||
|
||||
/// DO THE SAME THING FOR THE OTHER DIRECTION ///
|
||||
/// find the third point of the neighbor triangle ///
|
||||
neighborNotFound = GetNeighborsVertex(m, badotri, largestAngleCorner.x, largestAngleCorner.y,
|
||||
neighborNotFound = GetNeighborsVertex(badotri, largestAngleCorner.x, largestAngleCorner.y,
|
||||
smallestAngleCorner.x, smallestAngleCorner.y, ref thirdPoint, ref neighborotri);
|
||||
/// find the circumcenter of the neighbor triangle ///
|
||||
dxSecondSuggestion = dx; // if we cannot find any appropriate suggestion, we use circumcenter
|
||||
@@ -580,7 +591,8 @@ namespace TriangleNet
|
||||
neighborvertex_2 = neighborotri.Dest();
|
||||
neighborvertex_3 = neighborotri.Apex();
|
||||
// now calculate neighbor's circumcenter which is the voronoi site
|
||||
neighborCircumcenter = Primitives.FindCircumcenter(neighborvertex_1, neighborvertex_2, neighborvertex_3, ref xi_tmp, ref eta_tmp, false);
|
||||
neighborCircumcenter = Primitives.FindCircumcenter(neighborvertex_1, neighborvertex_2, neighborvertex_3,
|
||||
ref xi_tmp, ref eta_tmp);
|
||||
|
||||
/// compute petal and Voronoi edge intersection ///
|
||||
// in order to avoid degenerate cases, we need to do a vector based calculation for line
|
||||
@@ -747,7 +759,6 @@ namespace TriangleNet
|
||||
/// <summary>
|
||||
/// Find a new location for a Steiner point.
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <param name="torg"></param>
|
||||
/// <param name="tdest"></param>
|
||||
/// <param name="tapex"></param>
|
||||
@@ -756,10 +767,10 @@ namespace TriangleNet
|
||||
/// <param name="eta"></param>
|
||||
/// <param name="offcenter"></param>
|
||||
/// <param name="badotri"></param>
|
||||
static void FindNewLocation(Mesh m,
|
||||
Vertex torg, Vertex tdest, Vertex tapex,
|
||||
private void FindNewLocation(Vertex torg, Vertex tdest, Vertex tapex,
|
||||
Vertex circumcenter, ref double xi, ref double eta, bool offcenter, Otri badotri)
|
||||
{
|
||||
double offconstant = behavior.Offconstant;
|
||||
|
||||
// for calculating the distances of the edges
|
||||
double xdo, ydo, xao, yao, xda, yda;
|
||||
@@ -992,14 +1003,14 @@ namespace TriangleNet
|
||||
|
||||
}// end of switch
|
||||
// check for offcenter condition
|
||||
if (offcenter && (Behavior.Offconstant > 0.0))
|
||||
if (offcenter && (offconstant > 0.0))
|
||||
{
|
||||
// origin has the smallest angle
|
||||
if (orientation == 213 || orientation == 231)
|
||||
{
|
||||
// Find the position of the off-center, as described by Alper Ungor.
|
||||
dxoff = 0.5 * xShortestEdge - Behavior.Offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge + Behavior.Offconstant * xShortestEdge;
|
||||
dxoff = 0.5 * xShortestEdge - offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge + offconstant * xShortestEdge;
|
||||
// If the off-center is closer to destination than the
|
||||
// circumcenter, use the off-center instead.
|
||||
/// doubleLY BAD CASE ///
|
||||
@@ -1019,8 +1030,8 @@ namespace TriangleNet
|
||||
else if (orientation == 123 || orientation == 132)
|
||||
{
|
||||
// Find the position of the off-center, as described by Alper Ungor.
|
||||
dxoff = 0.5 * xShortestEdge + Behavior.Offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge - Behavior.Offconstant * xShortestEdge;
|
||||
dxoff = 0.5 * xShortestEdge + offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge - offconstant * xShortestEdge;
|
||||
// If the off-center is closer to the origin than the
|
||||
// circumcenter, use the off-center instead.
|
||||
/// doubleLY BAD CASE ///
|
||||
@@ -1039,8 +1050,8 @@ namespace TriangleNet
|
||||
else
|
||||
{//orientation == 312 || orientation == 321
|
||||
// Find the position of the off-center, as described by Alper Ungor.
|
||||
dxoff = 0.5 * xShortestEdge - Behavior.Offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge + Behavior.Offconstant * xShortestEdge;
|
||||
dxoff = 0.5 * xShortestEdge - offconstant * yShortestEdge;
|
||||
dyoff = 0.5 * yShortestEdge + offconstant * xShortestEdge;
|
||||
// If the off-center is closer to the origin than the
|
||||
// circumcenter, use the off-center instead.
|
||||
/// doubleLY BAD CASE ///
|
||||
@@ -1079,7 +1090,7 @@ namespace TriangleNet
|
||||
}
|
||||
/// RELOCATION (LOCAL SMOOTHING) ///
|
||||
/// check for possible relocation of one of triangle's points ///
|
||||
relocated = DoSmoothing(m, delotri, torg, tdest, tapex, ref newloc);
|
||||
relocated = DoSmoothing(delotri, torg, tdest, tapex, ref newloc);
|
||||
/// if relocation is possible, delete that vertex and insert a vertex at the new location ///
|
||||
if (relocated > 0)
|
||||
{
|
||||
@@ -1093,17 +1104,17 @@ namespace TriangleNet
|
||||
{
|
||||
case 1:
|
||||
//printf("Relocate: (%f,%f)\n", torg[0],torg[1]);
|
||||
m.DeleteVertex(ref delotri);
|
||||
mesh.DeleteVertex(ref delotri);
|
||||
break;
|
||||
case 2:
|
||||
//printf("Relocate: (%f,%f)\n", tdest[0],tdest[1]);
|
||||
delotri.LnextSelf();
|
||||
m.DeleteVertex(ref delotri);
|
||||
mesh.DeleteVertex(ref delotri);
|
||||
break;
|
||||
case 3:
|
||||
//printf("Relocate: (%f,%f)\n", tapex[0],tapex[1]);
|
||||
delotri.LprevSelf();
|
||||
m.DeleteVertex(ref delotri);
|
||||
mesh.DeleteVertex(ref delotri);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1114,9 +1125,9 @@ namespace TriangleNet
|
||||
// find the center of the circle and radius
|
||||
// choose minimum angle as the maximum of quality angle and the minimum angle of the bad triangle
|
||||
minangle = Math.Acos((middleEdgeDist + longestEdgeDist - shortestEdgeDist) / (2 * Math.Sqrt(middleEdgeDist) * Math.Sqrt(longestEdgeDist))) * 180.0 / Math.PI;
|
||||
if (Behavior.MinAngle > minangle)
|
||||
if (behavior.MinAngle > minangle)
|
||||
{
|
||||
minangle = Behavior.MinAngle;
|
||||
minangle = behavior.MinAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1155,7 +1166,7 @@ namespace TriangleNet
|
||||
xPetalCtr = xPetalCtr_2; yPetalCtr = yPetalCtr_2;
|
||||
}
|
||||
/// find the third point of the neighbor triangle ///
|
||||
neighborNotFound_first = GetNeighborsVertex(m, badotri, middleAngleCorner.x, middleAngleCorner.y,
|
||||
neighborNotFound_first = GetNeighborsVertex(badotri, middleAngleCorner.x, middleAngleCorner.y,
|
||||
smallestAngleCorner.x, smallestAngleCorner.y, ref thirdPoint, ref neighborotri);
|
||||
/// find the circumcenter of the neighbor triangle ///
|
||||
dxFirstSuggestion = dx; // if we cannot find any appropriate suggestion, we use circumcenter
|
||||
@@ -1171,7 +1182,7 @@ namespace TriangleNet
|
||||
// find the third point other than p and q
|
||||
petal_bisector_x = xPetalCtr + line_vector_x * petalRadius;
|
||||
petal_bisector_y = yPetalCtr + line_vector_y * petalRadius;
|
||||
alpha = (2.0 * Behavior.MaxAngle + minangle - 180.0) * Math.PI / 180.0;
|
||||
alpha = (2.0 * behavior.MaxAngle + minangle - 180.0) * Math.PI / 180.0;
|
||||
// rotate the vector cw around the petal center
|
||||
x_1 = petal_bisector_x * Math.Cos(alpha) + petal_bisector_y * Math.Sin(alpha) + xPetalCtr - xPetalCtr * Math.Cos(alpha) - yPetalCtr * Math.Sin(alpha);
|
||||
y_1 = -petal_bisector_x * Math.Sin(alpha) + petal_bisector_y * Math.Cos(alpha) + yPetalCtr + xPetalCtr * Math.Sin(alpha) - yPetalCtr * Math.Cos(alpha);
|
||||
@@ -1207,7 +1218,9 @@ namespace TriangleNet
|
||||
neighborvertex_2 = neighborotri.Dest();
|
||||
neighborvertex_3 = neighborotri.Apex();
|
||||
// now calculate neighbor's circumcenter which is the voronoi site
|
||||
neighborCircumcenter = Primitives.FindCircumcenter(neighborvertex_1, neighborvertex_2, neighborvertex_3, ref xi_tmp, ref eta_tmp, false);
|
||||
neighborCircumcenter = Primitives.FindCircumcenter(neighborvertex_1, neighborvertex_2, neighborvertex_3,
|
||||
ref xi_tmp, ref eta_tmp);
|
||||
|
||||
/// compute petal and Voronoi edge intersection ///
|
||||
// in order to avoid degenerate cases, we need to do a vector based calculation for line
|
||||
vector_x = (middleAngleCorner.y - smallestAngleCorner.y);//(-y, x)
|
||||
@@ -1285,7 +1298,7 @@ namespace TriangleNet
|
||||
(smallestAngleCorner.y - line_inter_y) *
|
||||
(smallestAngleCorner.y - line_inter_y)))
|
||||
&& (IsBadTriangleAngle(middleAngleCorner.x, middleAngleCorner.y, largestAngleCorner.x, largestAngleCorner.y, petal_slab_inter_x_first, petal_slab_inter_y_first))
|
||||
&& MinDistanceToNeighbor(m, petal_slab_inter_x_first, petal_slab_inter_y_first, ref neighborotri) > MinDistanceToNeighbor(m, line_inter_x, line_inter_y, ref neighborotri))
|
||||
&& MinDistanceToNeighbor(petal_slab_inter_x_first, petal_slab_inter_y_first, ref neighborotri) > MinDistanceToNeighbor(line_inter_x, line_inter_y, ref neighborotri))
|
||||
{
|
||||
//
|
||||
/// check the neighbor's vertices also, which one if better
|
||||
@@ -1379,7 +1392,7 @@ namespace TriangleNet
|
||||
(smallestAngleCorner.y - line_inter_y) *
|
||||
(smallestAngleCorner.y - line_inter_y)))
|
||||
&& (IsBadTriangleAngle(middleAngleCorner.x, middleAngleCorner.y, largestAngleCorner.x, largestAngleCorner.y, petal_slab_inter_x_first, petal_slab_inter_y_first))
|
||||
&& MinDistanceToNeighbor(m, petal_slab_inter_x_first, petal_slab_inter_y_first, ref neighborotri) > MinDistanceToNeighbor(m, line_inter_x, line_inter_y, ref neighborotri))
|
||||
&& MinDistanceToNeighbor(petal_slab_inter_x_first, petal_slab_inter_y_first, ref neighborotri) > MinDistanceToNeighbor(line_inter_x, line_inter_y, ref neighborotri))
|
||||
{
|
||||
//slab and petal intersection is advised
|
||||
dxFirstSuggestion = petal_slab_inter_x_first - torg.x;
|
||||
@@ -1497,7 +1510,7 @@ namespace TriangleNet
|
||||
|
||||
/// DO THE SAME THING FOR THE OTHER DIRECTION ///
|
||||
/// find the third point of the neighbor triangle ///
|
||||
neighborNotFound_second = GetNeighborsVertex(m, badotri, largestAngleCorner.x, largestAngleCorner.y,
|
||||
neighborNotFound_second = GetNeighborsVertex(badotri, largestAngleCorner.x, largestAngleCorner.y,
|
||||
smallestAngleCorner.x, smallestAngleCorner.y, ref thirdPoint, ref neighborotri);
|
||||
/// find the circumcenter of the neighbor triangle ///
|
||||
dxSecondSuggestion = dx; // if we cannot find any appropriate suggestion, we use circumcenter
|
||||
@@ -1514,7 +1527,8 @@ namespace TriangleNet
|
||||
neighborvertex_2 = neighborotri.Dest();
|
||||
neighborvertex_3 = neighborotri.Apex();
|
||||
// now calculate neighbor's circumcenter which is the voronoi site
|
||||
neighborCircumcenter = Primitives.FindCircumcenter(neighborvertex_1, neighborvertex_2, neighborvertex_3, ref xi_tmp, ref eta_tmp, false);
|
||||
neighborCircumcenter = Primitives.FindCircumcenter(neighborvertex_1, neighborvertex_2, neighborvertex_3,
|
||||
ref xi_tmp, ref eta_tmp);
|
||||
|
||||
/// compute petal and Voronoi edge intersection ///
|
||||
// in order to avoid degenerate cases, we need to do a vector based calculation for line
|
||||
@@ -1595,7 +1609,7 @@ namespace TriangleNet
|
||||
(smallestAngleCorner.y - line_inter_y) *
|
||||
(smallestAngleCorner.y - line_inter_y)))
|
||||
&& (IsBadTriangleAngle(middleAngleCorner.x, middleAngleCorner.y, largestAngleCorner.x, largestAngleCorner.y, petal_slab_inter_x_second, petal_slab_inter_y_second))
|
||||
&& MinDistanceToNeighbor(m, petal_slab_inter_x_second, petal_slab_inter_y_second, ref neighborotri) > MinDistanceToNeighbor(m, line_inter_x, line_inter_y, ref neighborotri))
|
||||
&& MinDistanceToNeighbor(petal_slab_inter_x_second, petal_slab_inter_y_second, ref neighborotri) > MinDistanceToNeighbor(line_inter_x, line_inter_y, ref neighborotri))
|
||||
{
|
||||
// slab and petal intersection is advised
|
||||
dxSecondSuggestion = petal_slab_inter_x_second - torg.x;
|
||||
@@ -1684,7 +1698,7 @@ namespace TriangleNet
|
||||
(smallestAngleCorner.y - line_inter_y) *
|
||||
(smallestAngleCorner.y - line_inter_y)))
|
||||
&& (IsBadTriangleAngle(middleAngleCorner.x, middleAngleCorner.y, largestAngleCorner.x, largestAngleCorner.y, petal_slab_inter_x_second, petal_slab_inter_y_second))
|
||||
&& MinDistanceToNeighbor(m, petal_slab_inter_x_second, petal_slab_inter_y_second, ref neighborotri) > MinDistanceToNeighbor(m, line_inter_x, line_inter_y, ref neighborotri))
|
||||
&& MinDistanceToNeighbor(petal_slab_inter_x_second, petal_slab_inter_y_second, ref neighborotri) > MinDistanceToNeighbor(line_inter_x, line_inter_y, ref neighborotri))
|
||||
{
|
||||
// slab and petal intersection is advised
|
||||
dxSecondSuggestion = petal_slab_inter_x_second - torg.x;
|
||||
@@ -2015,7 +2029,7 @@ namespace TriangleNet
|
||||
/// <param name="dadist"></param>
|
||||
/// <param name="dodist"></param>
|
||||
/// <returns>Returns a number indicating an orientation.</returns>
|
||||
static int LongestShortestEdge(double aodist, double dadist, double dodist)
|
||||
private int LongestShortestEdge(double aodist, double dadist, double dodist)
|
||||
{
|
||||
// 123: shortest: aodist // 213: shortest: dadist // 312: shortest: dodist
|
||||
// middle: dadist // middle: aodist // middle: aodist
|
||||
@@ -2075,15 +2089,14 @@ namespace TriangleNet
|
||||
/// <summary>
|
||||
/// Checks if smothing is possible for a given bad triangle.
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <param name="badotri"></param>
|
||||
/// <param name="torg"></param>
|
||||
/// <param name="tdest"></param>
|
||||
/// <param name="tapex"></param>
|
||||
/// <param name="newloc">The new location for the point, if somothing is possible.</param>
|
||||
/// <returns>Returns 1, 2 or 3 if smoothing will work, 0 otherwise.</returns>
|
||||
static int DoSmoothing(Mesh m, Otri badotri,
|
||||
Vertex torg, Vertex tdest, Vertex tapex, ref double[] newloc)
|
||||
private int DoSmoothing(Otri badotri, Vertex torg, Vertex tdest, Vertex tapex,
|
||||
ref double[] newloc)
|
||||
{
|
||||
|
||||
int numpoints_p = 0;// keeps the number of points in a star of point p, q, r
|
||||
@@ -2106,7 +2119,7 @@ namespace TriangleNet
|
||||
//********************* TRY TO RELOCATE POINT "p" ***************
|
||||
|
||||
// get the surrounding points of p, so this gives us the triangles
|
||||
numpoints_p = GetStarPoints(m, badotri, torg, tdest, tapex, 1, ref points_p);
|
||||
numpoints_p = GetStarPoints(badotri, torg, tdest, tapex, 1, ref points_p);
|
||||
// check if the points in counterclockwise order
|
||||
// p1[0] = points_p[0]; p1[1] = points_p[1];
|
||||
// p2[0] = points_p[2]; p2[1] = points_p[3];
|
||||
@@ -2130,13 +2143,13 @@ namespace TriangleNet
|
||||
{
|
||||
//newLocFound = getPetalIntersection(m, b, numpoints_p, points_p, newloc);
|
||||
//newLocFound = getPetalIntersectionBruteForce(m, b,numpoints_p, points_p, newloc,torg[0],torg[1]);
|
||||
if (Behavior.MaxAngle == 0.0)
|
||||
if (behavior.MaxAngle == 0.0)
|
||||
{
|
||||
newLocFound = GetWedgeIntersectionWithoutMaxAngle(m, numpoints_p, points_p, ref newloc);
|
||||
newLocFound = GetWedgeIntersectionWithoutMaxAngle(numpoints_p, points_p, ref newloc);
|
||||
}
|
||||
else
|
||||
{
|
||||
newLocFound = GetWedgeIntersection(m, numpoints_p, points_p, ref newloc);
|
||||
newLocFound = GetWedgeIntersection(numpoints_p, points_p, ref newloc);
|
||||
}
|
||||
//printf("call petal intersection for p\n");
|
||||
// make sure the relocated point is a free vertex
|
||||
@@ -2152,7 +2165,7 @@ namespace TriangleNet
|
||||
//********************* TRY TO RELOCATE POINT "q" ***************
|
||||
|
||||
// get the surrounding points of q, so this gives us the triangles
|
||||
numpoints_q = GetStarPoints(m, badotri, torg, tdest, tapex, 2, ref points_q);
|
||||
numpoints_q = GetStarPoints(badotri, torg, tdest, tapex, 2, ref points_q);
|
||||
// // check if the points in counterclockwise order
|
||||
// v1[0] = points_q[0]; v1[1] = points_q[1];
|
||||
// v2[0] = points_q[2]; v2[1] = points_q[3];
|
||||
@@ -2175,13 +2188,13 @@ namespace TriangleNet
|
||||
{
|
||||
//newLocFound = getPetalIntersection(m, b,numpoints_q, points_q, newloc);
|
||||
//newLocFound = getPetalIntersectionBruteForce(m, b,numpoints_q, points_q, newloc,tapex[0],tapex[1]);
|
||||
if (Behavior.MaxAngle == 0.0)
|
||||
if (behavior.MaxAngle == 0.0)
|
||||
{
|
||||
newLocFound = GetWedgeIntersectionWithoutMaxAngle(m, numpoints_q, points_q, ref newloc);
|
||||
newLocFound = GetWedgeIntersectionWithoutMaxAngle(numpoints_q, points_q, ref newloc);
|
||||
}
|
||||
else
|
||||
{
|
||||
newLocFound = GetWedgeIntersection(m, numpoints_q, points_q, ref newloc);
|
||||
newLocFound = GetWedgeIntersection(numpoints_q, points_q, ref newloc);
|
||||
}
|
||||
//printf("call petal intersection for q\n");
|
||||
|
||||
@@ -2198,7 +2211,7 @@ namespace TriangleNet
|
||||
|
||||
//********************* TRY TO RELOCATE POINT "q" ***************
|
||||
// get the surrounding points of r, so this gives us the triangles
|
||||
numpoints_r = GetStarPoints(m, badotri, torg, tdest, tapex, 3, ref points_r);
|
||||
numpoints_r = GetStarPoints(badotri, torg, tdest, tapex, 3, ref points_r);
|
||||
// check if the points in counterclockwise order
|
||||
// v1[0] = points_r[0]; v1[1] = points_r[1];
|
||||
// v2[0] = points_r[2]; v2[1] = points_r[3];
|
||||
@@ -2221,13 +2234,13 @@ namespace TriangleNet
|
||||
{
|
||||
//newLocFound = getPetalIntersection(m, b,numpoints_r, points_r, newloc);
|
||||
//newLocFound = getPetalIntersectionBruteForce(m, b,numpoints_r, points_r, newloc,tdest[0],tdest[1]);
|
||||
if (Behavior.MaxAngle == 0.0)
|
||||
if (behavior.MaxAngle == 0.0)
|
||||
{
|
||||
newLocFound = GetWedgeIntersectionWithoutMaxAngle(m, numpoints_r, points_r, ref newloc);
|
||||
newLocFound = GetWedgeIntersectionWithoutMaxAngle(numpoints_r, points_r, ref newloc);
|
||||
}
|
||||
else
|
||||
{
|
||||
newLocFound = GetWedgeIntersection(m, numpoints_r, points_r, ref newloc);
|
||||
newLocFound = GetWedgeIntersection(numpoints_r, points_r, ref newloc);
|
||||
}
|
||||
|
||||
//printf("call petal intersection for r\n");
|
||||
@@ -2281,7 +2294,6 @@ namespace TriangleNet
|
||||
/// <summary>
|
||||
/// Finds the star of a given point.
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <param name="badotri"></param>
|
||||
/// <param name="p"></param>
|
||||
/// <param name="q"></param>
|
||||
@@ -2289,12 +2301,8 @@ namespace TriangleNet
|
||||
/// <param name="whichPoint"></param>
|
||||
/// <param name="points">List of points on the star of the given point.</param>
|
||||
/// <returns>Number of points on the star of the given point.</returns>
|
||||
static int GetStarPoints(Mesh m, Otri badotri,
|
||||
Vertex p,
|
||||
Vertex q,
|
||||
Vertex r,
|
||||
int whichPoint,
|
||||
ref double[] points)
|
||||
private int GetStarPoints(Otri badotri, Vertex p, Vertex q, Vertex r,
|
||||
int whichPoint, ref double[] points)
|
||||
{
|
||||
|
||||
Otri neighotri = default(Otri); // for return value of the function
|
||||
@@ -2345,7 +2353,7 @@ namespace TriangleNet
|
||||
do
|
||||
{
|
||||
// find the neighbor's third point where it is incident to given edge
|
||||
if (!GetNeighborsVertex(m, tempotri, first_x, first_y, second_x, second_y, ref returnPoint, ref neighotri))
|
||||
if (!GetNeighborsVertex(tempotri, first_x, first_y, second_x, second_y, ref returnPoint, ref neighotri))
|
||||
{
|
||||
// go to next triangle
|
||||
tempotri = neighotri;
|
||||
@@ -2373,7 +2381,6 @@ namespace TriangleNet
|
||||
/// <summary>
|
||||
/// Gets a neighbours vertex.
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <param name="badotri"></param>
|
||||
/// <param name="first_x"></param>
|
||||
/// <param name="first_y"></param>
|
||||
@@ -2382,7 +2389,7 @@ namespace TriangleNet
|
||||
/// <param name="thirdpoint">Neighbor's third vertex incident to given edge.</param>
|
||||
/// <param name="neighotri">Pointer for the neighbor triangle.</param>
|
||||
/// <returns>Returns true if vertex was found.</returns>
|
||||
static bool GetNeighborsVertex(Mesh m, Otri badotri,
|
||||
private bool GetNeighborsVertex(Otri badotri,
|
||||
double first_x, double first_y,
|
||||
double second_x, double second_y,
|
||||
ref double[] thirdpoint, ref Otri neighotri)
|
||||
@@ -2534,13 +2541,12 @@ namespace TriangleNet
|
||||
/// <summary>
|
||||
/// Find a new point location by wedge intersection.
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <param name="numpoints"></param>
|
||||
/// <param name="points"></param>
|
||||
/// <param name="newloc">A new location for the point according to surrounding points.</param>
|
||||
/// <returns>Returns true if new location found</returns>
|
||||
static bool GetWedgeIntersectionWithoutMaxAngle(Mesh m,
|
||||
int numpoints, double[] points, ref double[] newloc)
|
||||
private bool GetWedgeIntersectionWithoutMaxAngle(int numpoints,
|
||||
double[] points, ref double[] newloc)
|
||||
{
|
||||
//double total_x = 0;
|
||||
//double total_y = 0;
|
||||
@@ -2586,9 +2592,9 @@ namespace TriangleNet
|
||||
y1 = points[2 * numpoints - 1];
|
||||
|
||||
// minimum angle
|
||||
alpha = Behavior.MinAngle * Math.PI / 180.0;
|
||||
alpha = behavior.MinAngle * Math.PI / 180.0;
|
||||
// initialize the constants
|
||||
if (Behavior.GoodAngle == 1.0)
|
||||
if (behavior.GoodAngle == 1.0)
|
||||
{
|
||||
petalcenterconstant = 0;
|
||||
petalradiusconstant = 0;
|
||||
@@ -2759,7 +2765,7 @@ namespace TriangleNet
|
||||
/// IF THERE IS A FEASIBLE INTERSECTION POLYGON, FIND ITS CENTROID AS THE NEW LOCATION
|
||||
FindPolyCentroid(numpolypoints, initialConvexPoly, ref newloc);
|
||||
|
||||
if (Behavior.FixedArea)
|
||||
if (behavior.FixedArea)
|
||||
{
|
||||
// numBadTriangle = 0;
|
||||
// for(j= 0; j < numpoints *2-2; j = j+2){
|
||||
@@ -2794,12 +2800,11 @@ namespace TriangleNet
|
||||
/// <summary>
|
||||
/// Find a new point location by wedge intersection.
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <param name="numpoints"></param>
|
||||
/// <param name="points"></param>
|
||||
/// <param name="newloc">A new location for the point according to surrounding points.</param>
|
||||
/// <returns>Returns true if new location found</returns>
|
||||
static bool GetWedgeIntersection(Mesh m, int numpoints, double[] points, ref double[] newloc)
|
||||
private bool GetWedgeIntersection(int numpoints, double[] points, ref double[] newloc)
|
||||
{
|
||||
//double total_x = 0;
|
||||
//double total_y = 0;
|
||||
@@ -2851,15 +2856,15 @@ namespace TriangleNet
|
||||
|
||||
// minimum / maximum angle
|
||||
double alpha, sinAlpha, cosAlpha, beta, sinBeta, cosBeta;
|
||||
alpha = Behavior.MinAngle * Math.PI / 180.0;
|
||||
alpha = behavior.MinAngle * Math.PI / 180.0;
|
||||
sinAlpha = Math.Sin(alpha);
|
||||
cosAlpha = Math.Cos(alpha);
|
||||
beta = Behavior.MaxAngle * Math.PI / 180.0;
|
||||
beta = behavior.MaxAngle * Math.PI / 180.0;
|
||||
sinBeta = Math.Sin(beta);
|
||||
cosBeta = Math.Cos(beta);
|
||||
|
||||
// initialize the constants
|
||||
if (Behavior.GoodAngle == 1.0)
|
||||
if (behavior.GoodAngle == 1.0)
|
||||
{
|
||||
petalcenterconstant = 0;
|
||||
petalradiusconstant = 0;
|
||||
@@ -2941,7 +2946,7 @@ namespace TriangleNet
|
||||
|
||||
/// DETERMINE HOW MANY POINTS TO USE ACCORDING TO THE MINANGLE-MAXANGLE COMBINATION
|
||||
// petal center angle
|
||||
alpha = (2.0 * Behavior.MaxAngle + Behavior.MinAngle - 180.0);
|
||||
alpha = (2.0 * behavior.MaxAngle + behavior.MinAngle - 180.0);
|
||||
if (alpha <= 0.0)
|
||||
{// when only angle lines needed
|
||||
// 4 point case
|
||||
@@ -3199,7 +3204,7 @@ namespace TriangleNet
|
||||
/// IF THERE IS A FEASIBLE INTERSECTION POLYGON, FIND ITS CENTROID AS THE NEW LOCATION
|
||||
FindPolyCentroid(numpolypoints, initialConvexPoly, ref newloc);
|
||||
|
||||
if (Behavior.MaxAngle != 0.0)
|
||||
if (behavior.MaxAngle != 0.0)
|
||||
{
|
||||
numBadTriangle = 0;
|
||||
for (j = 0; j < numpoints * 2 - 2; j = j + 2)
|
||||
@@ -3284,7 +3289,7 @@ namespace TriangleNet
|
||||
/// <param name="numpoints"></param>
|
||||
/// <param name="points"></param>
|
||||
/// <returns>Returns true if the polygon has angles greater than 2*minangle.</returns>
|
||||
static bool ValidPolygonAngles(int numpoints, double[] points)
|
||||
private bool ValidPolygonAngles(int numpoints, double[] points)
|
||||
{
|
||||
int i;//,j
|
||||
for (i = 0; i < numpoints; i++)
|
||||
@@ -3326,7 +3331,7 @@ namespace TriangleNet
|
||||
/// <param name="y3"></param>
|
||||
/// <returns>Returns true, if it is a BAD polygon corner, returns false if it is a GOOD
|
||||
/// polygon corner</returns>
|
||||
static bool IsBadPolygonAngle(double x1, double y1,
|
||||
private bool IsBadPolygonAngle(double x1, double y1,
|
||||
double x2, double y2, double x3, double y3)
|
||||
{
|
||||
// variables keeping the distance values for the edges
|
||||
@@ -3352,7 +3357,7 @@ namespace TriangleNet
|
||||
cosAngle = (dist12 + dist23 - dist31) / (2 * Math.Sqrt(dist12) * Math.Sqrt(dist23));
|
||||
// Check whether the angle is smaller than permitted which is 2*minangle!!!
|
||||
//printf("angle: %f 2*minangle = %f\n",acos(cosAngle)*180/PI, 2*acos(Math.Sqrt(b.goodangle))*180/PI);
|
||||
if (Math.Acos(cosAngle) < 2 * Math.Acos(Math.Sqrt(Behavior.GoodAngle)))
|
||||
if (Math.Acos(cosAngle) < 2 * Math.Acos(Math.Sqrt(behavior.GoodAngle)))
|
||||
{
|
||||
return true;// it is a BAD triangle
|
||||
}
|
||||
@@ -3375,7 +3380,7 @@ namespace TriangleNet
|
||||
/// <remarks>
|
||||
// referenced to: http://local.wasp.uwa.edu.au/~pbourke/geometry/
|
||||
/// </remarks>
|
||||
static void LineLineIntersection(
|
||||
private void LineLineIntersection(
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
@@ -3431,7 +3436,7 @@ namespace TriangleNet
|
||||
/// <remarks>
|
||||
/// http://www.mathematik.uni-ulm.de/stochastik/lehre/ws03_04/rt/Geometry2D.ps
|
||||
/// </remarks>
|
||||
static int HalfPlaneIntersection(int numvertices, ref double[] convexPoly, double x1, double y1, double x2, double y2)
|
||||
private int HalfPlaneIntersection(int numvertices, ref double[] convexPoly, double x1, double y1, double x2, double y2)
|
||||
{
|
||||
double dx, dy; // direction of the line
|
||||
double z, min, max;
|
||||
@@ -3509,7 +3514,7 @@ namespace TriangleNet
|
||||
/// <remarks>
|
||||
/// http://www.mathematik.uni-ulm.de/stochastik/lehre/ws03_04/rt/Geometry2D.ps
|
||||
/// </remarks>
|
||||
static int SplitConvexPolygon(int numvertices, double[] convexPoly, double x1, double y1, double x2, double y2, ref double[][] polys)
|
||||
private int SplitConvexPolygon(int numvertices, double[] convexPoly, double x1, double y1, double x2, double y2, ref double[][] polys)
|
||||
{
|
||||
// state = 0: before the first intersection (with the line)
|
||||
// state = 1: after the first intersection (with the line)
|
||||
@@ -3699,7 +3704,7 @@ namespace TriangleNet
|
||||
/// <remarks>
|
||||
/// http://www.mathematik.uni-ulm.de/stochastik/lehre/ws03_04/rt/Geometry2D.ps
|
||||
/// </remarks>
|
||||
static int LinePointLocation(double x1, double y1, double x2, double y2, double x, double y)
|
||||
private int LinePointLocation(double x1, double y1, double x2, double y2, double x, double y)
|
||||
{
|
||||
double z;
|
||||
if (Math.Atan((y2 - y1) / (x2 - x1)) * 180.0 / Math.PI == 90.0)
|
||||
@@ -3743,7 +3748,7 @@ namespace TriangleNet
|
||||
/// <remarks>
|
||||
/// referenced to: http://local.wasp.uwa.edu.au/~pbourke/geometry/
|
||||
/// </remarks>
|
||||
static void LineLineSegmentIntersection(
|
||||
private void LineLineSegmentIntersection(
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
@@ -3806,7 +3811,7 @@ namespace TriangleNet
|
||||
/// <param name="numpoints"></param>
|
||||
/// <param name="points"></param>
|
||||
/// <param name="centroid">Centroid of a given polygon </param>
|
||||
static void FindPolyCentroid(int numpoints, double[] points, ref double[] centroid)
|
||||
private void FindPolyCentroid(int numpoints, double[] points, ref double[] centroid)
|
||||
{
|
||||
int i;
|
||||
//double area = 0.0;//, temp
|
||||
@@ -3838,7 +3843,7 @@ namespace TriangleNet
|
||||
/// <remarks>
|
||||
/// referenced to: http://local.wasp.uwa.edu.au/~pbourke/geometry/sphereline/
|
||||
/// </remarks>
|
||||
static void CircleLineIntersection(
|
||||
private void CircleLineIntersection(
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3, double r, ref double[] p)
|
||||
@@ -3906,7 +3911,7 @@ namespace TriangleNet
|
||||
/// <param name="y3">P3 coordinates (circumcenter point)</param>
|
||||
/// <param name="isObtuse"></param>
|
||||
/// <returns>Returns true, if given point is the correct one otherwise return false.</returns>
|
||||
static bool ChooseCorrectPoint(
|
||||
private bool ChooseCorrectPoint(
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3, bool isObtuse)
|
||||
@@ -3959,7 +3964,7 @@ namespace TriangleNet
|
||||
/// <param name="x">P3 coordinates [point to be compared] (neighbor's circumcenter)</param>
|
||||
/// <param name="y">P3 coordinates [point to be compared] (neighbor's circumcenter)</param>
|
||||
/// <param name="p"></param>
|
||||
static void PointBetweenPoints(double x1, double y1, double x2, double y2, double x, double y, ref double[] p)
|
||||
private void PointBetweenPoints(double x1, double y1, double x2, double y2, double x, double y, ref double[] p)
|
||||
{
|
||||
// now check whether the point is close to circumcenter than intersection point
|
||||
// BETWEEN THE POINTS
|
||||
@@ -3991,7 +3996,7 @@ namespace TriangleNet
|
||||
/// <param name="x3"></param>
|
||||
/// <param name="y3"></param>
|
||||
/// <returns>Returns true, if it is a BAD triangle, returns false if it is a GOOD triangle.</returns>
|
||||
static bool IsBadTriangleAngle(double x1, double y1, double x2, double y2, double x3, double y3)
|
||||
private bool IsBadTriangleAngle(double x1, double y1, double x2, double y2, double x3, double y3)
|
||||
{
|
||||
// variables keeping the distance values for the edges
|
||||
double dxod, dyod, dxda, dyda, dxao, dyao;
|
||||
@@ -4077,7 +4082,7 @@ namespace TriangleNet
|
||||
|
||||
|
||||
// Check whether the angle is smaller than permitted.
|
||||
if ((angle > Behavior.GoodAngle) || (Behavior.MaxAngle != 0.00 && maxangle < Behavior.MaxGoodAngle))
|
||||
if ((angle > behavior.GoodAngle) || (behavior.MaxAngle != 0.00 && maxangle < behavior.MaxGoodAngle))
|
||||
{
|
||||
return true;// it is a bad triangle
|
||||
}
|
||||
@@ -4089,12 +4094,11 @@ namespace TriangleNet
|
||||
/// Given the triangulation, and a vertex returns the minimum distance to the
|
||||
/// vertices of the triangle where the given vertex located.
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <param name="newlocX"></param>
|
||||
/// <param name="newlocY"></param>
|
||||
/// <param name="searchtri"></param>
|
||||
/// <returns></returns>
|
||||
static double MinDistanceToNeighbor(Mesh m, double newlocX, double newlocY, ref Otri searchtri)
|
||||
private double MinDistanceToNeighbor(double newlocX, double newlocY, ref Otri searchtri)
|
||||
{
|
||||
Otri horiz = default(Otri); // for search operation
|
||||
LocateResult intersect = LocateResult.Outside;
|
||||
@@ -4139,7 +4143,7 @@ namespace TriangleNet
|
||||
// edge specified by 'searchtri'.
|
||||
searchtri.SymSelf();
|
||||
searchtri.Copy(ref horiz);
|
||||
intersect = m.PreciseLocate(newvertex, ref horiz, false);
|
||||
intersect = mesh.PreciseLocate(newvertex, ref horiz, false);
|
||||
}
|
||||
else if (ahead == 0.0)
|
||||
{
|
||||
@@ -4155,7 +4159,7 @@ namespace TriangleNet
|
||||
else
|
||||
{
|
||||
searchtri.Copy(ref horiz);
|
||||
intersect = m.PreciseLocate(newvertex, ref horiz, false);
|
||||
intersect = mesh.PreciseLocate(newvertex, ref horiz, false);
|
||||
}
|
||||
}
|
||||
if (intersect == LocateResult.OnVertex || intersect == LocateResult.Outside)
|
||||
|
||||
@@ -261,19 +261,10 @@ namespace TriangleNet
|
||||
/// <param name="tapex">Triangle point.</param>
|
||||
/// <param name="xi">Relative coordinate of new location.</param>
|
||||
/// <param name="eta">Relative coordinate of new location.</param>
|
||||
/// <param name="offcenter">Use off-center for new location.</param>
|
||||
/// <param name="offconstant">Off-center constant.</param>
|
||||
/// <returns>Coordinates of the circumcenter (or off-center)</returns>
|
||||
/// <remarks>
|
||||
/// The result is returned both in terms of x-y coordinates and xi-eta
|
||||
/// (barycentric) coordinates. The xi-eta coordinate system is defined in
|
||||
/// terms of the triangle: the origin of the triangle is the origin of the
|
||||
/// coordinate system; the destination of the triangle is one unit along the
|
||||
/// xi axis; and the apex of the triangle is one unit along the eta axis.
|
||||
/// 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, bool offcenter)
|
||||
ref double xi, ref double eta, double offconstant)
|
||||
{
|
||||
double xdo, ydo, xao, yao;
|
||||
double dodist, aodist, dadist;
|
||||
@@ -291,6 +282,7 @@ namespace TriangleNet
|
||||
aodist = xao * xao + yao * yao;
|
||||
dadist = (tdest.x - tapex.x) * (tdest.x - tapex.x) +
|
||||
(tdest.y - tapex.y) * (tdest.y - tapex.y);
|
||||
|
||||
if (Behavior.NoExact)
|
||||
{
|
||||
denominator = 0.5 / (xdo * yao - xao * ydo);
|
||||
@@ -304,6 +296,7 @@ namespace TriangleNet
|
||||
// Don't count the above as an orientation test.
|
||||
Statistic.CounterClockwiseCount--;
|
||||
}
|
||||
|
||||
dx = (yao * dodist - ydo * aodist) * denominator;
|
||||
dy = (xdo * aodist - xao * dodist) * denominator;
|
||||
|
||||
@@ -314,11 +307,11 @@ namespace TriangleNet
|
||||
// the input PSLG.
|
||||
if ((dodist < aodist) && (dodist < dadist))
|
||||
{
|
||||
if (offcenter && (Behavior.Offconstant > 0.0))
|
||||
if (offconstant > 0.0)
|
||||
{
|
||||
// Find the position of the off-center, as described by Alper Ungor.
|
||||
dxoff = 0.5 * xdo - Behavior.Offconstant * ydo;
|
||||
dyoff = 0.5 * ydo + Behavior.Offconstant * xdo;
|
||||
dxoff = 0.5 * xdo - offconstant * ydo;
|
||||
dyoff = 0.5 * ydo + offconstant * xdo;
|
||||
// If the off-center is closer to the origin than the
|
||||
// circumcenter, use the off-center instead.
|
||||
if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy)
|
||||
@@ -330,10 +323,10 @@ namespace TriangleNet
|
||||
}
|
||||
else if (aodist < dadist)
|
||||
{
|
||||
if (offcenter && (Behavior.Offconstant > 0.0))
|
||||
if (offconstant > 0.0)
|
||||
{
|
||||
dxoff = 0.5 * xao + Behavior.Offconstant * yao;
|
||||
dyoff = 0.5 * yao - Behavior.Offconstant * xao;
|
||||
dxoff = 0.5 * xao + offconstant * yao;
|
||||
dyoff = 0.5 * yao - offconstant * xao;
|
||||
// If the off-center is closer to the origin than the
|
||||
// circumcenter, use the off-center instead.
|
||||
if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy)
|
||||
@@ -345,12 +338,10 @@ namespace TriangleNet
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offcenter && (Behavior.Offconstant > 0.0))
|
||||
if (offconstant > 0.0)
|
||||
{
|
||||
dxoff = 0.5 * (tapex.x - tdest.x) -
|
||||
Behavior.Offconstant * (tapex.y - tdest.y);
|
||||
dyoff = 0.5 * (tapex.y - tdest.y) +
|
||||
Behavior.Offconstant * (tapex.x - tdest.x);
|
||||
dxoff = 0.5 * (tapex.x - tdest.x) - offconstant * (tapex.y - tdest.y);
|
||||
dyoff = 0.5 * (tapex.y - tdest.y) + offconstant * (tapex.x - tdest.x);
|
||||
// If the off-center is closer to the destination than the
|
||||
// circumcenter, use the off-center instead.
|
||||
if (dxoff * dxoff + dyoff * dyoff <
|
||||
@@ -362,7 +353,71 @@ namespace TriangleNet
|
||||
}
|
||||
}
|
||||
|
||||
Point circumcenter = new Point(torg.x + dx, torg.y + dy);
|
||||
// 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.
|
||||
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);
|
||||
}
|
||||
|
||||
/// <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="xi">Relative coordinate of new location.</param>
|
||||
/// <param name="eta">Relative coordinate of new location.</param>
|
||||
/// <returns>Coordinates of the circumcenter</returns>
|
||||
/// <remarks>
|
||||
/// The result is returned both in terms of x-y coordinates and xi-eta
|
||||
/// (barycentric) coordinates. The xi-eta coordinate system is defined in
|
||||
/// terms of the triangle: the origin of the triangle is the origin of the
|
||||
/// coordinate system; the destination of the triangle is one unit along the
|
||||
/// xi axis; and the apex of the triangle is one unit along the eta axis.
|
||||
/// 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)
|
||||
{
|
||||
double xdo, ydo, xao, yao;
|
||||
double dodist, aodist, dadist;
|
||||
double denominator;
|
||||
double dx, dy;
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
if (Behavior.NoExact)
|
||||
{
|
||||
denominator = 0.5 / (xdo * yao - xao * ydo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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);
|
||||
// Don't count the above as an orientation test.
|
||||
Statistic.CounterClockwiseCount--;
|
||||
}
|
||||
|
||||
dx = (yao * dodist - ydo * aodist) * denominator;
|
||||
dy = (xdo * aodist - xao * dodist) * denominator;
|
||||
|
||||
// To interpolate vertex attributes for the new vertex inserted at
|
||||
// the circumcenter, define a coordinate system with a xi-axis,
|
||||
@@ -372,7 +427,7 @@ namespace TriangleNet
|
||||
xi = (yao * dx - xao * dy) * (2.0 * denominator);
|
||||
eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
|
||||
|
||||
return circumcenter;
|
||||
return new Point(torg.x + dx, torg.y + dy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,19 +21,26 @@ namespace TriangleNet
|
||||
Queue<BadSubseg> badsubsegs;
|
||||
BadTriQueue queue;
|
||||
Mesh mesh;
|
||||
Behavior behavior;
|
||||
|
||||
NewLocation newLocation;
|
||||
|
||||
// Not used at the moment
|
||||
Func<Point, Point, Point, double, bool> userTest;
|
||||
|
||||
ILog<SimpleLogItem> logger;
|
||||
|
||||
public Quality(Mesh m)
|
||||
public Quality(Mesh mesh)
|
||||
{
|
||||
logger = SimpleLog.Instance;
|
||||
|
||||
badsubsegs = new Queue<BadSubseg>();
|
||||
queue = new BadTriQueue();
|
||||
mesh = m;
|
||||
|
||||
this.mesh = mesh;
|
||||
this.behavior = mesh.behavior;
|
||||
|
||||
newLocation = new NewLocation(mesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -278,9 +285,9 @@ namespace TriangleNet
|
||||
(eorg.y - eapex.y) * (edest.y - eapex.y);
|
||||
if (dotproduct < 0.0)
|
||||
{
|
||||
if (Behavior.ConformDel ||
|
||||
if (behavior.ConformDel ||
|
||||
(dotproduct * dotproduct >=
|
||||
(2.0 * Behavior.GoodAngle - 1.0) * (2.0 * Behavior.GoodAngle - 1.0) *
|
||||
(2.0 * behavior.GoodAngle - 1.0) * (2.0 * behavior.GoodAngle - 1.0) *
|
||||
((eorg.x - eapex.x) * (eorg.x - eapex.x) +
|
||||
(eorg.y - eapex.y) * (eorg.y - eapex.y)) *
|
||||
((edest.x - eapex.x) * (edest.x - eapex.x) +
|
||||
@@ -305,9 +312,9 @@ namespace TriangleNet
|
||||
(eorg.y - eapex.y) * (edest.y - eapex.y);
|
||||
if (dotproduct < 0.0)
|
||||
{
|
||||
if (Behavior.ConformDel ||
|
||||
if (behavior.ConformDel ||
|
||||
(dotproduct * dotproduct >=
|
||||
(2.0 * Behavior.GoodAngle - 1.0) * (2.0 * Behavior.GoodAngle - 1.0) *
|
||||
(2.0 * behavior.GoodAngle - 1.0) * (2.0 * behavior.GoodAngle - 1.0) *
|
||||
((eorg.x - eapex.x) * (eorg.x - eapex.x) +
|
||||
(eorg.y - eapex.y) * (eorg.y - eapex.y)) *
|
||||
((edest.x - eapex.x) * (edest.x - eapex.x) +
|
||||
@@ -318,7 +325,7 @@ namespace TriangleNet
|
||||
}
|
||||
}
|
||||
|
||||
if (encroached > 0 && (Behavior.NoBisect == 0 || ((Behavior.NoBisect == 1) && (sides == 2))))
|
||||
if (encroached > 0 && (behavior.NoBisect == 0 || ((behavior.NoBisect == 1) && (sides == 2))))
|
||||
{
|
||||
// Add the subsegment to the list of encroached subsegments.
|
||||
// Be sure to get the orientation right.
|
||||
@@ -422,11 +429,11 @@ namespace TriangleNet
|
||||
testtri.Lprev(ref tri1);
|
||||
}
|
||||
|
||||
if (Behavior.VarArea || Behavior.FixedArea || Behavior.Usertest)
|
||||
if (behavior.VarArea || behavior.FixedArea || behavior.Usertest)
|
||||
{
|
||||
// Check whether the area is larger than permitted.
|
||||
area = 0.5 * (dxod * dyda - dyod * dxda);
|
||||
if (Behavior.FixedArea && (area > Behavior.MaxArea))
|
||||
if (behavior.FixedArea && (area > behavior.MaxArea))
|
||||
{
|
||||
// Add this triangle to the list of bad triangles.
|
||||
queue.Enqueue(ref testtri, minedge, tapex, torg, tdest);
|
||||
@@ -434,7 +441,7 @@ namespace TriangleNet
|
||||
}
|
||||
|
||||
// Nonpositive area constraints are treated as unconstrained.
|
||||
if ((Behavior.VarArea) && (area > testtri.triangle.area) && (testtri.triangle.area > 0.0))
|
||||
if ((behavior.VarArea) && (area > testtri.triangle.area) && (testtri.triangle.area > 0.0))
|
||||
{
|
||||
// Add this triangle to the list of bad triangles.
|
||||
queue.Enqueue(ref testtri, minedge, tapex, torg, tdest);
|
||||
@@ -442,7 +449,7 @@ namespace TriangleNet
|
||||
}
|
||||
|
||||
// Check whether the user thinks this triangle is too large.
|
||||
if (Behavior.Usertest && userTest != null)
|
||||
if (behavior.Usertest && userTest != null)
|
||||
{
|
||||
if (userTest(torg, tdest, tapex, area))
|
||||
{
|
||||
@@ -476,7 +483,7 @@ namespace TriangleNet
|
||||
}
|
||||
|
||||
// Check whether the angle is smaller than permitted.
|
||||
if ((angle > Behavior.GoodAngle) || (maxangle < Behavior.MaxGoodAngle && Behavior.MaxAngle != 0.0))
|
||||
if ((angle > behavior.GoodAngle) || (maxangle < behavior.MaxGoodAngle && behavior.MaxAngle != 0.0))
|
||||
{
|
||||
// Use the rules of Miller, Pav, and Walkington to decide that certain
|
||||
// triangles should not be split, even if they have bad angles.
|
||||
@@ -643,7 +650,7 @@ namespace TriangleNet
|
||||
// If we're using Chew's algorithm (rather than Ruppert's)
|
||||
// to define encroachment, delete free vertices from the
|
||||
// subsegment's diametral circle.
|
||||
if (!Behavior.ConformDel && !acuteorg && !acutedest)
|
||||
if (!behavior.ConformDel && !acuteorg && !acutedest)
|
||||
{
|
||||
eapex = enctri.Apex();
|
||||
while ((eapex.type == VertexType.FreeVertex) &&
|
||||
@@ -673,7 +680,7 @@ namespace TriangleNet
|
||||
acuteorg = acuteorg || acuteorg2;
|
||||
|
||||
// Delete free vertices from the subsegment's diametral circle.
|
||||
if (!Behavior.ConformDel && !acuteorg2 && !acutedest2)
|
||||
if (!behavior.ConformDel && !acuteorg2 && !acutedest2)
|
||||
{
|
||||
eapex = testtri.Org();
|
||||
while ((eapex.type == VertexType.FreeVertex) &&
|
||||
@@ -845,15 +852,15 @@ namespace TriangleNet
|
||||
// for mesh refinement.
|
||||
// TODO: NewLocation doesn't work for refinement. Why? Maybe
|
||||
// reset VertexType?
|
||||
if (Behavior.FixedArea || Behavior.VarArea)
|
||||
if (behavior.FixedArea || behavior.VarArea)
|
||||
{
|
||||
Point tmp = Primitives.FindCircumcenter(borg, bdest, bapex, ref xi, ref eta, true);
|
||||
Point tmp = Primitives.FindCircumcenter(borg, bdest, bapex, ref xi, ref eta, behavior.Offconstant);
|
||||
newvertex.x = tmp.x;
|
||||
newvertex.y = tmp.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
NewLocation.FindLocation(mesh, borg, bdest, bapex, newvertex, ref xi, ref eta, true, badotri);
|
||||
newLocation.FindLocation(borg, bdest, bapex, newvertex, ref xi, ref eta, true, badotri);
|
||||
}
|
||||
|
||||
// Check whether the new vertex lies on a triangle vertex.
|
||||
@@ -959,7 +966,7 @@ namespace TriangleNet
|
||||
// triangulation should be (conforming) Delaunay.
|
||||
|
||||
// Next, we worry about enforcing triangle quality.
|
||||
if ((Behavior.MinAngle > 0.0) || Behavior.VarArea || Behavior.FixedArea || Behavior.Usertest)
|
||||
if ((behavior.MinAngle > 0.0) || behavior.VarArea || behavior.FixedArea || behavior.Usertest)
|
||||
{
|
||||
// TODO: Reset queue? (Or is it always empty at this point)
|
||||
|
||||
@@ -989,7 +996,7 @@ namespace TriangleNet
|
||||
// and have no low-quality triangles.
|
||||
|
||||
// Might we have run out of Steiner points too soon?
|
||||
if (Behavior.Verbose && Behavior.ConformDel && (badsubsegs.Count > 0) && (mesh.steinerleft == 0))
|
||||
if (Behavior.Verbose && behavior.ConformDel && (badsubsegs.Count > 0) && (mesh.steinerleft == 0))
|
||||
{
|
||||
|
||||
logger.Warning("I ran out of Steiner points, but the mesh has encroached subsegments, "
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace TriangleNet.Tools
|
||||
Vertex tdest = tri.Dest();
|
||||
Vertex tapex = tri.Apex();
|
||||
|
||||
cc = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta, false);
|
||||
cc = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta);
|
||||
|
||||
if (SegmentsIntersect(ref seg, cc, torg, ref pt, true))
|
||||
{
|
||||
@@ -217,12 +217,12 @@ namespace TriangleNet.Tools
|
||||
torg = f.Org();
|
||||
tdest = f.Dest();
|
||||
tapex = f.Apex();
|
||||
cc_f = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta, false);
|
||||
cc_f = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta);
|
||||
|
||||
torg = f_next.Org();
|
||||
tdest = f_next.Dest();
|
||||
tapex = f_next.Apex();
|
||||
cc_f_next = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta, false);
|
||||
cc_f_next = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta);
|
||||
|
||||
// if f is tagged non-blind then
|
||||
if (!f.triangle.infected)
|
||||
@@ -353,7 +353,7 @@ namespace TriangleNet.Tools
|
||||
torg = f.Org();
|
||||
tdest = f.Dest();
|
||||
tapex = f.Apex();
|
||||
cc_f = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta, false);
|
||||
cc_f = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta);
|
||||
|
||||
if (f_next.triangle == Mesh.dummytri)
|
||||
{
|
||||
@@ -375,7 +375,7 @@ namespace TriangleNet.Tools
|
||||
torg = f_next.Org();
|
||||
tdest = f_next.Dest();
|
||||
tapex = f_next.Apex();
|
||||
cc_f_next = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta, false);
|
||||
cc_f_next = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta);
|
||||
|
||||
// if f is tagged non-blind then
|
||||
if (!f.triangle.infected)
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace TriangleNet.Tools
|
||||
torg = tri.Org();
|
||||
tdest = tri.Dest();
|
||||
tapex = tri.Apex();
|
||||
circumcenter = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta, false);
|
||||
circumcenter = Primitives.FindCircumcenter(torg, tdest, tapex, ref xi, ref eta);
|
||||
|
||||
// X and y coordinates.
|
||||
this.points[i] = new Point(circumcenter.x, circumcenter.y);
|
||||
|
||||
Reference in New Issue
Block a user