| 205 | } |
| 206 | |
| 207 | FillHoleMetric getComplexFillMetric( const Mesh& mesh, EdgeId e0 ) |
| 208 | { |
| 209 | float maxEdgeLengthSq = 0.0f; |
| 210 | for ( auto e : leftRing( mesh.topology, e0 ) ) |
| 211 | maxEdgeLengthSq = std::max( maxEdgeLengthSq, mesh.edgeLengthSq( e ) ); |
| 212 | |
| 213 | assert( maxEdgeLengthSq > 0.0f ); |
| 214 | |
| 215 | float reverseCharacteristicTriArea{ 0.0f }; |
| 216 | if ( maxEdgeLengthSq <= 0.0f ) |
| 217 | reverseCharacteristicTriArea = 1.0f; |
| 218 | else |
| 219 | reverseCharacteristicTriArea = 1.0f / maxEdgeLengthSq; |
| 220 | |
| 221 | FillHoleMetric metric; |
| 222 | metric.triangleMetric = [&mesh, reverseCharacteristicTriArea] ( VertId a, VertId b, VertId c ) |
| 223 | { |
| 224 | double aspectRatio = triangleAspectRatio( mesh.points[a], mesh.points[b], mesh.points[c] ); |
| 225 | if ( aspectRatio > BadTriangulationMetric ) |
| 226 | return BadTriangulationMetric; |
| 227 | |
| 228 | double normedArea = TriangleAreaModifier * cross( mesh.points[b] - mesh.points[a], mesh.points[c] - mesh.points[a] ).length() * reverseCharacteristicTriArea; |
| 229 | |
| 230 | return aspectRatio + normedArea; |
| 231 | }; |
| 232 | metric.edgeMetric = [&mesh] ( VertId a, VertId b, VertId l, VertId r ) |
| 233 | { |
| 234 | auto abVec = mesh.points[b] - mesh.points[a]; |
| 235 | auto bcVec = -abVec; |
| 236 | auto normA = cross( mesh.points[r] - mesh.points[b], bcVec ); |
| 237 | auto normC = cross( mesh.points[l] - mesh.points[a], abVec ); |
| 238 | |
| 239 | auto s_Abc_double = normA.length(); |
| 240 | auto s_abC_double = normC.length(); |
| 241 | auto denom = s_Abc_double * s_abC_double; |
| 242 | if ( denom == 0.0f ) |
| 243 | return BadTriangulationMetric; |
| 244 | auto cosAC = dot( normA, normC ) / ( s_Abc_double * s_abC_double ); |
| 245 | |
| 246 | if ( cosAC <= -1.0f ) |
| 247 | return BadTriangulationMetric; |
| 248 | |
| 249 | return double( sqr( sqr( ( 1.0f - cosAC ) / ( 1.0f + cosAC ) ) ) ); |
| 250 | }; |
| 251 | return metric; |
| 252 | } |
| 253 | |
| 254 | FillHoleMetric getParallelPlaneFillMetric( const Mesh& mesh, EdgeId e0, const Plane3f* plane /*= nullptr */ ) |
| 255 | { |
no test coverage detected