3#include <wmtk/simplex/Simplex.hpp>
4#include <wmtk/utils/Logger.hpp>
11namespace wmtk::utils {
24 long long components = 0;
29 long long boundary_loops = 0;
38 std::vector<long long> parent;
39 void init(
long long n)
42 for (
long long i = 0; i < n; ++i) {
46 long long find(
long long x)
48 while (parent[x] != x) {
49 parent[x] = parent[parent[x]];
54 void unite(
long long a,
long long b) { parent[find(a)] = find(b); }
65template <
class Mesh,
class IsSurfaceFace>
68 using Tuple =
typename Mesh::Tuple;
69 constexpr size_t n_faces = Mesh::FACES_PER_CELL;
73 std::vector<simplex::Face> faces;
74 for (
size_t i = 0; i < m.cell_capacity(); ++i) {
75 if (!m.tuple_from_cell(i).is_valid(m)) {
78 for (
size_t j = 0; j < n_faces; ++j) {
79 const Tuple f = m.tuple_from_face(i, j);
80 const size_t fid = f.fid(m);
81 if (fid != n_faces * i + j) {
84 if (!is_surface(fid)) {
87 faces.emplace_back(m.simplex_from_face(f));
91 SurfaceTopoSignature sig;
92 sig.F =
static_cast<long long>(faces.size());
95 std::map<size_t, long long> vidx;
96 auto index_of = [&](
size_t v) ->
long long {
97 auto it = vidx.find(v);
98 if (it != vidx.end()) {
101 const long long id =
static_cast<long long>(vidx.size());
105 std::map<simplex::Edge, int> edge_count;
106 for (
const simplex::Face& f : faces) {
107 const auto& vs = f.vertices();
111 edge_count[simplex::Edge(vs[0], vs[1])]++;
112 edge_count[simplex::Edge(vs[1], vs[2])]++;
113 edge_count[simplex::Edge(vs[0], vs[2])]++;
115 sig.V =
static_cast<long long>(vidx.size());
116 sig.E =
static_cast<long long>(edge_count.size());
117 sig.euler = sig.V - sig.E + sig.F;
123 for (
const simplex::Face& f : faces) {
124 const auto& vs = f.vertices();
125 const long long a = vidx[vs[0]], b = vidx[vs[1]], c = vidx[vs[2]];
129 std::set<long long> roots;
130 for (
long long i = 0; i < sig.V; ++i) {
131 roots.insert(dsu.find(i));
133 sig.components =
static_cast<long long>(roots.size());
142 std::set<long long> bverts;
143 for (
const auto& [e, cnt] : edge_count) {
147 const long long ia = vidx[e.vertices()[0]], ib = vidx[e.vertices()[1]];
152 std::set<long long> broots;
153 for (
long long v : bverts) {
154 broots.insert(bd.find(v));
156 sig.boundary_loops =
static_cast<long long>(broots.size());
166inline void warn_if_surface_topology_changed(
167 const SurfaceTopoSignature& before,
168 const SurfaceTopoSignature& after,
171 if (after == before) {
175 "[surface-swap] surface topology CHANGED in {}: components {}->{}, V {}->{}, "
176 "E {}->{}, F {}->{}, euler {}->{}, boundary_loops {}->{}",
188 before.boundary_loops,
189 after.boundary_loops);
A topological fingerprint of a tracked surface inside a tet mesh.
Definition SurfaceTopology.hpp:23
Definition SurfaceTopology.hpp:37