From c17b0a73c43c02c40918e9a774f06ccea5ed6c44 Mon Sep 17 00:00:00 2001 From: Thomas Fischer <thomas.fischer@ufz.de> Date: Fri, 20 Nov 2020 15:14:51 +0100 Subject: [PATCH] [MeL/MeshQuality] Rework AngleSkewMetric criterion. --- MeshLib/MeshQuality/AngleSkewMetric.cpp | 175 ++++++++++-------------- MeshLib/MeshQuality/AngleSkewMetric.h | 15 +- 2 files changed, 82 insertions(+), 108 deletions(-) diff --git a/MeshLib/MeshQuality/AngleSkewMetric.cpp b/MeshLib/MeshQuality/AngleSkewMetric.cpp index d5f927d99f9..6a968315d13 100644 --- a/MeshLib/MeshQuality/AngleSkewMetric.cpp +++ b/MeshLib/MeshQuality/AngleSkewMetric.cpp @@ -43,19 +43,19 @@ void AngleSkewMetric::calculateQuality () _element_quality_metric[k] = -1.0; break; case MeshElemType::TRIANGLE: - _element_quality_metric[k] = checkTriangle (elem); + _element_quality_metric[k] = checkTriangle(elem); break; case MeshElemType::QUAD: - _element_quality_metric[k] = checkQuad (elem); + _element_quality_metric[k] = checkQuad(elem); break; case MeshElemType::TETRAHEDRON: - _element_quality_metric[k] = checkTetrahedron (elem); + _element_quality_metric[k] = checkTetrahedron(elem); break; case MeshElemType::HEXAHEDRON: - _element_quality_metric[k] = checkHexahedron (elem); + _element_quality_metric[k] = checkHexahedron(elem); break; case MeshElemType::PRISM: - _element_quality_metric[k] = checkPrism (elem); + _element_quality_metric[k] = checkPrism(elem); break; default: break; @@ -63,153 +63,128 @@ void AngleSkewMetric::calculateQuality () } } -double AngleSkewMetric::checkTriangle (Element const& elem) const +double AngleSkewMetric::checkTriangle(Element const& elem) const { - double const* const node0 (elem.getNode(0)->getCoords()); - double const* const node1 (elem.getNode(1)->getCoords()); - double const* const node2 (elem.getNode(2)->getCoords()); - - double min_angle(two_pi); - double max_angle(0.0); - getMinMaxAngleFromTriangle (node0, node1, node2, min_angle, max_angle); - + auto const& [min_angle, max_angle] = getMinMaxAngleFromTriangle( + *elem.getNode(0), *elem.getNode(1), *elem.getNode(2)); return std::max((max_angle - third_pi) / two_thirds_pi, (third_pi - min_angle) / third_pi); } -double AngleSkewMetric::checkQuad (Element const& elem) const +double AngleSkewMetric::checkQuad(Element const& elem) const { - double const* const node0 (elem.getNode(0)->getCoords()); - double const* const node1 (elem.getNode(1)->getCoords()); - double const* const node2 (elem.getNode(2)->getCoords()); - double const* const node3 (elem.getNode(3)->getCoords()); - - double min_angle (two_pi); - double max_angle (0.0); + auto const& [min_angle, max_angle] = getMinMaxAngleFromQuad( + *elem.getNode(0), *elem.getNode(1), *elem.getNode(2), *elem.getNode(3)); - getMinMaxAngleFromQuad (node0, node1, node2, node3, min_angle, max_angle); return std::max((max_angle - half_pi) / half_pi, (half_pi - min_angle) / half_pi); } -double AngleSkewMetric::checkTetrahedron (Element const& elem) const +double AngleSkewMetric::checkTetrahedron(Element const& elem) const { - double const* const node0 (elem.getNode(0)->getCoords()); - double const* const node1 (elem.getNode(1)->getCoords()); - double const* const node2 (elem.getNode(2)->getCoords()); - double const* const node3 (elem.getNode(3)->getCoords()); - - double min_angle (two_pi); - double max_angle (0.0); + std::array<double, 4> min; + std::array<double, 4> max; + for (auto face_number = 0; face_number < 4; ++face_number) + { + auto const& face = *elem.getFace(face_number); + std::tie(min[face_number], max[face_number]) = getMinMaxAngleFromTri( + *face.getNode(0), *face.getNode(1), *face.getNode(2)); + } - // first triangle (0,1,2) - getMinMaxAngleFromTriangle(node0, node1, node2, min_angle, max_angle); - // second triangle (0,1,3) - getMinMaxAngleFromTriangle(node0, node1, node3, min_angle, max_angle); - // third triangle (0,2,3) - getMinMaxAngleFromTriangle(node0, node2, node3, min_angle, max_angle); - // fourth triangle (1,2,3) - getMinMaxAngleFromTriangle(node1, node2, node3, min_angle, max_angle); + double const min_angle = *std::min_element(min.begin(), min.end()); + double const max_angle = *std::max_element(max.begin(), max.end()); return std::max((max_angle - third_pi) / two_thirds_pi, (third_pi - min_angle) / third_pi); } -double AngleSkewMetric::checkHexahedron (Element const& elem) const +double AngleSkewMetric::checkHexahedron(Element const& elem) const { - double const* const node0 (elem.getNode(0)->getCoords()); - double const* const node1 (elem.getNode(1)->getCoords()); - double const* const node2 (elem.getNode(2)->getCoords()); - double const* const node3 (elem.getNode(3)->getCoords()); - double const* const node4 (elem.getNode(4)->getCoords()); - double const* const node5 (elem.getNode(5)->getCoords()); - double const* const node6 (elem.getNode(6)->getCoords()); - double const* const node7 (elem.getNode(7)->getCoords()); - - double min_angle (two_pi); - double max_angle (0.0); - - // first surface (0,1,2,3) - getMinMaxAngleFromQuad (node0, node1, node2, node3, min_angle, max_angle); - // second surface (0,3,7,4) - getMinMaxAngleFromQuad (node0, node3, node7, node4, min_angle, max_angle); - // third surface (4,5,6,7) - getMinMaxAngleFromQuad (node4, node5, node6, node7, min_angle, max_angle); - // fourth surface (5,1,2,6) - getMinMaxAngleFromQuad (node5, node1, node2, node6, min_angle, max_angle); - // fifth surface (5,1,0,4) - getMinMaxAngleFromQuad (node5, node1, node0, node4, min_angle, max_angle); - // sixth surface (6,2,3,7) - getMinMaxAngleFromQuad (node6, node2, node3, node7, min_angle, max_angle); + std::array<double, 6> min; + std::array<double, 6> max; + for (auto face_number = 0; face_number < 6; ++face_number) + { + auto const& face = *elem.getFace(face_number); + std::tie(min[face_number], max[face_number]) = + getMinMaxAngleFromQuad(*face.getNode(0), *face.getNode(1), + *face.getNode(2), *face.getNode(3)); + } + + double const min_angle = *std::min_element(min.begin(), min.end()); + double const max_angle = *std::max_element(max.begin(), max.end()); return std::max((max_angle - half_pi) / half_pi, (half_pi - min_angle) / half_pi); } -double AngleSkewMetric::checkPrism (Element const& elem) const +double AngleSkewMetric::checkPrism(Element const& elem) const { - double const* const node0 (elem.getNode(0)->getCoords()); - double const* const node1 (elem.getNode(1)->getCoords()); - double const* const node2 (elem.getNode(2)->getCoords()); - double const* const node3 (elem.getNode(3)->getCoords()); - double const* const node4 (elem.getNode(4)->getCoords()); - double const* const node5 (elem.getNode(5)->getCoords()); - - double min_angle_tri (two_pi); - double max_angle_tri (0.0); - // first triangle (0,1,2) - getMinMaxAngleFromTriangle (node0, node1, node2, min_angle_tri, max_angle_tri); + auto const& [min_angle_tri0, max_angle_tri0] = getMinMaxAngleFromTriangle( + *elem.getNode(0), *elem.getNode(1), *elem.getNode(2)); // second surface (3,4,5) - getMinMaxAngleFromTriangle (node3, node4, node5, min_angle_tri, max_angle_tri); + auto const& [min_angle_tri1, max_angle_tri1] = getMinMaxAngleFromTriangle( + *elem.getNode(3), *elem.getNode(4), *elem.getNode(5)); + double const min_angle_tri = std::min(min_angle_tri0, min_angle_tri1); + double const max_angle_tri = std::max(max_angle_tri0, max_angle_tri1); double const tri_criterion( std::max((max_angle_tri - third_pi) / two_thirds_pi, (third_pi - min_angle_tri) / third_pi)); - double min_angle_quad (two_pi); - double max_angle_quad (0.0); // surface (0,3,4,1) - getMinMaxAngleFromQuad (node0, node3, node4, node1, min_angle_quad, max_angle_quad); + auto const& [min_angle_quad0, max_angle_quad0] = getMinMaxAngleFromQuad( + *elem.getNode(0), *elem.getNode(3), *elem.getNode(4), *elem.getNode(1)); // surface (2,5,3,0) - getMinMaxAngleFromQuad (node2, node5, node3, node0, min_angle_quad, max_angle_quad); + auto const& [min_angle_quad1, max_angle_quad1] = getMinMaxAngleFromQuad( + *elem.getNode(2), *elem.getNode(5), *elem.getNode(3), *elem.getNode(0)); // surface (1,2,5,4) - getMinMaxAngleFromQuad (node1, node2, node5, node4, min_angle_quad, max_angle_quad); + auto const& [min_angle_quad2, max_angle_quad2] = getMinMaxAngleFromQuad( + *elem.getNode(1), *elem.getNode(2), *elem.getNode(5), *elem.getNode(4)); - double const quad_criterion(std::max((max_angle_quad - half_pi) / half_pi, - (half_pi - min_angle_quad) / half_pi)); - - return std::min (tri_criterion, quad_criterion); + double const min_angle_quad = + std::min({min_angle_quad0, min_angle_quad1, min_angle_quad2}); + double const max_angle_quad = + std::max({max_angle_quad0, max_angle_quad1, max_angle_quad2}); } -void AngleSkewMetric::getMinMaxAngleFromQuad ( - double const* const n0, double const* const n1, - double const* const n2, double const* const n3, - double &min_angle, double &max_angle) const +std::tuple<double, double> AngleSkewMetric::getMinMaxAngleFromQuad( + MeshLib::Node const& n0, MeshLib::Node const& n1, MeshLib::Node const& n2, + MeshLib::Node const& n3) const { - const double* nodes[4] = {n0, n1, n2, n3}; - for (unsigned i=0; i<4; ++i) + double min_angle(two_pi); + double max_angle(0.0); + + std::array const nodes = {n0, n1, n2, n3}; + for (unsigned i = 0; i < nodes.size(); ++i) { - const double angle (MathLib::getAngle (nodes[i], nodes[(i+1)%4], nodes[(i+2)%4])); + const double angle(MathLib::getAngle(nodes[i].getCoords(), + nodes[(i + 1) % 4].getCoords(), + nodes[(i + 2) % 4].getCoords())); min_angle = std::min(angle, min_angle); max_angle = std::max(angle, max_angle); } + return {min_angle, max_angle}; } -void AngleSkewMetric::getMinMaxAngleFromTriangle(double const* const n0, - double const* const n1, - double const* const n2, - double &min_angle, - double &max_angle) const +std::tuple<double, double> AngleSkewMetric::getMinMaxAngleFromTriangle( + MeshLib::Node const& n0, MeshLib::Node const& n1, + MeshLib::Node const& n2) const { - const double* nodes[3] = {n0, n1, n2}; + double min_angle(two_pi); + double max_angle(0.0); + + std::array nodes = {n0, n1, n2}; for (unsigned i=0; i<3; ++i) { - const double angle (MathLib::getAngle (nodes[i], nodes[(i+1)%3], nodes[(i+2)%3])); + const double angle(MathLib::getAngle(nodes[i].getCoords(), + nodes[(i + 1) % 3].getCoords(), + nodes[(i + 2) % 3].getCoords())); min_angle = std::min(angle, min_angle); max_angle = std::max(angle, max_angle); } + return {min_angle, max_angle}; } } // end namespace MeshLib diff --git a/MeshLib/MeshQuality/AngleSkewMetric.h b/MeshLib/MeshQuality/AngleSkewMetric.h index c2765b2cf25..e7122955814 100644 --- a/MeshLib/MeshQuality/AngleSkewMetric.h +++ b/MeshLib/MeshQuality/AngleSkewMetric.h @@ -34,13 +34,12 @@ private: double checkQuad(Element const& elem) const; double checkTetrahedron(Element const& elem) const; double checkHexahedron(Element const& elem) const; - double checkPrism (Element const& elem) const; - void getMinMaxAngleFromQuad(double const* const n0, - double const* const n1, double const* const n2, - double const* const n3, double &min_angle, - double &max_angle) const; - void getMinMaxAngleFromTriangle(double const* const n0, - double const* const n1, double const* const n2, - double &min_angle, double &max_angle) const; + double checkPrism(Element const& elem) const; + std::tuple<double, double> getMinMaxAngleFromQuad( + MeshLib::Node const& n0, MeshLib::Node const& n1, + MeshLib::Node const& n2, MeshLib::Node const& n3) const; + std::tuple<double, double> getMinMaxAngleFromTriangle( + MeshLib::Node const& n0, MeshLib::Node const& n1, + MeshLib::Node const& n2) const; }; } // namespace MeshLib -- GitLab