| 90 | } |
| 91 | |
| 92 | FillHoleMetric getPlaneNormalizedFillMetric( const Mesh& mesh, EdgeId e0 ) |
| 93 | { |
| 94 | auto norm = Vector3d(); |
| 95 | for ( auto e : leftRing( mesh.topology, e0 ) ) |
| 96 | { |
| 97 | norm += cross( Vector3d( mesh.orgPnt( e ) ), Vector3d( mesh.destPnt( e ) ) ); |
| 98 | } |
| 99 | norm = norm.normalized(); |
| 100 | |
| 101 | FillHoleMetric metric; |
| 102 | metric.triangleMetric = [&mesh, norm] ( VertId a, VertId b, VertId c ) |
| 103 | { |
| 104 | Vector3d aP = Vector3d( mesh.points[a] ); |
| 105 | Vector3d bP = Vector3d( mesh.points[b] ); |
| 106 | Vector3d cP = Vector3d( mesh.points[c] ); |
| 107 | |
| 108 | auto faceNorm = cross( bP - aP, cP - aP ); |
| 109 | auto faceDblAreaSq = faceNorm.lengthSq(); |
| 110 | if ( faceDblAreaSq == 0.0f ) // degenerated |
| 111 | return BadTriangulationMetric; // DBL_MAX break any triangulation, just return big value to be allow some bad meshes |
| 112 | |
| 113 | auto dotRes = dot( norm, faceNorm ); |
| 114 | if ( ( dotRes < 0.0f ) || ( sqr( dotRes ) * 4.0f < faceDblAreaSq ) ) |
| 115 | return BadTriangulationMetric; // DBL_MAX break any triangulation, just return big value to be allow some bad meshes |
| 116 | |
| 117 | auto ar = triangleAspectRatio( aP, bP, cP ); |
| 118 | if ( ar > BadTriangulationMetric ) |
| 119 | return BadTriangulationMetric; // DBL_MAX break any triangulation, just return big value to be allow some bad meshes |
| 120 | |
| 121 | return circumcircleDiameter( aP, bP, cP ) * ar; |
| 122 | }; |
| 123 | return metric; |
| 124 | } |
| 125 | |
| 126 | FillHoleMetric getComplexStitchMetric( const Mesh& mesh ) |
| 127 | { |
no test coverage detected