Skip to content

Commit 493a459

Browse files
committed
fix(Quality): adding function to compute triangle quality, based on angles.
1 parent aa15606 commit 493a459

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

include/geode/geometry/quality.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
namespace geode
2929
{
3030
class Tetrahedron;
31+
FORWARD_DECLARATION_DIMENSION_CLASS( Triangle );
32+
ALIAS_2D_AND_3D( Triangle );
3133
} // namespace geode
3234

3335
namespace geode
@@ -39,4 +41,8 @@ namespace geode
3941

4042
[[nodiscard]] double opengeode_geometry_api
4143
tetrahedron_collapse_aspect_ratio( const Tetrahedron& tetra );
44+
45+
template < index_t dimension >
46+
[[nodiscard]] double opengeode_geometry_api triangle_angle_based_quality(
47+
const Triangle< dimension >& triangle );
4248
} // namespace geode

src/geode/geometry/quality.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@
3333

3434
namespace
3535
{
36+
template < geode::index_t dimension >
37+
double compute_angle( const geode::Point< dimension >& point,
38+
const geode::Point< dimension >& point_prev,
39+
const geode::Point< dimension >& point_next )
40+
{
41+
const auto prev =
42+
geode::Vector< dimension >{ point, point_prev }.normalize();
43+
const auto next =
44+
geode::Vector< dimension >{ point, point_next }.normalize();
45+
const auto angle = std::acos( prev.dot( next ) );
46+
if( std::isnan( angle ) )
47+
{
48+
return 0;
49+
}
50+
return angle;
51+
}
3652

3753
std::array< geode::local_index_t, 3 > lu_decomposition(
3854
geode::SquareMatrix3D& matrix )
@@ -241,4 +257,34 @@ namespace geode
241257
}
242258
return ( longest_edge_length * heightinv ) / std::sqrt( 3. / 2. );
243259
}
260+
261+
template < index_t dimension >
262+
double triangle_angle_based_quality( const Triangle< dimension >& triangle )
263+
{
264+
try
265+
{
266+
const auto& vertices = triangle.vertices();
267+
std::array< double, dimension > sinus;
268+
for( const auto v : LRange{ 3 } )
269+
{
270+
const auto point = vertices[v].get();
271+
const auto point_prev = vertices[( v + 2 ) % 3].get();
272+
const auto point_next = vertices[( v + 1 ) % 3].get();
273+
const auto angle =
274+
compute_angle( point, point_prev, point_next );
275+
sinus[v] = std::sin( angle );
276+
}
277+
return 4 * sinus[0] * sinus[1] * sinus[2]
278+
/ ( sinus[0] + sinus[1] + sinus[2] );
279+
}
280+
catch( ... )
281+
{
282+
return 0;
283+
}
284+
}
285+
286+
template opengeode_geometry_api double triangle_angle_based_quality< 2 >(
287+
const Triangle2D& );
288+
template opengeode_geometry_api double triangle_angle_based_quality< 3 >(
289+
const Triangle3D& );
244290
} // namespace geode

0 commit comments

Comments
 (0)