#if !defined(__RV_MATCH_CAL_H_INCLUDED_)
#define      __RV_MATCH_CAL_H_INCLUDED_

#include "CaliX.h"
#include "PattCal.h"
#include "areacal.h"

 


#define MC_MIN_SCALE  0.5f
#define MC_MAX_SCALE  2.f

typedef struct __pm_match_result_
{
	float cx, cy;         //中心点坐标
	float scaleX, scaleY; //缩放
	float tiltX, tiltY;   //变形
	float angle;          //旋转的角度
	float score;          //相似度分数
	//utilities
	int   pattIndex;      //匹配到的模板索引(调试用)
	int   mipLevel;       //模板的MIP层（调试用）
	int   angIdx;         //旋转模板位置(调试用)
	void* pPattern;       //模板指针(调试用)
}PM_MATCH_RESULT;
 

class CALIX_API CMatchCal :	public CCaliber
{
public:
	CMatchCal(void);
	virtual ~CMatchCal(void);

	//Angle Unit
	enum
	{
		PM_REVOLUTION =0, //转
		PM_DEGREE,        //度
		PM_RADIAN,        //弧度
		PM_GRADE,         //百分度
	};

	//freedom type
	enum
	{
		FT_ROTATION     = 1,      //是否支持旋转
		FT_SCALE        = (1<<1), //是否支持缩放
		FT_ANISO        = (1<<2),  //是否异向缩放
		FT_TILT         = (1<<3),  //是否支持仿射变形
	};

	//Display Style
	enum
	{
		PM_SEARCH_ROI  = 1,
		PM_PATTERN_ROI = (1<<1),
		PM_POSTIONS    = (1<<2),
	};

	//filter 
	enum
	{
		PM_NEAREST = RV_FM_NEAREST,
		PM_BILINEAR =RV_FM_BILINEAR,
	};

	

	//参数style被忽略
	virtual BOOL  Create(/*CDelegate* pDelegate ,*/ const TCHAR* strName = NULL, UINT id = -1, int style = RV_UC_DEFAULT_STYLE ) ;
	virtual void  Destroy(/*BOOL bEraseStroke =FALSE*/) ;

	//设置pattern轮廓形状，该形状以排除干扰区域为主
	//形状不需要与实际需要定位的PATTERN严格一致。
	//设置模板形状
	void SetPatternShape(int shape) ;

	//设置模板区的显示风格
	void SetPatternStyle(int style);

	RvPick GetPatternZone();
	RvPick GetSearchZone();


	virtual void SetStyle(int style);  

	 
	virtual void Move(double dx, double dy) ;

	virtual void BeginAlign();
	virtual void Offset(double dx, double dy, int dir = RV_DIR_BOTH)  ;
	//目前unbias仅最后一次调用有效
	virtual void Unbias(double cx, double cy, double angle) ;
	virtual void EndAlign(BOOL bUpdate);
	 


	virtual void Shot(int mode ,const RvImage image ) ;
	virtual void ShotEx(int mode ,const RvImage image , int left, int top);

	virtual void  SetDisplayStyle(int style);

	virtual int  HitTest(CDelegate* pDelegate, GPoint point) ;
    virtual int   CheckHit(CDelegate* pDelegate, GPoint point)   ;

	virtual void SetVisible( BOOL state ) ;	


	virtual BOOL Serialize(HANDLE device, BOOL bIn );
	virtual CUCObj* Clone(  CUCObj *twin) ;
	virtual void Show(CDelegate* pDelegate,int mode, BOOL bForce) ;
	virtual void ShowSketch(CDelegate* pDelegate,CSketchMark* pMark,   HGPD hGpd,int grabType, GPoint grabPos);
	//virtual void ShowSketch(RvPoint leftTop, RvPoint rightBottom);

	virtual void   SetCtrlRect(int left, int top, UINT width, UINT height) ; 
	//virtual RvRect GetCtrlRect();
	virtual void   SetCtrlPos(int x, int y);
	//virtual RvPoint GetCtrlPos();

	GRect GetSearchRect();
	GRect GetPatternRect();

	virtual BOOL    Learn(const RvImage image=NULL, int* pErrCode = NULL){ return FALSE;};
	virtual int     Recognize(const RvImage image=NULL, int* pErrCode = NULL){ return 0;};
	virtual void    Clear(){}; //清除所有已经学习的模板，恢复到未学习状态

	BOOL IsPatternExist();
	//重新设置模板
	//virtual void ResetPattern();

 
	virtual void Reset() ;

	//virtual CDelegate* BindDelegate(CDelegate* pDelegate);

	RvImage GetPatternImage();
	void    SetPatternImage(const RvImage image);


	//one of PM_REVOLUTION, PM_DEGREE,PM_RADIAN , PM_GRADE
	void SetAngleUnit(int nUnitType);
	int  GetAngleUnit();

	virtual void SetMaxInstances(int count);
	int  GetMaxInstances() {return m_nMaxInstances ; };


	 
	virtual void SetMaxInitInstances(int count);
	int  GetMaxInitInstances() {return m_nMaxInitInstances; };

	void SetAngleResolution(float nResolution); 
	float GetAngleResolution( ) { return m_nAngleResolution;} 

	void SetScaleResolution(float nResolution); 
	float GetScaleResolution( ) { return m_nScaleResolution;} 

	void  SetMinScale(float scale);
	float GetMinScale() {return m_nMinScale; };

	void  SetMaxScale(float scale);
	float GetMaxScale() {return m_nMaxScale; };

	void  SetMinScaleX(float scale);
	float GetMinScaleX() {return m_nMinScaleX; };

	void  SetMaxScaleX(float scale);
	float GetMaxScaleX() {return m_nMaxScaleX; };

	void  SetMinScaleY(float scale);
	float GetMinScaleY() {return m_nMinScaleY; };

	void  SetMaxScaleY(float scale);
	float GetMaxScaleY() {return m_nMaxScaleY; };
 
	 
	int GetResultCount() {return m_nResultCount; };
	PM_MATCH_RESULT* GetMatchResult(int index) ;

	//减少逻辑，增加鲁棒性
	//virtual void      SetLock(CRITICAL_SECTION* pLock);

public:
	//自由度
	int  m_nFreedom;
	//BOOL m_bAnisoScale;//anisotropic scale,是否进行异形因子缩放（即水平和垂直方向不一样的缩放因子）
	
	int  m_nDirect;

	//角度单位，默认为PM_DEGREE
	int     m_nAngleUnit ;
	
	float      m_nMaxOverlap;     //最大重叠度

	float  m_nStartAngle, m_nEndAngle; //支持角度旋转的范围。
	 
	  
	CPattCal  m_acPattern;
	CAreaCal  m_acSearch;

public:

	 virtual void OnBeginTrack(CDelegate* pDelegate,HGPD hCur, GPoint point, int nHitType) ;
	 virtual void OnEndTrack(CDelegate* pDelegate,HGPD hCur,  GPoint point, int nHitType) ;

	virtual BOOL OnPositionChange(HGPD hOri,HGPD hCur,HGPD hNew, GPoint grabPos, RvOffset &offset) ;
	virtual BOOL OnRotationChange( HGPD hCur, HGPD hNew, GPoint &curPos) ;
	             
	virtual BOOL OnExtenderChange( HGPD hCur, HGPD hNew, int index, GPoint &curPos) ;
	 
	virtual void DestroyGraphicDescriptor(HGPD hGpd)  ;

	virtual void CopyGraphicDescriptor(const HGPD src, HGPD dest)  ;

	virtual HGPD CreateGraphicDescriptor(CDelegate* pDelegate) ;

	virtual GRect  GetGrabberRect(CDelegate* pDelegate,RvSize size) ;
	virtual GRect  GetExtenderRect(CDelegate* pDelegate,int index, RvSize size) ;
 
	virtual int     GetExtenderCount() ;

	//virtual  void  SetSelectState(CDelegate::SELECT_STATE state) ;
	virtual void   SetSelectState(BOOL state) ;

	//virtual void SetBoundRect(GRect rect);

	virtual void  ShowExtender(CDelegate* pDelegate, CLeadMark* pMark/*, BOOL bGrabber*/);
	virtual void  ShowGrabber(CDelegate* pDelegate, CLeadMark* pMark );

	virtual void  ShowRotater(CDelegate* pDelegate, CRotatorMark* pMark );
	
protected:
	virtual RV_HANDLE DrawPatternInstances(HGDC dc, RV_HANDLE hStroke);
 
	 
	typedef struct _pattern_match_graphic_descriptor{
		HGPD hPatGpd;
		HGPD hSchGpd;
	}GdPixelMatch;

	//根据支持的角度计算旋转次数
	int GetRotationCount();
	 
	float  m_nAngleResolution; //角度分辨率，默认为1。
	float m_nScaleResolution;       //缩放分辨率，默认为0.1

	float m_nMinScale, m_nMaxScale; //同形缩放范围，一般为(0.5 -> 2.0)，默认都为1.
	float m_nMinScaleX, m_nMaxScaleX; //异形缩放范围，一般为(0.5 -> 2.0),默认都为1.
	float m_nMinScaleY, m_nMaxScaleY; //异形缩放范围，一般为(0.5 -> 2.0),默认都为1.

 

	 int m_nDisplayStyle;
 	 


	BOOL m_bPatternExist;
	//BOOL m_bPatternRoiVisible;
 
	//根据当前的角度单位，换算成弧度单位的角度值
	double GetAngleInRadian(double angle);
	//根据当前的角度单位，换算成度单位的角度值
	double GetAngleInDegree(double angle);

	int     m_nMaxInstances;         //模板目标最大数量。如果用于定位一般为1。
	
	//m_nMaxInitInstances 初始最多的位置数量，该参数为0的时候，初始阶段直接查找m_nMaxInstances。
	//默认情况下，该参数为0。
	int     m_nMaxInitInstances;  

	//样本最原始的宽度和高度
	//int    m_nOriWidth, m_nOriHeight;

	//运行时变量，无需保存
	int  m_nResultCount;
	PM_MATCH_RESULT* m_pResultArray;
	//***********************************

private:
	//运行时变量，无需保存
    CUCObj* m_pObjHit; //用于模板区或搜索区的HITTEST的临时保存
	//**************************************
	 
	//0,  重新设置
	//1,  仅大小发生变化
	//2 ， 仅位置 发生变化
	void Relayout(CUCObj* pActiveObj, int type, RvOffset& offset);
};



#endif //__RV_MATCH_CAL_H_INCLUDED_