30 {6, 7, 4, 5, 2, 3, 0, 1}};
37 std::size_t nNodes(id_map.size());
39 for (std::size_t i = 0; i < nNodes; ++i)
51 unsigned min_elem_dim)
const
60 std::vector<MeshLib::Node*> new_nodes =
62 std::vector<MeshLib::Element*> new_elements;
63 std::vector<std::size_t> element_ids;
65 for (std::size_t k(0); k < elements.size(); ++k)
75 std::size_t
const n_new_elements(
77 if (n_new_elements == 0)
79 ERR(
"Element {:d} has unknown element type.", k);
84 element_ids.insert(element_ids.end(), n_new_elements, k);
89 element_ids.push_back(k);
92 else if (n_unique_nodes < elem->getNumberOfBaseNodes() &&
96 elem, n_unique_nodes, new_nodes, new_elements, min_elem_dim));
97 element_ids.insert(element_ids.end(), n_new_elements, k);
101 ERR(
"Something is wrong, more unique nodes than actual nodes");
110 if (!new_elements.empty())
112 return new MeshLib::Mesh(new_mesh_name, new_nodes, new_elements,
124 std::vector<std::size_t> id_map(nNodes);
125 const double half_eps(eps / 2.0);
126 const double sqr_eps(eps * eps);
127 std::iota(id_map.begin(), id_map.end(), 0);
131 for (std::size_t k = 0; k < nNodes; ++k)
134 if (node->
getID() != k)
138 std::vector<std::vector<MeshLib::Node*>
const*> node_vectors(
141 const std::size_t nVectors(node_vectors.size());
142 for (std::size_t i = 0; i < nVectors; ++i)
144 const std::vector<MeshLib::Node*>& cell_vector(*node_vectors[i]);
145 const std::size_t nGridCellNodes(cell_vector.size());
146 for (std::size_t j = 0; j < nGridCellNodes; ++j)
151 if (id_map[node->
getID()] == id_map[test_node->
getID()])
159 if (test_node->
getID() != id_map[test_node->
getID()])
176 const std::vector<std::size_t>& id_map)
const
179 const std::size_t nNodes(nodes.size());
180 std::vector<MeshLib::Node*> new_nodes;
181 new_nodes.reserve(nNodes);
182 for (std::size_t k = 0; k < nNodes; ++k)
186 if (nodes[k]->getID() == id_map[k])
188 std::size_t
const id(new_nodes.size());
190 (*nodes[k])[0], (*nodes[k])[1], (*nodes[k])[2],
id));
198 nodes[k]->setID(nodes[id_map[k]]->getID());
208 unsigned count(nNodes);
210 for (
unsigned i = 0; i < nNodes - 1; ++i)
212 for (
unsigned j = i + 1; j < nNodes; ++j)
224 template <
typename T>
226 std::vector<T>
const& old_prop,
230 std::size_t
const n_nodes = node_ids.size();
231 for (std::size_t i = 0; i < n_nodes; ++i)
233 if (node_ids[i] != i)
237 new_prop.push_back(old_prop[i]);
241 template <
typename T>
243 std::vector<T>
const& old_prop,
247 std::transform(elem_ids.cbegin(), elem_ids.cend(),
248 std::back_inserter(new_prop),
249 [&](std::size_t
const i) { return old_prop[i]; });
254 std::vector<std::size_t>
const& node_ids,
255 std::vector<std::size_t>
const& elem_ids)
const
260 for (
auto name : prop_names)
314 WARN(
"PropertyVector {:s} not being converted.",
name);
316 return new_properties;
321 std::vector<MeshLib::Node*>
const& nodes,
322 std::vector<MeshLib::Element*>& elements)
const
345 unsigned n_unique_nodes,
346 std::vector<MeshLib::Node*>
const& nodes,
347 std::vector<MeshLib::Element*>& elements,
348 unsigned min_elem_dim)
const
361 if (n_unique_nodes == 3 && min_elem_dim < 3)
365 else if (min_elem_dim == 1)
373 return reduceHex(element, n_unique_nodes, nodes, elements,
378 this->
reducePyramid(element, n_unique_nodes, nodes, elements,
384 return reducePrism(element, n_unique_nodes, nodes, elements,
388 ERR(
"Unknown element type.");
394 std::vector<MeshLib::Node*>
const& nodes,
395 std::vector<MeshLib::Element*>& new_elements)
const
412 std::vector<MeshLib::Node*>
const& nodes,
413 std::vector<MeshLib::Element*>& new_elements)
const
415 std::array<Node*, 6> prism1_nodes;
426 std::array<Node*, 6> prism2_nodes;
442 std::vector<MeshLib::Node*>
const& nodes,
443 std::vector<MeshLib::Element*>& new_elements)
const
445 auto addTetrahedron =
446 [&pyramid, &nodes, &new_elements](std::size_t id0, std::size_t id1,
447 std::size_t id2, std::size_t id3)
449 std::array<Node*, 4> tet_nodes;
457 addTetrahedron(0, 1, 2, 4);
459 addTetrahedron(0, 2, 3, 4);
466 std::vector<MeshLib::Node*>
const& nodes,
467 std::vector<MeshLib::Element*>& new_elements)
const
469 auto addTetrahedron =
470 [&prism, &nodes, &new_elements](std::size_t id0, std::size_t id1,
471 std::size_t id2, std::size_t id3)
473 std::array<Node*, 4> tet_nodes;
481 addTetrahedron(0, 1, 2, 3);
483 addTetrahedron(3, 2, 4, 5);
485 addTetrahedron(2, 1, 3, 4);
491 unsigned n_unique_nodes,
492 std::vector<MeshLib::Node*>
const& nodes,
493 std::vector<MeshLib::Element*>& new_elements,
494 unsigned min_elem_dim)
const
500 if (n_unique_nodes == 7)
503 for (
unsigned i = 0; i < 7; ++i)
505 for (
unsigned j = i + 1; j < 8; ++j)
510 const std::array<unsigned, 4> base_nodes(
512 std::array pyr_nodes{
524 std::array prism_nodes{
539 else if (n_unique_nodes == 6)
542 for (
unsigned i = 0; i < 6; ++i)
548 std::array prism_nodes{
584 std::array prism_nodes{
621 for (
unsigned i = 0; i < 7; ++i)
623 for (
unsigned j = i + 1; j < 8; ++j)
628 for (
unsigned k = i; k < 7; ++k)
630 for (
unsigned l = k + 1; l < 8; ++l)
632 if (!(i == k && j == l) && org_elem->
isEdge(i, j) &&
637 const std::pair<unsigned, unsigned> back(
640 std::numeric_limits<unsigned>::max() ||
642 std::numeric_limits<unsigned>::max())
644 ERR(
"Unexpected error during Hex "
649 std::array<unsigned, 4> cutting_plane(
652 std::array pris1_nodes{
654 org_elem->
getNode(back.first)),
656 org_elem->
getNode(cutting_plane[0])),
658 org_elem->
getNode(cutting_plane[3])),
660 org_elem->
getNode(back.second)),
662 org_elem->
getNode(cutting_plane[1])),
664 org_elem->
getNode(cutting_plane[2]))};
667 prism1, 5, nodes, new_elements,
671 std::array pris2_nodes{
677 org_elem->
getNode(cutting_plane[0])),
679 org_elem->
getNode(cutting_plane[3])),
682 this->lutHexDiametralNode(
685 org_elem->
getNode(cutting_plane[1])),
687 org_elem->
getNode(cutting_plane[2]))};
690 prism2, 5, nodes, new_elements,
701 else if (n_unique_nodes == 5)
704 std::array<std::size_t, 4> first_four_nodes = {
710 bool tet_changed(
false);
716 tet1_nodes[0] = nodes[first_four_nodes[0]];
717 tet1_nodes[1] = nodes[first_four_nodes[1]];
718 tet1_nodes[2] = nodes[first_four_nodes[2]];
719 tet1_nodes[3] = nodes[org_elem->
getNode(fifth_node)->
getID()];
724 new_elements.push_back(tet1);
727 std::array tet2_nodes = {(tet_changed) ? nodes[first_four_nodes[0]]
728 : nodes[first_four_nodes[1]],
729 nodes[first_four_nodes[2]],
730 nodes[first_four_nodes[3]],
735 else if (n_unique_nodes == 4)
741 new_elements.push_back(elem);
745 else if (n_unique_nodes == 3 && min_elem_dim < 3)
747 new_elements.push_back(this->
constructTri(org_elem, nodes));
750 else if (min_elem_dim == 1)
752 new_elements.push_back(this->
constructLine(org_elem, nodes));
759 unsigned n_unique_nodes,
760 std::vector<MeshLib::Node*>
const& nodes,
761 std::vector<MeshLib::Element*>& new_elements,
762 unsigned min_elem_dim)
const
764 if (n_unique_nodes == 4)
770 new_elements.push_back(elem);
773 else if (n_unique_nodes == 3 && min_elem_dim < 3)
775 new_elements.push_back(this->
constructTri(org_elem, nodes));
777 else if (n_unique_nodes == 2 && min_elem_dim == 1)
779 new_elements.push_back(this->
constructLine(org_elem, nodes));
784 unsigned n_unique_nodes,
785 std::vector<MeshLib::Node*>
const& nodes,
786 std::vector<MeshLib::Element*>& new_elements,
787 unsigned min_elem_dim)
const
789 auto addTetrahedron =
790 [&org_elem, &nodes, &new_elements](std::size_t id0, std::size_t id1,
791 std::size_t id2, std::size_t id3)
793 std::array tet_nodes{nodes[org_elem->
getNode(id0)->
getID()],
807 if (n_unique_nodes == 5)
809 for (
unsigned i = 0; i < 5; ++i)
811 for (
unsigned j = i + 1; j < 6; ++j)
819 addTetrahedron((i + 1) % 3, (i + 2) % 3, i,
821 addTetrahedron((i + 1) % 3 + 3, (i + 2) % 3, i,
827 const unsigned i_offset = (i > 2) ? i - 3 : i + 3;
828 const unsigned j_offset = (i > 2) ? j - 3 : j + 3;
830 if (k == std::numeric_limits<unsigned>::max())
832 ERR(
"Unexpected error during prism reduction.");
835 const unsigned k_offset = (i > 2) ? k - 3 : k + 3;
837 addTetrahedron(i_offset, j_offset, k_offset, i);
846 const unsigned l_offset = (i > 2) ? l - 3 : l + 3;
847 addTetrahedron(l_offset, k_offset, i, k);
853 else if (n_unique_nodes == 4)
859 new_elements.push_back(elem);
862 else if (n_unique_nodes == 3 && min_elem_dim < 3)
864 new_elements.push_back(this->
constructTri(org_elem, nodes));
866 else if (n_unique_nodes == 2 && min_elem_dim == 1)
868 new_elements.push_back(this->
constructLine(org_elem, nodes));
875 const std::vector<MeshLib::Node*>& nodes)
const
877 std::array<Node*, 2> line_nodes;
879 line_nodes[1] =
nullptr;
888 assert(line_nodes[1] !=
nullptr);
894 const std::vector<MeshLib::Node*>& nodes)
const
900 std::array<Node*, 3> tri_nodes;
902 tri_nodes[2] =
nullptr;
905 if (element->
getNode(i)->
getID() != tri_nodes[0]->getID())
910 if (element->
getNode(j)->
getID() != tri_nodes[1]->getID())
922 assert(tri_nodes[2] !=
nullptr);
928 std::vector<MeshLib::Node*>
const& nodes,
929 unsigned min_elem_dim)
const
931 std::array<Node*, 4> new_nodes;
933 new_nodes[count++] = nodes[element->
getNode(0)->
getID()];
940 bool unique_node(
true);
941 for (
unsigned j = 0; j < i; ++j)
951 new_nodes[count++] = nodes[element->
getNode(i)->
getID()];
957 *new_nodes[2], *new_nodes[3]));
958 if (isQuad && min_elem_dim < 3)
961 for (
unsigned i = 1; i < 3; ++i)
970 new_nodes[i + 1] = new_nodes[i];
986 std::array<std::size_t, 4>
const& base_node_ids)
989 for (std::size_t i = 0; i < nNodes; ++i)
991 bool top_node =
true;
992 for (
unsigned j = 0; j < 4; ++j)
1004 return std::numeric_limits<unsigned>::max();
1016 std::array<unsigned, 4> nodes{};
1017 if (id1 == 0 && id2 == 1)
1024 else if (id1 == 1 && id2 == 2)
1031 else if (id1 == 2 && id2 == 3)
1038 else if (id1 == 3 && id2 == 0)
1045 else if (id1 == 4 && id2 == 5)
1052 else if (id1 == 5 && id2 == 6)
1059 else if (id1 == 6 && id2 == 7)
1066 else if (id1 == 7 && id2 == 4)
1073 else if (id1 == 0 && id2 == 4)
1080 else if (id1 == 1 && id2 == 5)
1087 else if (id1 == 2 && id2 == 6)
1094 else if (id1 == 3 && id2 == 7)
1102 else if (id1 == 1 && id2 == 0)
1109 else if (id1 == 2 && id2 == 1)
1116 else if (id1 == 3 && id2 == 2)
1123 else if (id1 == 0 && id2 == 3)
1130 else if (id1 == 5 && id2 == 4)
1137 else if (id1 == 6 && id2 == 5)
1144 else if (id1 == 7 && id2 == 6)
1151 else if (id1 == 4 && id2 == 7)
1158 else if (id1 == 4 && id2 == 0)
1165 else if (id1 == 5 && id2 == 1)
1172 else if (id1 == 6 && id2 == 2)
1179 else if (id1 == 7 && id2 == 3)
1195 std::pair<unsigned, unsigned> back(std::numeric_limits<unsigned>::max(),
1196 std::numeric_limits<unsigned>::max());
1243 if ((id1 == 0 && id2 == 1) || (id1 == 1 && id2 == 2))
1247 if ((id1 == 1 && id2 == 2) || (id1 == 2 && id2 == 1))
1251 if ((id1 == 0 && id2 == 2) || (id1 == 2 && id2 == 0))
1255 if ((id1 == 3 && id2 == 4) || (id1 == 4 && id2 == 3))
1259 if ((id1 == 4 && id2 == 5) || (id1 == 5 && id2 == 4))
1263 if ((id1 == 3 && id2 == 5) || (id1 == 5 && id2 == 3))
1267 return std::numeric_limits<unsigned>::max();
Definition of Duplicate functions.
Definition of the Grid class.
void ERR(char const *fmt, Args const &... args)
void WARN(char const *fmt, Args const &... args)
Definition of the MeshRevision class.
Definition of the Mesh class.
Collects error flags for mesh elements.
std::vector< std::vector< POINT * > const * > getPntVecsOfGridCellsIntersectingCube(P const ¢er, double half_len) const
std::size_t getID() const
virtual MeshElemType getGeomType() const =0
virtual const Node * getNode(unsigned idx) const =0
virtual ElementErrorCode validate() const =0
virtual unsigned getNumberOfBaseNodes() const =0
virtual const Element * getFace(unsigned i) const =0
Returns the i-th face of the element.
virtual bool isEdge(unsigned i, unsigned j) const =0
Returns true if these two indices form an edge and false otherwise.
virtual constexpr unsigned getDimension() const =0
Get dimension of the mesh element.
MeshLib::Element * constructTri(MeshLib::Element const *const element, const std::vector< MeshLib::Node * > &nodes) const
Mesh & _mesh
The original mesh used for constructing the class.
MeshLib::Properties copyProperties(MeshLib::Properties const &props, std::vector< std::size_t > const &node_ids, std::vector< std::size_t > const &elem_ids) const
unsigned getNumberOfCollapsableNodes(double eps=std::numeric_limits< double >::epsilon()) const
Returns the number of potentially collapsible nodes.
static unsigned lutHexDiametralNode(unsigned id)
unsigned subdividePrism(MeshLib::Element const *const prism, const std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &new_elements) const
Subdivides a prism with nonplanar quad faces into two tets.
void reducePyramid(MeshLib::Element const *const org_elem, unsigned n_unique_nodes, const std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &new_elements, unsigned min_elem_dim) const
static unsigned findPyramidTopNode(MeshLib::Element const &element, std::array< std::size_t, 4 > const &base_node_ids)
unsigned subdivideHex(MeshLib::Element const *const hex, const std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &new_elements) const
Subdivides a Hex with nonplanar faces into tets.
static std::array< unsigned, 4 > lutHexCuttingQuadNodes(unsigned id1, unsigned id2)
unsigned subdivideQuad(MeshLib::Element const *const quad, const std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &new_elements) const
Subdivides a nonplanar quad into two triangles.
static unsigned lutPrismThirdNode(unsigned id1, unsigned id2)
static std::pair< unsigned, unsigned > lutHexBackNodes(unsigned i, unsigned j, unsigned k, unsigned l)
MeshLib::Element * constructFourNodeElement(MeshLib::Element const *const element, const std::vector< MeshLib::Node * > &nodes, unsigned min_elem_dim=1) const
unsigned subdividePyramid(MeshLib::Element const *const pyramid, const std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &new_elements) const
Subdivides a pyramid with a nonplanar base into two tets.
std::vector< MeshLib::Node * > constructNewNodesArray(const std::vector< std::size_t > &id_map) const
static unsigned getNumberOfUniqueNodes(MeshLib::Element const *const element)
std::vector< std::size_t > collapseNodeIndices(double eps) const
MeshLib::Mesh * simplifyMesh(const std::string &new_mesh_name, double eps, unsigned min_elem_dim=1) const
unsigned reduceHex(MeshLib::Element const *const org_elem, unsigned n_unique_nodes, const std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &new_elements, unsigned min_elem_dim) const
std::size_t reduceElement(MeshLib::Element const *const element, unsigned n_unique_nodes, const std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &elements, unsigned min_elem_dim) const
static const std::array< unsigned, 8 > _hex_diametral_nodes
MeshRevision(MeshLib::Mesh &mesh)
unsigned reducePrism(MeshLib::Element const *const org_elem, unsigned n_unique_nodes, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &new_elements, unsigned min_elem_dim) const
MeshLib::Element * constructLine(MeshLib::Element const *const element, const std::vector< MeshLib::Node * > &nodes) const
std::size_t subdivideElement(MeshLib::Element const *const element, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &elements) const
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
void resetNodeIDs()
Resets the IDs of all mesh-nodes to their position in the node vector.
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Properties & getProperties()
std::size_t getNumberOfNodes() const
Get the number of nodes.
std::size_t getNumberOfElements() const
Get the number of elements.
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
std::vector< std::string > getPropertyVectorNames() const
PropertyVector< T > const * getPropertyVector(std::string const &name) const
bool existsPropertyVector(std::string const &name) const
PropertyVector< T > * createNewPropertyVector(std::string const &name, MeshItemType mesh_item_type, std::size_t n_components=1)
void cleanupVectorElements(std::vector< T1 * > const &items, std::vector< T2 * > const &dependent_items)
bool isCoplanar(const MathLib::Point3d &a, const MathLib::Point3d &b, const MathLib::Point3d &c, const MathLib::Point3d &d)
Checks if the four given points are located on a plane.
double sqrDist(MathLib::Point3d const &p0, MathLib::Point3d const &p1)
TemplateElement< MeshLib::TetRule4 > Tet
TemplateElement< MeshLib::LineRule2 > Line
TemplateElement< MeshLib::TriRule3 > Tri
unsigned getNodeIDinElement(Element const &element, const MeshLib::Node *node)
Returns the position of the given node in the node array of this element.
void fillNodeProperty(std::vector< T > &new_prop, std::vector< T > const &old_prop, std::vector< size_t > node_ids)
Element * copyElement(Element const *const element, const std::vector< Node * > &nodes, std::vector< std::size_t > const *const id_map)
void fillElemProperty(std::vector< T > &new_prop, std::vector< T > const &old_prop, std::vector< size_t > elem_ids)