/* +---------------------------------------------------------------------------+
   |          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 CFeature_H
#define CFeature_H

#include <MRPT/UTILS/CMRPTImage.h>

namespace MRVL
{
	/** Definition of a feature ID
	*/
	typedef uint64_t TFeatureID;
	/** Types of features
	*/
	enum TFeatureType
	{
		/** Scale Invariant Feature Transform [LOWE'04]
		  */
		featSIFT = -1,
		/** Kanade-Lucas-Tomasi feature [SHI'94]
		  */
		featKLT,
		/** Harris border and corner detector [HARRIS]
		  */
		featHarris,
		/** Speeded Up Robust Feature [BAY'06]
		  */
		featSURF
	};

	enum TKLTFeatureStatus
	{
		/** Inactive
		*/
		statusKLT_IDLE = -1,
		/** Out Of Bounds
		*/
		statusKLT_OOB,
		/** Determinant of the matrix too small
		*/
		statusKLT_SMALL_DET,
		/** Error too big
		*/
		statusKLT_LARGE_RESIDUE,
		/**
		*/
		statusKLT_MAX_RESIDUE,
		/** Feature correctly tracked
		*/
		statusKLT_TRACKED,
		/** Iteration maximum reached
		*/
		statusKLT_MAX_ITERATIONS
	};

	/****************************************************
					Class CFEATURE
	*****************************************************/
	/** A generic 2D feature from an image
	*/
	class CFeature
	{
	public:
		/** Coordinates in the image
		*/
		float			x,y;
		/** ID of the feature
		*/
		TFeatureID		ID;
		/** Type of feature
		*/
		TFeatureType	type;
		/** A patch of the image surrounding the feature
		*/
		CMRPTImage		patch;
		/** Size of the patch (patchSize x patchSize) (it should be an odd number)
		*/
		unsigned int	patchSize;

		/** Constructor
		*/
		CFeature();

		/** Virtual destructor */
		virtual ~CFeature() {  }

	}; // end of class

	/****************************************************
					Class CFEATUREKLT
	*****************************************************/
	/** A KLT feature from an image
	*/
	class CFeatureKLT : public CFeature
	{
	public:
		/** Status of the feature tracking process
		*/
		TKLTFeatureStatus	status;
		/** Value of the goodness of the feature
		*/
		float				val;

		/** Constructor
		*/
		CFeatureKLT();

		virtual ~CFeatureKLT() {  }
	}; // end of class

	/****************************************************
					Class CFEATURESIFT
	*****************************************************/
	/** A SIFT feature from an image
	*/
	class CFeatureSIFT : public CFeature
	{
	public:
		/** Main orientation of the feature
		*/
		float						orientation;
		/** Feature scale into the scale space
		*/
		float						scale;
		/** SIFT Descriptor
		*/
		std::vector<unsigned char>	descriptor;

		/** Constructor
		*/
		CFeatureSIFT();

		virtual ~CFeatureSIFT() { }

		/** Computes de Euclidean Distance between "this" and the "other" descriptors
		*/
		float descriptorDistanceTo( const CFeatureSIFT &oFeature ) const;

	}; // end of class

	/****************************************************
					Class CFEATURELIST
	*****************************************************/
	/** A list of features
	*/
	class CFeatureList : public std::deque<CFeature>
	{
	public:
		/** The type of feature which contains
		*/
		TFeatureType	type;

		/** Save feature list to a text file
		*/
		void saveToTextFile(const char *fileName);

		/** Constructor
		*/
		CFeatureList();
	}; // end of class

	/****************************************************
				Class CMATCHEDFEATURELIST
	*****************************************************/
	/** A list of features
	*/
	class CMatchedFeatureList : public std::deque<std::pair<CFeature,CFeature> >
	{
	public:
		/** The type of feature which contains
		*/
		TFeatureType	type;
		/** Save list of matched features to a text file
		*/
		void saveToTextFile(char *fileName);

		/** Constructor
		*/
		CMatchedFeatureList();

	}; // end of class

} // end of namespace

#endif

