/// <summary> /// Grow selection outwards from seed triangles, until it hits boundaries defined by triangle and edge filters. /// Edge filter is not effective unless it (possibly combined w/ triangle filter) defines closed loops. /// </summary> public void FloodFill(int[] Seeds, Func <int, bool> TriFilterF = null, Func <int, bool> EdgeFilterF = null) { DVector <int> stack = new DVector <int>(Seeds); for (int k = 0; k < Seeds.Length; ++k) { add(Seeds[k]); } while (stack.size > 0) { int tID = stack.back; stack.pop_back(); Index3i nbrs = Mesh.GetTriNeighbourTris(tID); for (int j = 0; j < 3; ++j) { int nbr_tid = nbrs[j]; if (nbr_tid == DMesh3.InvalidID || IsSelected(nbr_tid)) { continue; } if (TriFilterF != null && TriFilterF(nbr_tid) == false) { continue; } if (EdgeFilterF != null && EdgeFilterF(Mesh.GetTriEdge(tID, j)) == false) { continue; } add(nbr_tid); stack.push_back(nbr_tid); } } }
// insert point at bary_coords inside tid. If point is at vtx, just use that vtx. // If it is on an edge, do an edge split. Otherwise poke face. int insert_corner_from_bary(int iCorner, int tid, Vector3d bary_coords, double tol = MathUtil.ZeroTolerance) { Vector2d vInsert = Curve[iCorner]; Index3i tv = Mesh.GetTriangle(tid); // handle cases where corner is on a vertex if (bary_coords.x > 1 - tol) { return(tv.a); } else if (bary_coords.y > 1 - tol) { return(tv.b); } else if (bary_coords.z > 1 - tol) { return(tv.c); } // handle cases where corner is on an edge int split_edge = -1; if (bary_coords.x < tol) { split_edge = 1; } else if (bary_coords.y < tol) { split_edge = 2; } else if (bary_coords.z < tol) { split_edge = 0; } if (split_edge >= 0) { int eid = Mesh.GetTriEdge(tid, split_edge); DMesh3.EdgeSplitInfo split_info; MeshResult splitResult = Mesh.SplitEdge(eid, out split_info); if (splitResult != MeshResult.Ok) { throw new Exception("MeshInsertUVPolyCurve.insert_corner_special: edge split failed in case sum==2"); } SetPointF(split_info.vNew, vInsert); return(split_info.vNew); } // otherwise corner is inside triangle DMesh3.PokeTriangleInfo pokeinfo; MeshResult result = Mesh.PokeTriangle(tid, bary_coords, out pokeinfo); if (result != MeshResult.Ok) { throw new Exception("MeshInsertUVPolyCurve.insert_corner_special: face poke failed!"); } SetPointF(pokeinfo.new_vid, vInsert); return(pokeinfo.new_vid); }
// insert point at bary_coords inside tid. If point is at vtx, just use that vtx. // If it is on an edge, do an edge split. Otherwise poke face. int insert_corner_from_bary(int iCorner, int tid, Vector3d bary_coords, double bary_tol, double spatial_tol, out bool is_existing_v) { is_existing_v = false; Vector2d vInsert = Curve[iCorner]; Index3i tv = Mesh.GetTriangle(tid); // handle cases where corner is on a vertex int cornerv = -1; if (bary_coords.x > 1 - bary_tol) { cornerv = tv.a; } else if (bary_coords.y > 1 - bary_tol) { cornerv = tv.b; } else if (bary_coords.z > 1 - bary_tol) { cornerv = tv.c; } if (cornerv != -1 && PointF(cornerv).Distance(vInsert) < spatial_tol) { is_existing_v = true; return(cornerv); } // handle cases where corner is on an edge int split_edge = -1; if (bary_coords.x < bary_tol) { split_edge = 1; } else if (bary_coords.y < bary_tol) { split_edge = 2; } else if (bary_coords.z < bary_tol) { split_edge = 0; } if (split_edge >= 0) { int eid = Mesh.GetTriEdge(tid, split_edge); Index2i ev = Mesh.GetEdgeV(eid); Segment2d seg = new Segment2d(PointF(ev.a), PointF(ev.b)); if (seg.DistanceSquared(vInsert) < spatial_tol * spatial_tol) { Index2i et = Mesh.GetEdgeT(eid); spatial_remove_triangles(et.a, et.b); DMesh3.EdgeSplitInfo split_info; MeshResult splitResult = Mesh.SplitEdge(eid, out split_info); if (splitResult != MeshResult.Ok) { throw new Exception("MeshInsertUVPolyCurve.insert_corner_from_bary: edge split failed in case sum==2 - " + splitResult.ToString()); } SetPointF(split_info.vNew, vInsert); spatial_add_triangles(et.a, et.b); spatial_add_triangles(split_info.eNewT2, split_info.eNewT3); return(split_info.vNew); } } spatial_remove_triangle(tid); // otherwise corner is inside triangle DMesh3.PokeTriangleInfo pokeinfo; MeshResult result = Mesh.PokeTriangle(tid, bary_coords, out pokeinfo); if (result != MeshResult.Ok) { throw new Exception("MeshInsertUVPolyCurve.insert_corner_from_bary: face poke failed - " + result.ToString()); } SetPointF(pokeinfo.new_vid, vInsert); spatial_add_triangle(tid); spatial_add_triangle(pokeinfo.new_t1); spatial_add_triangle(pokeinfo.new_t2); return(pokeinfo.new_vid); }