| 422 | } |
| 423 | |
| 424 | void TriangleWrapper::poke_holes(Regions& regions) { |
| 425 | std::list<size_t> interior_faces; |
| 426 | for (auto& region : regions) { |
| 427 | VectorF seed_p; |
| 428 | bool seed_found = select_seed_point(region, seed_p); |
| 429 | |
| 430 | if (!seed_found) { |
| 431 | // All faces are degenerated in this region. |
| 432 | continue; |
| 433 | } |
| 434 | |
| 435 | Float wind_num = compute_winding_number(seed_p, m_points, m_segments); |
| 436 | if (fabs(wind_num) > 0.5) { |
| 437 | interior_faces.splice(interior_faces.end(), region); |
| 438 | } |
| 439 | } |
| 440 | |
| 441 | MatrixIr faces(interior_faces.size(), 3); |
| 442 | VectorI interior_regions(interior_faces.size()); |
| 443 | size_t count=0; |
| 444 | for (const auto& f_index : interior_faces) { |
| 445 | faces.row(count) = m_faces.row(f_index); |
| 446 | interior_regions[count] = m_regions[f_index]; |
| 447 | count++; |
| 448 | } |
| 449 | |
| 450 | IsolatedVertexRemoval remover(m_vertices, faces); |
| 451 | remover.run(); |
| 452 | m_vertices = remover.get_vertices(); |
| 453 | m_faces = remover.get_faces(); |
| 454 | |
| 455 | m_regions.swap(interior_regions); |
| 456 | } |
| 457 | |
| 458 | bool TriangleWrapper::select_seed_point(const Region& region, VectorF& seed_p) { |
| 459 | const Float degeneracy_tol = std::min(m_max_area * 0.01, 1e-6); |
nothing calls this directly
no test coverage detected