mirror of https://github.com/CGAL/cgal
164 lines
5.3 KiB
C++
164 lines
5.3 KiB
C++
#include "include/test_efficient_RANSAC_generators.h"
|
|
|
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
|
#include <CGAL/IO/read_points.h>
|
|
#include <CGAL/Simple_cartesian.h>
|
|
|
|
#include <CGAL/Shape_detection/Efficient_RANSAC.h>
|
|
#include <CGAL/Shape_regularization/regularize_planes.h>
|
|
#include <CGAL/Point_with_normal_3.h>
|
|
#include <CGAL/property_map.h>
|
|
|
|
template <class K>
|
|
bool test_scene(int argc, char** argv) {
|
|
|
|
typedef typename K::FT FT;
|
|
typedef CGAL::Point_with_normal_3<K> Pwn;
|
|
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::Efficient_RANSAC_traits<K, Pwn_vector, Point_map, Normal_map> Traits;
|
|
typedef CGAL::Shape_detection::Efficient_RANSAC<Traits> Efficient_ransac;
|
|
|
|
typedef typename Efficient_ransac::Point_index_range Point_index_range;
|
|
|
|
typedef CGAL::Shape_detection::Plane<Traits> Plane;
|
|
typedef CGAL::Shape_detection::Cone<Traits> Cone;
|
|
typedef CGAL::Shape_detection::Cylinder<Traits> Cylinder;
|
|
typedef CGAL::Shape_detection::Sphere<Traits> Sphere;
|
|
typedef CGAL::Shape_detection::Torus<Traits> Torus;
|
|
|
|
Pwn_vector points;
|
|
|
|
// Load point set from a file.
|
|
// read_points takes an OutputIterator for storing the points
|
|
// and a property map to store the normal vector with each point.
|
|
const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("points_3/cube.pwn");
|
|
|
|
if (!CGAL::IO::read_points(filename, 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;
|
|
}
|
|
|
|
Efficient_ransac ransac;
|
|
|
|
ransac.template add_shape_factory<Cone>();
|
|
|
|
ransac.clear_shape_factories();
|
|
|
|
ransac.template add_shape_factory<Cone>();
|
|
ransac.template add_shape_factory<Cylinder>();
|
|
ransac.template add_shape_factory<Plane>();
|
|
ransac.template add_shape_factory<Sphere>();
|
|
ransac.template add_shape_factory<Torus>();
|
|
|
|
ransac.set_input(points);
|
|
|
|
ransac.preprocess();
|
|
|
|
ransac.clear_octrees();
|
|
|
|
if (!ransac.detect()) {
|
|
std::cout << " aborted" << std::endl;
|
|
return false;
|
|
}
|
|
|
|
typename Efficient_ransac::Shape_range shapes = ransac.shapes();
|
|
|
|
typename Efficient_ransac::Shape_range::iterator it = shapes.begin();
|
|
|
|
FT average_distance = 0;
|
|
|
|
// Iterate through all shapes and access each point.
|
|
while (it != shapes.end()) {
|
|
std::shared_ptr<typename Efficient_ransac::Shape> shape = *it;
|
|
|
|
// Sum distances of points to detected shapes.
|
|
FT sum_distances = 0;
|
|
|
|
// Iterate through point indices assigned to each detected shape.
|
|
std::vector<std::size_t>::const_iterator
|
|
index_it = (*it)->indices_of_assigned_points().begin();
|
|
|
|
while (index_it != (*it)->indices_of_assigned_points().end()) {
|
|
|
|
// Retrieve point.
|
|
const Pwn &p = *(points.begin() + (*index_it));
|
|
|
|
// Add Euclidean distance between point and shape.
|
|
sum_distances += CGAL::sqrt((*it)->squared_distance(p));
|
|
|
|
// Proceed with next point.
|
|
index_it++;
|
|
}
|
|
|
|
// Compute average distance.
|
|
average_distance += sum_distances / shape->indices_of_assigned_points().size();
|
|
|
|
// Proceed with next detected shape.
|
|
it++;
|
|
}
|
|
|
|
// Check coverage. For this scene it should not fall below 75%.
|
|
double coverage = double(points.size() - ransac.number_of_unassigned_points()) / double(points.size());
|
|
if (coverage < 0.75) {
|
|
std::cout << " failed (coverage = " << coverage << " < 0.75)" << std::endl;
|
|
|
|
return false;
|
|
}
|
|
|
|
// Check average distance. It should not lie above 0.02.
|
|
average_distance = average_distance / shapes.size();
|
|
std::cout << average_distance << " " << std::endl;
|
|
if (average_distance > 0.02) {
|
|
std::cout << " failed" << std::endl;
|
|
|
|
return false;
|
|
}
|
|
|
|
// Test regularization
|
|
typename Efficient_ransac::Plane_range planes = ransac.planes();
|
|
CGAL::Shape_regularization::Planes::
|
|
regularize_planes(
|
|
planes,
|
|
CGAL::Shape_detection::Plane_map<Traits>(),
|
|
points,
|
|
Point_map(),
|
|
CGAL::parameters::plane_index_map(
|
|
CGAL::Shape_detection::Point_to_shape_index_map<Traits>(points, planes)).
|
|
regularize_parallelism(true).
|
|
regularize_orthogonality(true).
|
|
regularize_coplanarity(true).
|
|
regularize_axis_symmetry(true).
|
|
maximum_angle(FT(50)).
|
|
maximum_offset(FT(1) / FT(100)));
|
|
|
|
Point_index_range pts = ransac.indices_of_unassigned_points();
|
|
|
|
std::cout << " succeeded" << std::endl;
|
|
|
|
return true;
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
bool success = true;
|
|
|
|
std::cout << "test_scene<CGAL::Simple_cartesian<float>> ";
|
|
if (!test_scene<CGAL::Simple_cartesian<float> >(argc, argv))
|
|
success = false;
|
|
|
|
// std::cout << "test_scene<CGAL::Simple_cartesian<double>> ";
|
|
// if (!test_scene<CGAL::Simple_cartesian<double> >(argc, argv))
|
|
// success = false;
|
|
//
|
|
// std::cout << "test_scene<CGAL::Exact_predicates_inexact_constructions_kernel> ";
|
|
// if (!test_scene<CGAL::Exact_predicates_inexact_constructions_kernel>(argc, argv))
|
|
// success = false;
|
|
|
|
return (success) ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
}
|