Example #1
0
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_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_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;
  }
}