// GlassAlign.h: interface for the CGlassAlign class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_GLASSALIGN_H__A4EDE408_69C7_440F_9842_CCDFAA98048A__INCLUDED_) #define AFX_GLASSALIGN_H__A4EDE408_69C7_440F_9842_CCDFAA98048A__INCLUDED_ #include "Math.h" #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // ¿øÁ¡ÀÇ À§Ä¡ ¿Í xÃàÀÇ ¹æÇâ¿¡ ´ëÇÑ Á¤ÀÇ. // ¹Ý ½Ã°è¹æÇâ ¼³Á¤, ¼øÂ÷ÀûÀ¸·Î ¾Õ¼ø¼­ÀÇ µÞÀÚ¸¦ ½ÃÀÛ ±ÛÀÚ·Î ÁöÁ¤. enum OriginPos{OP_LEFT_TOP, OP_LEFT_BOTTOM, OP_RIGHT_BOTTOM, OP_RIGHT_TOP, OP_COUNT}; enum XDirection{XD_HORIZONTAL= 0, XD_VERTICAL= 1, XD_COUNT}; template class CCoordSystem { public: OriginPos m_OriginPos; XDirection m_XDirection; TTT m_Width; TTT m_Height; public: CCoordSystem() { m_OriginPos= OP_LEFT_TOP; m_XDirection= XD_HORIZONTAL; m_Width= 0; m_Height= 0; } CCoordSystem(OriginPos pos, XDirection xDir, TTT width, TTT height) { SetSystem(pos, xDir, width, height); } void SetSystem(OriginPos pos, XDirection xDir, TTT width, TTT height) { m_OriginPos = pos; m_XDirection = xDir; m_Width = width; m_Height = height; } BOOL operator ==(CCoordSystem &comp) { return m_OriginPos == comp.m_OriginPos && m_XDirection == comp.m_XDirection; } }; // x¿Í yÀÇ ºÎÈ£ º¯È¯,, x¿Í yÀÇ Ä¡È¯Àº xÃàÀÇ ¹æÇâ º¸°í °áÁ¤. static int transx[4][4][2]= { {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}} // 1 : (1~4) = Src(1) : Target(1~4) ,{{1, -1}, {1, 1}, {-1, 1}, {-1, -1}} // 2 : (1~4) ,{{-1, -1}, {-1, 1}, {1, 1}, {1, -1}} // 3 : (1~4) ,{{-1, 1}, {-1, -1}, {1, -1}, {1, 1}} // 4 : (1~4) }; // [pox, xdir]ÀÇ °öÀ¸·Î ÁÂÇ¥°è º¯È¯ÀÇ °á°ú¸¦ ¹Ý¿µÇÑ´Ù. // [LEFT_BOTTOM, XD_HORIZONTAL]=1, ¿¡¼­ [RIGHT_BOTTOM, XD_VERTICAL]= 1 À̸é 1*1 = 1 À̵ǹǷΠTHETAÀÇ ÇÕÀÌ ÃÖÁ¾ THETA°ªÀÌ µÈ´Ù. static int thetasign[4][2]= {{-1, 1}, {1, -1}, {-1, 1}, {1, -1} }; #define TRANS_PT(trans, pt, targetPt) trans.TransToTarget(pt.x, pt.y, targetPt.x, targetPt.y); #define ROTATE_PT(trans, pt, targetPt) trans.RotateToTarget(pt.x, pt.y, targetPt.x, targetPt.y); template class CCoordTrans { CCoordSystem m_SrcSystem; CCoordSystem m_TargetSystem; int a, b, width, height;// ¹æÇâ Àüȯ¿ë flag public: BOOL IsNeedeToTrans() { if(m_SrcSystem == m_TargetSystem) return FALSE;// ÁÂÇ¥°è°¡ °°À¸¸é º¯È¯ ÇÊ¿ä ¾øÀ½. return TRUE; } BOOL SetTransSystem(OriginPos srcPos, XDirection srcXDir, TTT width, TTT height, OriginPos targetPos, XDirection targetXDir) { m_SrcSystem.SetSystem(srcPos, srcXDir, width, height); m_TargetSystem.SetSystem(targetPos, targetXDir, width, height); SetTransSystem(m_SrcSystem, m_TargetSystem); return IsNeedeToTrans(); } BOOL SetTransSystem(CCoordSystem &src, CCoordSystem &target) { m_SrcSystem= src; m_TargetSystem= target; // x= a*x+ width; // y= b*y+ height; if(m_SrcSystem.m_XDirection == XD_HORIZONTAL)// HORIZONTALÀ» ±âÁØÀ¸·Î Å×ÀÌºí ¸¸µé¾îÁü. { a= transx[m_SrcSystem.m_OriginPos][m_TargetSystem.m_OriginPos][0]; b= transx[m_SrcSystem.m_OriginPos][m_TargetSystem.m_OriginPos][1]; }else { b= transx[m_SrcSystem.m_OriginPos][m_TargetSystem.m_OriginPos][0]; a= transx[m_SrcSystem.m_OriginPos][m_TargetSystem.m_OriginPos][1]; } if(a < 0) width= m_SrcSystem.m_Width; else width= 0; if(b < 0) height= m_SrcSystem.m_Height; else height= 0; if(m_SrcSystem.m_XDirection == m_TargetSystem.m_XDirection) { target.m_Width= m_TargetSystem.m_Width= m_SrcSystem.m_Width; target.m_Height= m_TargetSystem.m_Height= m_SrcSystem.m_Height; }else { target.m_Width= m_TargetSystem.m_Width= m_SrcSystem.m_Height; target.m_Height= m_TargetSystem.m_Height= m_SrcSystem.m_Width; } return IsNeedeToTrans(); } void TransToTarget(TTT x, TTT y, TTT &tx, TTT &ty) { // Ãà ¹æÇâ Àüȯ.(¹«º¯È­, x2= width- x, y2= height- y) x= x*a+ width; y= y*b+ height; // Ãà°£ Àüȯ. (¹«º¯È­, x <-> y) if(m_SrcSystem.m_XDirection == m_TargetSystem.m_XDirection) { tx= x; ty= y; }else { tx= y; ty= x; } } void RotateToTarget(TTT x, TTT y, TTT &tx, TTT &ty) { // Ãà ¹æÇâ Àüȯ.(¹«º¯È­, x2= width- x, y2= height- y) x= x*a; y= y*b; // Ãà°£ Àüȯ. (¹«º¯È­, x <-> y) if(m_SrcSystem.m_XDirection == m_TargetSystem.m_XDirection) { tx= x; ty= y; }else { tx= y; ty= x; } } // 1 or -1, theta°ªÀÇ ºÎÈ£¸¦ °áÁ¤ÇÑ´Ù. int GetThetaSign() { int srcDir= thetasign[m_SrcSystem.m_OriginPos][m_SrcSystem.m_XDirection]; int tarDir= thetasign[m_TargetSystem.m_OriginPos][m_TargetSystem.m_XDirection]; return srcDir*tarDir; } }; // ¾ó¶óÀÎ ¸¶Å©¸¦ ÀÌ¿ëÇÑ ÁÂÇ¥ º¸Á¤. // µÎ°³ÀÇ ¾ó¶óÀÎ ¸¶Å©Áß ÇѰ³ÀÇ ¾ó¶óÀÎ ¸¶Å©¸¦ ±âÁØÁ¡À¸·Î theta »ç¿ë. // Á¤º¸ : ¾ó¶óÀθ¶Å©(¾ó¶óÀÎ ±âÁØÁ¡)ÀÇ x, y, dx, dy(shiftÀ§Ä¡), theta(Ʋ¾îÁø °¢) // ¾ó¶óÀÎ ¸¶Å©±âÁØ¿¡ ÀÇÇÑ º¸Á¤°ú, ¿øÁ¡º¸Á¤À» ÅëÇÑ º¸Á¤ µÎ°¡Áö ¹æ¹ý »ç¿ë °¡´É. // 1. SetAlignData // 2. If Istilted(), then Correct().. struct stAlignPoint { int x, y; stAlignPoint() {ResetPoint();} void ResetPoint() {x= -1; y= -1;}// À½¼ö¸¦ °¡Áú ¼ö ¾ø´Ù. BOOL IsPointSet() {return x != -1 && y!= -1;} void SetPoint(int xx, int yy) {x= xx; y= yy;} stAlignPoint operator +(stAlignPoint& pt) { stAlignPoint npt; npt.x= x+ pt.x; npt.y= y+ pt.y; return npt; } stAlignPoint operator -(stAlignPoint& pt) { stAlignPoint npt; npt.x= x- pt.x; npt.y= y- pt.y; return npt; } void Scale(double rx, double ry) { x= (int)(x*rx); y= (int)(y*ry); } stAlignPoint operator-() { stAlignPoint pt; pt.x= -x; pt.y= -y; return pt; } }; struct stAlignInfo { BOOL m_bAlignFound; int m_xAlign, m_yAlign; // Align Position(x, y) int m_dxAlign, m_dyAlign; // Align Shift. double m_Theta; // Angle of Glass Tilt == Align Tilt. double m_BasicTheta; double m_ExtraTheta; public: void ResetAlignInfo() {m_bAlignFound= FALSE; m_Theta= 0; m_dxAlign= 0; m_dyAlign= 0; m_xAlign= m_yAlign= 0;} void SetAlignFound() {m_bAlignFound= TRUE;} BOOL IsAlignFound() {return m_bAlignFound;} BOOL IsTilted() {return m_Theta != 0 || m_dxAlign != 0 || m_dyAlign != 0;} public: stAlignInfo& SelfAlignInfo() {return *this;} }; class AFX_EXT_CLASS CAlignFind { public: // 1. ±Û¶ó½º »ó¿¡¼­ÀÇ ¾ó¶óÀθ¶Å© À§Ä¡¿Í Á¤º¸. CCoordSystem m_csOperator; // ±âÁØ ÁÂÇ¥°è (OP_LEFT_TOP, XD_HORIZONTAL : ÀÛ¾÷ÀÚ ½Ã°¢, ºÒº¯), SetAlignInGlass ¿¡¼­ ¼³Á¤µÈ´Ù. stAlignPoint m_FirstInGlass; // um ´ÜÀ§ stAlignPoint m_SecondInGlass; // um ´ÜÀ§ stAlignPoint m_FirstFindInGlass; stAlignPoint m_SecondFindInGlass; double m_BasicTheta; // ¼³Á¤ ¾ó¶óÀÎ ¸¶Å© À§Ä¡°¡ °¡Áø °íÀ¯ tilt double m_ExtraTheta; double m_TotalTheta; stAlignPoint m_AlignShift; stAlignPoint m_AlignDelta; // 2. debugÀ» À§Çؼ­ ÀúÀ常 ÇØµÐ´Ù. Ä«¸Þ¶ó¿¡¼­ÀÇ ¸¶Å© Á¤º¸. ¿ÜºÎ¿¡¼­ ¼³Á¤µÇ´Â ÀԷ°ªµéÀÌ´Ù. protected: stAlignPoint m_FirstAlign; // ±âÁØ ¾ó¶óÀÎ ¸¶Å© À§Ä¡. um ´ÜÀ§ stAlignPoint m_FirstFind; // ±âÁØ ¾ó¶óÀÎ ¸¶Å© ãÀº °÷. um ´ÜÀ§ CCoordSystem m_csFirst; stAlignPoint m_SecondAlign; // º¸Á¶ ¾ó¶óÀÎ ¸¶Å© À§Ä¡. um ´ÜÀ§ stAlignPoint m_SecondFind; // º¸Á¶ ¾ó¶óÀÎ ¸¶Å© ãÀº °÷. um ´ÜÀ§ CCoordSystem m_csSecond; // 3. debugÀ» À§Çؼ­ ÀúÀ常 ÇØµÐ´Ù. ±Û¶ó½º »ó ¾ó¶óÀÎ ¸¶Å©ÀÇ À§Ä¡¿Í ÁÂÇ¥. protected: int m_Dx, m_Dy; // ±Û¶ó½º ³¡¿¡¼­ ¾ó¶óÀÎ ¸¶Å© ±îÁöÀÇ °Å¸®.. OriginPos m_FirstPos; // ¾ó¶óÀÎ ¸¶Å© À§Ä¡. OriginPos m_SecondPos; // ¾ó¶óÀÎ ¸¶Å© À§Ä¡. public: int m_GlassWidth, m_GlassHeight;// ±Û¶ó½º Å©±â. public: CAlignFind(); CCoordSystem GetOperatorCoordSystem(){return m_csOperator;} void ResetAlignFind() { m_FirstFindInGlass.ResetPoint(); m_SecondFindInGlass.ResetPoint();} BOOL IsAlignFound() { return m_FirstFindInGlass.IsPointSet() && m_SecondFindInGlass.IsPointSet();} // 1. °Å¸® Á¤º¸·Î ±Û¶ó½º ¾ó¶óÀθ¶Å© À§Ã³ ±¸Çϱâ, ±Û¶ó½º ³¡´Ü(left, top)¿¡¼­ÀÇ ¾ó¶óÀθ¶Å© °Å¸® dx, dy¿Í glass Width, height¸¦ °¡Áö°í °¢ ¾ó¶óÀθ¶Å© À§Ä¡ ÁÂÇ¥ ±¸Çϱâ. void FillPos(int &x, int &y, OriginPos pos, int dx, int dy, int glassWidth, int glassHeight); public: // 2. ±Û¶ó½ºÀÇ ¾ó¶óÀθ¶Å© Á¤º¸ ¼³Á¤. ´ÜÀ§ um, ÀÛ¾÷ÀÚ ¹æÇâ¿¡¼­ÀÇ left, topÀ» ¿øÁ¡À¸·Î xDirectionÀº HorizontalÀ» ±âÁØÀ¸·Î ÇÏ´Â µ¥ÀÌÅÍ´Ù. void SetAlignInGlass(int dx, int dy, int glassWidth, int glassHeight, OriginPos firstPos, OriginPos secondPos, double basicTheta); // 3. ¾ó¶óÀθ¶Å© Á¤º¸ ¼³Á¤.. ´ÜÀ§ um, Ä«¸Þ¶ó¿¡¼­ÀÇ À§Ä¡¿Í ÁÂÇ¥°èÁ¤º¸. void SetFirstAlign(stAlignPoint first, stAlignPoint find, double rx, double ry, CCoordSystem cameraCoord); void SetSecondAlign(stAlignPoint second, stAlignPoint find, double rx, double ry, CCoordSystem cameraCoord); // 4. ¾ó¶óÀÎ º¸Á¤°ª ±¸Çϱâ. BOOL CalcAlignInfo(CCoordSystem &targetCoord, stAlignInfo &alignInfo);// operatorÁÂÇ¥°è·Î ¼³Á¤µÈ ¾ó¶óÀθ¶Å©·Î theta°è»êÈÄ targetCoordÁÂÇ¥°è·Î °ªÀ» ȯ»êÇØ ÁØ´Ù. double CalcAlignTheta_Operator(stAlignPoint delta, OriginPos opSrc, XDirection xdSrc);// operatorÁÂÇ¥°è¿¡¼­ÀÇ theta°ª ¸®ÅÏ. double CalcAlignTheta_Operator(stAlignPoint a1, stAlignPoint a2, OriginPos opSrc, XDirection xdSrc) { return CalcAlignTheta_Operator(a2- a1, opSrc, xdSrc); } }; // ¾ó¶óÀÎ ¸¶Å©ÀÇ shift¿Í theta ¸¦ ÀÌ¿ëÇØ ÁÂÇ¥ °è»êÇϱâ. // ¾ó¶óÀθ¶Å©ÀÇ shift¸¦ ÀÌ¿ëÇØ ¿øÁ¡ÀÇ shift·®À» °è»êÇÑ´Ù. theta´Â µ¿ÀÏ. SetAlignData // ¿øÁ¡¿¡¼­ÀÇ tilt(shift, theta)¸¦ ÀÌ¿ëÇØ ÀÓÀÇ ÁÂÇ¥ÀÇ tiltµÈ ÁÂÇ¥¸¦ °è»êÇØ³½´Ù. // ÁÂÇ¥´Â umÀ» ±âº» ´ÜÀ§·Î »ç¿ëÇÑ´Ù. class AFX_EXT_CLASS CBaseAligning : public stAlignInfo { protected: // AlignData¿¡¼­ 2Â÷ °¡°øµÇ´Â Á¤º¸. double m_dCosine; // Cosine(Theta) double m_dSine; // Sine(Theta) double m_dTangent; double m_dCosineBack; // Cosine(Theta) double m_dSineBack; // Sine(Theta) int m_dxOrigin, m_dyOrigin; // Shift of Glass Original Position public: CBaseAligning(); void SetAlignInfo(stAlignInfo &alignData); void SetAlignInfo(double theta, int xAlign, int yAlign, int dxAlign, int dyAlign); void Correct_00(int x, int y, int &xPrime, int &yPrime); // ÁÂÇ¥ ±âÁØÀ» ¾ó¶óÀθ¶Å© ±âÁØÀÌ ¾Æ´Ï¶ó ¿øÁ¡±âÁØÀ¸·Î º¯È¯ - ¿¬»ê°³¼ö°¡ ÁØ´Ù. void Correct_00(int &x, int &y) {Correct_00(x, y, x, y);} void Correct(int x, int y, int &xPrime, int &yPrime, int bForwardScan, int nGlassHeight); // x, y¸¦ ¾ó¶óÀθ¶Å© ±âÁØÀ¸·Î ÁÂÇ¥º¯È¯ÈÄ Æ¿Æ® º¸Á¤ ¹× ±Û¶ó½º ÁÂÇ¥°è·Î º¹¿ø. void Correct(int &x, int &y, int bForwardScan, int nGlassHeigh) {Correct(x, y, x, y, bForwardScan, nGlassHeigh);} }; // When use it(Correct_Scan()), first check if belows are called // 1. Reset(), 2. SetAlignData(), 3. SetScanData() 4. IsTilted() class AFX_EXT_CLASS CScanAligning : public CBaseAligning { public: double m_xResolution; // Resolution of X Axis ( Inspector cam) double m_yResolution; // Resolution of Y Axis ( Inspector cam) double m_xAccum; // UM of Cam's Left First Pixel (Left Margin) double m_xAccumOrigin; // UM of Cam's Left Pixel (0) int m_LeftMargin; // Left Margin of Each Cam. BOOL m_bForwardScan; int m_GlassHeight; // Length of Glass Height int m_GlassStart; // Pixel of Glass Start Line. public: void SetScanData(double xResolution, double yResolution, double xAccum, int leftMargin, int glassHeight, int glassStartLine, BOOL bForward); void Correct_Pixel2UM(int x, int y, int &xPrime, int &yPrime); void Correct_Pixel2Pixel(int x, int y, int &xPrime, int &yPrime); void CorrectBack_Pixel2UM(int x, int y, int &xPrime, int &yPrime); void CorrectBack_Pixel2Pixel(int x, int y, int &xPrime, int &yPrime); int GetDx_Pixel(int x, int y); int GetDy_Pixel(int x, int y); }; // CCoordTrans ¿ë·Ê. ÁÂÇ¥°è º¯È¯¿¡ µû¸¥ ÁÂÇ¥ º¯È¯ ¿¹. void Example_CoordTrans(); // ½ºÄµ¿¡¼­ ±Û¶ó½º·Î ÁÂÇ¥ º¯È¯°ªÀÌ ¿Ã¹Ù¸¥Áö Å×½ºÆ®Çغ¸ÀÚ. void Test_MakeScanAlignData(CScanAligning &alining); #endif // !defined(AFX_GLASSALIGN_H__A4EDE408_69C7_440F_9842_CCDFAA98048A__INCLUDED_)