diff --git a/Kinetic_surface_reconstruction/examples/Kinetic_surface_reconstruction/parameters.cpp b/Kinetic_surface_reconstruction/examples/Kinetic_surface_reconstruction/parameters.cpp index 00883e0c43a..8431281b6ac 100644 --- a/Kinetic_surface_reconstruction/examples/Kinetic_surface_reconstruction/parameters.cpp +++ b/Kinetic_surface_reconstruction/examples/Kinetic_surface_reconstruction/parameters.cpp @@ -105,6 +105,11 @@ int main(const int argc, const char** argv) { Point_set point_set(parameters.with_normals); CGAL::IO::read_point_set(parameters.data, point_set); + if (point_set.size() == 0) { + std::cout << "input file not found or empty!" << std::endl; + return EXIT_FAILURE; + } + if (!point_set.has_normal_map()) { point_set.add_normal_map(); CGAL::pca_estimate_normals(point_set, 9); @@ -195,7 +200,7 @@ int main(const int argc, const char** argv) { FT after_reconstruction = timer.time(); if (polylist.size() > 0) - CGAL::IO::write_polygon_soup("polylist_" + std::to_string(parameters.graphcut_beta) + ".off", vtx, polylist); + CGAL::IO::write_polygon_soup("polylist_" + std::to_string(parameters.graphcut_beta) + (parameters.use_ground ? "_g" : "_") + ".off", vtx, polylist); timer.stop(); const FT time = static_cast(timer.time()); @@ -217,7 +222,7 @@ int main(const int argc, const char** argv) { if (polylist.size() > 0) - CGAL::IO::write_polygon_soup("polylist_" + std::to_string(l) + ".off", vtx, polylist); + CGAL::IO::write_polygon_soup("polylist_" + std::to_string(l) + (parameters.use_ground ? "_g" : "_") + ".off", vtx, polylist); } std::cout << "Shape detection: " << after_shape_detection << " seconds!" << std::endl; diff --git a/Kinetic_surface_reconstruction/include/CGAL/Kinetic_surface_reconstruction_3.h b/Kinetic_surface_reconstruction/include/CGAL/Kinetic_surface_reconstruction_3.h index 5db2233c5c6..e6f19816b89 100644 --- a/Kinetic_surface_reconstruction/include/CGAL/Kinetic_surface_reconstruction_3.h +++ b/Kinetic_surface_reconstruction/include/CGAL/Kinetic_surface_reconstruction_3.h @@ -705,7 +705,8 @@ private: collect_points_for_faces_lcc(); count_volume_votes_lcc(); - std::cout << "* computing data term ... "; + if (m_verbose) + std::cout << "* computing data term ... "; std::size_t max_inside = 0, max_outside = 0; for (std::size_t i = 0; i < m_volumes.size(); i++) { @@ -1869,47 +1870,50 @@ private: } // Estimate ground plane by finding a low mostly horizontal plane - { - std::vector candidates; - FT low_z_peak = (std::numeric_limits::max)(); - FT bbox_min[] = { (std::numeric_limits::max)(), (std::numeric_limits::max)(), (std::numeric_limits::max)() }; - FT bbox_max[] = { -(std::numeric_limits::max)(), -(std::numeric_limits::max)(), -(std::numeric_limits::max)() }; - for (const auto& p : m_points) { - const auto& point = get(m_point_map, p); - for (std::size_t i = 0; i < 3; i++) { - bbox_min[i] = (std::min)(point[i], bbox_min[i]); - bbox_max[i] = (std::max)(point[i], bbox_max[i]); - } + std::vector candidates; + FT low_z_peak = (std::numeric_limits::max)(); + FT bbox_min[] = { (std::numeric_limits::max)(), (std::numeric_limits::max)(), (std::numeric_limits::max)() }; + FT bbox_max[] = { -(std::numeric_limits::max)(), -(std::numeric_limits::max)(), -(std::numeric_limits::max)() }; + for (const auto& p : m_points) { + const auto& point = get(m_point_map, p); + for (std::size_t i = 0; i < 3; i++) { + bbox_min[i] = (std::min)(point[i], bbox_min[i]); + bbox_max[i] = (std::max)(point[i], bbox_max[i]); } + } - FT bbox_center[] = { 0.5 * (bbox_min[0] + bbox_max[0]), 0.5 * (bbox_min[1] + bbox_max[1]), 0.5 * (bbox_min[2] + bbox_max[2]) }; + FT bbox_center[] = { 0.5 * (bbox_min[0] + bbox_max[0]), 0.5 * (bbox_min[1] + bbox_max[1]), 0.5 * (bbox_min[2] + bbox_max[2]) }; - for (std::size_t i = 0; i < m_regions.size(); i++) { - Vector_3 d = m_regions[i].first.orthogonal_vector(); - if (abs(d.z()) > 0.98) { - candidates.push_back(i); - FT z = m_regions[i].first.projection(Point_3(bbox_center[0], bbox_center[1], bbox_center[2])).z(); - low_z_peak = (std::min)(z, low_z_peak); - } + for (std::size_t i = 0; i < m_regions.size(); i++) { + Vector_3 d = m_regions[i].first.orthogonal_vector(); + if (abs(d.z()) > 0.98) { + candidates.push_back(i); + FT z = m_regions[i].first.projection(Point_3(bbox_center[0], bbox_center[1], bbox_center[2])).z(); + low_z_peak = (std::min)(z, low_z_peak); } + } - m_ground_polygon_index = -1; - std::vector other_ground; - for (std::size_t i = 0; i < candidates.size(); i++) { - Vector_3 d = m_regions[candidates[i]].first.orthogonal_vector(); - FT z = m_regions[candidates[i]].first.projection(Point_3(bbox_center[0], bbox_center[1], bbox_center[2])).z(); - if (z - low_z_peak < max_distance_to_plane) { - if (m_ground_polygon_index == -1) - m_ground_polygon_index = candidates[i]; - else - other_ground.push_back(candidates[i]); - } + m_ground_polygon_index = -1; + std::vector other_ground; + for (std::size_t i = 0; i < candidates.size(); i++) { + Vector_3 d = m_regions[candidates[i]].first.orthogonal_vector(); + FT z = m_regions[candidates[i]].first.projection(Point_3(bbox_center[0], bbox_center[1], bbox_center[2])).z(); + if (z - low_z_peak < max_distance_to_plane) { + if (m_ground_polygon_index == -1) + m_ground_polygon_index = candidates[i]; + else + other_ground.push_back(candidates[i]); } + } + + if (m_ground_polygon_index != -1) { for (std::size_t i = 0; i < other_ground.size(); i++) std::move(m_regions[other_ground[i]].second.begin(), m_regions[other_ground[i]].second.end(), std::back_inserter(m_regions[m_ground_polygon_index].second)); - std::cout << "ground polygon " << m_ground_polygon_index << ", merging other polygons"; + if (m_verbose) + std::cout << "ground polygon " << m_ground_polygon_index << ", merging other polygons"; + while (other_ground.size() != 0) { m_regions.erase(m_regions.begin() + other_ground.back()); std::cout << " " << other_ground.back(); @@ -1941,7 +1945,8 @@ private: //KSP_3::dump_polygon(polys_debug[i], std::to_string(i) + "-detected-region.ply"); } - KSP_3::internal::dump_polygons(polys_debug, "merged-" + std::to_string(m_regions.size()) + "-polygons.ply"); + if (m_debug) + KSP_3::internal::dump_polygons(polys_debug, "merged-" + std::to_string(m_regions.size()) + "-polygons.ply"); std::vector pl; @@ -1970,8 +1975,10 @@ private: } CGAL_assertion(m_planar_regions.size() == m_regions.size()); - std::cout << "found " << num_shapes << " planar shapes regularized into " << m_planar_regions.size() << std::endl; - std::cout << "from " << m_points.size() << " input points " << unassigned << " remain unassigned" << std::endl; + if (m_verbose) { + std::cout << "found " << num_shapes << " planar shapes regularized into " << m_planar_regions.size() << std::endl; + std::cout << "from " << m_points.size() << " input points " << unassigned << " remain unassigned" << std::endl; + } } void map_points_to_faces(const std::size_t polygon_index, const std::vector& pts, std::vector > >& face_to_points) { diff --git a/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/CMakeLists.txt b/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/CMakeLists.txt index c7c8ef28984..dd3b82ff517 100644 --- a/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/CMakeLists.txt +++ b/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/CMakeLists.txt @@ -19,7 +19,7 @@ if(Boost_FOUND) message(STATUS "Found Eigen") include(CGAL_Eigen_support) - set(targets ksr_test) + set(targets ksr_test ksr_reorientation ksr_regularization) set(project_linked_libraries) set(project_compilation_definitions) diff --git a/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/hilbert_cube.ply b/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/hilbert_cube.ply new file mode 100644 index 00000000000..baf5fc3fedc Binary files /dev/null and b/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/hilbert_cube.ply differ diff --git a/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/ksr_regularization.cpp b/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/ksr_regularization.cpp new file mode 100644 index 00000000000..aa85bfa209b --- /dev/null +++ b/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/ksr_regularization.cpp @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include + +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +using FT = typename Kernel::FT; +using Point_3 = typename Kernel::Point_3; +using Vector_3 = typename Kernel::Vector_3; +using Segment_3 = typename Kernel::Segment_3; + +using Point_set = CGAL::Point_set_3; +using Point_map = typename Point_set::Point_map; +using Normal_map = typename Point_set::Vector_map; + +using KSR = CGAL::Kinetic_surface_reconstruction_3; + +int main(const int argc, const char** argv) { + // Input. + + Point_set point_set; + CGAL::IO::read_point_set("hilbert_cube.ply", point_set); + + auto with_reg = CGAL::parameters::maximum_distance(0.1) + .maximum_angle(10) + .k_neighbors(12) + .minimum_region_size(10) + .regularize_coplanarity(true) + .regularize_parallelism(true) + .maximum_offset(0.1) + .angle_tolerance(10) + .debug(true); + + auto without_reg = CGAL::parameters::maximum_distance(0.1) + .maximum_angle(10) + .k_neighbors(12) + .minimum_region_size(10) + .regularize_coplanarity(false) + .regularize_parallelism(false); + + // Algorithm. + KSR ksr(point_set); + + ksr.detect_planar_shapes(without_reg); + + std::size_t detected = ksr.detected_planar_shapes().size(); + + ksr.detect_planar_shapes(with_reg); + + std::size_t regularized = ksr.detected_planar_shapes().size(); + + std::cout << detected << " planar shapes regularized into " << regularized << std::endl; + + return regularized < detected ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/ksr_reorientation.cpp b/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/ksr_reorientation.cpp new file mode 100644 index 00000000000..85fe1f9ee6d --- /dev/null +++ b/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/ksr_reorientation.cpp @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include + +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +using FT = typename Kernel::FT; +using Point_3 = typename Kernel::Point_3; +using Vector_3 = typename Kernel::Vector_3; +using Segment_3 = typename Kernel::Segment_3; + +using Point_set = CGAL::Point_set_3; +using Point_map = typename Point_set::Point_map; +using Normal_map = typename Point_set::Vector_map; + +using KSR = CGAL::Kinetic_surface_reconstruction_3; + +int main(const int argc, const char** argv) { + // Input. + + Point_set point_set; + CGAL::IO::read_point_set("Cottage_cut.ply", point_set); + + auto param = CGAL::parameters::maximum_distance(0.33) + .maximum_angle(32) + .k_neighbors(12) + .minimum_region_size(330) + .reorient_bbox(false); + + // Algorithm. + KSR ksr(point_set, param); + + ksr.detection_and_partition(1, param); + + std::vector vtx; + std::vector > polylist; + + bool failed = false; + + ksr.reconstruct_with_ground(0.5, std::back_inserter(vtx), std::back_inserter(polylist)); + + if (vtx.size() != 314 && polylist.size() != 91) { + std::cerr << "reconstruction with reorientation and ground estimation set to outside provided wrong result: #vtx " << vtx.size() << " expected: 314, #polys: " << polylist.size() << " expected: 91" << std::endl; + failed = true; + } + + if (!failed) + std::cout << "done!"; + + return failed ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/ksr_test.cpp b/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/ksr_test.cpp index 5292b9b6e58..56e8632a254 100644 --- a/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/ksr_test.cpp +++ b/Kinetic_surface_reconstruction/test/Kinetic_surface_reconstruction/ksr_test.cpp @@ -25,13 +25,18 @@ int main(const int argc, const char** argv) { auto param = CGAL::parameters::maximum_distance(0.05) .maximum_angle(10) .k_neighbors(12) - .minimum_region_size(50); + .minimum_region_size(50) + .regularize_coplanarity(true) + .regularize_parallelism(true) + .maximum_offset(0.1); // Algorithm. KSR ksr(point_set, param); ksr.detection_and_partition(1, param); + std::cout << ksr.detected_planar_shapes().size() << " planar shapes" << std::endl; + std::vector vtx; std::vector > polylist; @@ -66,5 +71,8 @@ int main(const int argc, const char** argv) { failed = true; } + if (!failed) + std::cout << "done!"; + return failed ? EXIT_FAILURE : EXIT_SUCCESS; }