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 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 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; } } }