/// <summary> /// For each on-face vtx, we poke the face, and re-sort /// the remaining vertices on that face onto new faces/edges /// </summary> void insert_face_vertices() { while (FaceVertices.Count > 0) { var pair = FaceVertices.First(); int tid = pair.Key; List <SegmentVtx> triVerts = pair.Value; SegmentVtx v = triVerts[triVerts.Count - 1]; triVerts.RemoveAt(triVerts.Count - 1); DMesh3.PokeTriangleInfo pokeInfo; MeshResult result = Target.PokeTriangle(tid, out pokeInfo); if (result != MeshResult.Ok) { throw new Exception("shit"); } int new_v = pokeInfo.new_vid; Target.SetVertex(new_v, v.v); v.vtx_id = new_v; VIDToSegVtxMap[v.vtx_id] = v; PointHash.InsertPoint(v.vtx_id, v.v); // remove this triangles vtx list because it is no longer valid FaceVertices.Remove(tid); // update remaining verts Index3i pokeEdges = pokeInfo.new_edges; var pokeTris = new Index3i(tid, pokeInfo.new_t1, pokeInfo.new_t2); foreach (SegmentVtx sv in triVerts) { update_from_poke(sv, pokeEdges, pokeTris); if (sv.type == 1) { add_edge_vtx(sv.elem_id, sv); } else if (sv.type == 2) { add_face_vtx(sv.elem_id, sv); } } // track poke subfaces add_poke_subfaces(tid, ref pokeInfo); } }
protected bool check_for_cracks(DMesh3 mesh, out int boundary_edge_count, double crack_tol = MathUtil.ZeroTolerancef) { boundary_edge_count = 0; var boundary_verts = new MeshVertexSelection(mesh); foreach (int eid in mesh.BoundaryEdgeIndices()) { Index2i ev = mesh.GetEdgeV(eid); boundary_verts.Select(ev.a); boundary_verts.Select(ev.b); boundary_edge_count++; } if (boundary_verts.Count == 0) { return(false); } AxisAlignedBox3d bounds = mesh.CachedBounds; var borderV = new PointHashGrid3d <int>(bounds.MaxDim / 128, -1); foreach (int vid in boundary_verts) { Vector3d v = mesh.GetVertex(vid); var result = borderV.FindNearestInRadius(v, crack_tol, (existing_vid) => { return(v.Distance(mesh.GetVertex(existing_vid))); }); if (result.Key != -1) { return(true); // we found a crack vertex! } borderV.InsertPoint(vid, v); } // found no cracks return(false); }
protected virtual DMesh3 BuildMesh_TolerantWeld(STLSolid solid, double weld_tolerance) { var builder = new DMesh3Builder(); builder.AppendNewMesh(false, false, false, false); DVectorArray3f vertices = solid.Vertices; int N = vertices.Count; int[] mapV = new int[N]; AxisAlignedBox3d bounds = AxisAlignedBox3d.Empty; for (int i = 0; i < N; ++i) { bounds.Contain(vertices[i]); } // [RMS] because we are only searching within tiny radius, there is really no downside to // using lots of bins here, except memory usage. If we don't, and the mesh has a ton of triangles // very close together (happens all the time on big meshes!), then this step can start // to take an *extremely* long time! int num_bins = 256; if (N > 100000) { num_bins = 512; } if (N > 1000000) { num_bins = 1024; } if (N > 2000000) { num_bins = 2048; } if (N > 5000000) { num_bins = 4096; } var uniqueV = new PointHashGrid3d <int>(bounds.MaxDim / (float)num_bins, -1); var pos = new Vector3f[N]; for (int vi = 0; vi < N; ++vi) { Vector3f v = vertices[vi]; var pair = uniqueV.FindNearestInRadius(v, weld_tolerance, (vid) => { return(v.Distance(pos[vid])); }); if (pair.Key == -1) { int vid = builder.AppendVertex(v.x, v.y, v.z); uniqueV.InsertPoint(vid, v); mapV[vi] = vid; pos[vid] = v; } else { mapV[vi] = pair.Key; } } append_mapped_triangles(solid, builder, mapV); return(builder.Meshes[0]); }