diff --git a/network_process/src/prim_gen/filter_tet_by_subface.cpp b/network_process/src/prim_gen/filter_tet_by_subface.cpp index 5b04291..8067722 100644 --- a/network_process/src/prim_gen/filter_tet_by_subface.cpp +++ b/network_process/src/prim_gen/filter_tet_by_subface.cpp @@ -71,6 +71,10 @@ void filter_tet_by_subface(const btree_map_mp> tetrahedron_active_subface_start_index.reserve(tetrahedrons.size() + 1); active_subface_indices.reserve(tetrahedrons.size()); tetrahedron_active_subface_start_index.emplace_back(0); + + flat_hash_map_mp old_to_new_tet_idx{}; + old_to_new_tet_idx.reserve(tetrahedrons.size() / 4); + for (auto i = 0; i < tetrahedrons.size(); ++i) { const auto& tet_info = sign_counts[i]; for (auto j = 0; j < tet_info.size(); ++j) { @@ -78,6 +82,8 @@ void filter_tet_by_subface(const btree_map_mp> if ((sign & 0x0F) < 4 && (sign >> 4) < 4) { active_subface_indices.emplace_back(j); } } 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(i)] = static_cast(filtered_tets.size()); tetrahedron_active_subface_start_index.emplace_back(active_subface_indices.size()); const auto& vertices = filtered_tets.emplace_back(std::move(tetrahedrons[i])); 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> filtered_active_vertices.shrink_to_fit(); 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 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 // without any intermediate vertices std::sort(filtered_active_vertices.begin(), filtered_active_vertices.end());