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.