Visual Computing Library  devel
Loading...
Searching...
No Matches
mesh.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_MESH_MESH_H
24#define VCL_MESH_MESH_H
25
26#include "mesh_components.h"
27#include "mesh_containers.h"
28
29#include <vclib/algorithms/core.h>
30
31namespace vcl {
32
66template<typename... Args>
67class Mesh : public Args...
68{
69 static_assert(HasVertices<Args...>, "A Mesh must have a VertexContainer.");
70
71 template<typename El, bool b>
72 friend struct comp::detail::CustomComponentsData;
73
74 template<typename El, bool b>
75 friend struct comp::detail::ComponentData;
76
77 template<ElementConcept T>
78 friend class mesh::ElementContainer;
79
80 template<uint ELEM_ID, typename MeshType, comp::ComponentConcept... Comps>
81 friend class Element;
82
83 // Predicate structures
84
85 template<uint ELEM_ID>
87 public mesh::ContainerOfElement<ELEM_ID, Mesh<Args...>>
88 {
89 };
90
101 template<ElementConcept El>
102 struct ContainerOf : public ContainerOfElement<El::ELEMENT_ID>
103 {
104 };
105
106public:
114 TypeWrapper<Args...>>::type;
115
122 FilterTypesByCondition<comp::IsComponentPred, TypeWrapper<Args...>>::
123 type;
124
136 template<uint ELEM_ID>
138
150 template<uint ELEM_ID>
152
153 /* Constexpr static member functions */
154
179 template<ElementConcept El>
180 static constexpr bool hasContainerOf()
181 {
182 return mesh::HasContainerOfPred<El, Mesh<Args...>>::value;
183 }
184
202 template<uint ELEM_ID>
203 static constexpr bool hasContainerOf()
204 {
205 return mesh::HasContainerOfElementPred<ELEM_ID, Mesh<Args...>>::value;
206 }
207
226 template<uint ELEM_ID, uint COMP_ID>
227 static constexpr bool hasPerElementComponent()
228 {
229 return mesh::HasPerElementComponent<Mesh<Args...>, ELEM_ID, COMP_ID>;
230 }
231
251 template<uint ELEM_ID, uint COMP_ID>
252 static constexpr bool hasPerElementOptionalComponent()
253 {
254 return mesh::
255 HasPerElementOptionalComponent<Mesh<Args...>, ELEM_ID, COMP_ID>;
256 }
257
258 /* Constructors */
259
264 {
265 // Set to all element containers their parent mesh (this)
266 updateAllParentMeshPointers();
267 }
268
276 Mesh(const Mesh& oth) :
277 Args(oth)... // call auto copy constructors for all the container
278 // elements and components
279 {
280 // Set to all element containers their parent mesh (this)
281 updateAllParentMeshPointers();
282
283 // for each container of oth, save its base pointer
284 // will need it to update all the pointers of this mesh
285 constexpr uint N_CONTAINERS =
286 NumberOfTypes<typename Mesh<Args...>::Containers>::value;
287 std::array<const void*, N_CONTAINERS> othBases =
289
290 // update all the pointers contained on each container
291 // use the base pointer of each container of oth to update all the
292 // pointers in this mesh. Each pointer of oth that was copied in this
293 // mesh, will be updated computing its offset wrt the base of oth, and
294 // then adding that offset to the new base pointer of this mesh
296 }
297
305 {
306 swap(oth); // use copy and swap idiom: this (empty) mesh is swapped with
307 // the input one
308 }
309
310 /* Member functions */
311
318 bool isCompact() const
319 {
320 bool isCompact = true;
322 return isCompact;
323 }
324
329 void clear() { (clearContainer<Args>(), ...); }
330
337 void compact() { (compactContainer<Args>(), ...); }
338
347
356
386 template<typename OtherMeshType>
388 {
389 // enable all optional components of this Mesh depending on what's
390 // available in the OtherMeshType
391
393 }
394
408 void append(const Mesh& m)
409 {
410 // for each container of this mesh, save its size
411 // will need it to update all the pointers/indices of this mesh
412 constexpr uint N_CONTAINERS =
413 NumberOfTypes<typename Mesh<Args...>::Containers>::value;
414 std::array<std::size_t, N_CONTAINERS> sizes =
416
417 // for each container of the other mesh m, save its bases
418 // will need it to update all the pointers of this mesh
419 std::array<const void*, N_CONTAINERS> bases =
421
422 // call the append function for each container
423 (appendContainer<Args>(m), ...);
424
425 // update all the pointers/indices contained on each container
427 ...);
428
429 // manage transform matrix
430 if constexpr (mesh::HasTransformMatrix<Mesh<Args...>>) {
431 using Matrixtype = typename Mesh<Args...>::TransformMatrixType;
432
433 Matrixtype matrix = this->transformMatrix();
434 matrix = matrix.inverse().eval();
435 matrix *= m.transformMatrix();
436
437 if (matrix != Matrixtype::Identity()) {
439 *this, sizes, matrix),
440 ...);
441 }
442 }
443
444 if constexpr (mesh::HasMaterials<Mesh<Args...>>) {
445 uint nMaterials = this->materialsNumber();
446
447 // mapping from material indices of m to material indices of this
448 std::vector<uint> mapping(m.materialsNumber());
449
450 // for each material of the other mesh, add it to this mesh
451 // if it does not exist yet
452 for (uint i = 0; i < m.materialsNumber(); ++i) {
453 auto it = std::find(
454 this->materialBegin(), this->materialEnd(), m.material(i));
455
456 if (it == this->materialEnd()) {
457 this->pushMaterial(m.material(i));
458 mapping[i] = nMaterials++;
459 }
460 else {
461 mapping[i] = std::distance(this->materialBegin(), it);
462 }
463 }
464
465 // update all the material indices in this mesh and add the texture
466 // images
467 if (nMaterials > 0 || mapping.size() > 0) {
468 for (const auto& p : m.textureImages()) {
469 this->pushTextureImage(p.first, p.second);
470 }
471
473 *this, sizes, mapping),
474 ...);
475 }
476 }
477 }
478
493 template<typename OtherMeshType>
495 {
496 // This function will first:
497 // Call, for each Container and Component of the mesh, its importFrom
498 // function. In case of containers, it first creates the same number of
499 // elements in the container, and then calls the importFrom function for
500 // each new element.
501
502 (Args::importFrom(m), ...);
503
504 // Set to all element containers their parent mesh (this)
505 updateAllParentMeshPointers();
506
507 if constexpr (mesh::HasFaceContainer<Mesh<Args...>>) {
508 // Now I need to manage imports between different types of meshes
509 // (same type of meshes are already managed from importFrom member
510 // function).
511 //
512 // Generally speaking, Polygon meshes can import from any other type
513 // of mesh. We need to take care when this mesh has static vertex
514 // references number in the face container (VERTEX_NUMBER >= 3).
515 //
516 // The follwing case don't need to be managed:
517 // - import polygon mesh from triangle mesh
518 //
519 // I can manage the following cases:
520 // - import triangle mesh from polygon mesh: need triangulation
521 //
522 // I cannot manage the follwing cases:
523 // - import static non-triangle mesh from polygon mesh or from a
524 // mesh with different VERTEX_NUMBER
525
526 // in case of import from poly to triangle mesh, I need to manage
527 // triangulation of polygons and create additional triangle faces
528 // for each of the imported polygons. This function statically
529 // asserts that the import can be done.
531 using FaceContainer = typename Mesh<Args...>::FaceContainer;
532 FaceContainer::manageImportTriFromPoly(m);
533 }
534 }
535 }
536
541 void swap(Mesh& m2)
542 {
543 Mesh<Args...>& m1 = *this;
544
545 constexpr uint N_CONTAINERS =
546 NumberOfTypes<typename Mesh<Args...>::Containers>::value;
547 static_assert(N_CONTAINERS != 0);
548
549 // container bases of each container for m1 and m2
550 // we save the bases of the containers before swap
551 std::array<const void*, N_CONTAINERS> m1Bases =
553 std::array<const void*, N_CONTAINERS> m2Bases =
555
556 // actual swap of all the containers and the components of the mesh
557 // using pack expansion: swap will be called for each of the containers
558 // (or components!) that compose the Mesh
559 using std::swap;
560 (swap((Args&) m1, (Args&) m2), ...);
561
562 // Set to all elements their parent mesh
563 m1.updateAllParentMeshPointers();
564 m2.updateAllParentMeshPointers();
565
566 // update all the refs to m1 and m2: old base of m1 is now "old
567 // base" of m2, and viceversa
570 }
571
580 friend void swap(Mesh& a, Mesh& b) { a.swap(b); }
581
589 {
590 swap(oth);
591 return *this;
592 }
593
594 /*** Generic Element functions ***/
595
607 template<ElementConcept El>
608 uint index(const El& e) const requires (hasContainerOf<El>())
609 {
610 using Container = ContainerOf<El>::type;
611 return Container::index(&e);
612 }
613
625 template<ElementConcept El>
626 uint index(const El* e) const requires (hasContainerOf<El>())
627 {
628 using Container = ContainerOf<El>::type;
629 return Container::index(e);
630 }
631
646 template<uint ELEM_ID>
647 const auto& element(uint i) const requires (hasContainerOf<ELEM_ID>())
648 {
650
651 return Cont::element(i);
652 }
653
668 template<uint ELEM_ID>
670 {
672
673 return Cont::element(i);
674 }
675
685 template<uint ELEM_ID>
687 {
689
690 return Cont::elementNumber();
691 }
692
707 template<uint ELEM_ID>
709 {
711
712 return Cont::elementContainerSize();
713 }
714
725 template<uint ELEM_ID>
727 {
729
730 return Cont::deletedElementNumber();
731 }
732
747 template<uint ELEM_ID>
749 {
751
752 return Cont::addElement();
753 }
754
770 template<uint ELEM_ID>
772 {
774
775 return Cont::addElements(n); // add the number elements
776 }
777
798 template<uint ELEM_ID>
800 {
802
803 Cont::clearElements();
804 }
805
839 template<uint ELEM_ID>
841 {
843
844 Cont::resizeElements(n);
845 }
846
867 template<uint ELEM_ID>
869 {
871
872 Cont::reserveElements(n);
873 }
874
881 template<uint ELEM_ID>
883 {
885
886 Cont::compactElements();
887 }
888
906 template<uint ELEM_ID>
908 {
910
911 Cont::deleteElement(i);
912 }
913
931 template<ElementConcept El>
932 void deleteElement(const El* e) const requires (hasContainerOf<El>())
933 {
935 return Cont::deleteElement(e);
936 }
937
955 template<ElementConcept El>
956 void deleteElement(const El& e) const requires (hasContainerOf<El>())
957 {
959 return Cont::deleteElement(&e);
960 }
961
979 template<uint ELEM_ID>
980 std::vector<uint> compactIndices() const
981 requires (hasContainerOf<ELEM_ID>())
982 {
984
985 return Cont::elementCompactIndices();
986 }
987
1014 template<uint ELEM_ID>
1015 void updateIndices(const std::vector<uint>& newIndices)
1016 requires (hasContainerOf<ELEM_ID>())
1017 {
1019
1020 return Cont::updateElementIndices(newIndices);
1021 }
1022
1023 void serialize(std::ostream& os) const
1024 {
1025 (preSerialization<Args>(os), ...);
1026
1028 }
1029
1030 void deserialize(std::istream& is)
1031 {
1032 (preDeserialization<Args>(is), ...);
1033
1034 (postDeserialization<Args>(is), ...);
1035 }
1036
1054 template<uint ELEM_ID>
1055 auto begin(bool jumpDeleted = true) requires (hasContainerOf<ELEM_ID>())
1056 {
1058
1059 return Cont::elementBegin(jumpDeleted);
1060 }
1061
1073 template<uint ELEM_ID>
1074 auto end() requires (hasContainerOf<ELEM_ID>())
1075 {
1077
1078 return Cont::elementEnd();
1079 }
1080
1098 template<uint ELEM_ID>
1099 auto begin(bool jumpDeleted = true) const
1100 requires (hasContainerOf<ELEM_ID>())
1101 {
1103
1104 return Cont::elementBegin(jumpDeleted);
1105 }
1106
1118 template<uint ELEM_ID>
1119 auto end() const requires (hasContainerOf<ELEM_ID>())
1120 {
1122
1123 return Cont::elementEnd();
1124 }
1125
1148 template<uint ELEM_ID>
1149 auto elements(bool jumpDeleted = true) requires (hasContainerOf<ELEM_ID>())
1150 {
1152
1153 return Cont::elements(jumpDeleted);
1154 }
1155
1185 template<uint ELEM_ID>
1187 requires (hasContainerOf<ELEM_ID>())
1188 {
1190
1191 return Cont::elements(begin, end);
1192 }
1193
1216 template<uint ELEM_ID>
1217 auto elements(bool jumpDeleted = true) const
1218 requires (hasContainerOf<ELEM_ID>())
1219 {
1221
1222 return Cont::elements(jumpDeleted);
1223 }
1224
1254 template<uint ELEM_ID>
1256 requires (hasContainerOf<ELEM_ID>())
1257 {
1259
1260 return Cont::elements(begin, end);
1261 }
1262
1276 template<uint ELEM_ID, uint COMP_ID>
1284
1296 template<uint ELEM_ID, uint COMP_ID>
1304
1316 template<uint ELEM_ID, uint COMP_ID>
1324
1341 template<uint ELEM_ID>
1342 bool hasPerElementCustomComponent(const std::string& name) const
1344 {
1346
1347 return Cont::hasElemCustomComponent(name);
1348 }
1349
1362 template<uint ELEM_ID>
1363 std::vector<std::string> perElementCustomComponentNames() const
1364 requires (hasPerElementComponent<ELEM_ID, CompId::CUSTOM_COMPONENTS>())
1365 {
1367
1368 return Cont::elemCustomComponentNames();
1369 }
1370
1385 template<uint ELEM_ID, typename K>
1386 bool isPerElementCustomComponentOfType(const std::string& name) const
1388 {
1390
1391 return Cont::template isElemCustomComponentOfType<K>(name);
1392 }
1393
1407 template<uint ELEM_ID>
1408 std::type_index perElementCustomComponentType(const std::string& name) const
1410 {
1412
1413 return Cont::elemCustomComponentType(name);
1414 }
1415
1429 template<uint ELEM_ID, typename K>
1431 requires (hasPerElementComponent<ELEM_ID, CompId::CUSTOM_COMPONENTS>())
1432 {
1434
1435 return Cont::template elemCustomComponentNamesOfType<K>();
1436 }
1437
1450 template<uint ELEM_ID, typename K>
1451 void addPerElementCustomComponent(const std::string& name)
1453 {
1455
1456 Cont::template addElemCustomComponent<K>(name);
1457 }
1458
1470 template<uint ELEM_ID>
1471 void deletePerElementCustomComponent(const std::string& name)
1473 {
1475
1476 Cont::deleteElemCustomComponent(name);
1477 }
1478
1520 template<uint ELEM_ID, typename K>
1529
1571 template<uint ELEM_ID, typename K>
1580
1606 template<uint ELEM_ID, typename K>
1608 {
1610
1612 }
1613
1626 template<uint ELEM_ID, typename K>
1633
1634protected:
1635 template<typename Cont>
1636 bool isContainerCompact() const
1637 {
1638 if constexpr (mesh::ElementContainerConcept<Cont>) {
1639 return Cont::elementNumber() == Cont::elementContainerSize();
1640 }
1641 else {
1642 return true; // does not count as a container
1643 }
1644 }
1645
1655 template<typename Cont>
1657 {
1658 if constexpr (mesh::ElementContainerConcept<Cont>) {
1659 if (Cont::elementNumber() != Cont::elementContainerSize()) {
1660 Cont::compactElements();
1661 }
1662 }
1663 }
1664
1674 template<typename Cont>
1676 {
1677 if constexpr (mesh::ElementContainerConcept<Cont>) {
1678 Cont::enableAllOptionalComponents();
1679 }
1680 }
1681
1691 template<typename Cont>
1693 {
1694 if constexpr (mesh::ElementContainerConcept<Cont>) {
1695 Cont::disableAllOptionalComponents();
1696 }
1697 }
1698
1708 template<typename Cont>
1710 {
1711 if constexpr (mesh::ElementContainerConcept<Cont>) {
1712 Cont::clearElements();
1713 }
1714 }
1715
1716 template<ElementConcept Element>
1717 void updateAllReferences(const Element* oldBase)
1718 {
1719 if (oldBase != nullptr)
1721 }
1722
1723 // this function is required in order to get msvc compile
1724 template<typename Element, typename... A>
1725 void updateReferences(const Element* oldBase, TypeWrapper<A...>)
1726 {
1727 updateReferences(
1728 oldBase, TypeWrapper<A...>(), std::array<std::size_t, 0>(), 0);
1729 }
1730
1731 // this function is required in order to get msvc compile
1732 template<typename Cont, typename Element>
1733 void updateReferences(const Element* oldBase)
1734 {
1735 updateReferences<Cont>(oldBase, std::array<std::size_t, 0>(), 0);
1736 }
1737
1738 // this additional function is necessary because otherwise msvc jumps
1739 // totally the pack expansion if called directly in the function
1740 // updateReferencesOfContainerTypeAfterAppend
1741 template<typename Element, std::size_t N, typename... A>
1742 void updateReferences(
1743 const Element* oldBase,
1744 TypeWrapper<A...>,
1745 const std::array<std::size_t, N>& sizes = std::array<std::size_t, 0>(),
1746 uint offset = 0)
1747 {
1748 (updateReferences<A>(oldBase, sizes, offset), ...);
1749 }
1750
1751 template<typename Cont, typename Element, std::size_t N>
1752 void updateReferences(
1753 const Element* oldBase,
1754 const std::array<std::size_t, N>& sizes = std::array<std::size_t, 0>(),
1755 uint offset = 0)
1756 {
1757 if constexpr (mesh::ElementContainerConcept<Cont>) {
1758 if constexpr (N > 0) {
1759 using Containers = Mesh<Args...>::Containers;
1760 constexpr uint I = IndexInTypes<Cont, Containers>::value;
1761 static_assert(I >= 0 && I != UINT_NULL);
1762 Cont::updateReferences(oldBase, sizes[I], offset);
1763 }
1764 else {
1765 Cont::updateReferences(oldBase);
1766 }
1767 }
1768 }
1769
1770 template<ElementConcept Element>
1771 void updateAllReferences(const std::vector<uint>& newIndices)
1772 {
1773 (updateReferences<Args, Element>(newIndices), ...);
1774 }
1775
1776 template<typename Cont, typename Element>
1777 void updateReferences(const std::vector<uint>& newIndices)
1778 {
1779 if constexpr (mesh::ElementContainerConcept<Cont>) {
1780 Cont::template updateReferences<Element>(newIndices);
1781 }
1782 }
1783
1784private:
1785 // hide init and isAvailable members
1786 void init() {};
1787
1788 bool isAvailable() const { return true; }
1789
1790 // enable optional components
1791
1792 template<typename Cont, typename OtherMeshType>
1793 void enableSameOptionalComponentsOf(const OtherMeshType& m)
1794 {
1795 if constexpr (mesh::ElementContainerConcept<Cont>) {
1796 Cont::enableOptionalComponentsOf(m);
1797 }
1798 }
1799
1800 // private parent mesh pointers functions
1801
1802 void updateAllParentMeshPointers() { (setParentMeshPointers<Args>(), ...); }
1803
1804 template<typename Cont>
1805 void setParentMeshPointers()
1806 {
1807 if constexpr (mesh::ElementContainerConcept<Cont>) {
1808 Cont::setParentMeshPointers(this);
1809 }
1810 }
1811
1812 template<typename Cont>
1813 void appendContainer(const Mesh& m)
1814 {
1815 if constexpr (mesh::ElementContainerConcept<Cont>) {
1816 Cont::append((const Cont&) m);
1817 }
1818 }
1819
1820 // private copy and swap member functions
1821
1829 template<uint I, typename Cont, typename Array, typename... A>
1831 {
1832 // since this function is called using pack expansion, it means that
1833 // Cont could be a mesh component and not a cointainer. We check if Cont
1834 // is a container
1835 if constexpr (mesh::ElementContainerConcept<Cont>) {
1836 static_assert(I >= 0 && I != UINT_NULL);
1837 bases[I] = m.Cont::mElemVec.data();
1838 }
1839 }
1840
1841 template<typename... A>
1842 static auto getContainerBases(const Mesh<A...>& m)
1843 {
1844 using Containers = Mesh<A...>::Containers;
1845
1846 // the number of containers in Mesh<A...>
1848 // each element of this array will contain the base pointer of the
1849 // vector of elements contained in each container of Mesh<A...>
1850 std::array<const void*, N_CONTAINERS> bases;
1851
1852 // for each container/component of Mesh<A...>, we call the function
1853 // that sets the base of the container in its index
1855 ...);
1856
1857 return bases;
1858 }
1859
1867 template<uint I, typename Cont, typename Array, typename... A>
1869 {
1870 // since this function is called using pack expansion, it means that
1871 // Cont could be a mesh component and not a cointainer. We check if Cont
1872 // is a container
1873 if constexpr (mesh::ElementContainerConcept<Cont>) {
1874 static_assert(I >= 0 && I != UINT_NULL);
1875 sizes[I] = m.Cont::mElemVec.size();
1876 }
1877 }
1878
1879 template<typename... A>
1880 static auto getContainerSizes(const Mesh<A...>& m)
1881 {
1882 using Containers = Mesh<A...>::Containers;
1883
1884 // the number of containers in Mesh<A...>
1886 // each element of this array will contain the size of the
1887 // vector of elements contained in each container of Mesh<A...>
1888 std::array<std::size_t, N_CONTAINERS> sizes;
1889
1890 // for each container/component of Mesh<A...>, we set call the function
1891 // that sets the size of the container in its index
1893 ...);
1894
1895 return sizes;
1896 }
1897
1922 template<typename Cont, typename Array, typename... A>
1924 Mesh<A...>& m,
1925 const Array& bases)
1926 {
1927 // since this function is called using pack expansion, it means that
1928 // Cont could be a mesh component and not a cointainer. We check if Cont
1929 // is a container
1930 if constexpr (mesh::ElementContainerConcept<Cont>) {
1931 // The element type contained in the container
1932 // We need it to get back the actual type of the element from the
1933 // old bases
1934 using ElType = Cont::ElementType;
1935
1936 using Containers = Mesh<A...>::Containers;
1938 static_assert(I >= 0 && I != UINT_NULL);
1939
1940 using ContainerWrapper = TypeWrapper<A...>;
1941
1942 // for each Container A in m, we update the references of ElType.
1943 // old base is contained in the array bases, the new base is the
1944 // base of the container
1945 m.updateReferences(
1946 reinterpret_cast<const ElType*>(bases[I]), ContainerWrapper());
1947 }
1948 }
1949
1950 template<typename Cont, typename ArrayB, typename ArrayS, typename... A>
1951 static void updateReferencesOfContainerTypeAfterAppend(
1952 Mesh<A...>& m,
1953 const ArrayB& bases,
1954 const ArrayS& sizes)
1955 {
1956 // since this function is called using pack expansion, it means that
1957 // Cont could be a mesh component and not a cointainer. We check if Cont
1958 // is a container
1959 if constexpr (mesh::ElementContainerConcept<Cont>) {
1960 // The element type contained in the container
1961 // We need it to get back the actual type of the element from the
1962 // old bases
1963 using ElType = Cont::ElementType;
1964
1965 using Containers = Mesh<A...>::Containers;
1966 constexpr uint I = IndexInTypes<Cont, Containers>::value;
1967 static_assert(I >= 0 && I != UINT_NULL);
1968
1969 using ContainerWrapper = TypeWrapper<A...>;
1970
1971 // for each Container A in m, we update the references of ElType.
1972 // old base is contained in the array bases
1973 m.updateReferences(
1974 reinterpret_cast<const ElType*>(bases[I]),
1976 sizes,
1977 sizes[I]);
1978 }
1979 }
1980
1981 // swap two elements
1982 template<typename ElementType>
1983 void swapVerticalComponents(ElementType& e1, ElementType& e2)
1984 {
1985 using Cont = ContainerOf<ElementType>::type;
1986
1987 Cont::swapVerticalComponents(e1.index(), e2.index());
1988 }
1989
1990 // private append functions
1991
1992 template<
1993 typename Cont,
1994 typename ArrayS,
1995 Matrix44Concept MatrixType,
1996 typename... A>
1997 static void updatePosAndNormalsOfContainerTypeAfterAppend(
1998 Mesh<A...>& m,
1999 const ArrayS& sizes,
2000 const MatrixType& matrix)
2001 {
2002 // since this function is called using pack expansion, it means that
2003 // Cont could be a mesh component and not a cointainer. We check if Cont
2004 // is a container
2005 if constexpr (mesh::ElementContainerConcept<Cont>) {
2006 // The element type contained in the container
2007 // We need it to get back the actual type of the element from the
2008 // old bases
2009 using ElType = Cont::ElementType;
2010 static constexpr uint ELEM_ID = ElType::ELEMENT_ID;
2011
2012 using Containers = Mesh<A...>::Containers;
2013 constexpr uint I = IndexInTypes<Cont, Containers>::value;
2014 static_assert(I >= 0 && I != UINT_NULL);
2015
2016 if constexpr (hasPerElementComponent<ELEM_ID, CompId::POSITION>()) {
2017 auto posview = m.template elements<ELEM_ID>((uint) sizes[I]) |
2018 vcl::views::positions;
2019
2020 multiplyPointsByMatrix(posview, matrix);
2021 }
2022
2023 if constexpr (hasPerElementComponent<ELEM_ID, CompId::NORMAL>()) {
2024 if (m.Cont::template isComponentAvailable<CompId::NORMAL>()) {
2025 auto norview =
2026 m.template elements<ELEM_ID>((uint) sizes[I]) |
2027 vcl::views::normals;
2028
2029 multiplyNormalsByMatrix(norview, matrix);
2030 }
2031 }
2032 }
2033 }
2034
2035 template<typename Cont, typename ArrayS, typename... A>
2036 static void updateMaterialIndicesOfContainerTypeAfterAppend(
2037 Mesh<A...>& m,
2038 const ArrayS& sizes,
2039 const std::vector<uint>& mapping)
2040 {
2041 // since this function is called using pack expansion, it means that
2042 // Cont could be a mesh component and not a cointainer. We check if Cont
2043 // is a container
2044 if constexpr (mesh::ElementContainerConcept<Cont>) {
2045 // The element type contained in the container
2046 // We need it to get back the actual type of the element from the
2047 // old bases
2048 using ElType = Cont::ElementType;
2049 static constexpr uint ELEM_ID = ElType::ELEMENT_ID;
2050
2051 using Containers = Mesh<A...>::Containers;
2052 constexpr uint I = IndexInTypes<Cont, Containers>::value;
2053 static_assert(I >= 0 && I != UINT_NULL);
2054
2055 if constexpr (hasPerElementComponent<
2056 ELEM_ID,
2057 CompId::MATERIAL_INDEX>()) {
2058 if (m.Cont::template isComponentAvailable<
2059 CompId::MATERIAL_INDEX>()) {
2060 auto elems = m.template elements<ELEM_ID>((uint) sizes[I]);
2061 for (auto& e : elems) {
2062 e.materialIndex() = mapping[e.materialIndex()];
2063 }
2064 }
2065 }
2066 }
2067 }
2068
2069 // serialization/deserialization
2070
2071 template<typename Cont>
2072 void preSerialization(std::ostream& os) const
2073 {
2074 if constexpr (mesh::ElementContainerConcept<Cont>) {
2075 Cont::serializeOptionalComponentsAndElementsNumber(os);
2076 }
2077 }
2078
2079 template<typename Cont>
2080 void postSerialization(std::ostream& os) const
2081 {
2082 if constexpr (mesh::ElementContainerConcept<Cont>) {
2083 Cont::serializeElements(os);
2084 }
2085 else {
2086 // cont is a component...
2087 Cont::serialize(os);
2088 }
2089 }
2090
2091 template<typename Cont>
2092 void preDeserialization(std::istream& is)
2093 {
2094 if constexpr (mesh::ElementContainerConcept<Cont>) {
2095 Cont::deserializeOptionalComponentsAndElementsNumber(is);
2096 }
2097 }
2098
2099 template<typename Cont>
2100 void postDeserialization(std::istream& is)
2101 {
2102 if constexpr (mesh::ElementContainerConcept<Cont>) {
2103 Cont::deserializeElements(is);
2104 }
2105 else {
2106 // cont is a component...
2107 Cont::deserialize(is);
2108 }
2109 }
2110
2111 // member functions used by friends
2112
2113 template<uint ELEM_ID, typename T>
2114 uint elementIndex(const T* el) const
2115 {
2116 using Cont = ContainerOfElement<ELEM_ID>::type;
2117 using ElType = Cont::ElementType;
2118 return index(static_cast<const ElType*>(el));
2119 }
2120
2121 template<typename El>
2122 auto& customComponents()
2123 {
2124 using ElCont = ContainerOf<El>::type;
2125
2126 return ElCont::mCustomCompVecMap;
2127 }
2128
2129 template<typename El>
2130 const auto& customComponents() const
2131 {
2132 using ElCont = ContainerOf<El>::type;
2133
2134 return ElCont::mCustomCompVecMap;
2135 }
2136
2137 template<typename El>
2138 auto& verticalComponents()
2139 {
2140 using ElCont = ContainerOf<El>::type;
2141
2142 return ElCont::mVerticalCompVecTuple;
2143 }
2144
2145 template<typename El>
2146 const auto& verticalComponents() const
2147 {
2148 using ElCont = ContainerOf<El>::type;
2149
2150 return ElCont::mVerticalCompVecTuple;
2151 }
2152};
2153
2154/* Concepts */
2155
2168template<typename T>
2170 IsDerivedFromSpecializationOfV<T, Mesh> && mesh::HasVertexContainer<T>;
2171
2181template<typename T>
2183
2184} // namespace vcl
2185
2186#endif // VCL_MESH_MESH_H
The Array class is a dynamically allocated N-dimensional array stored in RowWise mode.
Definition array.h:60
A class representing a box in N-dimensional space.
Definition box.h:46
PointT size() const
Computes the size of the box.
Definition box.h:267
The Element class.
Definition element.h:75
The Mesh class represents a generic 3D mesh. A mesh is composed of a generic number of containers of ...
Definition mesh.h:68
bool isCompact() const
Returns true if this mesh is compact, meaning that all its containers have no deleted elements (size ...
Definition mesh.h:318
auto elements(bool jumpDeleted=true) const
Definition mesh.h:1217
uint deletedNumber() const
Returns the number of deleted elements of the given type in this mesh.
Definition mesh.h:726
void deleteElement(uint i)
Marks as deleted the element at the given index from its container, deduced from the template index E...
Definition mesh.h:907
void deleteElement(const El &e) const
Marks as deleted the given element from its container.
Definition mesh.h:956
Mesh()
Empty constructor, constructs an empty mesh.
Definition mesh.h:263
Mesh(const Mesh &oth)
Copy constructor of the Mesh. Will create a deep copy of the given input mesh, taking care of copying...
Definition mesh.h:276
auto begin(bool jumpDeleted=true)
Returns an iterator to the begining of the container of the elements having ID ELEM_ID in the mesh.
Definition mesh.h:1055
CustomComponentVectorHandle< K > perElementCustomComponentVectorHandle(const std::string &name)
Returns a vector handle to the custom component of type K having the given name associated to the Ele...
Definition mesh.h:1521
std::type_index perElementCustomComponentType(const std::string &name) const
Returns the std::type_index of the custom component having the given name associated to the Element h...
Definition mesh.h:1408
void compactContainer()
Definition mesh.h:1656
auto elements(bool jumpDeleted=true)
Definition mesh.h:1149
void compactElements()
Compacts the Container of the given element, removing all the elements marked as deleted....
Definition mesh.h:882
void enableSameOptionalComponentsOf(const OtherMeshType &m)
Enables all the OptionalComponents of this mesh according to the Components available on the OtherMes...
Definition mesh.h:387
Mesh(Mesh &&oth)
Move constructor, moves the given mesh into this one, without any other resource acquisition.
Definition mesh.h:304
bool hasPerElementCustomComponent(const std::string &name) const
Returns true if the Element having ID ELEM_ID has a custom component with the given name.
Definition mesh.h:1342
std::vector< uint > compactIndices() const
Returns a vector that tells, for each element of the container of ELEM_ID in the mesh,...
Definition mesh.h:980
void deserializePerElementCustomComponentsOfType(std::istream &is)
Deserializes the custom components of type K of the element with ID ELEM_ID.
Definition mesh.h:1627
void deleteElement(const El *e) const
Marks as deleted the given element from its container.
Definition mesh.h:932
void disableAllOptionalComponents()
Disables all the optional components of the elements of the containers if the mesh.
Definition mesh.h:352
void addPerElementCustomComponent(const std::string &name)
Adds a custom component of type K having the given name to the Element having ID ELEM_ID.
Definition mesh.h:1451
void append(const Mesh &m)
Appends all the elements contained in the mesh m to this mesh.
Definition mesh.h:408
auto end()
Returns an iterator to the end of the container of the elements having ID ELEM_ID in the mesh.
Definition mesh.h:1074
void enableAllOptionalComponentsInContainer()
Definition mesh.h:1675
bool isPerElementCustomComponentOfType(const std::string &name) const
Returns true if the Element having ID ELEM_ID has a custom component of type K with the given name.
Definition mesh.h:1386
uint add()
Adds a new element of the given type into its container, returning the index of the added element in ...
Definition mesh.h:748
void clear()
Clears all the Elements contained in the mesh.
Definition mesh.h:329
uint add(uint n)
Adds n new elements of the given type into its container, returning the index of the first added elem...
Definition mesh.h:771
void swap(Mesh &m2)
Swaps this mesh with the other input Mesh m2.
Definition mesh.h:541
uint containerSize() const
Returns the size of the container of elements of the given type in this mesh.
Definition mesh.h:708
void clearElements()
Clears the container of ELEM_ID elements the Mesh, deleting all the Elements.
Definition mesh.h:799
void importFrom(const OtherMeshType &m)
Imports all the components that can be imported from another type of mesh.
Definition mesh.h:494
bool isPerElementComponentEnabled() const
Returns true if optional Component having ID COMP_ID is enabled for elements having ID ELEM_ID in the...
Definition mesh.h:1277
const auto & element(uint i) const
Returns the element of the given type at the given index inside its container of this mesh.
Definition mesh.h:647
auto elements(uint begin, uint end=UINT_NULL) const
Returns a lightweight const view object that stores the begin and end const iterators of the containe...
Definition mesh.h:1255
void compact()
Compacts all the containers of the mesh.
Definition mesh.h:337
void updateIndices(const std::vector< uint > &newIndices)
Updates all the indices and pointers of the elements of the container of ELEM_ID in the mesh,...
Definition mesh.h:1015
Mesh & operator=(Mesh oth)
Assignment operator of the Mesh.
Definition mesh.h:588
void clearContainer()
Definition mesh.h:1709
void deletePerElementCustomComponent(const std::string &name)
Deletes the custom component of the given name from the Element having ID ELEM_ID.
Definition mesh.h:1471
void reserve(uint n)
Reserves a number of elements of the given type in its container. The function does not add any eleme...
Definition mesh.h:868
void resize(uint n)
Resizes the Element container to contain n Elements of type ELEM_ID.
Definition mesh.h:840
static void updateReferencesOfContainerType(Mesh< A... > &m, const Array &bases)
Definition mesh.h:1923
auto end() const
Returns a const iterator to the end of the container of the elements having ID ELEM_ID in the mesh.
Definition mesh.h:1119
void enableAllOptionalComponents()
Enables all the optional components of the elements of the containers if the mesh.
Definition mesh.h:343
std::vector< std::string > perElementCustomComponentNames() const
Returns a vector containing all the names of the custom components of any type associated to the Elem...
Definition mesh.h:1363
void disableAllOptionalComponentsInContainer()
Definition mesh.h:1692
static constexpr bool hasPerElementComponent()
Returns true if this Mesh has a container of elements having the same Element ID of the template ELEM...
Definition mesh.h:227
static void setContainerBase(const Mesh< A... > &m, Array &bases)
Definition mesh.h:1830
friend void swap(Mesh &a, Mesh &b)
Specializes the swap function to allow the swapping of two Mesh objects.
Definition mesh.h:580
FilterTypesByCondition< mesh::IsElementContainerPred, TypeWrapper< Args... > >::type Containers
Containers is a vcl::TypeWrapper that wraps all the types from which the Mesh inherits (Args) that ar...
Definition mesh.h:114
auto & element(uint i)
Returns the element of the given type at the given index inside its container of this mesh.
Definition mesh.h:669
void enablePerElementComponent()
Enables the optional Component having ID COMP_ID for elements having ID ELEM_ID in the mesh.
Definition mesh.h:1297
uint index(const El *e) const
Returns the index of the given element in its Container of the Mesh.
Definition mesh.h:626
void disablePerElementComponent()
Disables the optional Component having ID COMP_ID for elements having ID ELEM_ID in the mesh.
Definition mesh.h:1317
ConstCustomComponentVectorHandle< K > perElementCustomComponentVectorHandle(const std::string &name) const
Returns a const vector handle to the custom component of type K having the given name associated to t...
Definition mesh.h:1572
uint number() const
Returns the number of elements of the given type in this mesh.
Definition mesh.h:686
ContainerType< ELEM_ID >::ElementType ElementType
ElementType is an alias that exposes the type of the Element identified by the template parameter ELE...
Definition mesh.h:151
uint index(const El &e) const
Returns the index of the given element in its Container of the Mesh.
Definition mesh.h:608
auto begin(bool jumpDeleted=true) const
Returns a const iterator to the begining of the container of the elements having ID ELEM_ID in the me...
Definition mesh.h:1099
auto elements(uint begin, uint end=UINT_NULL)
Definition mesh.h:1186
static constexpr bool hasPerElementOptionalComponent()
Returns true if this Mesh has a container of elements having the same Element ID of the template ELEM...
Definition mesh.h:252
static constexpr bool hasContainerOf()
Returns true if this Mesh has a container of elements having the same Element ID of the template Elem...
Definition mesh.h:180
std::vector< std::string > perElementCustomComponentNamesOfType() const
Returns a vector containing all the names of the custom components of type K associated to the Elemen...
Definition mesh.h:1430
void serializePerElementCustomComponentsOfType(std::ostream &os) const
Serializes the custom components of type K of the element with ID ELEM_ID.
Definition mesh.h:1607
static void setContainerSize(const Mesh< A... > &m, Array &sizes)
Definition mesh.h:1868
Definition element.h:64
Definition element.h:54
A concept that checks whether a class is a Mesh or an Element.
Definition mesh.h:2182
HasVertices concepts is satisfied when at least one of its types is (or inherits from) a vcl::mesh::V...
Definition vertex_container.h:1346
A concept that checks whether a class is (inherits from) a Mesh class.
Definition mesh.h:2169
The ComponentConcept is evaluated to true whenever the type T is a valid component,...
Definition component.h:46
A concept that checks whether a class has (inherits from) an FaceContainer class.
Definition face_container.h:1389
Definition mesh_components.h:55
Definition mesh_components.h:59
A concept that checks whether a class has (inherits from) a VertexContainer class.
Definition vertex_container.h:1305
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
The CompId struct enumerates the components that can compose a element or a mesh.
Definition base.h:48
Removes all types that do not satisfy a condition, and get them as a TypeWrapper.
Definition filter_types.h:70
Get the index of a type T in a pack of types (variadic templates) or a TypeWrapper.
Definition variadic_templates.h:138
Definition mesh.h:88
The ContainerOf struct allows to get the Container of an Element on this Mesh.
Definition mesh.h:103
Get the number of types in a pack of types (variadic templates) or a TypeWrapper.
Definition variadic_templates.h:189
A simple structure that wraps a list of variadic templates, without instantiating anything....
Definition type_wrapper.h:39
The ContainerOfElement structure exposes the type of the container of the given MeshType having eleme...
Definition base.h:107
Definition base.h:138
The predicate IsElementContainerPred sets its bool value to true when the type T satisfies the Elemen...
Definition base.h:81