PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
MeshBoundary.h
Go to the documentation of this file.
1
10
11#ifndef PBAT_GEOMETRY_MESH_BOUNDARY_H
12#define PBAT_GEOMETRY_MESH_BOUNDARY_H
13
14#include "pbat/Aliases.h"
16#include "pbat/common/Hash.h"
18
19#include <algorithm>
20#include <exception>
21#include <fmt/format.h>
22#include <string>
23#include <tuple>
24#include <unordered_map>
25
26namespace pbat {
27namespace geometry {
28
39template <common::CIndex TIndex = Index>
41 Eigen::Ref<Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic> const> const& C,
42 TIndex n)
43 -> std::tuple<
44 Eigen::Vector<TIndex, Eigen::Dynamic>,
45 Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic>>
46{
47 PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.SimplexMeshBoundary");
48 if (n < 0)
49 n = C.maxCoeff() + 1;
50
51 auto nSimplexNodes = C.rows();
52 auto nSimplexFacets = nSimplexNodes;
53 if (nSimplexFacets < 3 or nSimplexFacets > 4)
54 {
55 std::string const what = fmt::format(
56 "SimplexMeshBoundary expected triangle (3x|#elems|) or tetrahedral (4x|#elems|) input "
57 "mesh, but got {}x{}",
58 C.rows(),
59 C.cols());
60 throw std::invalid_argument(what);
61 }
62 auto nFacetNodes = nSimplexNodes - 1;
63 auto nSimplices = C.cols();
64 Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic> F(
65 nFacetNodes,
66 nSimplexFacets * nSimplices);
67 for (TIndex c = 0; c < nSimplices; ++c)
68 {
69 // Tetrahedra
70 if (nSimplexFacets == 4)
71 {
72 auto Fc = F.template block<3, 4>(0, c * 4);
73 Fc.col(0) << C(0, c), C(1, c), C(3, c);
74 Fc.col(1) << C(1, c), C(2, c), C(3, c);
75 Fc.col(2) << C(2, c), C(0, c), C(3, c);
76 Fc.col(3) << C(0, c), C(2, c), C(1, c);
77 }
78 // Triangles
79 if (nSimplexFacets == 3)
80 {
81 auto Fc = F.template block<2, 3>(0, c * 3);
82 Fc.col(0) << C(0, c), C(1, c);
83 Fc.col(1) << C(1, c), C(2, c);
84 Fc.col(2) << C(2, c), C(0, c);
85 }
86 }
87 // Sort face indices to identify duplicates next
88 Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic> FS = F;
89 for (TIndex f = 0; f < FS.cols(); ++f)
90 {
91 std::sort(FS.col(f).begin(), FS.col(f).end());
92 }
93 // Count face occurrences and pick out boundary facets
94 auto fExtractBoundary = [&](auto const& FU) {
95 TIndex nFacets{0};
96 for (auto f = 0; f < FS.cols(); ++f)
97 nFacets += (FU.at(FS.col(f)) == 1);
98 Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic> B(nFacetNodes, nFacets);
99 for (auto f = 0, b = 0; f < F.cols(); ++f)
100 if (FU.at(FS.col(f)) == 1)
101 B.col(b++) = F.col(f);
102 return B;
103 };
104 auto fExtractVertices = [&](Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic> B) {
105 auto begin = B.data();
106 auto end = B.data() + B.size();
107 std::sort(begin, end);
108 auto it = std::unique(begin, end);
109 auto nBoundaryVertices = std::distance(begin, it);
110 Eigen::Vector<TIndex, Eigen::Dynamic> V(nBoundaryVertices);
111 std::copy(begin, it, V.data());
112 return V;
113 };
114 Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic> B{};
115 if (nSimplexFacets == 4)
116 {
117 std::unordered_map<IndexVector<3>, TIndex> FU{};
118 FU.reserve(static_cast<std::size_t>(FS.cols()));
119 for (TIndex f = 0; f < FS.cols(); ++f)
120 ++FU[FS.col(f)];
121 B = fExtractBoundary(FU);
122 }
123 if (nSimplexFacets == 3)
124 {
125 std::unordered_map<IndexVector<2>, TIndex> FU{};
126 FU.reserve(static_cast<std::size_t>(FS.cols()));
127 for (TIndex f = 0; f < FS.cols(); ++f)
128 ++FU[FS.col(f)];
129 B = fExtractBoundary(FU);
130 }
131 Eigen::Vector<TIndex, Eigen::Dynamic> V = fExtractVertices(B);
132 return {V, B};
133}
134
135} // namespace geometry
136} // namespace pbat
137
138#endif // PBAT_GEOMETRY_MESH_BOUNDARY_H
Hash functions for std::pair, std::tuple, and pbat::IndexVector.
Concepts for common types.
Geometric queries, quantities and data structures.
Definition AabbKdTreeHierarchy.h:23
auto SimplexMeshBoundary(Eigen::Ref< Eigen::Matrix< TIndex, Eigen::Dynamic, Eigen::Dynamic > const > const &C, TIndex n) -> std::tuple< Eigen::Vector< TIndex, Eigen::Dynamic >, Eigen::Matrix< TIndex, Eigen::Dynamic, Eigen::Dynamic > >
Obtains the boundary mesh of a simplex mesh.
Definition MeshBoundary.h:40
The main namespace of the library.
Definition Aliases.h:15
Profiling utilities for the Physics-Based Animation Toolkit (PBAT)