|
|
#include "stdafx.h"
|
|
|
#include "HTrackerTransform.h"
|
|
|
|
|
|
HTrackerTransform::HTrackerTransform()
|
|
|
:m_handle(0)
|
|
|
,m_bDrag(false)
|
|
|
,m_bCanMoved(false)
|
|
|
,m_nAllowMovePixel(5)
|
|
|
,m_kind(HTRACKER_TRANSFORM_KIND_SCALE)
|
|
|
{
|
|
|
m_StartPhi = 0.0f;
|
|
|
m_Transform.Reset();
|
|
|
}
|
|
|
|
|
|
//参数:mousePt 开始拖拽时,鼠标的坐标.
|
|
|
void HTrackerTransform::Init(int handle, const CRect & boundRect, CPoint mousePt)
|
|
|
{
|
|
|
m_bDrag = true;
|
|
|
m_bCanMoved = false;
|
|
|
m_StartPhi = 0.0f;
|
|
|
m_StartPoint = mousePt;
|
|
|
|
|
|
if (handle == 8) //平移
|
|
|
m_kind = HTRACKER_TRANSFORM_KIND_MOVE;
|
|
|
else
|
|
|
m_kind = HTRACKER_TRANSFORM_KIND_SCALE;
|
|
|
|
|
|
m_Transform.Reset();
|
|
|
m_boundRect = boundRect;
|
|
|
m_calculator.Calculate(m_boundRect);
|
|
|
m_handle = handle;
|
|
|
SetFixedPoints();
|
|
|
}
|
|
|
|
|
|
void HTrackerTransform::Draging(CPoint mousePt)
|
|
|
{
|
|
|
if (m_bDrag == false)
|
|
|
return;
|
|
|
|
|
|
if (m_kind == HTRACKER_TRANSFORM_KIND_SCALE)
|
|
|
Scale(mousePt);
|
|
|
else if (m_kind == HTRACKER_TRANSFORM_KIND_MOVE)
|
|
|
Move(mousePt);
|
|
|
else if (m_kind == HTRACKER_TRANSFORM_KIND_ROTATION)
|
|
|
Rotate(mousePt);
|
|
|
else //KIND_SHEAR
|
|
|
Shear(mousePt);
|
|
|
}
|
|
|
|
|
|
void HTrackerTransform::EndDrag()
|
|
|
{
|
|
|
m_bDrag = false;
|
|
|
m_Transform.Reset();
|
|
|
m_handle = 0;
|
|
|
m_bCanMoved = false;
|
|
|
m_StartPhi = 0.0f;
|
|
|
m_kind = HTRACKER_TRANSFORM_KIND_SCALE;
|
|
|
}
|
|
|
|
|
|
Gdiplus::Matrix * HTrackerTransform::GetMatrix()
|
|
|
{
|
|
|
return &m_Transform;
|
|
|
}
|
|
|
|
|
|
void HTrackerTransform::SetKind(HTRACKER_TRANSFORM_KIND kind)
|
|
|
{
|
|
|
m_kind = kind;
|
|
|
SetFixedPoints();
|
|
|
}
|
|
|
|
|
|
//函数功能:设置选中的handle对应的不动点。
|
|
|
// HandleTopLeft HandleTop HandleTopRight
|
|
|
// 0 1 2
|
|
|
// *-----------*-----------*
|
|
|
// | |
|
|
|
// | |
|
|
|
// HandleLeft 7 * * 8 * 3 HandleRight
|
|
|
// | HandleCenter |
|
|
|
// | |
|
|
|
// *-----------*-----------*
|
|
|
// 6 5 4
|
|
|
//拖拽Handle时的不动点
|
|
|
//拖拽0Handle时,对应的不动点为4。拖拽1Handle时,对应的不动点为5。依次为2-->6,3-->7,
|
|
|
//4-->0,5-->1,6-->2,7-->3.
|
|
|
//handle ^ 4, 会找到对应的不动点。
|
|
|
void HTrackerTransform::SetFixedPoints()
|
|
|
{
|
|
|
//m_handle的范围:[0,8]
|
|
|
if (m_handle < 0 || m_handle>8)
|
|
|
return ;
|
|
|
|
|
|
int hFixed = m_handle ^ 4;
|
|
|
|
|
|
//m_FixedSrc = GetHandlePoint(m_PointSrc, hFixed);
|
|
|
//m_FixedDest = GetHandlePoint(m_PointDest, hFixed);
|
|
|
m_FixedSrc = m_calculator.GetHandlePoint(hFixed);
|
|
|
m_FixedDest = m_FixedSrc;
|
|
|
|
|
|
if (m_kind == HTRACKER_TRANSFORM_KIND_ROTATION)
|
|
|
{
|
|
|
CSize sz = CPoint(m_calculator.Test(m_handle / 2)) - m_FixedSrc;
|
|
|
m_StartPhi = 180.0f * (Gdiplus::REAL) (atan2((double)sz.cy, sz.cx) / PI);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//参数:point 鼠标点
|
|
|
void HTrackerTransform::Scale(CPoint & point)
|
|
|
{
|
|
|
//m_FixedDest is the selected handle point of destination rectangle
|
|
|
CSize sz = point - m_FixedDest;
|
|
|
//m_FixedSrc is the selected handle point of source rectangle
|
|
|
CSize szSrc = m_StartPoint - m_FixedSrc;
|
|
|
Gdiplus::REAL scaleX = 1.0f;
|
|
|
Gdiplus::REAL scaleY = 1.0f;
|
|
|
if ((m_handle & 1) == 0) //偶数点为角点,X,Y方向缩放。
|
|
|
{
|
|
|
if (szSrc.cx != 0)
|
|
|
scaleX = (Gdiplus::REAL) sz.cx / (Gdiplus::REAL) szSrc.cx;
|
|
|
//if (!(m_Options & OptionAllowMirror) && scaleX < 0.0f)
|
|
|
// scaleX = 0.0f; //no allow mirror x
|
|
|
if (szSrc.cy != 0)
|
|
|
scaleY = (Gdiplus::REAL) sz.cy / (Gdiplus::REAL) szSrc.cy;
|
|
|
|
|
|
//if (!(m_Options & OptionAllowMirror) && scaleY < 0.0f)
|
|
|
// scaleY = 0.0f; //no allow mirror y
|
|
|
|
|
|
// if (!(nFlags & MK_SHIFT)) // maintain proportions, //当按下SHIFT键时等比例缩放
|
|
|
// {
|
|
|
// Gdiplus::REAL scaleXabs = fabsf(scaleX);
|
|
|
// Gdiplus::REAL scaleYabs = fabsf(scaleY);
|
|
|
// if (scaleXabs > scaleYabs) scaleX = (scaleX < 0) ? -scaleYabs : scaleYabs;
|
|
|
// else scaleY = (scaleY < 0) ? -scaleXabs : scaleXabs;
|
|
|
// }
|
|
|
|
|
|
// Set cursor; might be changed after flipping
|
|
|
//int curs = (m_Handle & 2) / 2; // 0 or 1
|
|
|
//if (m_bMapFlip) curs ^= 1;
|
|
|
//curs ^= scaleX < 0;
|
|
|
//curs ^= scaleY < 0;
|
|
|
//HCURSOR h = g_hCursor[curs];
|
|
|
//if (h)
|
|
|
// ::SetCursor(h);
|
|
|
}
|
|
|
else if ((m_handle & 3) == 1) // horizontal edge, scale vertical
|
|
|
{
|
|
|
if (szSrc.cy != 0)
|
|
|
scaleY = (Gdiplus::REAL) sz.cy / (Gdiplus::REAL) szSrc.cy;
|
|
|
//if (!(m_Options & OptionAllowMirror) && scaleY < 0.0f)
|
|
|
// scaleY = 0.0f;
|
|
|
//if (nFlags & MK_SHIFT)
|
|
|
// scaleX = scaleY; //当按下SHIFT键时等比例缩放
|
|
|
}
|
|
|
else if ((m_handle & 3) == 3) // vertical edge, scale horizontal
|
|
|
{
|
|
|
if (szSrc.cx != 0)
|
|
|
scaleX = (Gdiplus::REAL) sz.cx / (Gdiplus::REAL) szSrc.cx;
|
|
|
//if (!(m_Options & OptionAllowMirror) && scaleX < 0.0f)
|
|
|
// scaleX = 0.0f;
|
|
|
// if (nFlags & MK_SHIFT)
|
|
|
// scaleY = scaleX; //当按下SHIFT键时等比例缩放
|
|
|
}
|
|
|
|
|
|
m_Transform.Reset();
|
|
|
// Translate the fixed point to the origin.
|
|
|
m_Transform.Translate((Gdiplus::REAL) - m_FixedSrc.x, (Gdiplus::REAL) - m_FixedSrc.y, Gdiplus::MatrixOrderAppend);
|
|
|
// Scale the object.
|
|
|
m_Transform.Scale(scaleX, scaleY, Gdiplus::MatrixOrderAppend);
|
|
|
// Translate back to fixed point (which may be different).
|
|
|
m_Transform.Translate((Gdiplus::REAL)m_FixedDest.x, (Gdiplus::REAL)m_FixedDest.y, Gdiplus::MatrixOrderAppend);
|
|
|
}
|
|
|
|
|
|
void HTrackerTransform::Move(CPoint & point)
|
|
|
{
|
|
|
CSize sz = point - m_StartPoint;
|
|
|
|
|
|
//为了防止不小心移动元素,当超过该值时才起作用(允许移动像素个数)
|
|
|
if (IsCanMove(point, m_StartPoint))
|
|
|
{
|
|
|
m_Transform.Reset();
|
|
|
m_Transform.Translate((Gdiplus::REAL)sz.cx, (Gdiplus::REAL)sz.cy);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool HTrackerTransform::IsCanMove(const CPoint& nPrevPoint, const CPoint& nCurPoint)
|
|
|
{
|
|
|
if (m_bCanMoved)
|
|
|
return true;
|
|
|
|
|
|
CSize sz = nCurPoint - nPrevPoint;
|
|
|
//为了防止不小心移动元素,当超过该值时才起作用(允许移动像素个数)
|
|
|
if (abs(sz.cx) >= m_nAllowMovePixel || abs(sz.cy) >= m_nAllowMovePixel)
|
|
|
{
|
|
|
m_bCanMoved = true;
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
void HTrackerTransform::Rotate(CPoint & point)
|
|
|
{
|
|
|
CSize sz = point - m_FixedDest;
|
|
|
Gdiplus::REAL phi = 180.0f * (Gdiplus::REAL)(atan2((double)sz.cy, (double)sz.cx) / PI) - m_StartPhi;
|
|
|
while (phi <= -180.0f)
|
|
|
phi += 360.0f; // (-180, 180]
|
|
|
|
|
|
m_Transform.Reset();
|
|
|
m_Transform.Translate((Gdiplus::REAL) - m_FixedSrc.x, (Gdiplus::REAL) - m_FixedSrc.y);
|
|
|
m_Transform.Rotate(phi, Gdiplus::MatrixOrderAppend);
|
|
|
m_Transform.Translate((Gdiplus::REAL) m_FixedDest.x, (Gdiplus::REAL) m_FixedDest.y, Gdiplus::MatrixOrderAppend);
|
|
|
}
|
|
|
|
|
|
void HTrackerTransform::Shear(CPoint & point)
|
|
|
{
|
|
|
CSize sz = point - m_FixedDest;
|
|
|
CSize szSrc = m_StartPoint - m_FixedSrc;
|
|
|
|
|
|
Gdiplus::REAL shearX = 0.0f;
|
|
|
Gdiplus::REAL shearY = 0.0f;
|
|
|
Gdiplus::REAL scaleX = 1.0f;
|
|
|
Gdiplus::REAL scaleY = 1.0f;
|
|
|
|
|
|
if (m_handle & 2) // vertical edge
|
|
|
{
|
|
|
if (sz.cx != 0)
|
|
|
shearY = (Gdiplus::REAL) sz.cy / (Gdiplus::REAL) sz.cx;
|
|
|
if (szSrc.cx != 0)
|
|
|
scaleX = (Gdiplus::REAL) sz.cx / (Gdiplus::REAL) szSrc.cx;
|
|
|
//if (!(m_Options&OptionAllowMirror) && scaleX < 0.0f) scaleX = 0.0f;
|
|
|
}
|
|
|
else // horizontal edge
|
|
|
{
|
|
|
if (sz.cy != 0)
|
|
|
shearX = (Gdiplus::REAL) sz.cx / (Gdiplus::REAL) sz.cy;
|
|
|
if (szSrc.cy != 0)
|
|
|
scaleY = (Gdiplus::REAL) sz.cy / (Gdiplus::REAL) szSrc.cy;
|
|
|
//if (!(m_Options&OptionAllowMirror) && scaleY < 0.0f) scaleY = 0.0f;
|
|
|
}
|
|
|
|
|
|
m_Transform.Reset();
|
|
|
m_Transform.Translate((Gdiplus::REAL) - m_FixedSrc.x, (Gdiplus::REAL) - m_FixedSrc.y);
|
|
|
|
|
|
// Don't scale the other direction if Shift is pressed
|
|
|
//if ((nFlags & MK_SHIFT) == 0) m_Transform.Scale(scaleX, scaleY, Gdiplus::MatrixOrderAppend);
|
|
|
|
|
|
m_Transform.Shear(shearX, shearY, Gdiplus::MatrixOrderAppend);
|
|
|
m_Transform.Translate((Gdiplus::REAL) m_FixedDest.x, (Gdiplus::REAL) m_FixedDest.y, Gdiplus::MatrixOrderAppend);
|
|
|
} |