|
|
@ -71,6 +71,10 @@ void filter_tet_by_subface(const btree_map_mp<uint32_t, stl_vector_mp<uint32_t>> |
|
|
tetrahedron_active_subface_start_index.reserve(tetrahedrons.size() + 1); |
|
|
tetrahedron_active_subface_start_index.reserve(tetrahedrons.size() + 1); |
|
|
active_subface_indices.reserve(tetrahedrons.size()); |
|
|
active_subface_indices.reserve(tetrahedrons.size()); |
|
|
tetrahedron_active_subface_start_index.emplace_back(0); |
|
|
tetrahedron_active_subface_start_index.emplace_back(0); |
|
|
|
|
|
|
|
|
|
|
|
flat_hash_map_mp<uint32_t, uint32_t> old_to_new_tet_idx{}; |
|
|
|
|
|
old_to_new_tet_idx.reserve(tetrahedrons.size() / 4); |
|
|
|
|
|
|
|
|
for (auto i = 0; i < tetrahedrons.size(); ++i) { |
|
|
for (auto i = 0; i < tetrahedrons.size(); ++i) { |
|
|
const auto& tet_info = sign_counts[i]; |
|
|
const auto& tet_info = sign_counts[i]; |
|
|
for (auto j = 0; j < tet_info.size(); ++j) { |
|
|
for (auto j = 0; j < tet_info.size(); ++j) { |
|
|
@ -78,6 +82,8 @@ void filter_tet_by_subface(const btree_map_mp<uint32_t, stl_vector_mp<uint32_t>> |
|
|
if ((sign & 0x0F) < 4 && (sign >> 4) < 4) { active_subface_indices.emplace_back(j); } |
|
|
if ((sign & 0x0F) < 4 && (sign >> 4) < 4) { active_subface_indices.emplace_back(j); } |
|
|
} |
|
|
} |
|
|
if (active_subface_indices.size() > tetrahedron_active_subface_start_index.back()) { |
|
|
if (active_subface_indices.size() > tetrahedron_active_subface_start_index.back()) { |
|
|
|
|
|
// Record mapping BEFORE emplace_back so filtered_tets.size() is the new index.
|
|
|
|
|
|
old_to_new_tet_idx[static_cast<uint32_t>(i)] = static_cast<uint32_t>(filtered_tets.size()); |
|
|
tetrahedron_active_subface_start_index.emplace_back(active_subface_indices.size()); |
|
|
tetrahedron_active_subface_start_index.emplace_back(active_subface_indices.size()); |
|
|
const auto& vertices = filtered_tets.emplace_back(std::move(tetrahedrons[i])); |
|
|
const auto& vertices = filtered_tets.emplace_back(std::move(tetrahedrons[i])); |
|
|
filtered_active_vertices.insert(filtered_active_vertices.end(), vertices.begin(), vertices.end()); |
|
|
filtered_active_vertices.insert(filtered_active_vertices.end(), vertices.begin(), vertices.end()); |
|
|
@ -88,6 +94,31 @@ void filter_tet_by_subface(const btree_map_mp<uint32_t, stl_vector_mp<uint32_t>> |
|
|
filtered_active_vertices.shrink_to_fit(); |
|
|
filtered_active_vertices.shrink_to_fit(); |
|
|
std::swap(filtered_tets, tetrahedrons); |
|
|
std::swap(filtered_tets, tetrahedrons); |
|
|
|
|
|
|
|
|
|
|
|
// Remap zero_vertex_to_incident_tet_mapping: replace every stored original tet
|
|
|
|
|
|
// index with its new compact index, and drop indices for tets that were filtered out.
|
|
|
|
|
|
// The list must remain sorted (set_intersection is used on it later).
|
|
|
|
|
|
for (auto& [vertex_idx, tet_list] : zero_vertex_to_incident_tet_mapping) { |
|
|
|
|
|
stl_vector_mp<uint32_t> updated; |
|
|
|
|
|
updated.reserve(tet_list.size()); |
|
|
|
|
|
for (const auto old_idx : tet_list) { |
|
|
|
|
|
auto it = old_to_new_tet_idx.find(old_idx); |
|
|
|
|
|
if (it != old_to_new_tet_idx.end()) { updated.push_back(it->second); } |
|
|
|
|
|
} |
|
|
|
|
|
// The mapping is order-preserving (filtered tets keep their relative order),
|
|
|
|
|
|
// so updated is already sorted, but sort explicitly for safety.
|
|
|
|
|
|
std::sort(updated.begin(), updated.end()); |
|
|
|
|
|
tet_list = std::move(updated); |
|
|
|
|
|
} |
|
|
|
|
|
// Remove entries whose every incident tet was filtered out — they can no longer
|
|
|
|
|
|
// contribute to any chain and would cause .at() failures if looked up.
|
|
|
|
|
|
for (auto it = zero_vertex_to_incident_tet_mapping.begin(); it != zero_vertex_to_incident_tet_mapping.end();) { |
|
|
|
|
|
if (it->second.empty()) { |
|
|
|
|
|
it = zero_vertex_to_incident_tet_mapping.erase(it); |
|
|
|
|
|
} else { |
|
|
|
|
|
++it; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// change vertex adjacency with filtered vertices, so that each vertex pair in adjacency map is connected directly
|
|
|
// change vertex adjacency with filtered vertices, so that each vertex pair in adjacency map is connected directly
|
|
|
// without any intermediate vertices
|
|
|
// without any intermediate vertices
|
|
|
std::sort(filtered_active_vertices.begin(), filtered_active_vertices.end()); |
|
|
std::sort(filtered_active_vertices.begin(), filtered_active_vertices.end()); |
|
|
|