#pragma once

 
#include "PatMat.h" 


//typedef struct __sm_ecd_x_
//{
//	float downScale, upScale; //
//	int left, top;
//	RvImage image;
//	RvMask  mask;
//	iRvEcdCntrE1*  pEcd;
//}SM_ECDX;



//DUMP FLAGS
#define SM_DUMP_COARSE    1
#define SM_DUMP_FINE      (1<<1)
#define SM_DUMP_SUBPIXEL  (1<< 2)



class PATMAT_API CShapeMatch :	public CMatchCal
{
public:
	CShapeMatch(void);
	virtual ~CShapeMatch(void);

	enum SM_TYPE{
	    SM_NORMAL=0,   //常规
		SM_SCALED,     //缩放
		SM_ANISO,      //异向缩放
		SM_DEFORMED,   //变形模板
	};
	
	enum SM_COLOR{
		SM_HSV = CAreaCal::GM_HSV,
	    SM_RED = CAreaCal::GM_RED,
	    SM_GREEN = CAreaCal::GM_GREEN,
	    SM_BLUE = CAreaCal::GM_BLUE,
	    SM_MAX = CAreaCal::GM_MAX,
	    SM_MIN = CAreaCal::GM_MIN,
	    SM_AVG = CAreaCal::GM_AVG,
	};

	enum SM_OPT{
	   SM_OPT_AUTO,
	   SM_OPT_NONE=0,
	   SM_OPT_LOW,
	   SM_OPT_MEDIAN,
	   SM_OPT_HIGH,
	};

	enum SM_POLAR{
	    SM_IGNORE=0,//不适用极性，需要两个明暗度图完全相同。
		SM_LOCAL,  //局部极性，局部亮度变换
		SM_GLOBAL, //全局完全相反是也可以
	};
	 
	enum SM_SUBPIXEL{
		SM_SP_NONE=0,
		SM_SP_BILINEAR, //插值
		SM_SP_MINERR0,  //最小错误(基本精度, 角度最低1度, 像素最低1PIX)
		SM_SP_MINERR1,  //亚像素精度（低） 1/10 pix, 1/12.5 deg
		SM_SP_MINERR2,  //亚像素精度（中） 1/20 pix, 1/25 deg
		SM_SP_MINERR3,  //亚像素精度（高） 1/40 pix, 1/50 deg
	};

	virtual BOOL Serialize(HANDLE device, BOOL bIn );
	virtual CUCObj* Clone(  CUCObj *twin) ;
	//该函数可以去掉，过时 
	//virtual void Reset();

	BOOL  Create(/*CDelegate* pDelegate ,*/ const TCHAR* strName  , UINT id =-1 , int style =RV_UC_DEFAULT_STYLE  ) ;

	virtual BOOL    Learn(const RvImage image=NULL, int* pErrCode = NULL);  
	virtual int     Recognize(const RvImage image=NULL, int* pErrCode = NULL);
	virtual void    Clear(); //释放所有已经学习的模板

	int  GetContourType();
	void SetContourType(int type);
	
	//void EnablePregen(BOOL flag);
	//BOOL IsPregenEnabled();


	//重建实例集（缩放，变形，极性模板等）
	//BOOL Rebuild();

	//SM_ECDX* GetEcdx(BOOL bFine);
	void* GetPatternSet();
	int   GetPatternSize();

	//void  ReleaseEcdPrimitives();
	//void  ReleaseEcdVariants();
	

	//客户程序应该释放GetPatternImage返回的对象
	//0为coarse, 1为fine. -1为原始图像
	virtual RvImage GetPatternImage(int mipLevel, int pattIndex,  int angleIndex);
	//客户程序应该释放GetPatternMask返回的对象
	virtual RvMask  GetPatternMask(int mipLevel, int pattIndex,  int angleIndex);

	BOOL   GetLearnedMipLevels(int& coarse , int &fine);
	//BOOL   GetLearnedAngles(double& start, double& extent, double& coarseStep, double& fineStep);
	BOOL   GetLearnedAngles(double& start, double& extent, double& reso);

	RvPoint_f   GetLearnedPos();  //学习时模板位置
	BOOL   IsPatternRotatable(){ return m_bHasRotatedPatterns; };

	//定位以后的位置,以第一个结果为参考
	RvPoint_f GetCurRefpos();
	
public:
	static void  CloneEcdSet(PM_ECDX* pSourceSet, int nSrcSize, PM_ECDX** ppDestSet, int* pDestSize/*, BOOL bPregen*/);
	static void  ReleaseEcdSet(PM_ECDX* &pEcdSet, int& nEcdSize);

	 //For debug only
	//for scene pattern, shot search zone before dump
	//nOutputType: 0 - 输出数据，非标准pcd格式
	//             1 - 输出数据，标准pcd格式
	//             2 - 输出图像, 
	void DumpPatterns(const TCHAR* strFilePath, BOOL bScenePattern, int nOutputType );
	virtual RV_HANDLE DrawPatternInstances(HGDC dc, RV_HANDLE hStroke);

public:
	
	int        m_nCoarseReso;     //糙金字塔，设计时设定，学习过程中可能会改变
	int        m_nFineReso;       //精金字塔层，设计时设定，学习过程中可能会改变
	BOOL       m_bAutoReso;       //自动分辨率
	int        m_nResample;       //优化方法，采样
	int        m_nPolar;         //对象极性
	int        m_nEdgeStrength;   //边缘强度（对比度）
	int        m_nLowerContrast;    //滞后最小对比
	int        m_nUpperContrast;  //滞后最大对比
	int        m_nColorChannel  ; //彩色图像的通道

	float      m_nInitScore; //初始分数,       0-1.0
	float      m_nMinScore;       //最小分数
	float      m_nSearchForce;    //搜索力度系数
	       
	
	int        m_nSubPixelMethod; //亚像素精度方法	
	RvPoint    m_refpos;  //模板参考位置，一般在中心
	BOOL       m_bCustRefpos;


	static size_t MEM_PAGE_SIZE ;
	

	////临时变量，算法调试用，不保存，不复制
	int m_nDumpFlags;

protected:
	int CoarseMatch(const RvImage image, BOOL bRotate, float initScore, int edgeStrength, PM_MATCH_RESULT*   pResultArr, int nResultCount);
	void  FineMatch(const RvImage image, PM_MATCH_RESULT*   pResultArr, int nResultCount, BOOL bRotate, float minScore );

	//BOOL BuildRotatedEcds(const RvImage image, const RvMask mask);
	BOOL BuildRotatedEcds(PM_ECDX* pEcdArr, int ecdCount, const RvImage image, const RvPick pick);

	//BOOL BuildNormalEcds(const RvImage image, const RvMask mask, int left, int top);
	BOOL BuildNormalEcds(PM_ECDX* pEcdArr, int ecdCount, const RvImage image, const RvPick pick/*, int left, int top*/);

	PM_ECDX* InitPrimitives(const RvImage image, int& size );

	//iRvEcdCntrE1*   SetInitPatt(void* pEcdx, const RvImage image, const RvImage imMask/*, BOOL bFine*/);
	iRvEcdCntrE1*   SetInitPatt (/*void* pEcdx,*/ const RvImage image, const RvPick pkRoi );

	iRvEcdCntrE1*   GenRotatedPatt(/*void* pEcdx,*/ const RvImage image, const RvPick pkRoi, double angle  );

	RvImage*  GenSceneMips(const RvImage image, int& nImageCount );
	void      RelScenceMips( RvImage* pImageArray, int  nImageCount )  ;

	RV_HANDLE DrawPositions(HGDC dc,    PM_MATCH_RESULT* pResultArray, int nResultCount,  PM_ECDX* pEcdSet, int nSetSize,  RV_HANDLE hStroke );
     
	//void GenResultArray(void* pPatternSet, int size);
 
    int   CheckFreedom(int contourType);
	//void  DrawContour(BOOL bForce);
	
	BOOL ReadEcdSet(HANDLE device,PM_ECDX** ppPatternSet, int* pPatterSize);
	BOOL WriteEcdSet(HANDLE device, PM_ECDX* pPatternSet, int size);

	int DoEcdMatch(const RvImage imOri, const RvImage* pSceneMip, int nImageCount  );
	int ChooseFinalResults(PM_MATCH_RESULT*  pMatResultArr,  int resultCount, int expectedCount);

	float CalcLms(const RvImage image, PM_MATCH_RESULT*   pResultArr, int nResultCount,  int transReso, int angleReso, BOOL bRotate/*, BOOL bOriSize*/);

   // int ChooseResults (void* _pPattSet, int setSize, int resultCount);	

	//预先生成模板
	//BOOL  m_bPregen;
	int   m_nContourType;    //边缘类型：常规，缩放，异向缩放，


 	RvImage m_imPattern;
 	RvMask  m_mkPattern;
	double   m_nInitAngle,m_nAngleExtent, m_nAngleReso /*m_nCoarseAngleStep, m_nFineAngleStep*/;
	int      m_nInitMipLevel, m_nFinalMipLevel; //学习的模板MIP
	float    m_nPattX, m_nPattY; //学习时的模板ROI位置(相对整个视场)
	BOOL     m_bHasRotatedPatterns;

	int        m_nLearnedEdgeStrength;    
	int        m_nLearnedLowerContrast;    
	int        m_nLearnedUpperContrast;  

	int   m_nSetSize;
	PM_ECDX* m_pEcdSet;
	  

};

