# CGAL function pointer callback in isosurface example

## weblog/

I really struggled with the CGAL templating madness in their isosurface example today. The following example contours the 0-level isosurface given an implicit function of a sphere (i.e. a pointer to a function `sphere_function`):

``````#include <CGAL/Surface_mesh_default_triangulation_3.h>
#include <CGAL/Complex_2_in_triangulation_3.h>
#include <CGAL/make_surface_mesh.h>
#include <CGAL/Implicit_surface_3.h>
// default triangulation for Surface_mesher
typedef CGAL::Surface_mesh_default_triangulation_3 Tr;
// c2t3
typedef CGAL::Complex_2_in_triangulation_3<Tr> C2t3;
typedef Tr::Geom_traits GT;
typedef GT::Sphere_3 Sphere_3;
typedef GT::Point_3 Point_3;
typedef GT::FT FT;
typedef FT (*Function)(Point_3);
typedef CGAL::Implicit_surface_3<GT, Function> Surface_3;
FT sphere_function (Point_3 p) {
const FT x2=p.x()*p.x(), y2=p.y()*p.y(), z2=p.z()*p.z();
return x2+y2+z2-1;
}
int main() {
Tr tr;            // 3D-Delaunay triangulation
C2t3 c2t3 (tr);   // 2D-complex in 3D-Delaunay triangulation
// defining the surface
Surface_3 surface(sphere_function,             // pointer to function
Sphere_3(CGAL::ORIGIN, 2.)); // bounding sphere
// Note that "2." above is the *squared* radius of the bounding sphere!
// defining meshing criteria
CGAL::Surface_mesh_default_criteria_3<Tr> criteria(30.,  // angular bound
0.1); // distance bound
// meshing surface
CGAL::make_surface_mesh(c2t3, surface, criteria, CGAL::Non_manifold_tag());
std::cout << "Final number of points: " << tr.number_of_vertices() << "\n";
}
``````

I wanted to adapt this example to use a different implicit function, so I tried creating a sphere function that also took another parameter (x-axis scaling):

``````FT scale_sphere_function (double a,Point_3 p) {
const FT x2=a*p.x()*p.x(), y2=p.y()*p.y(), z2=p.z()*p.z();
return x2+y2+z2-1;
}
``````

Then my idea was to use `std::bind` to bind a local variable or value to the first argument so I could pass it to `Surface_3`. Something like

``````double a = 2.0;
Surface_3 surface(
std::bind(&scale_sphere_function,a,std::placeholders::_1),
Sphere_3(CGAL::ORIGIN, 2.)); // bounding sphere
``````

But I get compiler errors because it's trying to convert the `std::bind` output (`std::function<>`) to a function pointer:

``````/opt/local/include/CGAL/Implicit_surface_3.h:50:5: note: CGAL::Implicit_surface_3<GT, Function_>::Implicit_surface_3(CGAL::Implicit_surface_3<GT, Function_>::Function, CGAL::Implicit_surface_3<GT, Function_>::Sphere_3, CGAL::Implicit_surface_3<GT, Function_>::FT, CGAL::Implicit_surface_3<GT, Function_>::Geom_traits) [with GT = CGAL::Robust_circumcenter_traits_3<CGAL::Epick>; Function_ = double (*)(CGAL::Point_3<CGAL::Epick>); CGAL::Implicit_surface_3<GT, Function_>::Function = double (*)(CGAL::Point_3<CGAL::Epick>); CGAL::Implicit_surface_3<GT, Function_>::Sphere_3 = CGAL::Sphere_3<CGAL::Epick>; CGAL::Implicit_surface_3<GT, Function_>::FT = double; CGAL::Implicit_surface_3<GT, Function_>::Geom_traits = CGAL::Robust_circumcenter_traits_3<CGAL::Epick>]
/opt/local/include/CGAL/Implicit_surface_3.h:50:5: note:   no known conversion for argument 1 from 'std::_Bind_helper<false, double (&)(double, CGAL::Point_3<CGAL::Epick>), int, const std::_Placeholder<1>&>::type {aka std::_Bind<double (*(int, std::_Placeholder<1>))(double, CGAL::Point_3<CGAL::Epick>)>}' to 'CGAL::Implicit_surface_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, double (*)(CGAL::Point_3<CGAL::Epick>)>::Function {aka double (*)(CGAL::Point_3<CGAL::Epick>)}'
/opt/local/include/CGAL/Implicit_surface_3.h:34:9: note: constexpr CGAL::Implicit_surface_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, double (*)(CGAL::Point_3<CGAL::Epick>)>::Implicit_surface_3(const CGAL::Implicit_surface_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, double (*)(CGAL::Point_3<CGAL::Epick>)>&)
/opt/local/include/CGAL/Implicit_surface_3.h:34:9: note:   candidate expects 1 argument, 2 provided
/opt/local/include/CGAL/Implicit_surface_3.h:34:9: note: constexpr CGAL::Implicit_surface_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, double (*)(CGAL::Point_3<CGAL::Epick>)>::Implicit_surface_3(CGAL::Implicit_surface_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, double (*)(CGAL::Point_3<CGAL::Epick>)>&&)
/opt/local/include/CGAL/Implicit_surface_3.h:34:9: note:   candidate expects 1 argument, 2 provided
``````

I tried all sorts of conversions and casts and uses of `target()` (which is pointless and only works when you originally started with a function pointer) to twist my `std::bind` into a function pointer. But the problem turned out to be very simple. The example had defined `Surface_3` to use a function pointer:

``````typedef FT (*Function)(Point_3);
typedef CGAL::Implicit_surface_3<GT, Function> Surface_3;
``````

I can just define it to use a `std::function<>` instead:

``````typedef std::function<FT (Point_3)> Function;
typedef CGAL::Implicit_surface_3<GT, Function> Surface_3;
``````

Then I can create a `Surface_3` with `std::bind`:

``````double a = 2.0;
Surface_3 surface(
std::bind(&sphere_function,a,std::placeholders::_1),
Sphere_3(CGAL::ORIGIN, 2.)); // bounding sphere
``````

or even an inline lambda with capturing:

``````Surface_3 surface(
[&a](Point_3 p)->FT{ return sphere_function(a,p);},
Sphere_3(CGAL::ORIGIN, 2.)); // bounding sphere
``````

I'm apparently not the only one with problem. Probably CGAL should just use `std::function` or `boost::function` in the example since it's easy to convert to those from a function pointer (but as I learned it's impossible the other way).