\chapter{Extensible Kernel} \section{Introduction} The following manual sections describe how users can plug user defined geometric classes in existing \cgal\ kernels. \section{The Anatomy of a Kernel} \subsection{Introduction} \cgal\ defines the concept of a geometry kernel. Such a kernel provides types, construction objects and generalized predicates. Most implementations of Computational Geometry algorithms and data structures in the basic library of \cgal\ were done in a way that classes or functions can be parametrized with a geometric traits class. In most cases this geometric traits class must be a model of the \cgal\ geometry kernel concept (but there are some exceptions). \subsection{An Example} Assume you have the following point class, where the coordinates are stored in an array of \ccc{doubles}, where we have another data member \ccc{color}, which shows up in the constructor. \ccHtmlLinksOff \begin{ccExampleCode} class MyPointC2 { private: double vec[2]; int col; public: MyPointC2() : col(0) { *vec = 0; *(vec+1) = 0; } MyPointC2(const double x, const double y, int c) : col(c) { *vec = x; *(vec+1) = y; } const double& x() const { return *vec; } const double& y() const { return *(vec+1); } double & x() { return *vec; } double& y() { return *(vec+1); } int color() const { return col; } int& color() { return col; } bool operator==(const MyPointC2 &p) const { return ( *vec == *(p.vec) ) && ( *(vec+1) == *(p.vec + 1) && ( col == p.col) ); } bool operator!=(const MyPointC2 &p) const { return !(*this == p); } }; \end{ccExampleCode} \ccHtmlLinksOn As said earlier the class is pretty minimalistic, for example it has no \ccc{bbox()} method. One might assume that a basic library algorithm which computes a bounding box (e.g, to compute the bounding box of a polygon), will not compile. Luckily it will, because it does not use of member functions of geometric objects, but it makes use of the functor \ccc{Kernel::Construct_bbox_2}. To make the right thing happen with \ccc{MyPointC2} we have to provide the following functor. \ccHtmlLinksOff \begin{ccExampleCode} template class MyConstruct_bbox_2 : public ConstructBbox_2 { public: CGAL::Bbox_2 operator()(const typename MyPointC2& p) const { return CGAL::Bbox_2(p.x(), p.y(), p.x(), p.y()); } }; \end{ccExampleCode} \ccHtmlLinksOn Things are similar for random access to the \ccHtmlNoLinksFrom{Cartesian} coordinates of a point. As the coordinates are stored in an array of \ccc{doubles} we can use \ccc{double*} as random access iterator. \ccHtmlLinksOff \begin{ccExampleCode} class MyConstruct_coord_iterator { public: const double* operator()(const MyPointC2& p) { return &p.x(); } const double* operator()(const MyPointC2& p, int) { const double* pyptr = &p.y(); pyptr++; return pyptr; } }; \end{ccExampleCode} \ccHtmlLinksOn The last functor we have to provide is the one which constructs points. That is you are not forced to add the constructor with the \ccc{Origin} as parameter to your class, nor the constructor with homogeneous coordinates, and at the same time you can pass the additional color argument to your point constructor. The functor is a kind of glue layer between the \cgal\ algorithms and your class. \ccHtmlLinksOff \begin{ccExampleCode} template class MyConstruct_point_2 { typedef typename K::RT RT; typedef typename K::Point_2 Point_2; public: typedef Point_2 result_type; typedef CGAL::Arity_tag< 1 > Arity; Point_2 operator()() const { return Point_2(); } Point_2 operator()(CGAL::Origin o) const { return Point_2(0,0, 0); } Point_2 operator()(const RT& x, const RT& y) const { return Point_2(x, y, 0); } // We need this one, as such a functor is in the Filtered_kernel Point_2 operator()(const RT& x, const RT& y, const RT& w) const { if(w != 1){ return Point_2(x/w, y/w, 0); } else { return Point_2(x,y, 0); } } }; \end{ccExampleCode} \ccHtmlLinksOn Now we are ready to put the puzzle together. To do so we scavenge code. We won't explain it in detail, but you see that there are \ccc{typedefs} to the new point class and the functors. All the other types are inherited. \ccHtmlLinksOff \begin{ccExampleCode} #ifndef MYKERNEL_H #define MYKERNEL_H #include #include #include "MyPointC2.h" // Taken from include/CGAL/Cartesian/Cartesian_base.h template < typename K_ > struct MyCartesian_base : public CGAL::Cartesian_base< K_ > { typedef K_ Kernel; typedef CGAL::Cartesian_base< K_ > Base; typedef MyPointC2 Point_2; typedef MyConstruct_point_2 Construct_point_2; typedef const double* Cartesian_const_iterator_2; typedef MyConstruct_coord_iterator Construct_cartesian_const_iterator_2; typedef MyConstruct_bbox_2 Construct_bbox_2; }; // Taken from include/CGAL/Cartesian.h template < typename FT_, typename Kernel > struct MyCartesian_base_no_ref_count : public MyCartesian_base< Kernel > { typedef FT_ RT; typedef FT_ FT; // The mecanism that allows to specify reference-counting or not. template < typename T > struct Handle { typedef CGAL::Simple_Handle_for type; }; template < typename Kernel2 > struct Base { typedef MyCartesian_base_no_ref_count Type; }; static FT make_FT(const RT & num, const RT& denom) { return num/denom;} static FT make_FT(const RT & num) { return num;} static RT FT_numerator(const FT &r) { return r;} static RT FT_denominator(const FT &) { return RT(1);} }; template < typename FT_ > struct MyKernel : public MyCartesian_base_no_ref_count > { public: typedef MyCartesian_base_no_ref_count > Kernel_base; }; CGAL_ITERATOR_TRAITS_POINTER_SPEC_TEMPLATE(MyKernel) #endif // MYKERNEL_H \end{ccExampleCode} \ccHtmlLinksOn Finally, we give an example how this new kernel can be used. \ccHtmlLinksOff \begin{ccExampleCode} #include #include #include ``./MyKernel.h'' #include typedef MyKernel MyK; typedef CGAL::Filtered_kernel K; typedef K::Point_2 Point_2; int main() { std::list input; Point_2 act; input.push_back(act); std::list output; K traits; CGAL::convex_hull_2(input.begin(), input.end(), std::back_inserter(output), traits); return 0; } \end{ccExampleCode} \ccHtmlLinksOn \subsection{Limitations} The point class must have member functions \ccc{x()} and \ccc{y()} (and \ccc{z()} for the 3d point). We work on that. Global functions operating on, for example \ccc{CGAL::Orientation(CGAL::Point_2, CGAL::Point_2, CGAL::Point_2)} will not work. Instead you have to use the functor \ccc{MyKernel::Orientation_2}. Rewriting the code is however pretty easy, as you can give the functor object the same name as the global function.