Files
core/ASCImageStudio3/AVSImageView5/Tracking/TrackExternal.h

490 lines
12 KiB
C++

#pragma once
#include "Tracking.h"
#include <Messages.h>
namespace Tracking
{
//-------------------------------------------------------------------------------------
// Âíåøíèé ãàáàðèòíûé òðýêèíã
//-------------------------------------------------------------------------------------
class CTrackExternal : public CTrackObject
{
// 8
// |
// 0---4---1
// | |
// 7 9 5
// | |
// 3---6---2
public:
inline void Create ( double dLeft, double dTop, double dRight, double dBottom, double dAngle = 0.0, double dStickAngle = 0.0 )
{
m_bIsOffesetMove = false;
m_bIsPointMove = false;
m_bBlockeMode = true;
m_bRotateHasOccurred = false;
m_nRotateAngle = 0.0;
// if create by mouse
if( abs( dRight - dLeft ) < 1 || abs( dBottom - dTop ) < 1 ) m_IsFirstResize = true;
else m_IsFirstResize = false;
m_dStickAngle = dStickAngle;
SetType( Constants::sc_nTrackTypeRectangleRotatable );
Clear();
Add( dLeft, dTop );
Add( dRight, dTop );
Add( dRight, dBottom );
Add( dLeft, dBottom );
Add( 0.5 * ( dLeft + dRight ), dTop );
Add( dRight, 0.5 * ( dTop + dBottom ) );
Add( 0.5 * ( dLeft + dRight ), dBottom );
Add( dLeft, 0.5 * ( dTop + dBottom ) );
Add( 0.5 * ( dLeft + dRight ), dTop - 30 ); //rotate selector
Add( 0.5 * ( dLeft + dRight ), 0.5 * ( dTop + dBottom ) ); //center
Add( 0.5 * ( dLeft + dRight ), 0.5 * ( dTop + dBottom ) );
SetCurrentPointIndex(-1);
RotateToAlpha( rad( dAngle ) );
}
// IMouseButtonHandlers
bool IMouseButtonHandlers::OnMouseMove ( int MouseX, int MouseY )
{
if (!IsCurrentPointValid())
return false;
double dX = MapToDataX(MouseX);
double dY = MapToDataY(MouseY);
//int nCurrentPoint = GetCurrentPointIndex();
int nCurrentPoint = m_IsFirstResize ? 2 : GetCurrentPointIndex();
if (nCurrentPoint == 9 || nCurrentPoint == GetCount() - 1 || GetAsyncKeyState(VK_CONTROL))
{
OffsetByDouble(dX - GetCurrentPoint().dX, dY - GetCurrentPoint().dY);
//SendMessage(Constants::sc_nMessageTrackPointProcessAll, GetCurrentPointIndex());
m_bIsOffesetMove = true;
m_bIsPointMove = false;
m_bRotateHasOccurred = false;
}
else
{
m_bIsOffesetMove = false;
m_bIsPointMove = true;
m_bRotateHasOccurred = false;
// correct rectangle points
double dx, dy;
double eX1, eX2, eY1, eY2;
if (nCurrentPoint <= 8)
{
eX1 = 1.0; eY1 = 0.0;
eX2 = 0.0; eY2 = 1.0;
double mAngle = Geometry::GetAngle( GetAt(9).dX, GetAt(9).dY, GetAt(8).dX, GetAt(8).dY ) + M_PI / 2.0;
Geometry::RotatePoint( eX1, eY1, 0.0, 0.0, mAngle );
Geometry::RotatePoint( eX2, eY2, 0.0, 0.0, mAngle );
}
if (nCurrentPoint == 0)
{
dX -= GetAt(0).dX;
dY -= GetAt(0).dY;
dx = dX*eX1 + dY*eY1;
dy = dX*eX2 + dY*eY2;
GetAt(0).dX += dX;
GetAt(0).dY += dY;
GetAt(1).dX += eX2*dy;
GetAt(1).dY += eY2*dy;
GetAt(3).dX += eX1*dx;
GetAt(3).dY += eY1*dx;
}
else if (nCurrentPoint == 1)
{
dX -= GetAt(1).dX;
dY -= GetAt(1).dY;
dx = dX*eX1 + dY*eY1;
dy = dX*eX2 + dY*eY2;
GetAt(1).dX += dX;
GetAt(1).dY += dY;
GetAt(0).dX += eX2*dy;
GetAt(0).dY += eY2*dy;
GetAt(2).dX += eX1*dx;
GetAt(2).dY += eY1*dx;
}
else if (nCurrentPoint == 2)
{
dX -= GetAt(2).dX;
dY -= GetAt(2).dY;
dx = dX*eX1 + dY*eY1;
dy = dX*eX2 + dY*eY2;
GetAt(2).dX += dX;
GetAt(2).dY += dY;
GetAt(1).dX += eX1*dx;
GetAt(1).dY += eY1*dx;
GetAt(3).dX += eX2*dy;
GetAt(3).dY += eY2*dy;
}
else if (nCurrentPoint == 3)
{
dX -= GetAt(3).dX;
dY -= GetAt(3).dY;
dx = dX*eX1 + dY*eY1;
dy = dX*eX2 + dY*eY2;
GetAt(3).dX += dX;
GetAt(3).dY += dY;
GetAt(0).dX += eX1*dx;
GetAt(0).dY += eY1*dx;
GetAt(2).dX += eX2*dy;
GetAt(2).dY += eY2*dy;
}
else if (nCurrentPoint == 4)
{
dX -= GetAt(4).dX;
dY -= GetAt(4).dY;
dx = dX*eX1 + dY*eY1;
dy = dX*eX2 + dY*eY2;
GetAt(4).dX += dX;
GetAt(4).dY += dY;
GetAt(0).dX += eX2*dy;
GetAt(0).dY += eY2*dy;
GetAt(1).dX += eX2*dy;
GetAt(1).dY += eY2*dy;
}
else if (nCurrentPoint == 5)
{
dX -= GetAt(5).dX;
dY -= GetAt(5).dY;
dx = dX*eX1 + dY*eY1;
dy = dX*eX2 + dY*eY2;
GetAt(5).dX += dX;
GetAt(5).dY += dY;
GetAt(1).dX += eX1*dx;
GetAt(1).dY += eY1*dx;
GetAt(2).dX += eX1*dx;
GetAt(2).dY += eY1*dx;
}
else if (nCurrentPoint == 6)
{
dX -= GetAt(6).dX;
dY -= GetAt(6).dY;
dx = dX*eX1 + dY*eY1;
dy = dX*eX2 + dY*eY2;
GetAt(6).dX += dX;
GetAt(6).dY += dY;
GetAt(2).dX += eX2*dy;
GetAt(2).dY += eY2*dy;
GetAt(3).dX += eX2*dy;
GetAt(3).dY += eY2*dy;
}
else if (nCurrentPoint == 7)
{
dX -= GetAt(7).dX;
dY -= GetAt(7).dY;
dx = dX*eX1 + dY*eY1;
dy = dX*eX2 + dY*eY2;
GetAt(7).dX += dX;
GetAt(7).dY += dY;
GetAt(0).dX += eX1*dx;
GetAt(0).dY += eY1*dx;
GetAt(3).dX += eX1*dx;
GetAt(3).dY += eY1*dx;
}
else if (nCurrentPoint == 8)
{
m_bRotateHasOccurred = true;
double baseAngle = Geometry::GetAngle( GetAt(9).dX, GetAt(9).dY, dX, dY );
StickAngle( baseAngle, m_dStickAngle );
double mAngle = baseAngle - Geometry::GetAngle( GetAt(9).dX, GetAt(9).dY, GetAt(8).dX, GetAt(8).dY );
RotateToAlpha ( mAngle );
m_nRotateAngle = mAngle;
}
// recompute centers
if (nCurrentPoint >= 0 && nCurrentPoint < 8)
{
GetAt(4).Create( 0.5*( GetAt(0).dX + GetAt(1).dX ), 0.5*( GetAt(1).dY + GetAt(0).dY ) );
GetAt(5).Create( 0.5*( GetAt(1).dX + GetAt(2).dX ), 0.5*( GetAt(1).dY + GetAt(2).dY ) );
GetAt(6).Create( 0.5*( GetAt(3).dX + GetAt(2).dX ), 0.5*( GetAt(3).dY + GetAt(2).dY ) );
GetAt(7).Create( 0.5*( GetAt(3).dX + GetAt(0).dX ), 0.5*( GetAt(3).dY + GetAt(0).dY ) );
double vX = GetAt(4).dX - GetAt(6).dX;
double vY = GetAt(4).dY - GetAt(6).dY;
double length = Geometry::GetLength( GetAt(4).dX, GetAt(4).dY,GetAt(6).dX, GetAt(6).dY );
if( length < 1 )
{
vX = -eX2;
vY = -eY2;
}
else
{
vX /= length;
vY /= length;
}
GetAt(8).dX = GetAt(4).dX + vX * 30;
GetAt(8).dY = GetAt(4).dY + vY * 30;
GetAt(9).Create(0.5*(GetAt(0).dX + GetAt(2).dX), 0.5 * ( GetAt(2).dY + GetAt(0).dY ) );
}
//SendMessage(Constants::sc_nMessageTrackPointProcess, GetCurrentPointIndex());
}
return true;
}
bool IMouseButtonHandlers::OnLButtonDown ( int MouseX, int MouseY )
{
int nTrackIndex = GetPointUnderCursor( MouseX, MouseY );
if( nTrackIndex == GetCount() - 1 )
GetAt(nTrackIndex).Create( MapToDataX( MouseX ), MapToDataY( MouseY ) );
SetCurrentPointIndex( nTrackIndex );
SendMessage( Constants::sc_nMessageTrackPointBegin, nTrackIndex );
return true;
}
bool IMouseButtonHandlers::OnLButtonUp ( int MouseX, int MouseY )
{
m_IsFirstResize = false;
if (!IsCurrentPointValid())
return false;
SendMessage( Constants::sc_nMessageTrackPointEnd, GetCurrentPointIndex() );
SetCurrentPointIndex(-1);
return true;
}
bool IMouseButtonHandlers::OnRButtonDown ( int MouseX, int MouseY )
{
return false;
}
bool IMouseButtonHandlers::OnRButtonUp ( int MouseX, int MouseY )
{
return false;
}
bool IMouseButtonHandlers::OnMButtonDown ( int MouseX, int MouseY )
{
return false;
}
bool IMouseButtonHandlers::OnMButtonUp ( int MouseX, int MouseY )
{
return false;
}
inline int GetPointUnderCursor ( int nX, int nY )
{
int nTrackIndex = FindByInteger( nX, nY, c_nTrackPointSizeTouch, FALSE );
if( nTrackIndex < 0 )
{
Structures::RECTI rectD;
double dX = MapToDataX( nX );
double dY = MapToDataY( nY );
double dAngle = Geometry::GetAngle( GetAt(9).dX, GetAt(9).dY, GetAt(8).dX, GetAt(8).dY ) + M_PI_2;
double tX = 0.0;
double tY = 0.0;
double cosA = cos ( -dAngle );
double sinA = sin ( -dAngle );
tX = dX - GetAt(9).dX;
tY = dY - GetAt(9).dY;
dX = GetAt(9).dX + tX * cosA - tY * sinA;
dY = GetAt(9).dY + tX * sinA + tY * cosA;
Structures::POINTI pointTrack ( (int)dX, (int)dY );
rectD.left = (int)GetAt(0).dX;
rectD.top = (int)GetAt(0).dY;
rectD.right = (int)GetAt(2).dX;
rectD.bottom = (int)GetAt(2).dY;
tX = GetAt(0).dX - GetAt(9).dX;
tY = GetAt(0).dY - GetAt(9).dY;
rectD.left = (int) ( GetAt(9).dX + tX * cosA - tY * sinA );
rectD.top = (int) ( GetAt(9).dY + tX * sinA + tY * cosA );
tX = GetAt(2).dX - GetAt(9).dX;
tY = GetAt(2).dY - GetAt(9).dY;
rectD.right = (int) ( GetAt(9).dX + tX * cosA - tY * sinA );
rectD.bottom = (int) ( GetAt(9).dY + tX * sinA + tY * cosA );
if( rectD.right < rectD.left )
{
double tmpRight = rectD.right;
rectD.right = rectD.left;
rectD.left = (int)tmpRight;
}
if( rectD.top > rectD.bottom )
{
double tmpBottom = rectD.bottom;
rectD.bottom = rectD.top;
rectD.top = (int)tmpBottom;
}
if( rectD.IsPointInside( pointTrack ) )
nTrackIndex = GetCount() - 1;
}
return nTrackIndex;
}
inline void RotateToAlpha ( double alpha )
{
for( int index = 0; index < 9; ++index )
Geometry::RotatePoint( GetAt(index).dX, GetAt(index).dY, GetAt(9).dX, GetAt(9).dY, alpha );
}
inline void StickAngle ( double &dAngle, double angleStick )
{
int countStick = 0;
double tmpBaseAngle = dAngle;
double rangeStick = rad(2);
if( 0 == angleStick || rangeStick > angleStick ) angleStick = M_PI_2;
if( dAngle < 0 ) angleStick = -angleStick;
while( (dAngle < 0) ? (tmpBaseAngle < angleStick + rangeStick) : (tmpBaseAngle > angleStick - rangeStick) )
{
tmpBaseAngle -= angleStick;
countStick++;
}
if( abs( tmpBaseAngle ) < rangeStick )
{
tmpBaseAngle = countStick * angleStick;
dAngle = tmpBaseAngle;
}
}
virtual BOOL OnSetCursor(int nX, int nY, int& nPointStatus, int& nChangeStatus)
{
nPointStatus = c_nTrackPointStatusNone;
nChangeStatus = c_nTrackChangeStatusNone;
int nTrackIndex = GetCurrentPointIndex();
if (nTrackIndex < 0)
nTrackIndex = GetPointUnderCursor(nX, nY);
if ( nTrackIndex == 9 || (nTrackIndex == GetCount() - 1) || (nTrackIndex >= 0 && GetAsyncKeyState(VK_CONTROL) < 0))
{
nPointStatus = c_nTrackPointStatusSizeAll;
nChangeStatus = c_nTrackChangeStatusMove;
}
else if ( nTrackIndex >= 0 && nTrackIndex < 8 )
{
nPointStatus = c_nTrackPointStatusPoint;
nChangeStatus = c_nTrackChangeStatusSize;
}
else if (nTrackIndex == 8)
{
nPointStatus = c_nTrackPointStatusRotation;
nChangeStatus = c_nTrackChangeStatusRotation;
}
else
{
nPointStatus = c_nTrackPointStatusNone;
nChangeStatus = c_nTrackChangeStatusNone;
}
return FALSE;
}
virtual void OnPaintLines(Tracking::CTrackPainter& oPainter)
{
oPainter.DrawRectangleRotatable(this);
}
virtual void OnPaintPoints(Tracking::CTrackPainter& oPainter)
{
oPainter.DrawPoints(this, GetCount() - 3, c_nTrackPointSizePaint);
}
inline bool IsAllOffsetMove () const
{
return m_bIsOffesetMove;
}
inline bool IsPointMove () const
{
return m_bIsPointMove;
}
inline bool HasOccurredRotate () const
{
return m_bRotateHasOccurred;
}
inline double RotateAngle () const
{
return m_nRotateAngle;
}
inline CTrackPoint RotateCenter ()
{
return GetAt(9);
}
private:
bool m_IsFirstResize;
double m_dStickAngle;
bool m_bIsOffesetMove;
bool m_bIsPointMove;
bool m_bBlockeMode;
// âðàùåíèå
bool m_bRotateHasOccurred;
//
double m_nRotateAngle;
};
}