23#ifndef VCL_ALGORITHMS_MESH_FILTER_H
24#define VCL_ALGORITHMS_MESH_FILTER_H
26#include <vclib/mesh/requirements.h>
27#include <vclib/misc/comparators.h>
35template<MeshConcept OutMeshType, u
int ELEM_ID, MeshConcept InMeshType>
36OutMeshType perElementMeshFilter(
38 Range
auto&& elemFilterRng,
39 bool saveBirthIndicesInCustomComponent =
true)
41 using OutElemType = OutMeshType::template ElementType<ELEM_ID>;
43 std::string ccname =
"birth" + elementEnumString<ELEM_ID>();
46 res.enableSameOptionalComponentsOf(m);
49 if constexpr (comp::HasCustomComponents<OutElemType>) {
50 if (saveBirthIndicesInCustomComponent) {
51 res.template addPerElementCustomComponent<ELEM_ID, uint>(ccname);
55 for (
const auto& [birthV, filter] :
56 std::views::zip(m.template elements<ELEM_ID>(), elemFilterRng)) {
58 uint v = res.template add<ELEM_ID>();
60 res.template element<ELEM_ID>(v).importFrom(birthV,
false);
62 if constexpr (comp::HasCustomComponents<OutElemType>) {
63 if (saveBirthIndicesInCustomComponent) {
64 res.template element<ELEM_ID>(v)
65 .template customComponent<uint>(ccname) =
75template<MeshConcept OutMeshType, u
int ELEM_ID, MeshConcept InMeshType>
76OutMeshType perElementMeshFilter(
78 const std::function<
bool(
79 const typename InMeshType::template ElementType<ELEM_ID>&)>& elemFilter,
80 bool saveBirthIndicesInCustomComponent =
true)
83 m.template elements<ELEM_ID>() | std::views::transform(elemFilter);
85 return perElementMeshFilter<OutMeshType, ELEM_ID, InMeshType>(
86 m, view, saveBirthIndicesInCustomComponent);
89template<MeshConcept OutMeshType, u
int ELEM_ID, MeshConcept InMeshType>
90OutMeshType perElementMeshFilterWithVRefs(
92 Range
auto&& elemFilterRng,
93 bool saveBirthIndicesInCustomComponent =
true)
95 using InVertexType = InMeshType::VertexType;
96 using OutElemType = OutMeshType::template ElementType<ELEM_ID>;
98 std::string ccname =
"birth" + elementEnumString<ELEM_ID>();
101 res.enableSameOptionalComponentsOf(m);
104 if constexpr (HasPerVertexCustomComponents<OutMeshType>) {
105 if (saveBirthIndicesInCustomComponent) {
106 res.template addPerVertexCustomComponent<uint>(
"birthVertex");
111 if constexpr (comp::HasCustomComponents<OutElemType>) {
112 if (saveBirthIndicesInCustomComponent) {
113 res.template addPerElementCustomComponent<ELEM_ID, uint>(ccname);
117 std::vector<uint> vertexMapping(m.vertexContainerSize(),
UINT_NULL);
119 for (
const auto& [birthF, filter] :
120 std::views::zip(m.template elements<ELEM_ID>(), elemFilterRng)) {
122 std::vector<uint> verts(birthF.vertexNumber(),
UINT_NULL);
131 for (
const InVertexType* v : birthF.
vertices()) {
133 if (vertexMapping[m.index(v)] ==
UINT_NULL) {
135 uint ov = res.addVertex();
137 res.vertex(ov).importFrom(*v,
false);
138 if constexpr (HasPerVertexCustomComponents<OutMeshType>) {
140 if (saveBirthIndicesInCustomComponent) {
141 res.vertex(ov).template customComponent<uint>(
142 "birthVertex") = m.index(v);
145 vertexMapping[m.index(v)] = ov;
149 verts[vi] = vertexMapping[m.index(v)];
156 uint f = res.template add<ELEM_ID>();
158 res.template element<ELEM_ID>(f).importFrom(birthF,
false);
160 if constexpr (OutElemType::VERTEX_NUMBER < 0) {
161 res.template element<ELEM_ID>(f).resizeVertices(verts.size());
164 res.template element<ELEM_ID>(f).setVertices(verts);
166 if constexpr (comp::HasCustomComponents<OutElemType>) {
168 if (saveBirthIndicesInCustomComponent) {
169 res.template element<ELEM_ID>(f)
170 .template customComponent<uint>(ccname) =
179template<MeshConcept OutMeshType, u
int ELEM_ID, MeshConcept InMeshType>
180OutMeshType perElementMeshFilterWithVRefs(
182 const std::function<
bool(
183 const typename InMeshType::template ElementType<ELEM_ID>&)>& elemFilter,
184 bool saveBirthIndicesInCustomComponent =
true)
187 m.template elements<ELEM_ID>() | std::views::transform(elemFilter);
189 return perElementMeshFilterWithVRefs<OutMeshType, ELEM_ID, InMeshType>(
190 m, view, saveBirthIndicesInCustomComponent);
222template<MeshConcept InMeshType, MeshConcept OutMeshType = InMeshType>
223OutMeshType perVertexMeshFilter(
225 const std::function<
bool(
const typename InMeshType::VertexType&)>&
227 bool saveBirthIndicesInCustomComponent =
true)
230 perElementMeshFilter<OutMeshType, ElemId::VERTEX, InMeshType>(
231 m, vertexFilter, saveBirthIndicesInCustomComponent);
262template<MeshConcept InMeshType, MeshConcept OutMeshType = InMeshType>
263OutMeshType perVertexMeshFilter(
265 Range
auto&& vertexFilterRng,
266 bool saveBirthIndicesInCustomComponent =
true)
269 perElementMeshFilter<OutMeshType, ElemId::VERTEX, InMeshType>(
270 m, vertexFilterRng, saveBirthIndicesInCustomComponent);
298template<MeshConcept InMeshType, MeshConcept OutMeshType = InMeshType>
299OutMeshType perVertexSelectionMeshFilter(
301 bool saveBirthIndicesInCustomComponent =
true)
303 auto selView = m.vertices() | views::selection;
306 perElementMeshFilter<OutMeshType, ElemId::VERTEX, InMeshType>(
307 m, selView, saveBirthIndicesInCustomComponent);
340template<FaceMeshConcept InMeshType, FaceMeshConcept OutMeshType = InMeshType>
341OutMeshType perFaceMeshFilter(
343 const std::function<
bool(
const typename InMeshType::FaceType&)>& faceFilter,
344 bool saveBirthIndicesInCustomComponent =
true)
347 perElementMeshFilterWithVRefs<OutMeshType, ElemId::FACE, InMeshType>(
348 m, faceFilter, saveBirthIndicesInCustomComponent);
381template<FaceMeshConcept InMeshType, FaceMeshConcept OutMeshType = InMeshType>
382OutMeshType perFaceMeshFilter(
384 Range
auto&& faceFilterRng,
385 bool saveBirthIndicesInCustomComponent =
true)
388 perElementMeshFilterWithVRefs<OutMeshType, ElemId::FACE, InMeshType>(
389 m, faceFilterRng, saveBirthIndicesInCustomComponent);
419template<FaceMeshConcept InMeshType, FaceMeshConcept OutMeshType = InMeshType>
420OutMeshType perFaceSelectionMeshFilter(
422 bool saveBirthIndicesInCustomComponent =
true)
424 auto selView = m.faces() | views::selection;
427 perElementMeshFilterWithVRefs<OutMeshType, ElemId::FACE, InMeshType>(
428 m, selView, saveBirthIndicesInCustomComponent);
461template<EdgeMeshConcept InMeshType, EdgeMeshConcept OutMeshType = InMeshType>
462OutMeshType perEdgeMeshFilter(
464 const std::function<
bool(
const typename InMeshType::EdgeType&)>& edgeFilter,
465 bool saveBirthIndicesInCustomComponent =
true)
468 perElementMeshFilterWithVRefs<OutMeshType, ElemId::EDGE, InMeshType>(
469 m, edgeFilter, saveBirthIndicesInCustomComponent);
502template<EdgeMeshConcept InMeshType, EdgeMeshConcept OutMeshType = InMeshType>
503OutMeshType perEdgeMeshFilter(
505 Range
auto&& edgeFilterRng,
506 bool saveBirthIndicesInCustomComponent =
true)
509 perElementMeshFilterWithVRefs<OutMeshType, ElemId::EDGE, InMeshType>(
510 m, edgeFilterRng, saveBirthIndicesInCustomComponent);
540template<EdgeMeshConcept InMeshType, EdgeMeshConcept OutMeshType = InMeshType>
541OutMeshType perEdgeSelectionMeshFilter(
543 bool saveBirthIndicesInCustomComponent =
true)
545 auto selView = m.edges() | views::selection;
548 perElementMeshFilterWithVRefs<OutMeshType, ElemId::EDGE, InMeshType>(
549 m, selView, saveBirthIndicesInCustomComponent);
580template<EdgeMeshConcept OutMeshType, FaceMeshConcept InMeshType>
581OutMeshType perFaceEdgeMeshFilter(
583 const std::function<
bool(
const typename InMeshType::FaceType&, uint)>&
585 bool dontDuplicateEdges =
true,
586 bool saveBirthIndicesInCustomComponent =
true)
588 using InVertexType = InMeshType::VertexType;
589 using OutEdgeType = OutMeshType::EdgeType;
593 res.enableSameOptionalComponentsOf(m);
596 if constexpr (HasPerVertexCustomComponents<OutMeshType>) {
597 if (saveBirthIndicesInCustomComponent) {
598 res.template addPerVertexCustomComponent<uint>(
"birthVertex");
602 std::vector<uint> vertexMapping(m.vertexContainerSize(),
UINT_NULL);
604 std::set<std::pair<uint, uint>, UnorderedPairComparator<uint>>
607 for (
const auto& f : m.
faces()) {
608 for (uint ei = 0; ei < f.vertexNumber(); ++ei) {
609 if (faceEdgeFilter(f, ei)) {
611 for (uint i = 0; i < 2; ++i) {
612 const InVertexType* v = f.vertexMod(ei + i);
613 if (vertexMapping[m.index(v)] ==
UINT_NULL) {
614 uint ov = res.addVertex();
615 res.vertex(ov).importFrom(*v,
false);
616 if constexpr (HasPerVertexCustomComponents<
618 if (saveBirthIndicesInCustomComponent) {
619 res.vertex(ov).template customComponent<uint>(
620 "birthVertex") = m.index(v);
623 vertexMapping[m.index(v)] = ov;
627 verts[i] = vertexMapping[m.index(v)];
631 std::pair<uint, uint> ep {verts[0], verts[1]};
632 if (!dontDuplicateEdges || !unorderedEdges.contains(ep)) {
633 uint e = res.addEdge(verts[0], verts[1]);
634 unorderedEdges.insert(ep);
671template<EdgeMeshConcept OutMeshType, FaceMeshConcept InMeshType>
672OutMeshType perFaceEdgeMeshFilter(
674 const std::function<
bool(uint, uint)>& faceEdgeFilter,
675 bool dontDuplicateEdges =
true,
676 bool saveBirthIndicesInCustomComponent =
true)
678 auto filter = [&](
const typename InMeshType::FaceType& f, uint ei) {
679 return faceEdgeFilter(m.index(f), ei);
682 return perFaceEdgeMeshFilter<OutMeshType, InMeshType>(
683 m, filter, dontDuplicateEdges, saveBirthIndicesInCustomComponent);
710template<EdgeMeshConcept OutMeshType, FaceMeshConcept InMeshType>
711OutMeshType perFaceEdgeSelectionMeshFilter(
713 bool dontDuplicateEdges =
true,
714 bool saveBirthIndicesInCustomComponent =
true)
716 auto filter = [&](
const typename InMeshType::FaceType& f, uint ei) {
717 return f.edgeSelected(ei);
720 return perFaceEdgeMeshFilter<OutMeshType, InMeshType>(
721 m, filter, dontDuplicateEdges, saveBirthIndicesInCustomComponent);
constexpr uint UINT_NULL
The UINT_NULL value represent a null value of uint that is the maximum value that can be represented ...
Definition base.h:48
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:52
constexpr detail::VerticesView vertices
A view that allows to iterate over the Vertex elements of an object.
Definition vertex.h:60