41 Eigen::Ref<Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic>
const>
const& C,
44 Eigen::Vector<TIndex, Eigen::Dynamic>,
45 Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic>>
47 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.SimplexMeshBoundary");
51 auto nSimplexNodes = C.rows();
52 auto nSimplexFacets = nSimplexNodes;
53 if (nSimplexFacets < 3 or nSimplexFacets > 4)
55 std::string
const what = fmt::format(
56 "SimplexMeshBoundary expected triangle (3x|#elems|) or tetrahedral (4x|#elems|) input "
57 "mesh, but got {}x{}",
60 throw std::invalid_argument(what);
62 auto nFacetNodes = nSimplexNodes - 1;
63 auto nSimplices = C.cols();
64 Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic> F(
66 nSimplexFacets * nSimplices);
67 for (TIndex c = 0; c < nSimplices; ++c)
70 if (nSimplexFacets == 4)
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);
79 if (nSimplexFacets == 3)
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);
88 Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic> FS = F;
89 for (TIndex f = 0; f < FS.cols(); ++f)
91 std::sort(FS.col(f).begin(), FS.col(f).end());
94 auto fExtractBoundary = [&](
auto const& FU) {
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);
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());
114 Eigen::Matrix<TIndex, Eigen::Dynamic, Eigen::Dynamic> B{};
115 if (nSimplexFacets == 4)
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)
121 B = fExtractBoundary(FU);
123 if (nSimplexFacets == 3)
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)
129 B = fExtractBoundary(FU);
131 Eigen::Vector<TIndex, Eigen::Dynamic> V = fExtractVertices(B);
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