You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kev/Drawer/Module/GeoSigmaDraw/HTrackerTransform.cpp

247 lines
7.1 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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);
}