/* +---------------------------------------------------------------------------+
   |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
   |                                                                           |
   |                   http://mrpt.sourceforge.net/                            |
   |                                                                           |
   |   Copyright (C) 2005-2008  University of Malaga                           |
   |                                                                           |
   |    This software was written by the Perception and Robotics               |
   |      research group, University of Malaga (Spain).                        |
   |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
   |                                                                           |
   |  This file is part of the MRPT project.                                   |
   |                                                                           |
   |     MRPT 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.                                   |
   |                                                                           |
   |   MRPT 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 MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
   |                                                                           |
   +---------------------------------------------------------------------------+ */
#ifndef CDescriptorComputation_H
#define CDescriptorComputation_H

#include <MRPT/UTILS/CMRPTImage.h>
#include <MRPT/UTILS/CMRPTImageFloat.h>
#include <MRPT/MRVL/CImageConvolution.h>
#include <MRPT/MRVL/VisionUtils.h>

namespace MRVL
{
	class CDescriptorComputation
	{
	public:
		enum TDescriptor
			{
				descSIFT = 0,		// Lowe
				descLocalJet,		// Schmid & Mohr
				descPatch			// Davison
			};

		struct TOptions
		{
			/** Initalizer
			*/
			TOptions();

			/** Descriptor type
			*/
			TDescriptor descriptorType;

			struct TSIFTOptions
			{
				TSIFTOptions();

				/** SIFT Options
				  */
				unsigned int descDim;		// Dimension of the descriptor: descDim x descDim x dirCount
				unsigned int dirCount;
				unsigned int descLen;

			} SIFTOptions;

			struct TLocalJetOptions
			{

			} localJetOptions;

			struct TPatchOptions
			{
				/** Patch Options
				  */
			} patchOptions;

		} options;

		/** Constructor
		*/
		CDescriptorComputation();

		/** Virtual destructor.
		*/
		virtual ~CDescriptorComputation();

		/** Compute descriptors from the image and keypoints inputs.
		* \param img The image from where to compute the descriptors.
		* \param x Vector containing the feature 'x' coordinates.
		* \param y Vector containing the feature 'y' coordinates.
		* \param sigma Gaussian smooth process sigma. Default: 3.
		* \param x_min Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param x_max Maximum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_min Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_max Maximum y coordinate in the image where the extraction is performed. Default: All the image.
		*/
		void  computeDescriptor(
			CMRPTImageFloat			&img,
			vector_float			&x,
			vector_float			&y,
			TSIFTFeatureList		&out_list,
			float					sigma = 3,
			unsigned int			x_min = 0,
			unsigned int			x_max = 0,
			unsigned int			y_min = 0,
			unsigned int			y_max = 0);

	private:
		/** Compute image gradient magnitude and direction.
		* \param img The input image.
		* \param mag The gradient magnitude image (output). It has the same size as img.
		* \param dir The gradient direction image (output). It has the same size as img.
		*/

		void  computeMagAndDir(const CMRPTImageFloat	&img,
										CMRPTImageFloat &mag,
										CMRPTImageFloat &dir);

		/** Computes descriptor of the keypoints based on the SIFT method.
		* \param img The image from where the points were extracted.
		* \param x Vector containing the feature 'x' coordinates.
		* \param y Vector containing the feature 'y' coordinates.
		* \param sigma Number of features to be extracted. Default: authomatic.
		* \param x_min Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param x_max Maximum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_min Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_max Maximum y coordinate in the image where the extraction is performed. Default: All the image.
		*/
		void  computeDescriptorSIFT(
			CMRPTImageFloat			&img,
			vector_float			&x,
			vector_float			&y,
			TSIFTFeatureList		&out_list,
			float					sigma = 3,
			unsigned int			x_min = 0,
			unsigned int			x_max = 0,
			unsigned int			y_min = 0,
			unsigned int			y_max = 0);

		/** Computes descriptor of the keypoints based on the Local Jet.
		* \param img The image from where the points were extracted.
		* \param x Vector containing the feature 'x' coordinates.
		* \param y Vector containing the feature 'y' coordinates.
		* \param sigma Gaussian smooth process sigma. Default: 3.
		* \param x_min Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param x_max Maximum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_min Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_max Maximum y coordinate in the image where the extraction is performed. Default: All the image.
		*/
		void  computeDescriptorLocalJet(
			CMRPTImageFloat			&img,
			vector_float			&x,
			vector_float			&y,
			TSIFTFeatureList		&out_list,
			float					sigma = 3,
			unsigned int			x_min = 0,
			unsigned int			x_max = 0,
			unsigned int			y_min = 0,
			unsigned int			y_max = 0);

		/** Computes descriptor of the keypoints based on the Patch.
		* \param img The image from where the points were extracted.
		* \param x Vector containing the feature 'x' coordinates.
		* \param y Vector containing the feature 'y' coordinates.
		* \param sigma Gaussian smooth process sigma. Default: 3.
		* \param x_min Minimum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param x_max Maximum x coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_min Minimum y coordinate in the image where the extraction is performed. Default: All the image.
		* \param y_max Maximum y coordinate in the image where the extraction is performed. Default: All the image.
		*/
		void  computeDescriptorPatch(
			CMRPTImageFloat			&img,
			vector_float			&x,
			vector_float			&y,
			TSIFTFeatureList		&out_list,
			float					sigma = 3,
			unsigned int			x_min = 0,
			unsigned int			x_max = 0,
			unsigned int			y_min = 0,
			unsigned int			y_max = 0);

		/** Check if the point (x,y) is within a circle centered in (0,0) and of radius 'radius'.
		* \param x X coordinate.
		* \param y Y coordinate.
		* \param radius Radius of the circle
		*/
		bool  isInCircle (float x, float y, int radius);

		/** Fits a parabola to three points and interpolates the maximum value and position.
		* \param left Point in the left.
		* \param middle Point in the middle.
		* \param right Point in the right.
		* \param outMax (out) Maximum of the interpolated parabola.
		* \param outOffset (out) Offset within (-1,1) respect to the middle point where is the maximum.
		*/
		void  getParabolaMaximum(
			const float left,
			const float middle,
			const float right,
			float &outMax,
			float &outOffset);

		}; //end of class

} // end of namespace
#endif
