
/*
    Copyright (c) 2010, 
	Luis Alvarez <lalvarez@dis.ulpgc.es>
	Pedro Henriquez <phenriquez@ctim.es>
	All rights reserved.
	
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * \page code_point2d.h \link point2d.h \endlink
 * \brief Code of  \ref code_point2d.h "point2d.h"
 * \includelineno point2d.h
 */

/**
 * \file point2d.h
 * \brief point2d class definition
 * \author Luis Alvarez \n \n
 * \brief \b Code: \n
 * - \ref code_point2d.h "point2d.h"
*/
#ifndef POINT2D_H
#define POINT2D_H
#include <iostream>
#include <math.h>
#include <vector>
//#include <ami_library_entry.h>


namespace ami
{

/**
 * \class point2d
 * \brief class to store 2D points and basic methods
 * \author Luis Alvarez
 */
template < class T >
class point2d {

  public :
  T x /** point x coordinate */;
  T y /** point y coordinate */;
	point2d():x( (T) 0), y( (T) 0){};
	~point2d(){};
	point2d(T xx , T yy){x=xx; y=yy;}
	point2d & operator=(const point2d &p){ x=p.x; y=p.y; return *this;}
    point2d (const point2d<T> &p){x=p.x; y=p.y;}
	point2d operator+(const point2d &p)const {return point2d(x+p.x,y+p.y);}
	point2d operator-(const point2d &p)const {return point2d(x-p.x,y-p.y);}
	point2d operator*(const T &a)const {return point2d(a*x,a*y);}
	double operator*(const point2d &p)const {return ( (double) x*p.x+y*p.y);}
	inline T norm(){T paso=x*x+y*y; return(paso>0.?sqrtf((float) paso):0.);}
	inline T norm2(){ return(x*x+y*y);}
	void print(){ std::cout << "point2d : (" << x << "," << y << ")" << std::endl;}
	int find_nearest_point(std::vector< point2d <T> > primitive);
	void find_nearest_point(std::vector< point2d <T> > primitive,int &id, T &distance);
};

//////////////////////////////////////////////////////////////////////////////////////////////
/**
 * \fn template <class T>  int point2d<T>::find_nearest_point(std::vector< point2d <T> > primitive)
 * \brief Find the point in th primitive that is the neareast to point, and returns its index
 * \param [in] primitive Vector with points 2d, it can represente a line,a polygon,a contour,etc..
 * \author Pedro Henríquez
*/
template <class T>
  int point2d<T>::find_nearest_point(std::vector< point2d <T> > primitive)
  {
    //FIND THE NEAREST POINT TO THE ACTUAL POINT
    T min_dist,dist;
    int min=-1;
    min_dist=99999;
    point2d<T> point_p;
    for(unsigned int i=0;i<primitive.size();i++)
    {
      point_p.x=primitive[i].x;
      point_p.y=primitive[i].y;
      dist = ((*this)-point_p).norm2(); //DISTANCE
      if(dist < min_dist)
      {
        min_dist=dist;
        min=i;
      }
    }
    return min;
  }


/**
 * \fn template <class T>  void point2d<T>::find_nearest_point(std::vector< point2d <T> > primitive,int &id, T &distance)
 * \brief Find the point in th primitive that is the neareast to point, and returns its index
 * \param [in] primitive Vector with points 2d, it can represente a line,a polygon,a contour,etc..
 * \author Pedro Henríquez
*/
template <class T>
  void point2d<T>::find_nearest_point(std::vector< point2d <T> > primitive,int &id, T &distance)
  {
    //FIND THE NEAREST POINT TO THE ACTUAL POINT
    T dist;
    id=-1;
    distance=99999;
    point2d<T> point_p;
    for(unsigned int i=0;i<primitive.size();i++)
    {
      point_p.x=primitive[i].x;
      point_p.y=primitive[i].y;
      dist = ((*this)-point_p).norm2(); //DISTANCE
      if(dist < distance)
      {
        distance=dist;
        id=i;
      }
    }
  }

}
#endif
