Files
Dec2017-Script-Dump/Triangle/QualityMesher.cs
T
2026-06-04 11:42:34 +02:00

490 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using TriangleNet.Data;
using TriangleNet.Geometry;
using TriangleNet.Log;
namespace TriangleNet
{
// Token: 0x02000007 RID: 7
internal class QualityMesher
{
// Token: 0x06000053 RID: 83 RVA: 0x0000A12C File Offset: 0x0000832C
public QualityMesher(Mesh mesh)
{
this.logger = SimpleLog.Instance;
this.badsubsegs = new Queue<BadSubseg>();
this.queue = new BadTriQueue();
this.mesh = mesh;
this.behavior = mesh.behavior;
this.newLocation = new NewLocation(mesh);
}
// Token: 0x06000054 RID: 84 RVA: 0x0000A17F File Offset: 0x0000837F
public void AddBadSubseg(BadSubseg badseg)
{
this.badsubsegs.Enqueue(badseg);
}
// Token: 0x06000055 RID: 85 RVA: 0x0000A190 File Offset: 0x00008390
public int CheckSeg4Encroach(ref Osub testsubseg)
{
Otri otri = default(Otri);
Osub osub = default(Osub);
int num = 0;
int num2 = 0;
Vertex vertex = testsubseg.Org();
Vertex vertex2 = testsubseg.Dest();
testsubseg.TriPivot(ref otri);
if (otri.triangle != Mesh.dummytri)
{
num2++;
Vertex vertex3 = otri.Apex();
double num3 = (vertex.x - vertex3.x) * (vertex2.x - vertex3.x) + (vertex.y - vertex3.y) * (vertex2.y - vertex3.y);
if (num3 < 0.0 && (this.behavior.ConformingDelaunay || num3 * num3 >= (2.0 * this.behavior.goodAngle - 1.0) * (2.0 * this.behavior.goodAngle - 1.0) * ((vertex.x - vertex3.x) * (vertex.x - vertex3.x) + (vertex.y - vertex3.y) * (vertex.y - vertex3.y)) * ((vertex2.x - vertex3.x) * (vertex2.x - vertex3.x) + (vertex2.y - vertex3.y) * (vertex2.y - vertex3.y))))
{
num = 1;
}
}
testsubseg.Sym(ref osub);
osub.TriPivot(ref otri);
if (otri.triangle != Mesh.dummytri)
{
num2++;
Vertex vertex3 = otri.Apex();
double num3 = (vertex.x - vertex3.x) * (vertex2.x - vertex3.x) + (vertex.y - vertex3.y) * (vertex2.y - vertex3.y);
if (num3 < 0.0 && (this.behavior.ConformingDelaunay || num3 * num3 >= (2.0 * this.behavior.goodAngle - 1.0) * (2.0 * this.behavior.goodAngle - 1.0) * ((vertex.x - vertex3.x) * (vertex.x - vertex3.x) + (vertex.y - vertex3.y) * (vertex.y - vertex3.y)) * ((vertex2.x - vertex3.x) * (vertex2.x - vertex3.x) + (vertex2.y - vertex3.y) * (vertex2.y - vertex3.y))))
{
num += 2;
}
}
if (num > 0 && (this.behavior.NoBisect == 0 || (this.behavior.NoBisect == 1 && num2 == 2)))
{
BadSubseg badSubseg = new BadSubseg();
if (num == 1)
{
badSubseg.encsubseg = testsubseg;
badSubseg.subsegorg = vertex;
badSubseg.subsegdest = vertex2;
}
else
{
badSubseg.encsubseg = osub;
badSubseg.subsegorg = vertex2;
badSubseg.subsegdest = vertex;
}
this.badsubsegs.Enqueue(badSubseg);
}
return num;
}
// Token: 0x06000056 RID: 86 RVA: 0x0000A4DC File Offset: 0x000086DC
public void TestTriangle(ref Otri testtri)
{
Otri otri = default(Otri);
Otri otri2 = default(Otri);
Osub osub = default(Osub);
Vertex vertex = testtri.Org();
Vertex vertex2 = testtri.Dest();
Vertex vertex3 = testtri.Apex();
double num = vertex.x - vertex2.x;
double num2 = vertex.y - vertex2.y;
double num3 = vertex2.x - vertex3.x;
double num4 = vertex2.y - vertex3.y;
double num5 = vertex3.x - vertex.x;
double num6 = vertex3.y - vertex.y;
double num7 = num * num;
double num8 = num2 * num2;
double num9 = num3 * num3;
double num10 = num4 * num4;
double num11 = num5 * num5;
double num12 = num6 * num6;
double num13 = num7 + num8;
double num14 = num9 + num10;
double num15 = num11 + num12;
double num16;
double num17;
Vertex vertex4;
Vertex vertex5;
if (num13 < num14 && num13 < num15)
{
num16 = num13;
num17 = num3 * num5 + num4 * num6;
num17 = num17 * num17 / (num14 * num15);
vertex4 = vertex;
vertex5 = vertex2;
testtri.Copy(ref otri);
}
else if (num14 < num15)
{
num16 = num14;
num17 = num * num5 + num2 * num6;
num17 = num17 * num17 / (num13 * num15);
vertex4 = vertex2;
vertex5 = vertex3;
testtri.Lnext(ref otri);
}
else
{
num16 = num15;
num17 = num * num3 + num2 * num4;
num17 = num17 * num17 / (num13 * num14);
vertex4 = vertex3;
vertex5 = vertex;
testtri.Lprev(ref otri);
}
if (this.behavior.VarArea || this.behavior.fixedArea || this.behavior.UserTest != null)
{
double num18 = 0.5 * (num * num4 - num2 * num3);
if (this.behavior.fixedArea && num18 > this.behavior.MaxArea)
{
this.queue.Enqueue(ref testtri, num16, vertex3, vertex, vertex2);
return;
}
if (this.behavior.VarArea && num18 > testtri.triangle.area && testtri.triangle.area > 0.0)
{
this.queue.Enqueue(ref testtri, num16, vertex3, vertex, vertex2);
return;
}
if (this.behavior.UserTest != null && this.behavior.UserTest(testtri.triangle, num18))
{
this.queue.Enqueue(ref testtri, num16, vertex3, vertex, vertex2);
return;
}
}
double num19;
if (num13 > num14 && num13 > num15)
{
num19 = (num14 + num15 - num13) / (2.0 * Math.Sqrt(num14 * num15));
}
else if (num14 > num15)
{
num19 = (num13 + num15 - num14) / (2.0 * Math.Sqrt(num13 * num15));
}
else
{
num19 = (num13 + num14 - num15) / (2.0 * Math.Sqrt(num13 * num14));
}
if (num17 > this.behavior.goodAngle || (num19 < this.behavior.maxGoodAngle && this.behavior.MaxAngle != 0.0))
{
if (vertex4.type == VertexType.SegmentVertex && vertex5.type == VertexType.SegmentVertex)
{
otri.SegPivot(ref osub);
if (osub.seg == Mesh.dummysub)
{
otri.Copy(ref otri2);
do
{
otri.OprevSelf();
otri.SegPivot(ref osub);
}
while (osub.seg == Mesh.dummysub);
Vertex vertex6 = osub.SegOrg();
Vertex vertex7 = osub.SegDest();
do
{
otri2.DnextSelf();
otri2.SegPivot(ref osub);
}
while (osub.seg == Mesh.dummysub);
Vertex vertex8 = osub.SegOrg();
Vertex vertex9 = osub.SegDest();
Vertex vertex10 = null;
if (vertex7.x == vertex8.x && vertex7.y == vertex8.y)
{
vertex10 = vertex7;
}
else if (vertex6.x == vertex9.x && vertex6.y == vertex9.y)
{
vertex10 = vertex6;
}
if (vertex10 != null)
{
double num20 = (vertex4.x - vertex10.x) * (vertex4.x - vertex10.x) + (vertex4.y - vertex10.y) * (vertex4.y - vertex10.y);
double num21 = (vertex5.x - vertex10.x) * (vertex5.x - vertex10.x) + (vertex5.y - vertex10.y) * (vertex5.y - vertex10.y);
if (num20 < 1.001 * num21 && num20 > 0.999 * num21)
{
return;
}
}
}
}
this.queue.Enqueue(ref testtri, num16, vertex3, vertex, vertex2);
}
}
// Token: 0x06000057 RID: 87 RVA: 0x0000A99C File Offset: 0x00008B9C
private void TallyEncs()
{
Osub osub = default(Osub);
osub.orient = 0;
foreach (Segment segment in this.mesh.subsegs.Values)
{
osub.seg = segment;
this.CheckSeg4Encroach(ref osub);
}
}
// Token: 0x06000058 RID: 88 RVA: 0x0000AA14 File Offset: 0x00008C14
private void SplitEncSegs(bool triflaws)
{
Otri otri = default(Otri);
Otri otri2 = default(Otri);
Osub osub = default(Osub);
Osub osub2 = default(Osub);
while (this.badsubsegs.Count > 0 && this.mesh.steinerleft != 0)
{
BadSubseg badSubseg = this.badsubsegs.Dequeue();
osub2 = badSubseg.encsubseg;
Vertex vertex = osub2.Org();
Vertex vertex2 = osub2.Dest();
if (!Osub.IsDead(osub2.seg) && vertex == badSubseg.subsegorg && vertex2 == badSubseg.subsegdest)
{
osub2.TriPivot(ref otri);
otri.Lnext(ref otri2);
otri2.SegPivot(ref osub);
bool flag = osub.seg != Mesh.dummysub;
otri2.LnextSelf();
otri2.SegPivot(ref osub);
bool flag2 = osub.seg != Mesh.dummysub;
if (!this.behavior.ConformingDelaunay && !flag && !flag2)
{
Vertex vertex3 = otri.Apex();
while (vertex3.type == VertexType.FreeVertex && (vertex.x - vertex3.x) * (vertex2.x - vertex3.x) + (vertex.y - vertex3.y) * (vertex2.y - vertex3.y) < 0.0)
{
this.mesh.DeleteVertex(ref otri2);
osub2.TriPivot(ref otri);
vertex3 = otri.Apex();
otri.Lprev(ref otri2);
}
}
otri.Sym(ref otri2);
if (otri2.triangle != Mesh.dummytri)
{
otri2.LnextSelf();
otri2.SegPivot(ref osub);
bool flag3 = osub.seg != Mesh.dummysub;
flag2 = flag2 || flag3;
otri2.LnextSelf();
otri2.SegPivot(ref osub);
bool flag4 = osub.seg != Mesh.dummysub;
flag = flag || flag4;
if (!this.behavior.ConformingDelaunay && !flag4 && !flag3)
{
Vertex vertex3 = otri2.Org();
while (vertex3.type == VertexType.FreeVertex && (vertex.x - vertex3.x) * (vertex2.x - vertex3.x) + (vertex.y - vertex3.y) * (vertex2.y - vertex3.y) < 0.0)
{
this.mesh.DeleteVertex(ref otri2);
otri.Sym(ref otri2);
vertex3 = otri2.Apex();
otri2.LprevSelf();
}
}
}
double num3;
if (flag || flag2)
{
double num = Math.Sqrt((vertex2.x - vertex.x) * (vertex2.x - vertex.x) + (vertex2.y - vertex.y) * (vertex2.y - vertex.y));
double num2 = 1.0;
while (num > 3.0 * num2)
{
num2 *= 2.0;
}
while (num < 1.5 * num2)
{
num2 *= 0.5;
}
num3 = num2 / num;
if (flag2)
{
num3 = 1.0 - num3;
}
}
else
{
num3 = 0.5;
}
Vertex vertex4 = new Vertex(vertex.x + num3 * (vertex2.x - vertex.x), vertex.y + num3 * (vertex2.y - vertex.y), osub2.Mark(), this.mesh.nextras);
vertex4.type = VertexType.SegmentVertex;
Vertex vertex5 = vertex4;
Mesh mesh = this.mesh;
int hash_vtx = mesh.hash_vtx;
mesh.hash_vtx = hash_vtx + 1;
vertex5.hash = hash_vtx;
vertex4.id = vertex4.hash;
this.mesh.vertices.Add(vertex4.hash, vertex4);
for (int i = 0; i < this.mesh.nextras; i++)
{
vertex4.attributes[i] = vertex.attributes[i] + num3 * (vertex2.attributes[i] - vertex.attributes[i]);
}
if (!Behavior.NoExact)
{
double num4 = Primitives.CounterClockwise(vertex, vertex2, vertex4);
double num5 = (vertex.x - vertex2.x) * (vertex.x - vertex2.x) + (vertex.y - vertex2.y) * (vertex.y - vertex2.y);
if (num4 != 0.0 && num5 != 0.0)
{
num4 /= num5;
if (!double.IsNaN(num4))
{
vertex4.x += num4 * (vertex2.y - vertex.y);
vertex4.y += num4 * (vertex.x - vertex2.x);
}
}
}
if ((vertex4.x == vertex.x && vertex4.y == vertex.y) || (vertex4.x == vertex2.x && vertex4.y == vertex2.y))
{
this.logger.Error("Ran out of precision: I attempted to split a segment to a smaller size than can be accommodated by the finite precision of floating point arithmetic.", "Quality.SplitEncSegs()");
throw new Exception("Ran out of precision");
}
InsertVertexResult insertVertexResult = this.mesh.InsertVertex(vertex4, ref otri, ref osub2, true, triflaws);
if (insertVertexResult != InsertVertexResult.Successful && insertVertexResult != InsertVertexResult.Encroaching)
{
this.logger.Error("Failure to split a segment.", "Quality.SplitEncSegs()");
throw new Exception("Failure to split a segment.");
}
if (this.mesh.steinerleft > 0)
{
this.mesh.steinerleft--;
}
this.CheckSeg4Encroach(ref osub2);
osub2.NextSelf();
this.CheckSeg4Encroach(ref osub2);
}
badSubseg.subsegorg = null;
}
}
// Token: 0x06000059 RID: 89 RVA: 0x0000B00C File Offset: 0x0000920C
private void TallyFaces()
{
Otri otri = default(Otri);
otri.orient = 0;
foreach (Triangle triangle in this.mesh.triangles.Values)
{
otri.triangle = triangle;
this.TestTriangle(ref otri);
}
}
// Token: 0x0600005A RID: 90 RVA: 0x0000B084 File Offset: 0x00009284
private void SplitTriangle(BadTriangle badtri)
{
Otri otri = default(Otri);
double num = 0.0;
double num2 = 0.0;
otri = badtri.poortri;
Vertex vertex = otri.Org();
Vertex vertex2 = otri.Dest();
Vertex vertex3 = otri.Apex();
if (!Otri.IsDead(otri.triangle) && vertex == badtri.triangorg && vertex2 == badtri.triangdest && vertex3 == badtri.triangapex)
{
bool flag = false;
Point point;
if (this.behavior.fixedArea || this.behavior.VarArea)
{
point = Primitives.FindCircumcenter(vertex, vertex2, vertex3, ref num, ref num2, this.behavior.offconstant);
}
else
{
point = this.newLocation.FindLocation(vertex, vertex2, vertex3, ref num, ref num2, true, otri);
}
if ((point.x == vertex.x && point.y == vertex.y) || (point.x == vertex2.x && point.y == vertex2.y) || (point.x == vertex3.x && point.y == vertex3.y))
{
if (Behavior.Verbose)
{
this.logger.Warning("New vertex falls on existing vertex.", "Quality.SplitTriangle()");
flag = true;
}
}
else
{
Vertex vertex4 = new Vertex(point.x, point.y, 0, this.mesh.nextras);
vertex4.type = VertexType.FreeVertex;
for (int i = 0; i < this.mesh.nextras; i++)
{
vertex4.attributes[i] = vertex.attributes[i] + num * (vertex2.attributes[i] - vertex.attributes[i]) + num2 * (vertex3.attributes[i] - vertex.attributes[i]);
}
if (num2 < num)
{
otri.LprevSelf();
}
Osub osub = default(Osub);
InsertVertexResult insertVertexResult = this.mesh.InsertVertex(vertex4, ref otri, ref osub, true, true);
if (insertVertexResult == InsertVertexResult.Successful)
{
Vertex vertex5 = vertex4;
Mesh mesh = this.mesh;
int hash_vtx = mesh.hash_vtx;
mesh.hash_vtx = hash_vtx + 1;
vertex5.hash = hash_vtx;
vertex4.id = vertex4.hash;
this.mesh.vertices.Add(vertex4.hash, vertex4);
if (this.mesh.steinerleft > 0)
{
this.mesh.steinerleft--;
}
}
else if (insertVertexResult == InsertVertexResult.Encroaching)
{
this.mesh.UndoVertex();
}
else if (insertVertexResult != InsertVertexResult.Violating && Behavior.Verbose)
{
this.logger.Warning("New vertex falls on existing vertex.", "Quality.SplitTriangle()");
flag = true;
}
}
if (flag)
{
this.logger.Error("The new vertex is at the circumcenter of triangle: This probably means that I am trying to refine triangles to a smaller size than can be accommodated by the finite precision of floating point arithmetic.", "Quality.SplitTriangle()");
throw new Exception("The new vertex is at the circumcenter of triangle.");
}
}
}
// Token: 0x0600005B RID: 91 RVA: 0x0000B358 File Offset: 0x00009558
public void EnforceQuality()
{
this.TallyEncs();
this.SplitEncSegs(false);
if (this.behavior.MinAngle > 0.0 || this.behavior.VarArea || this.behavior.fixedArea || this.behavior.UserTest != null)
{
this.TallyFaces();
this.mesh.checkquality = true;
while (this.queue.Count > 0 && this.mesh.steinerleft != 0)
{
BadTriangle badTriangle = this.queue.Dequeue();
this.SplitTriangle(badTriangle);
if (this.badsubsegs.Count > 0)
{
this.queue.Enqueue(badTriangle);
this.SplitEncSegs(true);
}
}
}
if (Behavior.Verbose && this.behavior.ConformingDelaunay && this.badsubsegs.Count > 0 && this.mesh.steinerleft == 0)
{
this.logger.Warning("I ran out of Steiner points, but the mesh has encroached subsegments, and therefore might not be truly Delaunay. If the Delaunay property is important to you, try increasing the number of Steiner points.", "Quality.EnforceQuality()");
}
}
// Token: 0x04000031 RID: 49
private Queue<BadSubseg> badsubsegs;
// Token: 0x04000032 RID: 50
private BadTriQueue queue;
// Token: 0x04000033 RID: 51
private Mesh mesh;
// Token: 0x04000034 RID: 52
private Behavior behavior;
// Token: 0x04000035 RID: 53
private NewLocation newLocation;
// Token: 0x04000036 RID: 54
private ILog<SimpleLogItem> logger;
}
}