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

700 lines
18 KiB
C#

using System;
using System.Collections.Generic;
using TriangleNet.Data;
using TriangleNet.Geometry;
using TriangleNet.Log;
using TriangleNet.Tools;
namespace TriangleNet
{
// Token: 0x02000004 RID: 4
internal class ConstraintMesher
{
// Token: 0x0600002C RID: 44 RVA: 0x00002603 File Offset: 0x00000803
public ConstraintMesher(Mesh mesh)
{
this.mesh = mesh;
this.behavior = mesh.behavior;
this.locator = mesh.locator;
this.viri = new List<Triangle>();
this.logger = SimpleLog.Instance;
}
// Token: 0x0600002D RID: 45 RVA: 0x00002640 File Offset: 0x00000840
public void CarveHoles()
{
Otri otri = default(Otri);
Triangle[] array = null;
if (!this.mesh.behavior.Convex)
{
this.InfectHull();
}
if (!this.mesh.behavior.NoHoles)
{
foreach (Point point in this.mesh.holes)
{
if (this.mesh.bounds.Contains(point))
{
otri.triangle = Mesh.dummytri;
otri.orient = 0;
otri.SymSelf();
Point point2 = otri.Org();
Vertex vertex = otri.Dest();
if (Primitives.CounterClockwise(point2, vertex, point) > 0.0 && this.mesh.locator.Locate(point, ref otri) != LocateResult.Outside && !otri.IsInfected())
{
otri.Infect();
this.viri.Add(otri.triangle);
}
}
}
}
if (this.mesh.regions.Count > 0)
{
int num = 0;
array = new Triangle[this.mesh.regions.Count];
foreach (RegionPointer regionPointer in this.mesh.regions)
{
array[num] = Mesh.dummytri;
if (this.mesh.bounds.Contains(regionPointer.point))
{
otri.triangle = Mesh.dummytri;
otri.orient = 0;
otri.SymSelf();
Point point3 = otri.Org();
Vertex vertex = otri.Dest();
if (Primitives.CounterClockwise(point3, vertex, regionPointer.point) > 0.0 && this.mesh.locator.Locate(regionPointer.point, ref otri) != LocateResult.Outside && !otri.IsInfected())
{
array[num] = otri.triangle;
array[num].region = regionPointer.id;
}
}
num++;
}
}
if (this.viri.Count > 0)
{
this.Plague();
}
if (array != null)
{
RegionIterator regionIterator = new RegionIterator(this.mesh);
for (int i = 0; i < array.Length; i++)
{
if (array[i] != Mesh.dummytri && !Otri.IsDead(array[i]))
{
regionIterator.Process(array[i]);
}
}
}
this.viri.Clear();
}
// Token: 0x0600002E RID: 46 RVA: 0x000028E0 File Offset: 0x00000AE0
public void FormSkeleton(InputGeometry input)
{
this.mesh.insegments = 0;
if (this.behavior.Poly)
{
if (this.mesh.triangles.Count == 0)
{
return;
}
if (input.HasSegments)
{
this.mesh.MakeVertexMap();
}
foreach (Edge edge in input.segments)
{
this.mesh.insegments++;
int p = edge.P0;
int p2 = edge.P1;
int boundary = edge.Boundary;
if (p < 0 || p >= this.mesh.invertices)
{
if (Behavior.Verbose)
{
this.logger.Warning("Invalid first endpoint of segment.", "Mesh.FormSkeleton().1");
}
}
else if (p2 < 0 || p2 >= this.mesh.invertices)
{
if (Behavior.Verbose)
{
this.logger.Warning("Invalid second endpoint of segment.", "Mesh.FormSkeleton().2");
}
}
else
{
Vertex vertex = this.mesh.vertices[p];
Vertex vertex2 = this.mesh.vertices[p2];
if (vertex.x == vertex2.x && vertex.y == vertex2.y)
{
if (Behavior.Verbose)
{
this.logger.Warning(string.Concat(new object[] { "Endpoints of segment (IDs ", p, "/", p2, ") are coincident." }), "Mesh.FormSkeleton()");
}
}
else
{
this.InsertSegment(vertex, vertex2, boundary);
}
}
}
}
if (this.behavior.Convex || !this.behavior.Poly)
{
this.MarkHull();
}
}
// Token: 0x0600002F RID: 47 RVA: 0x00002AD0 File Offset: 0x00000CD0
private void InfectHull()
{
Otri otri = default(Otri);
Otri otri2 = default(Otri);
Otri otri3 = default(Otri);
Osub osub = default(Osub);
otri.triangle = Mesh.dummytri;
otri.orient = 0;
otri.SymSelf();
otri.Copy(ref otri3);
do
{
if (!otri.IsInfected())
{
otri.SegPivot(ref osub);
if (osub.seg == Mesh.dummysub)
{
if (!otri.IsInfected())
{
otri.Infect();
this.viri.Add(otri.triangle);
}
}
else if (osub.seg.boundary == 0)
{
osub.seg.boundary = 1;
Vertex vertex = otri.Org();
Vertex vertex2 = otri.Dest();
if (vertex.mark == 0)
{
vertex.mark = 1;
}
if (vertex2.mark == 0)
{
vertex2.mark = 1;
}
}
}
otri.LnextSelf();
otri.Oprev(ref otri2);
while (otri2.triangle != Mesh.dummytri)
{
otri2.Copy(ref otri);
otri.Oprev(ref otri2);
}
}
while (!otri.Equal(otri3));
}
// Token: 0x06000030 RID: 48 RVA: 0x00002BF4 File Offset: 0x00000DF4
private void Plague()
{
Otri otri = default(Otri);
Otri otri2 = default(Otri);
Osub osub = default(Osub);
for (int i = 0; i < this.viri.Count; i++)
{
otri.triangle = this.viri[i];
otri.Uninfect();
otri.orient = 0;
while (otri.orient < 3)
{
otri.Sym(ref otri2);
otri.SegPivot(ref osub);
if (otri2.triangle == Mesh.dummytri || otri2.IsInfected())
{
if (osub.seg != Mesh.dummysub)
{
this.mesh.SubsegDealloc(osub.seg);
if (otri2.triangle != Mesh.dummytri)
{
otri2.Uninfect();
otri2.SegDissolve();
otri2.Infect();
}
}
}
else if (osub.seg == Mesh.dummysub)
{
otri2.Infect();
this.viri.Add(otri2.triangle);
}
else
{
osub.TriDissolve();
if (osub.seg.boundary == 0)
{
osub.seg.boundary = 1;
}
Vertex vertex = otri2.Org();
Vertex vertex2 = otri2.Dest();
if (vertex.mark == 0)
{
vertex.mark = 1;
}
if (vertex2.mark == 0)
{
vertex2.mark = 1;
}
}
otri.orient++;
}
otri.Infect();
}
foreach (Triangle triangle in this.viri)
{
otri.triangle = triangle;
otri.orient = 0;
while (otri.orient < 3)
{
Vertex vertex3 = otri.Org();
if (vertex3 != null)
{
bool flag = true;
otri.SetOrg(null);
otri.Onext(ref otri2);
while (otri2.triangle != Mesh.dummytri && !otri2.Equal(otri))
{
if (otri2.IsInfected())
{
otri2.SetOrg(null);
}
else
{
flag = false;
}
otri2.OnextSelf();
}
if (otri2.triangle == Mesh.dummytri)
{
otri.Oprev(ref otri2);
while (otri2.triangle != Mesh.dummytri)
{
if (otri2.IsInfected())
{
otri2.SetOrg(null);
}
else
{
flag = false;
}
otri2.OprevSelf();
}
}
if (flag)
{
vertex3.type = VertexType.UndeadVertex;
this.mesh.undeads++;
}
}
otri.orient++;
}
otri.orient = 0;
while (otri.orient < 3)
{
otri.Sym(ref otri2);
if (otri2.triangle == Mesh.dummytri)
{
this.mesh.hullsize--;
}
else
{
otri2.Dissolve();
this.mesh.hullsize++;
}
otri.orient++;
}
this.mesh.TriangleDealloc(otri.triangle);
}
this.viri.Clear();
}
// Token: 0x06000031 RID: 49 RVA: 0x00002F2C File Offset: 0x0000112C
private FindDirectionResult FindDirection(ref Otri searchtri, Vertex searchpoint)
{
Otri otri = default(Otri);
Vertex vertex = searchtri.Org();
Vertex vertex2 = searchtri.Dest();
Vertex vertex3 = searchtri.Apex();
double num = Primitives.CounterClockwise(searchpoint, vertex, vertex3);
bool flag = num > 0.0;
double num2 = Primitives.CounterClockwise(vertex, searchpoint, vertex2);
bool flag2 = num2 > 0.0;
if (flag && flag2)
{
searchtri.Onext(ref otri);
if (otri.triangle == Mesh.dummytri)
{
flag = false;
}
else
{
flag2 = false;
}
}
while (flag)
{
searchtri.OnextSelf();
if (searchtri.triangle == Mesh.dummytri)
{
this.logger.Error("Unable to find a triangle on path.", "Mesh.FindDirection().1");
throw new Exception("Unable to find a triangle on path.");
}
vertex3 = searchtri.Apex();
num2 = num;
num = Primitives.CounterClockwise(searchpoint, vertex, vertex3);
flag = num > 0.0;
}
while (flag2)
{
searchtri.OprevSelf();
if (searchtri.triangle == Mesh.dummytri)
{
this.logger.Error("Unable to find a triangle on path.", "Mesh.FindDirection().2");
throw new Exception("Unable to find a triangle on path.");
}
vertex2 = searchtri.Dest();
num = num2;
num2 = Primitives.CounterClockwise(vertex, searchpoint, vertex2);
flag2 = num2 > 0.0;
}
if (num == 0.0)
{
return FindDirectionResult.Leftcollinear;
}
if (num2 == 0.0)
{
return FindDirectionResult.Rightcollinear;
}
return FindDirectionResult.Within;
}
// Token: 0x06000032 RID: 50 RVA: 0x00003088 File Offset: 0x00001288
private void SegmentIntersection(ref Otri splittri, ref Osub splitsubseg, Vertex endpoint2)
{
Osub osub = default(Osub);
Vertex vertex = splittri.Apex();
Vertex vertex2 = splittri.Org();
Vertex vertex3 = splittri.Dest();
double num = vertex3.x - vertex2.x;
double num2 = vertex3.y - vertex2.y;
double num3 = endpoint2.x - vertex.x;
double num4 = endpoint2.y - vertex.y;
double num5 = vertex2.x - endpoint2.x;
double num6 = vertex2.y - endpoint2.y;
double num7 = num2 * num3 - num * num4;
if (num7 == 0.0)
{
this.logger.Error("Attempt to find intersection of parallel segments.", "Mesh.SegmentIntersection()");
throw new Exception("Attempt to find intersection of parallel segments.");
}
double num8 = (num4 * num5 - num3 * num6) / num7;
Vertex vertex4 = new Vertex(vertex2.x + num8 * (vertex3.x - vertex2.x), vertex2.y + num8 * (vertex3.y - vertex2.y), splitsubseg.seg.boundary, this.mesh.nextras);
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;
for (int i = 0; i < this.mesh.nextras; i++)
{
vertex4.attributes[i] = vertex2.attributes[i] + num8 * (vertex3.attributes[i] - vertex2.attributes[i]);
}
this.mesh.vertices.Add(vertex4.hash, vertex4);
if (this.mesh.InsertVertex(vertex4, ref splittri, ref splitsubseg, false, false) != InsertVertexResult.Successful)
{
this.logger.Error("Failure to split a segment.", "Mesh.SegmentIntersection()");
throw new Exception("Failure to split a segment.");
}
vertex4.tri = splittri;
if (this.mesh.steinerleft > 0)
{
this.mesh.steinerleft--;
}
splitsubseg.SymSelf();
splitsubseg.Pivot(ref osub);
splitsubseg.Dissolve();
osub.Dissolve();
do
{
splitsubseg.SetSegOrg(vertex4);
splitsubseg.NextSelf();
}
while (splitsubseg.seg != Mesh.dummysub);
do
{
osub.SetSegOrg(vertex4);
osub.NextSelf();
}
while (osub.seg != Mesh.dummysub);
this.FindDirection(ref splittri, vertex);
Vertex vertex6 = splittri.Dest();
Vertex vertex7 = splittri.Apex();
if (vertex7.x == vertex.x && vertex7.y == vertex.y)
{
splittri.OnextSelf();
return;
}
if (vertex6.x != vertex.x || vertex6.y != vertex.y)
{
this.logger.Error("Topological inconsistency after splitting a segment.", "Mesh.SegmentIntersection()");
throw new Exception("Topological inconsistency after splitting a segment.");
}
}
// Token: 0x06000033 RID: 51 RVA: 0x00003358 File Offset: 0x00001558
private bool ScoutSegment(ref Otri searchtri, Vertex endpoint2, int newmark)
{
Otri otri = default(Otri);
Osub osub = default(Osub);
FindDirectionResult findDirectionResult = this.FindDirection(ref searchtri, endpoint2);
Vertex vertex = searchtri.Dest();
Vertex vertex2 = searchtri.Apex();
if ((vertex2.x == endpoint2.x && vertex2.y == endpoint2.y) || (vertex.x == endpoint2.x && vertex.y == endpoint2.y))
{
if (vertex2.x == endpoint2.x && vertex2.y == endpoint2.y)
{
searchtri.LprevSelf();
}
this.mesh.InsertSubseg(ref searchtri, newmark);
return true;
}
if (findDirectionResult == FindDirectionResult.Leftcollinear)
{
searchtri.LprevSelf();
this.mesh.InsertSubseg(ref searchtri, newmark);
return this.ScoutSegment(ref searchtri, endpoint2, newmark);
}
if (findDirectionResult == FindDirectionResult.Rightcollinear)
{
this.mesh.InsertSubseg(ref searchtri, newmark);
searchtri.LnextSelf();
return this.ScoutSegment(ref searchtri, endpoint2, newmark);
}
searchtri.Lnext(ref otri);
otri.SegPivot(ref osub);
if (osub.seg == Mesh.dummysub)
{
return false;
}
this.SegmentIntersection(ref otri, ref osub, endpoint2);
otri.Copy(ref searchtri);
this.mesh.InsertSubseg(ref searchtri, newmark);
return this.ScoutSegment(ref searchtri, endpoint2, newmark);
}
// Token: 0x06000034 RID: 52 RVA: 0x00003484 File Offset: 0x00001684
private void DelaunayFixup(ref Otri fixuptri, bool leftside)
{
Otri otri = default(Otri);
Otri otri2 = default(Otri);
Osub osub = default(Osub);
fixuptri.Lnext(ref otri);
otri.Sym(ref otri2);
if (otri2.triangle == Mesh.dummytri)
{
return;
}
otri.SegPivot(ref osub);
if (osub.seg != Mesh.dummysub)
{
return;
}
Vertex vertex = otri.Apex();
Vertex vertex2 = otri.Org();
Vertex vertex3 = otri.Dest();
Vertex vertex4 = otri2.Apex();
if (leftside)
{
if (Primitives.CounterClockwise(vertex, vertex2, vertex4) <= 0.0)
{
return;
}
}
else if (Primitives.CounterClockwise(vertex4, vertex3, vertex) <= 0.0)
{
return;
}
if (Primitives.CounterClockwise(vertex3, vertex2, vertex4) > 0.0 && Primitives.InCircle(vertex2, vertex4, vertex3, vertex) <= 0.0)
{
return;
}
this.mesh.Flip(ref otri);
fixuptri.LprevSelf();
this.DelaunayFixup(ref fixuptri, leftside);
this.DelaunayFixup(ref otri2, leftside);
}
// Token: 0x06000035 RID: 53 RVA: 0x00003584 File Offset: 0x00001784
private void ConstrainedEdge(ref Otri starttri, Vertex endpoint2, int newmark)
{
Otri otri = default(Otri);
Otri otri2 = default(Otri);
Osub osub = default(Osub);
Vertex vertex = starttri.Org();
starttri.Lnext(ref otri);
this.mesh.Flip(ref otri);
bool flag = false;
bool flag2 = false;
do
{
Vertex vertex2 = otri.Org();
if (vertex2.x == endpoint2.x && vertex2.y == endpoint2.y)
{
otri.Oprev(ref otri2);
this.DelaunayFixup(ref otri, false);
this.DelaunayFixup(ref otri2, true);
flag2 = true;
}
else
{
double num = Primitives.CounterClockwise(vertex, endpoint2, vertex2);
if (num == 0.0)
{
flag = true;
otri.Oprev(ref otri2);
this.DelaunayFixup(ref otri, false);
this.DelaunayFixup(ref otri2, true);
flag2 = true;
}
else
{
if (num > 0.0)
{
otri.Oprev(ref otri2);
this.DelaunayFixup(ref otri2, true);
otri.LprevSelf();
}
else
{
this.DelaunayFixup(ref otri, false);
otri.OprevSelf();
}
otri.SegPivot(ref osub);
if (osub.seg == Mesh.dummysub)
{
this.mesh.Flip(ref otri);
}
else
{
flag = true;
this.SegmentIntersection(ref otri, ref osub, endpoint2);
flag2 = true;
}
}
}
}
while (!flag2);
this.mesh.InsertSubseg(ref otri, newmark);
if (flag && !this.ScoutSegment(ref otri, endpoint2, newmark))
{
this.ConstrainedEdge(ref otri, endpoint2, newmark);
}
}
// Token: 0x06000036 RID: 54 RVA: 0x000036F0 File Offset: 0x000018F0
private void InsertSegment(Vertex endpoint1, Vertex endpoint2, int newmark)
{
Otri otri = default(Otri);
Otri otri2 = default(Otri);
Vertex vertex = null;
otri = endpoint1.tri;
if (otri.triangle != null)
{
vertex = otri.Org();
}
if (vertex != endpoint1)
{
otri.triangle = Mesh.dummytri;
otri.orient = 0;
otri.SymSelf();
if (this.locator.Locate(endpoint1, ref otri) != LocateResult.OnVertex)
{
this.logger.Error("Unable to locate PSLG vertex in triangulation.", "Mesh.InsertSegment().1");
throw new Exception("Unable to locate PSLG vertex in triangulation.");
}
}
this.locator.Update(ref otri);
if (this.ScoutSegment(ref otri, endpoint2, newmark))
{
return;
}
endpoint1 = otri.Org();
vertex = null;
otri2 = endpoint2.tri;
if (otri2.triangle != null)
{
vertex = otri2.Org();
}
if (vertex != endpoint2)
{
otri2.triangle = Mesh.dummytri;
otri2.orient = 0;
otri2.SymSelf();
if (this.locator.Locate(endpoint2, ref otri2) != LocateResult.OnVertex)
{
this.logger.Error("Unable to locate PSLG vertex in triangulation.", "Mesh.InsertSegment().2");
throw new Exception("Unable to locate PSLG vertex in triangulation.");
}
}
this.locator.Update(ref otri2);
if (this.ScoutSegment(ref otri2, endpoint1, newmark))
{
return;
}
endpoint2 = otri2.Org();
this.ConstrainedEdge(ref otri, endpoint2, newmark);
}
// Token: 0x06000037 RID: 55 RVA: 0x0000383C File Offset: 0x00001A3C
private void MarkHull()
{
Otri otri = default(Otri);
Otri otri2 = default(Otri);
Otri otri3 = default(Otri);
otri.triangle = Mesh.dummytri;
otri.orient = 0;
otri.SymSelf();
otri.Copy(ref otri3);
do
{
this.mesh.InsertSubseg(ref otri, 1);
otri.LnextSelf();
otri.Oprev(ref otri2);
while (otri2.triangle != Mesh.dummytri)
{
otri2.Copy(ref otri);
otri.Oprev(ref otri2);
}
}
while (!otri.Equal(otri3));
}
// Token: 0x0400001E RID: 30
private Mesh mesh;
// Token: 0x0400001F RID: 31
private Behavior behavior;
// Token: 0x04000020 RID: 32
private TriangleLocator locator;
// Token: 0x04000021 RID: 33
private List<Triangle> viri;
// Token: 0x04000022 RID: 34
private ILog<SimpleLogItem> logger;
}
}