Reconstruct a single block of points.
| 390 | |
| 391 | // Reconstruct a single block of points. |
| 392 | colmap::PlyMesh ReconstructBlock( |
| 393 | const std::vector<colmap::PlyPoint>& points, |
| 394 | const std::vector<K::Segment_3>& rays, |
| 395 | const colmap::mvs::AdvancingFrontMeshingOptions& options) { |
| 396 | // Build the Surface_mesh with colored vertices. |
| 397 | SurfaceMesh mesh; |
| 398 | MeshConstructor constructor(mesh, points); |
| 399 | |
| 400 | // Build 3D Delaunay triangulation from the mesh vertices. |
| 401 | using CC = CGAL::Cartesian_converter<K, K>; |
| 402 | CC cc; |
| 403 | AFSRTriangulation triangulation( |
| 404 | boost::make_transform_iterator( |
| 405 | mesh.points().begin(), CGAL::AFSR::Auto_count_cc<K::Point_3, CC>(cc)), |
| 406 | boost::make_transform_iterator( |
| 407 | mesh.points().end(), CGAL::AFSR::Auto_count_cc<K::Point_3, CC>(cc))); |
| 408 | |
| 409 | LOG(INFO) << "Built triangulation with " << triangulation.number_of_vertices() |
| 410 | << " vertices."; |
| 411 | |
| 412 | // Pre-filtering: cast visibility rays through triangulation. |
| 413 | VisibilityCounter visibility_counter; |
| 414 | if (!rays.empty() && !options.visibility_post_filtering) { |
| 415 | LOG(INFO) << "Pre-filtering: casting " << rays.size() |
| 416 | << " visibility rays..."; |
| 417 | const AFSRRayCaster ray_caster(triangulation); |
| 418 | const int num_omp_threads = omp_get_max_threads(); |
| 419 | std::vector<VisibilityCounter> thread_counters(num_omp_threads); |
| 420 | #pragma omp parallel |
| 421 | { |
| 422 | std::vector<AFSRTriangulation::Facet> intersections; |
| 423 | auto& local_counter = thread_counters[omp_get_thread_num()]; |
| 424 | const int64_t num_rays = static_cast<int64_t>(rays.size()); |
| 425 | #pragma omp for schedule(dynamic) |
| 426 | for (int64_t i = 0; i < num_rays; ++i) { |
| 427 | ray_caster.CastRaySegment(rays[i], &intersections); |
| 428 | for (const auto& intersection : intersections) { |
| 429 | local_counter[intersection]++; |
| 430 | } |
| 431 | } |
| 432 | } |
| 433 | // Start from the largest thread-local map to minimize rehashing. |
| 434 | const auto max_it = std::max_element( |
| 435 | thread_counters.begin(), |
| 436 | thread_counters.end(), |
| 437 | [](const auto& a, const auto& b) { return a.size() < b.size(); }); |
| 438 | visibility_counter = std::move(*max_it); |
| 439 | for (auto& tc : thread_counters) { |
| 440 | if (&tc == &*max_it) continue; |
| 441 | for (auto& [facet, count] : tc) { |
| 442 | visibility_counter[facet] += count; |
| 443 | } |
| 444 | } |
| 445 | LOG(INFO) << "Visibility counter has " << visibility_counter.size() |
| 446 | << " entries."; |
| 447 | } |
| 448 | |
| 449 | // Run advancing front surface reconstruction. |
no test coverage detected