/*---------------------------------------------------------------
	FILE: CMRPTCanvas.h
	USE: See doc.

   Part of the MRPT Library
   ISA - Universidad de Malaga - http://www.isa.uma.es
  ---------------------------------------------------------------*/
#ifndef CMRPTCanvas_H
#define CMRPTCanvas_H

#include <MRPT/UTILS/utils_defs.h>
#include <MRPT/UTILS/CMatrixTemplateNumeric.h>

namespace UTILS
{
	class CMatrix;
	class CMatrixD;
	class CMRPTImage;
	class CMRPTImageFloat;

	/** This virtual class defines the interface of any object accepting drawing primitives on it.
	 *
	 * \sa CMRPTImage, CMRPTImageFloat
	 */
	class CMRPTCanvas
	{
	public:

		/** Definition of pen styles
		  */
		enum TPenStyle
		{
			psSolid = 0,
			psDash,			/* -------  */
			psDot,			/* .......  */
			psDashDot,		/* _._._._  */
			psDashDotDot	/* _.._.._  */
		};

		/** Dummy virtual destructor:
		  */
        virtual ~CMRPTCanvas()
        {
        }

		/** Changes the value of the pixel (x,y).
		  *  Pixel coordinates starts at the left-top corner of the image, and start in (0,0).
		  *  The meaning of the parameter "color" depends on the implementation: it will usually
		  *   be a 24bit RGB value (0x00RRGGBB), but it can also be just a 8bit gray level.
		  *  This method must support (x,y) values OUT of the actual image size without neither
		  *   raising exceptions, nor leading to memory access errors.
		  */
		virtual void  setPixel( int x, int y, unsigned int color) =0;

		/** Returns the width of the image in pixels
		  */
		virtual unsigned int  getWidth() const = 0;

		/** Returns the height of the image in pixels
		  */
		virtual unsigned int  getHeight() const = 0;

		/** Draws a line.
		  * \param x0 The starting point x coordinate
		  * \param y0 The starting point y coordinate
		  * \param x1 The end point x coordinate
		  * \param y1 The end point y coordinate
		  * \param color The color of the line
		  * \param width The desired width of the line (this is IGNORED in this virtual class)
		  *  This method may be redefined in some classes implementing this interface in a more appropiate manner.
		  */
		virtual void  line(
			int				x0,
			int				y0,
			int				x1,
			int				y1,
			unsigned int	color,
			unsigned int	width = 1,
			TPenStyle		penStyle = psSolid);

		/** Draws a rectangle (an empty rectangle, without filling)
		  * \param x0 The top-left x coordinate
		  * \param y0 The top-left y coordinate
		  * \param x1 The right-bottom x coordinate
		  * \param y1 The right-bottom y coordinate
		  * \param color The color of the line
		  * \param width The desired width of the line.
		  * \sa filledRectangle
		  */
		void  rectangle(
			int				x0,
			int				y0,
			int				x1,
			int				y1,
			unsigned int	color,
			unsigned int	width = 1 );

/*****************************************************AJOGD***************************************************/
		/** Draws a triangle
		  * \param x0 The triangle center x coordinate
		  * \param y0 The triangle center y coordinate
		  * \param size The size of the triangle
		  * \param color The color of the line
		  *	\param inferior The position of the triangle
		  * \param width The desired width of the line.
		  * \sa triangle
		  */
		void  triangle(
			int				x0,
			int				y0,
			int				size,
			unsigned int	color,
			bool			inferior = true,
			unsigned int	width = 1 );
/************************************************************************************************************/

		/** Draws a filled rectangle.
		  * \param x0 The top-left x coordinate
		  * \param y0 The top-left y coordinate
		  * \param x1 The right-bottom x coordinate
		  * \param y1 The right-bottom y coordinate
		  * \param color The color of the rectangle fill
		  *  This method may be redefined in some classes implementing this interface in a more appropiate manner.
		  * \sa rectangle
		  */
		virtual void  filledRectangle(
			int				x0,
			int				y0,
			int				x1,
			int				y1,
			unsigned int	color
			);

		/** Places a text label.
		  * \param x0 The x coordinates
		  * \param y0 The y coordinates
		  * \param str The string to put
		  * \param color The text color
		  *  This method may be redefined in some classes implementing this interface in a more appropiate manner.
		  * \sa selectTextFont
		  */
		virtual void  textOut(
			int					x0,
			int					y0,
			const std::string	&str,
			unsigned int		color
			);

		/** Select the current font used when drawing text.
		  * \param fontName The face name of a font (e.g. "Arial","System",...)
		  * \param fontSize The size of the font in pts.
		  * \param bold Whether the font is bold
		  * \param italic Whether the font is italic
		  * \sa textOut
		  */
		virtual void  selectTextFont(
			const std::string  &fontName,
			int					fontSize,
			bool				bold = false,
			bool				italic = false );

		/** Draws an image as a bitmap at a given position.
		  * \param x0 The top-left corner x coordinates on this canvas where the image is to be drawn
		  * \param y0 The top-left corner y coordinates on this canvas where the image is to be drawn
		  * \param img The image to be drawn in this canvas
		  *  This method may be redefined in some classes implementing this interface in a more appropiate manner.
		  */
		virtual void  drawImage(
			int						x,
			int						y,
			const UTILS::CMRPTImage	&img );

		/** Draw a cross.
		* \param x0 The point x coordinate
		* \param y0 The point y coordinate
		* \param color The color of the cross
		* \param size The size of the cross
		* \param type The cross type. It could be: "x" or "+"
		* \param width The desired width of the cross (this is IGNORED yet)
		*/
		void  cross (int x0,int y0, unsigned int color,char type, unsigned int size=5, unsigned int width = 1);

		/** Draws an image as a bitmap at a given position, with some custom scale and rotation changes.
		  * \param x0 The top-left corner x coordinates on this canvas where the image is to be drawn
		  * \param y0 The top-left corner y coordinates on this canvas where the image is to be drawn
		  * \param rotation The rotation in radians, positive values being anti-clockwise direction, 0 is the normal position.
		  * \param scale The scale factor, e.g. 2 means twice the original size.
		  * \param img The image to be drawn in this canvas
		  *  This method may be redefined in some classes implementing this interface in a more appropiate manner.
		  */
		virtual void  drawImage(
			int						x,
			int						y,
			const UTILS::CMRPTImage	&img,
			float					rotation,
			float					scale );

		/** Draws an image as a bitmap at a given position.
		  * \param x0 The top-left corner x coordinates on this canvas where the image is to be drawn
		  * \param y0 The top-left corner y coordinates on this canvas where the image is to be drawn
		  * \param img The image to be drawn in this canvas
		  * This method actually calls internally to "drawImage" with a "CMRPTImage" parameter.
		  */
		void  drawImage(
			int								x,
			int								y,
			const UTILS::CMRPTImageFloat	&img );

		/** Draws an image as a bitmap at a given position, with some custom scale and rotation changes.
		  * \param x0 The top-left corner x coordinates on this canvas where the image is to be drawn
		  * \param y0 The top-left corner y coordinates on this canvas where the image is to be drawn
		  * \param rotation The rotation in radians, positive values being anti-clockwise direction, 0 is the normal position.
		  * \param scale The scale factor, e.g. 2 means twice the original size.
		  * \param img The image to be drawn in this canvas
		  * This method actually calls internally to "drawImage" with a "CMRPTImage" parameter.
		  */
		void  drawImage(
			int						x,
			int						y,
			const UTILS::CMRPTImageFloat	&img,
			float					rotation,
			float					scale );


		/** Draws an ellipse representing a given confidence interval of a 2D Gaussian distribution.
		  * \param mean_x The x coordinate of the center point of the ellipse.
		  * \param mean_y The y coordinate of the center point of the ellipse.
		  * \param cov2D A 2x2 covariance matrix.
		  * \param confIntervalStds How many "sigmas" for the confidence level (i.e. 2->95%, 3=99.97%,...)
		  * \param color The color of the ellipse
		  * \param width The desired width of the line (this is IGNORED in this virtual class)
		  * \param nEllipsePoints The number of points to generate to approximate the ellipse shape.
		  * \exception std::exception On an invalid matrix.
		  */
		template <class T>
		void  ellipseGaussian(
			CMatrixTemplateNumeric<T>	*cov2D,
			T							mean_x,
			T							mean_y,
			float						confIntervalStds = 2,
			unsigned int				color = 0xFFFFFF,
			unsigned int				width = 1,
			int							nEllipsePoints = 20
			)
		{
			MRPT_TRY_START;
			int								x1=0,y1=0,x2=0,y2=0;
			double							ang;
			CMatrixTemplateNumeric<T>		eigVal,eigVec;
			int								i;

			// Compute the eigen-vectors & values:
			cov2D->eigenVectors(eigVec,eigVal);

			eigVal.Sqrt();
			CMatrixTemplateNumeric<T>		M( eigVal * (~eigVec) );

			// Compute the points of the 2D ellipse:
			for (i=0,ang=0;i<nEllipsePoints;i++,ang+= (M_2PI/(nEllipsePoints-1)))
			{
				float	ccos = (float)cos(ang);
				float	ssin = (float)sin(ang);

				x2 = round( mean_x + confIntervalStds * (ccos * M(0,0) + ssin * M(1,0)) );
				y2 = round( mean_y + confIntervalStds * (ccos * M(0,1) + ssin * M(1,1)) );

				if (i>0)
					line( x1, y1,x2, y2,color,width );

				x1 = x2;
				y1 = y2;
			} // end for points on ellipse

			MRPT_TRY_END_WITH_CLEAN_UP( \
				std::cout << "Covariance matrix leading to error is:" << std::endl << *cov2D << std::endl; \
				);
		}

	}; // End of class

} // end of namespace UTILS

#endif
