
// Kernel.h -- Implementation of various kernel shapes.
// Class hierarchy :
//                    Kernel --- CylinderKernel
//                            |
//                            +- ConeKernel
//                            |
//                            +- K2Kernel
//                            |
//                            +- EpanechnikovKernel



#ifndef KERNEL_H
#define KERNEL_H


// Define various kernel shapes.
typedef enum
{ 
  DE_CYLINDER_KERNEL, DE_CONE_KERNEL, DE_K2_KERNEL, DE_EPANECHNIKOV_KERNEL 
} DEKernelShape;


// Abstract class : represents a generic reconstruction kernel with a rounded support
class Kernel
{
public:
  // Constructor.
  // PRE:  /
  // POST: A kernel of width 1.0 has been created (NULL if memory allocation failed).
  Kernel();

  // Kernel factory.
  // IN:   A kernel shape identifier.
  // OUT:  A kernel of the shape passed in argument or NULL if memory allocation failed.
  static Kernel* newKernel(DEKernelShape ks);

  // Get the kernel width.
  // OUT: The kernel width.
  inline float geth() {return h;}

  // Change kernel width.
  // IN:   The new kernel width, newh.
  // PRE:  newh>0.0f
  // POST: The kernel size is newh.
  void setSize(const float newh);

  // Check if one point is inside a kernel.
  // IN:  The position of a 2D point.
  //      The position of the center of the kernel.
  // OUT: 0    , if the point is outside the kernel.
  //      non 0, otherwise.
  int isInside(const VEC2D &point,const VEC2D &center);

  // Evaluate the kernel.
  // IN:  The position of a 2D point.
  //      The position of the center of the kernel.
  // OUT: The value of the kernel at the point. (a positive number or 0.0f)
  virtual float evaluate(const VEC2D &point,const VEC2D &center) = 0;

  // Check if one line segment intersects a kernel.
  // IN:  The origin of the line segment.
  //      The direction of the line segment.
  //      The length of the line segment.
  //      The position of the center of the kernel.
  // PRE: The direction vector has a length of 1.0f.
  // OUT: 0    , if there are no intersections.
  //      non 0, otherwise.
  int intersectSegment(const VEC2D &lorg,const VEC2D &ldir,const float ls,const VEC2D &cc);


protected:
  float h;       // Kernel size.
  float h2;      // h2=h*h.
  float h2inv;   // h2inv=1/h2.
};


// A cylinder shaped kernel (constant value on support)
class CylinderKernel : public Kernel
{
  float evaluate(const VEC2D &point,const VEC2D &center);
};

// A cone shaped kernel (linear progression from center to edge)
class ConeKernel : public Kernel
{
  float evaluate(const VEC2D &point,const VEC2D &center);
};

// K2Kernel -- see Density Estimation for Statistics and Data Analysis for more details
class K2Kernel : public Kernel
{
  float evaluate(const VEC2D &point,const VEC2D &center);
};

// EpanechnikovKernel -- see Densisty Estimation for Statistics and Data Analysis for more details
class EpanechnikovKernel : public Kernel
{
  float evaluate(const VEC2D &point,const VEC2D &center);
};

#endif







