\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 ConstructBbox_2>
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 <typename K>
  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 <CGAL/Cartesian/Cartesian_base.h>
#include <CGAL/Simple_Handle_for.h>


#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<Kernel>       Construct_point_2;
  typedef const double*                     Cartesian_const_iterator_2;
  typedef MyConstruct_coord_iterator        Construct_cartesian_const_iterator_2;
  typedef MyConstruct_bbox_2<typename Base::Construct_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<T>   type; };

    template < typename Kernel2 >
    struct Base { typedef MyCartesian_base_no_ref_count<FT_, Kernel2>  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<FT_, MyKernel<FT_> >
{
public:
  typedef MyCartesian_base_no_ref_count<FT_, MyKernel<FT_> > 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 <CGAL/basic.h>
#include <CGAL/convex_hull_2.h>
#include ``./MyKernel.h''
#include <list>

typedef MyKernel<double>           MyK;
typedef CGAL::Filtered_kernel<MyK> K;
typedef K::Point_2                 Point_2;

int main()
{
  std::list<Point_2> input;
  
  Point_2 act;
  input.push_back(act);

  std::list<Point_2> 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<K>, CGAL::Point_2<K>,
CGAL::Point_2<K>)} will not work. Instead you have to
use the functor \ccc{MyKernel<double>::Orientation_2}.

Rewriting the code is however pretty easy, as you can give
the functor object the same name as the global function.
