Files
2026-06-04 11:42:34 +02:00

652 lines
18 KiB
C#

using System;
using System.Collections.Generic;
using TriangleNet.Data;
using TriangleNet.Geometry;
using TriangleNet.Log;
using TriangleNet.Tools;
namespace TriangleNet.Algorithm
{
// Token: 0x0200003E RID: 62
internal class SweepLine
{
// Token: 0x0600022E RID: 558 RVA: 0x0001AA18 File Offset: 0x00018C18
private int randomnation(int choices)
{
SweepLine.randomseed = (SweepLine.randomseed * 1366 + 150889) % 714025;
return SweepLine.randomseed / (714025 / choices + 1);
}
// Token: 0x0600022F RID: 559 RVA: 0x0001AA48 File Offset: 0x00018C48
private void HeapInsert(SweepLine.SweepEvent[] heap, int heapsize, SweepLine.SweepEvent newevent)
{
double xkey = newevent.xkey;
double ykey = newevent.ykey;
int num = heapsize;
bool flag = num > 0;
while (flag)
{
int num2 = num - 1 >> 1;
if (heap[num2].ykey < ykey || (heap[num2].ykey == ykey && heap[num2].xkey <= xkey))
{
flag = false;
}
else
{
heap[num] = heap[num2];
heap[num].heapposition = num;
num = num2;
flag = num > 0;
}
}
heap[num] = newevent;
newevent.heapposition = num;
}
// Token: 0x06000230 RID: 560 RVA: 0x0001AAC0 File Offset: 0x00018CC0
private void Heapify(SweepLine.SweepEvent[] heap, int heapsize, int eventnum)
{
SweepLine.SweepEvent sweepEvent = heap[eventnum];
double xkey = sweepEvent.xkey;
double ykey = sweepEvent.ykey;
int num = 2 * eventnum + 1;
bool flag = num < heapsize;
while (flag)
{
int num2;
if (heap[num].ykey < ykey || (heap[num].ykey == ykey && heap[num].xkey < xkey))
{
num2 = num;
}
else
{
num2 = eventnum;
}
int num3 = num + 1;
if (num3 < heapsize && (heap[num3].ykey < heap[num2].ykey || (heap[num3].ykey == heap[num2].ykey && heap[num3].xkey < heap[num2].xkey)))
{
num2 = num3;
}
if (num2 == eventnum)
{
flag = false;
}
else
{
heap[eventnum] = heap[num2];
heap[eventnum].heapposition = eventnum;
heap[num2] = sweepEvent;
sweepEvent.heapposition = num2;
eventnum = num2;
num = 2 * eventnum + 1;
flag = num < heapsize;
}
}
}
// Token: 0x06000231 RID: 561 RVA: 0x0001ABA4 File Offset: 0x00018DA4
private void HeapDelete(SweepLine.SweepEvent[] heap, int heapsize, int eventnum)
{
SweepLine.SweepEvent sweepEvent = heap[heapsize - 1];
if (eventnum > 0)
{
double xkey = sweepEvent.xkey;
double ykey = sweepEvent.ykey;
bool flag;
do
{
int num = eventnum - 1 >> 1;
if (heap[num].ykey < ykey || (heap[num].ykey == ykey && heap[num].xkey <= xkey))
{
flag = false;
}
else
{
heap[eventnum] = heap[num];
heap[eventnum].heapposition = eventnum;
eventnum = num;
flag = eventnum > 0;
}
}
while (flag);
}
heap[eventnum] = sweepEvent;
sweepEvent.heapposition = eventnum;
this.Heapify(heap, heapsize - 1, eventnum);
}
// Token: 0x06000232 RID: 562 RVA: 0x0001AC28 File Offset: 0x00018E28
private void CreateHeap(out SweepLine.SweepEvent[] eventheap)
{
int num = 3 * this.mesh.invertices / 2;
eventheap = new SweepLine.SweepEvent[num];
int num2 = 0;
foreach (Vertex vertex in this.mesh.vertices.Values)
{
SweepLine.SweepEvent sweepEvent = new SweepLine.SweepEvent();
sweepEvent.vertexEvent = vertex;
sweepEvent.xkey = vertex.x;
sweepEvent.ykey = vertex.y;
this.HeapInsert(eventheap, num2++, sweepEvent);
}
}
// Token: 0x06000233 RID: 563 RVA: 0x0001ACCC File Offset: 0x00018ECC
private SweepLine.SplayNode Splay(SweepLine.SplayNode splaytree, Point searchpoint, ref Otri searchtri)
{
if (splaytree == null)
{
return null;
}
if (splaytree.keyedge.Dest() == splaytree.keydest)
{
bool flag = this.RightOfHyperbola(ref splaytree.keyedge, searchpoint);
SweepLine.SplayNode splayNode;
if (flag)
{
splaytree.keyedge.Copy(ref searchtri);
splayNode = splaytree.rchild;
}
else
{
splayNode = splaytree.lchild;
}
if (splayNode == null)
{
return splaytree;
}
if (splayNode.keyedge.Dest() != splayNode.keydest)
{
splayNode = this.Splay(splayNode, searchpoint, ref searchtri);
if (splayNode == null)
{
if (flag)
{
splaytree.rchild = null;
}
else
{
splaytree.lchild = null;
}
return splaytree;
}
}
bool flag2 = this.RightOfHyperbola(ref splayNode.keyedge, searchpoint);
SweepLine.SplayNode splayNode2;
if (flag2)
{
splayNode.keyedge.Copy(ref searchtri);
splayNode2 = this.Splay(splayNode.rchild, searchpoint, ref searchtri);
splayNode.rchild = splayNode2;
}
else
{
splayNode2 = this.Splay(splayNode.lchild, searchpoint, ref searchtri);
splayNode.lchild = splayNode2;
}
if (splayNode2 == null)
{
if (flag)
{
splaytree.rchild = splayNode.lchild;
splayNode.lchild = splaytree;
}
else
{
splaytree.lchild = splayNode.rchild;
splayNode.rchild = splaytree;
}
return splayNode;
}
if (flag2)
{
if (flag)
{
splaytree.rchild = splayNode.lchild;
splayNode.lchild = splaytree;
}
else
{
splaytree.lchild = splayNode2.rchild;
splayNode2.rchild = splaytree;
}
splayNode.rchild = splayNode2.lchild;
splayNode2.lchild = splayNode;
}
else
{
if (flag)
{
splaytree.rchild = splayNode2.lchild;
splayNode2.lchild = splaytree;
}
else
{
splaytree.lchild = splayNode.rchild;
splayNode.rchild = splaytree;
}
splayNode.lchild = splayNode2.rchild;
splayNode2.rchild = splayNode;
}
return splayNode2;
}
else
{
SweepLine.SplayNode splayNode3 = this.Splay(splaytree.lchild, searchpoint, ref searchtri);
SweepLine.SplayNode splayNode4 = this.Splay(splaytree.rchild, searchpoint, ref searchtri);
this.splaynodes.Remove(splaytree);
if (splayNode3 == null)
{
return splayNode4;
}
if (splayNode4 == null)
{
return splayNode3;
}
if (splayNode3.rchild == null)
{
splayNode3.rchild = splayNode4.lchild;
splayNode4.lchild = splayNode3;
return splayNode4;
}
if (splayNode4.lchild == null)
{
splayNode4.lchild = splayNode3.rchild;
splayNode3.rchild = splayNode4;
return splayNode3;
}
SweepLine.SplayNode splayNode5 = splayNode3.rchild;
while (splayNode5.rchild != null)
{
splayNode5 = splayNode5.rchild;
}
splayNode5.rchild = splayNode4;
return splayNode3;
}
}
// Token: 0x06000234 RID: 564 RVA: 0x0001AF00 File Offset: 0x00019100
private SweepLine.SplayNode SplayInsert(SweepLine.SplayNode splayroot, Otri newkey, Point searchpoint)
{
SweepLine.SplayNode splayNode = new SweepLine.SplayNode();
this.splaynodes.Add(splayNode);
newkey.Copy(ref splayNode.keyedge);
splayNode.keydest = newkey.Dest();
if (splayroot == null)
{
splayNode.lchild = null;
splayNode.rchild = null;
}
else if (this.RightOfHyperbola(ref splayroot.keyedge, searchpoint))
{
splayNode.lchild = splayroot;
splayNode.rchild = splayroot.rchild;
splayroot.rchild = null;
}
else
{
splayNode.lchild = splayroot.lchild;
splayNode.rchild = splayroot;
splayroot.lchild = null;
}
return splayNode;
}
// Token: 0x06000235 RID: 565 RVA: 0x0001AF94 File Offset: 0x00019194
private SweepLine.SplayNode FrontLocate(SweepLine.SplayNode splayroot, Otri bottommost, Vertex searchvertex, ref Otri searchtri, ref bool farright)
{
bottommost.Copy(ref searchtri);
splayroot = this.Splay(splayroot, searchvertex, ref searchtri);
bool flag = false;
while (!flag && this.RightOfHyperbola(ref searchtri, searchvertex))
{
searchtri.OnextSelf();
flag = searchtri.Equal(bottommost);
}
farright = flag;
return splayroot;
}
// Token: 0x06000236 RID: 566 RVA: 0x0001AFE0 File Offset: 0x000191E0
private SweepLine.SplayNode CircleTopInsert(SweepLine.SplayNode splayroot, Otri newkey, Vertex pa, Vertex pb, Vertex pc, double topy)
{
Point point = new Point();
Otri otri = default(Otri);
double num = Primitives.CounterClockwise(pa, pb, pc);
double num2 = pa.x - pc.x;
double num3 = pa.y - pc.y;
double num4 = pb.x - pc.x;
double num5 = pb.y - pc.y;
double num6 = num2 * num2 + num3 * num3;
double num7 = num4 * num4 + num5 * num5;
point.x = pc.x - (num3 * num7 - num5 * num6) / (2.0 * num);
point.y = topy;
return this.SplayInsert(this.Splay(splayroot, point, ref otri), newkey, point);
}
// Token: 0x06000237 RID: 567 RVA: 0x0001B098 File Offset: 0x00019298
private bool RightOfHyperbola(ref Otri fronttri, Point newsite)
{
Statistic.HyperbolaCount += 1L;
Vertex vertex = fronttri.Dest();
Vertex vertex2 = fronttri.Apex();
if (vertex.y < vertex2.y || (vertex.y == vertex2.y && vertex.x < vertex2.x))
{
if (newsite.x >= vertex2.x)
{
return true;
}
}
else if (newsite.x <= vertex.x)
{
return false;
}
double num = vertex.x - newsite.x;
double num2 = vertex.y - newsite.y;
double num3 = vertex2.x - newsite.x;
double num4 = vertex2.y - newsite.y;
return num2 * (num3 * num3 + num4 * num4) > num4 * (num * num + num2 * num2);
}
// Token: 0x06000238 RID: 568 RVA: 0x0001B160 File Offset: 0x00019360
private double CircleTop(Vertex pa, Vertex pb, Vertex pc, double ccwabc)
{
Statistic.CircleTopCount += 1L;
double num = pa.x - pc.x;
double num2 = pa.y - pc.y;
double num3 = pb.x - pc.x;
double num4 = pb.y - pc.y;
double num5 = pa.x - pb.x;
double num6 = pa.y - pb.y;
double num7 = num * num + num2 * num2;
double num8 = num3 * num3 + num4 * num4;
double num9 = num5 * num5 + num6 * num6;
return pc.y + (num * num8 - num3 * num7 + Math.Sqrt(num7 * num8 * num9)) / (2.0 * ccwabc);
}
// Token: 0x06000239 RID: 569 RVA: 0x0001B218 File Offset: 0x00019418
private void Check4DeadEvent(ref Otri checktri, SweepLine.SweepEvent[] eventheap, ref int heapsize)
{
SweepLine.SweepEventVertex sweepEventVertex = checktri.Org() as SweepLine.SweepEventVertex;
if (sweepEventVertex != null)
{
int heapposition = sweepEventVertex.evt.heapposition;
this.HeapDelete(eventheap, heapsize, heapposition);
heapsize--;
checktri.SetOrg(null);
}
}
// Token: 0x0600023A RID: 570 RVA: 0x0001B260 File Offset: 0x00019460
private int RemoveGhosts(ref Otri startghost)
{
Otri otri = default(Otri);
Otri otri2 = default(Otri);
Otri otri3 = default(Otri);
bool flag = !this.mesh.behavior.Poly;
startghost.Lprev(ref otri);
otri.SymSelf();
Mesh.dummytri.neighbors[0] = otri;
startghost.Copy(ref otri2);
int num = 0;
do
{
num++;
otri2.Lnext(ref otri3);
otri2.LprevSelf();
otri2.SymSelf();
if (flag && otri2.triangle != Mesh.dummytri)
{
Vertex vertex = otri2.Org();
if (vertex.mark == 0)
{
vertex.mark = 1;
}
}
otri2.Dissolve();
otri3.Sym(ref otri2);
this.mesh.TriangleDealloc(otri3.triangle);
}
while (!otri2.Equal(startghost));
return num;
}
// Token: 0x0600023B RID: 571 RVA: 0x0001B33C File Offset: 0x0001953C
public int Triangulate(Mesh mesh)
{
this.mesh = mesh;
this.xminextreme = 10.0 * mesh.bounds.MinX - 9.0 * mesh.bounds.MaxX;
Otri otri = default(Otri);
Otri otri2 = default(Otri);
Otri otri3 = default(Otri);
Otri otri4 = default(Otri);
Otri otri5 = default(Otri);
Otri otri6 = default(Otri);
Otri otri7 = default(Otri);
bool flag = false;
this.splaynodes = new List<SweepLine.SplayNode>();
SweepLine.SplayNode splayNode = null;
SweepLine.SweepEvent[] array;
this.CreateHeap(out array);
int i = mesh.invertices;
mesh.MakeTriangle(ref otri3);
mesh.MakeTriangle(ref otri4);
otri3.Bond(ref otri4);
otri3.LnextSelf();
otri4.LprevSelf();
otri3.Bond(ref otri4);
otri3.LnextSelf();
otri4.LprevSelf();
otri3.Bond(ref otri4);
Vertex vertexEvent = array[0].vertexEvent;
this.HeapDelete(array, i, 0);
i--;
while (i != 0)
{
Vertex vertexEvent2 = array[0].vertexEvent;
this.HeapDelete(array, i, 0);
i--;
if (vertexEvent.x == vertexEvent2.x && vertexEvent.y == vertexEvent2.y)
{
if (Behavior.Verbose)
{
SimpleLog.Instance.Warning("A duplicate vertex appeared and was ignored (ID " + vertexEvent2.id + ").", "SweepLine.Triangulate().1");
}
vertexEvent2.type = VertexType.UndeadVertex;
mesh.undeads++;
}
if (vertexEvent.x != vertexEvent2.x || vertexEvent.y != vertexEvent2.y)
{
otri3.SetOrg(vertexEvent);
otri3.SetDest(vertexEvent2);
otri4.SetOrg(vertexEvent2);
otri4.SetDest(vertexEvent);
otri3.Lprev(ref otri);
Vertex vertex = vertexEvent2;
while (i > 0)
{
SweepLine.SweepEvent sweepEvent = array[0];
this.HeapDelete(array, i, 0);
i--;
bool flag2 = true;
if (sweepEvent.xkey < mesh.bounds.MinX)
{
Otri otriEvent = sweepEvent.otriEvent;
otriEvent.Oprev(ref otri5);
this.Check4DeadEvent(ref otri5, array, ref i);
otriEvent.Onext(ref otri6);
this.Check4DeadEvent(ref otri6, array, ref i);
if (otri5.Equal(otri))
{
otriEvent.Lprev(ref otri);
}
mesh.Flip(ref otriEvent);
otriEvent.SetApex(null);
otriEvent.Lprev(ref otri3);
otriEvent.Lnext(ref otri4);
otri3.Sym(ref otri5);
if (this.randomnation(SweepLine.SAMPLERATE) == 0)
{
otriEvent.SymSelf();
Vertex vertex2 = otriEvent.Dest();
Vertex vertex3 = otriEvent.Apex();
Vertex vertex4 = otriEvent.Org();
splayNode = this.CircleTopInsert(splayNode, otri3, vertex2, vertex3, vertex4, sweepEvent.ykey);
}
}
else
{
Vertex vertexEvent3 = sweepEvent.vertexEvent;
if (vertexEvent3.x == vertex.x && vertexEvent3.y == vertex.y)
{
if (Behavior.Verbose)
{
SimpleLog.Instance.Warning("A duplicate vertex appeared and was ignored (ID " + vertexEvent3.id + ").", "SweepLine.Triangulate().2");
}
vertexEvent3.type = VertexType.UndeadVertex;
mesh.undeads++;
flag2 = false;
}
else
{
vertex = vertexEvent3;
splayNode = this.FrontLocate(splayNode, otri, vertexEvent3, ref otri2, ref flag);
this.Check4DeadEvent(ref otri2, array, ref i);
otri2.Copy(ref otri6);
otri2.Sym(ref otri5);
mesh.MakeTriangle(ref otri3);
mesh.MakeTriangle(ref otri4);
Vertex vertex5 = otri6.Dest();
otri3.SetOrg(vertex5);
otri3.SetDest(vertexEvent3);
otri4.SetOrg(vertexEvent3);
otri4.SetDest(vertex5);
otri3.Bond(ref otri4);
otri3.LnextSelf();
otri4.LprevSelf();
otri3.Bond(ref otri4);
otri3.LnextSelf();
otri4.LprevSelf();
otri3.Bond(ref otri5);
otri4.Bond(ref otri6);
if (!flag && otri6.Equal(otri))
{
otri3.Copy(ref otri);
}
if (this.randomnation(SweepLine.SAMPLERATE) == 0)
{
splayNode = this.SplayInsert(splayNode, otri3, vertexEvent3);
}
else if (this.randomnation(SweepLine.SAMPLERATE) == 0)
{
otri4.Lnext(ref otri7);
splayNode = this.SplayInsert(splayNode, otri7, vertexEvent3);
}
}
}
if (flag2)
{
Vertex vertex2 = otri5.Apex();
Vertex vertex3 = otri3.Dest();
Vertex vertex4 = otri3.Apex();
double num = Primitives.CounterClockwise(vertex2, vertex3, vertex4);
if (num > 0.0)
{
SweepLine.SweepEvent sweepEvent2 = new SweepLine.SweepEvent();
sweepEvent2.xkey = this.xminextreme;
sweepEvent2.ykey = this.CircleTop(vertex2, vertex3, vertex4, num);
sweepEvent2.otriEvent = otri3;
this.HeapInsert(array, i, sweepEvent2);
i++;
otri3.SetOrg(new SweepLine.SweepEventVertex(sweepEvent2));
}
vertex2 = otri4.Apex();
vertex3 = otri4.Org();
vertex4 = otri6.Apex();
double num2 = Primitives.CounterClockwise(vertex2, vertex3, vertex4);
if (num2 > 0.0)
{
SweepLine.SweepEvent sweepEvent2 = new SweepLine.SweepEvent();
sweepEvent2.xkey = this.xminextreme;
sweepEvent2.ykey = this.CircleTop(vertex2, vertex3, vertex4, num2);
sweepEvent2.otriEvent = otri6;
this.HeapInsert(array, i, sweepEvent2);
i++;
otri6.SetOrg(new SweepLine.SweepEventVertex(sweepEvent2));
}
}
}
this.splaynodes.Clear();
otri.LprevSelf();
return this.RemoveGhosts(ref otri);
}
}
SimpleLog.Instance.Error("Input vertices are all identical.", "SweepLine.Triangulate()");
throw new Exception("Input vertices are all identical.");
}
// Token: 0x04000131 RID: 305
private static int randomseed = 1;
// Token: 0x04000132 RID: 306
private static int SAMPLERATE = 10;
// Token: 0x04000133 RID: 307
private Mesh mesh;
// Token: 0x04000134 RID: 308
private double xminextreme;
// Token: 0x04000135 RID: 309
private List<SweepLine.SplayNode> splaynodes;
// Token: 0x02000046 RID: 70
private class SweepEvent
{
// Token: 0x0400014C RID: 332
public double xkey;
// Token: 0x0400014D RID: 333
public double ykey;
// Token: 0x0400014E RID: 334
public Vertex vertexEvent;
// Token: 0x0400014F RID: 335
public Otri otriEvent;
// Token: 0x04000150 RID: 336
public int heapposition;
}
// Token: 0x02000047 RID: 71
private class SweepEventVertex : Vertex
{
// Token: 0x06000258 RID: 600 RVA: 0x0001BE5D File Offset: 0x0001A05D
public SweepEventVertex(SweepLine.SweepEvent e)
{
this.evt = e;
}
// Token: 0x04000151 RID: 337
public SweepLine.SweepEvent evt;
}
// Token: 0x02000048 RID: 72
private class SplayNode
{
// Token: 0x04000152 RID: 338
public Otri keyedge;
// Token: 0x04000153 RID: 339
public Vertex keydest;
// Token: 0x04000154 RID: 340
public SweepLine.SplayNode lchild;
// Token: 0x04000155 RID: 341
public SweepLine.SplayNode rchild;
}
}
}