1

I want to compare the distances between some geometrical objects in a robust way. For instance, I want to measure perpendicular distance between a point and a plane. I want to do this measurement to many planes from the same point. In the end, I want to pick the closest plane to my point.

Since the double/float operations cause inexact computations, I want to do this operation by using CGAL's robustness predicates. However, I do not have the theoretical background about the predicates. I have seen that there are concepts like "Filtered_predicate", "Exact_predicates_inexact_constructions_kernel". I do not which one to use and how to use. Could you help me?

My guess is to define the point and planes with "Exact_predicates_inexact_constructions_kernel". And then call Exact_predicates_inexact_constructions_kernel::FT CGAL::squared_distance(plane, point) method. And then compare the FT result obtained by each plane.Is it a right approach?

Merve A
  • 31
  • 4
  • The easiest safe way would be to use Exact_predicates_exact_constructions_kernel. FT is then an exact (lazy) type, you can compute distances and compare them without caring about precision. With Exact_predicates_inexact_constructions_kernel, you need to make sure you use Compare_squared_distance_3, computing the distance as a separate step would be unsafe. – Marc Glisse Dec 27 '22 at 18:16
  • What is the reason that you care about "robustness" ? Do you believe that your planes are significantly often at similar distances ? If yes, are the planes known accurately ? –  Dec 28 '22 at 10:16
  • The planes are my input, we define them with 3 points and assume they are accurate. This is an academic study and reviewers state that it is acceptable only if my operations are robust. Not only the exactness, but also the performance is important for us. Therefore, I decided to define the planes as inexact_constructions until I find the closest one with compare_squared_distance_3. Then, I plan to find the exact closest distance by defining the found plane with exact_constructions. As far as I understand this should work. Thanks for the reply. – Merve A Dec 28 '22 at 11:28
  • Make sure to handle the cases with several closest planes, then. –  Dec 28 '22 at 11:43
  • You will have to benchmark, but it might be just as fast to use exact constructions directly (they are done lazily). – Marc Glisse Dec 28 '22 at 11:44

1 Answers1

0

I have written the following code by using filtered_predicate. It works for now, yet I did not try with nearly-planar planes.

typedef CGAL::Simple_cartesian<double>                          C;
typedef CGAL::Simple_cartesian<CGAL::Interval_nt_advanced>      FC;
typedef CGAL::Simple_cartesian<CGAL::MP_Float>                  EC;
typedef CGAL::Cartesian_converter<C, EC>                        C2E;
typedef CGAL::Cartesian_converter<C, FC>                        C2F;


template <typename K>
struct my_closest_check {
    typedef typename K::RT                      RT;
    typedef typename K::Point_3                 Point_3;
    typedef typename K::Sphere_3                Sphere_3;
    typedef typename CGAL::Uncertain<bool>      result_type;

    result_type operator()(const Sphere_3& sphere, const Point_3& point) const
    {
        return sphere.has_on_unbounded_side(point);
    }
};

typedef CGAL::Filtered_predicate<my_closest_check<EC>, my_closest_check<FC>, C2E, C2F>      FK;


int find_the_closest_plane(C::Point_3 point, vector<C::Plane_3> plane_set;) {

    int closest_plane_id = 0;
    C::Plane_3 closest_plane = plane_set[closest_plane_id];
    C::FT sq_closest_distance = CGAL::squared_distance(point, closest_plane);
    C::Sphere_3 smallest_sphere = C::Sphere_3(point, sq_closest_distance, CGAL::Orientation::COUNTERCLOCKWISE);

    for (int i = 1; i < plane_set.size(); i++) {
        C::Plane_3 current_plane = plane_set[i];
        C::Point_3 projection_point = current_plane.projection(point);
        FK is_inside;
        if (!is_inside(smallest_sphere, projection_point)) {
            closest_plane_id = i;
            closest_plane = current_plane;
            sq_closest_distance = CGAL::squared_distance(point, closest_plane);
            smallest_sphere = C::Sphere_3(point, sq_closest_distance, CGAL::Orientation::COUNTERCLOCKWISE);
        }
    }

    return closest_plane_id;
}

The only part that I am not sure is whether I should put the whole calculation inside filtered_kernel, or filtering only the in_sphere test is enough. I do not need any interstep computation (like constructing the sphere exactly, finding the point-plane distance, projecting point onto plane) to be accurate, yet I want the latest output (which is the closest plane) to be exact.

Merve A
  • 31
  • 4