public Process ( TriangleNet.Data.Triangle triangle ) : void | ||
triangle | TriangleNet.Data.Triangle | |
return | void |
/// <summary> /// Find the holes and infect them. Find the area constraints and infect /// them. Infect the convex hull. Spread the infection and kill triangles. /// Spread the area constraints. /// </summary> public void CarveHoles() { Otri searchtri = default(Otri); Vertex searchorg, searchdest; LocateResult intersect; Triangle[] regionTris = null; if (!mesh.behavior.Convex) { // Mark as infected any unprotected triangles on the boundary. // This is one way by which concavities are created. InfectHull(); } if (!mesh.behavior.NoHoles) { // Infect each triangle in which a hole lies. foreach (var hole in mesh.holes) { // Ignore holes that aren't within the bounds of the mesh. if (mesh.bounds.Contains(hole)) { // Start searching from some triangle on the outer boundary. searchtri.triangle = Mesh.dummytri; searchtri.orient = 0; searchtri.SymSelf(); // Ensure that the hole is to the left of this boundary edge; // otherwise, locate() will falsely report that the hole // falls within the starting triangle. searchorg = searchtri.Org(); searchdest = searchtri.Dest(); if (Primitives.CounterClockwise(searchorg, searchdest, hole) > 0.0) { // Find a triangle that contains the hole. intersect = mesh.locator.Locate(hole, ref searchtri); if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected())) { // Infect the triangle. This is done by marking the triangle // as infected and including the triangle in the virus pool. searchtri.Infect(); viri.Add(searchtri.triangle); } } } } } // Now, we have to find all the regions BEFORE we carve the holes, because locate() won't // work when the triangulation is no longer convex. (Incidentally, this is the reason why // regional attributes and area constraints can't be used when refining a preexisting mesh, // which might not be convex; they can only be used with a freshly triangulated PSLG.) if (mesh.regions.Count > 0) { int i = 0; regionTris = new Triangle[mesh.regions.Count]; // Find the starting triangle for each region. foreach (var region in mesh.regions) { regionTris[i] = Mesh.dummytri; // Ignore region points that aren't within the bounds of the mesh. if (mesh.bounds.Contains(region.point)) { // Start searching from some triangle on the outer boundary. searchtri.triangle = Mesh.dummytri; searchtri.orient = 0; searchtri.SymSelf(); // Ensure that the region point is to the left of this boundary // edge; otherwise, locate() will falsely report that the // region point falls within the starting triangle. searchorg = searchtri.Org(); searchdest = searchtri.Dest(); if (Primitives.CounterClockwise(searchorg, searchdest, region.point) > 0.0) { // Find a triangle that contains the region point. intersect = mesh.locator.Locate(region.point, ref searchtri); if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected())) { // Record the triangle for processing after the // holes have been carved. regionTris[i] = searchtri.triangle; regionTris[i].region = region.id; } } } i++; } } if (viri.Count > 0) { // Carve the holes and concavities. Plague(); } if (regionTris != null) { var iterator = new RegionIterator(mesh); for (int i = 0; i < regionTris.Length; i++) { if (regionTris[i] != Mesh.dummytri) { // Make sure the triangle under consideration still exists. // It may have been eaten by the virus. if (!Otri.IsDead(regionTris[i])) { // Apply one region's attribute and/or area constraint. iterator.Process(regionTris[i]); } } } } // Free up memory (virus pool should be empty anyway). viri.Clear(); }