int main (int argc, char** argv) { // Points with normals. Pwn_vector points; // Loading point set from a file. std::ifstream stream(argc>1 ? argv[1] : "data/cube.pwn"); if (!stream || !CGAL::read_xyz_points(stream, std::back_inserter(points), CGAL::parameters::point_map(Point_map()). normal_map(Normal_map()))) { std::cerr << "Error: cannot read file cube.pwn" << std::endl; return EXIT_FAILURE; } std::cerr << points.size() << " point(s) read." << std::endl; // Shape detection Efficient_ransac ransac; ransac.set_input(points); ransac.add_shape_factory<Plane>(); ransac.detect(); Efficient_ransac::Plane_range planes = ransac.planes(); Pwn_vector structured_pts; CGAL::structure_point_set (points, planes, std::back_inserter (structured_pts), 0.015, // epsilon for structuring points CGAL::parameters::point_map (Point_map()). normal_map (Normal_map()). plane_map (CGAL::Shape_detection_3::Plane_map<Traits>()). plane_index_map (CGAL::Shape_detection_3::Point_to_shape_index_map<Traits>(points, planes))); std::cerr << structured_pts.size () << " structured point(s) generated." << std::endl; std::ofstream out ("out.pwn"); CGAL::write_xyz_points (out, structured_pts, CGAL::parameters::point_map(Point_map()).normal_map(Normal_map())); out.close(); return EXIT_SUCCESS; }
bool test_torus_connected_component() { const int NB_ROUNDS = 10; const int NB_POINTS = 2000; typedef typename K::FT FT; typedef CGAL::Point_with_normal_3<K> Pwn; typedef CGAL::Point_3<K> Point; typedef CGAL::Vector_3<K> Vector; typedef std::vector<Pwn> Pwn_vector; typedef CGAL::Identity_property_map<Pwn> Point_map; typedef CGAL::Normal_of_point_with_normal_map<K> Normal_map; typedef CGAL::Shape_detection_3::Shape_detection_traits< K, Pwn_vector, Point_map, Normal_map> Traits; typedef CGAL::Shape_detection_3::Efficient_RANSAC<Traits> Efficient_ransac; typedef CGAL::Shape_detection_3::Torus<Traits> Torus; std::size_t success = 0; for (int i = 0;i<NB_ROUNDS;i++) { Pwn_vector points; // generate random points on torus CGAL::Bbox_3 bbox(-10, -10, -10, 10, 10, 10); FT minor_radius = (FT) 0.7; FT major_radius = (FT) 2.0; Vector axis = random_normal<K>(); Point center = random_point_in<K>(bbox); sample_torus(NB_POINTS, center, axis, major_radius, minor_radius, std::back_inserter(points)); CGAL::Vector_3<K> n = random_normal<K>(); n = CGAL::cross_product(axis, n); n = n * (FT) 1.0 / (CGAL::sqrt(n.squared_length())); CGAL::Plane_3<K> pl(center, n); FT spacing = (FT) 1; filter_by_distance(pl, spacing * FT(0.5), points); Efficient_ransac ransac; ransac.template add_shape_factory<Torus>(); ransac.set_input(points); // Same parameters as for the parameters unit tests, besides // the cluster_epsilon. typename Efficient_ransac::Parameters parameters; parameters.probability = 0.05f; parameters.min_points = points.size()/10; parameters.epsilon = 0.002f; parameters.normal_threshold = 0.9f; // The first half of rounds choose a high cluster_epsilon to get only // a single shape and a lower cluster_epsilon for the second half // to get two separated shapes. if (i < NB_ROUNDS/2) parameters.cluster_epsilon = spacing * (FT) 1.5; else parameters.cluster_epsilon = spacing * (FT) 0.9; if (!ransac.detect(parameters)) { std::cout << " aborted" << std::endl; return false; } typename Efficient_ransac::Shape_range shapes = ransac.shapes(); if (i < NB_ROUNDS/2 && shapes.size() != 1) continue; if (i >= NB_ROUNDS/2 && shapes.size() != 2) continue; success++; } if (success >= NB_ROUNDS * 0.8) { std::cout << " succeeded" << std::endl; return true; } else { std::cout << " failed" << std::endl; return false; } }
bool test_sphere_parameters() { const int NB_ROUNDS = 10; const int NB_POINTS = 1000; typedef typename K::FT FT; typedef CGAL::Point_with_normal_3<K> Pwn; typedef CGAL::Point_3<K> Point; typedef std::vector<Pwn> Pwn_vector; typedef CGAL::Identity_property_map<Pwn> Point_map; typedef CGAL::Normal_of_point_with_normal_pmap<K> Normal_map; typedef CGAL::Shape_detection_3::Efficient_RANSAC_traits< K, Pwn_vector, Point_map, Normal_map> Traits; typedef CGAL::Shape_detection_3::Efficient_RANSAC<Traits> Efficient_ransac; typedef CGAL::Shape_detection_3::Sphere<Traits> Sphere; std::size_t success = 0; for (int i = 0;i<NB_ROUNDS;i++) { Pwn_vector points; // generate random points on random sphere FT radius = 0; Point center; CGAL::Bbox_3 bbox(-10, -10, -10, 10, 10, 10); sample_random_sphere_in_box(NB_POINTS, bbox, center, radius, std::back_inserter(points)); // add outliers in second half of rounds if (i >= NB_ROUNDS / 2) for (std::size_t j = 0; j < NB_POINTS / 2; j++) points.push_back(random_pwn_in<K>(bbox)); Efficient_ransac ransac; Traits traits = ransac.traits(); ransac.template add_shape_factory<Sphere>(); ransac.set_input(points); // Set cluster epsilon to a high value as just the parameters of // the extracted primitives are to be tested. typename Efficient_ransac::Parameters parameters; parameters.probability = 0.05f; parameters.min_points = NB_POINTS/10; parameters.epsilon = 0.002f; parameters.cluster_epsilon = 1.0f; parameters.normal_threshold = 0.9f; if (!ransac.detect(parameters)) { std::cout << " aborted" << std::endl; return false; } typename Efficient_ransac::Shape_range shapes = ransac.shapes(); // check: unique shape detected if (shapes.size() != 1) continue; boost::shared_ptr<Sphere> sphere = boost::dynamic_pointer_cast<Sphere>((*shapes.first)); // check: shape detected is a cylinder if (!sphere) continue; // Check radius and alignment with axis. if (CGAL::abs(radius - sphere->radius()) > (FT) 0.02) continue; // Check center. Point pos = sphere->center(); FT center_pos_sqlen = traits.compute_squared_length_3_object()( traits.construct_vector_3_object()(center, pos)); if (center_pos_sqlen > FT(0.0004)) continue; std::string info = sphere->info(); success++; } if (success >= NB_ROUNDS * 0.8) { std::cout << " succeeded" << std::endl; return true; } else { std::cout << " failed" << std::endl; return false; } }
bool test_plane_connected_component() { const int NB_ROUNDS = 10; typedef typename K::FT FT; typedef CGAL::Point_with_normal_3<K> Pwn; typedef CGAL::Point_3<K> Point; typedef CGAL::Vector_3<K> Vector; typedef std::vector<Pwn> Pwn_vector; typedef CGAL::Identity_property_map<Pwn> Point_map; typedef CGAL::Normal_of_point_with_normal_map<K> Normal_map; typedef typename CGAL::Shape_detection_3::Shape_detection_traits<K, Pwn_vector, Point_map, Normal_map> Traits; typedef typename CGAL::Shape_detection_3::Efficient_RANSAC<Traits> Efficient_ransac; typedef typename CGAL::Shape_detection_3::Plane<Traits> Plane; std::size_t success = 0; for (int i = 0 ; i < NB_ROUNDS ; i++) { Pwn_vector points; Vector normal; CGAL::Bbox_3 bbox(-10, -10, -10, 10, 10, 10); // Sample 4 rectangles with 0.05 spacing between points // and 0.2 spacing between rectangles. Vector offset[] = {Vector((FT) 0, (FT) 0, (FT) 0), Vector((FT) 1.2, (FT) 0, (FT) 0), Vector((FT) 0, (FT) 1.2, (FT) 0), Vector((FT) 1.2, (FT) 1.2, (FT) 0)}; for (std::size_t j = 0;j<4;j++) { for (std::size_t x = 0;x<=20;x++) for (std::size_t y = 0;y<=20;y++) points.push_back(Pwn(Point(FT(x * 0.05), FT(y * 0.05), (FT) 1.0) + offset[j], Vector((FT) 0, (FT) 0, (FT) 1))); } Efficient_ransac ransac; ransac.template add_shape_factory<Plane>(); ransac.set_input(points); // Same parameters as for the parameters unit tests, besides // the cluster_epsilon. typename Efficient_ransac::Parameters parameters; parameters.probability = 0.05f; parameters.min_points = 100; parameters.epsilon = 0.002f; parameters.normal_threshold = 0.9f; // For the first half the rounds chose a high cluster_epsilon to find one // shape and for the second half choose a small cluster_epsilon to find // four separated shapes. if (i < NB_ROUNDS/2) parameters.cluster_epsilon = 0.201f; else parameters.cluster_epsilon = 0.051f; if (!ransac.detect(parameters)) { std::cout << " aborted" << std::endl; return false; } typename Efficient_ransac::Shape_range shapes = ransac.shapes(); if (i < NB_ROUNDS/2 && shapes.size() != 1) continue; if (i >= NB_ROUNDS/2 && shapes.size() != 4) continue; success++; } if (success >= NB_ROUNDS * 0.8) { std::cout << " succeeded" << std::endl; return true; } else { std::cout << " failed" << std::endl; return false; } }