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(); 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 viri; // Token: 0x04000022 RID: 34 private ILog logger; } }