📄 rectobj.cpp
字号:
//rectobj.cpp 矩形类的实现文档
#include "StdAfx.h"
#include ".\rectobj.h"
#include "visdrawview.h"
#include "visdrawdoc.h"
#include <math.h>
IMPLEMENT_SERIAL(CRectObj, CFigureObj, 0)
CRectObj::CRectObj(void)
{
}
CRectObj::~CRectObj(void)
{
}
CRectObj::CRectObj(const CRect& position)
: CFigureObj(position)
{
ASSERT_VALID(this);
m_nShape=lineshape;
m_ltx=0.0;m_lty=0.0;m_rbx=0.0;m_rby=0.0;
}
void CRectObj::Draw(CVisDrawView* pView, CDC* pDC)
{
ASSERT_VALID(this);
CBrush brush;
if (!brush.CreateBrushIndirect(&m_logbrush))
return;
CPen pen;
if (!pen.CreatePenIndirect(&m_logpen))
return;
CBrush* pOldBrush;
CPen* pOldPen;
if (m_bBrush)
pOldBrush = pDC->SelectObject(&brush);
else
pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
if (m_bPen)
pOldPen = pDC->SelectObject(&pen);
else
pOldPen = (CPen*)pDC->SelectStockObject(NULL_PEN);
//把世界坐标转化为逻辑坐标
CPoint m_ltPoint, m_rbPoint;
CRect rect = CalcBounds(pView);
switch (m_nShape)
{
case rectshape: //绘制矩形图元
pDC->Rectangle(rect);
break;
case lineshape: //绘制直线图元
pDC->MoveTo(rect.TopLeft());
pDC->LineTo(rect.BottomRight());
break;
}
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
}
void CRectObj::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
//调用基类串行化
CFigureObj::Serialize(ar);
if (ar.IsStoring())
{
ar << (WORD) m_nShape;
ar << m_ltx << m_lty << m_rbx << m_rby;
}
else
{
WORD wTemp;
ar >> wTemp; m_nShape = (Shape)wTemp;
ar >> m_ltx >> m_lty >> m_rbx >> m_rby;
}
}
//设定直线端点坐标,为世界坐标
void CRectObj::SetPoint(int ptNumber, double x, double y)
{
ASSERT(ptNumber <=2);
switch(ptNumber)
{
case 1:
m_ltx = x;
m_lty = y;
break;
case 2:
m_rbx = x;
m_rby = y;
break;
}
}
//返回直线端点的世界坐标
void CRectObj::GetPoint(int ptNumber, double& x, double& y)
{
ASSERT(ptNumber <=2);
switch(ptNumber)
{
case 1:
x = m_ltx;
y = m_lty;
break;
case 2:
x = m_rbx;
y = m_rby;
break;
}
}
//计算外接矩形,以逻辑坐标表示
CRect CRectObj::CalcBounds(CVisDrawView* pView)
{
CRect rect;
CPoint ltPoint, rbPoint;
pView->WorldToClient(ltPoint,m_ltx,m_lty);
pView->WorldToClient(rbPoint,m_rbx,m_rby);
rect.TopLeft() = ltPoint;
rect.BottomRight() = rbPoint;
m_position = rect;
return rect;
}
double CRectObj::PointToLine(CPoint nStartPt,CPoint nEndPt, CPoint pt)
{
int A,B,C;
double distance;
//计算直线参数
A = nStartPt.y - nEndPt.y;
B = nEndPt.x - nStartPt.x;
C = nStartPt.x*nEndPt.y - nEndPt.x*nStartPt.y;
//计算点到直线距离
distance = (A*pt.x + B*pt.y + C)*(A*pt.x + B*pt.y + C)/(A*A + B*B);
distance = sqrt(distance);
return distance;
}
BOOL CRectObj::IsSelected(CVisDrawView* pView, const CPoint& point)
{
CPoint local, StartPt, EndPt;
int distance, nSelectDistance;
local = point;
CRect rect = m_position;
//矩形设备坐标
pView->DocToClient(rect);
//识别精度值
nSelectDistance = pView->GetDocument()->GetSetectDistance()/2;
//鼠标点的设备坐标
pView->DocToClient(local);
switch (m_nShape)
{
case rectshape: //绘制矩形图元
//第一条直线
distance = abs(local.y - rect.top);
if(distance < nSelectDistance) return true;
//第二条直线
distance = abs(local.x - rect.right);
if(distance < nSelectDistance) return true;
//第三条直线
distance = abs(local.y - rect.bottom);
if(distance < nSelectDistance) return true;
//第四条直线
distance = abs(local.x - rect.left);
if(distance < nSelectDistance) return true;
break;
case lineshape: //绘制直线图元
StartPt = rect.TopLeft();
EndPt = rect.BottomRight();
//鼠标点到直线距离
distance = (int)PointToLine(StartPt, EndPt, local);
//根据拾取条件判断图元是否被拾取
return (distance < nSelectDistance);
break;
}
return false;
}
//返回手柄个数
int CRectObj::GetHandleCount()
{
ASSERT_VALID(this);
//如果图元类型为直线,手柄个数为3个
//否则图元为矩形,手柄个数调用基类成员函数得到
return m_nShape == lineshape ?3 :
CFigureObj::GetHandleCount() ;
}
// 返回手柄中心逻辑坐标
CPoint CRectObj::GetHandle(CVisDrawView* pView, int nHandle)
{
ASSERT_VALID(this);
//如果图元类型为直线
if(m_nShape == lineshape)
{
//图元直线1、2、3号手柄相当于基类中1、5、9号手柄
switch(nHandle)
{
case 2:
nHandle = 5;
break;
case 3:
nHandle = 9;
break;
}
}
//调整手柄号后调用基类成员函数
return CFigureObj::GetHandle(pView, nHandle);
}
// point 为逻辑坐标
void CRectObj::MoveHandleTo(int nHandle, CPoint point, CVisDrawView* pView)
{
ASSERT_VALID(this);
//把鼠标逻辑坐标转化为世界坐标
double pointx,pointy;
pView->ClientToWorld(point,pointx,pointy);
//如果图元类型为直线
if(m_nShape == lineshape)
{
//图元直线1、2、3号手柄相当于基类中1、5、9号手柄
switch(nHandle)
{
case 2:
nHandle = 5;
break;
case 3:
nHandle = 9;
break;
}
}
switch (nHandle)
{
default:
ASSERT(FALSE);
case 1:
SetPoint(1,pointx,pointy);
break;
case 2:
SetPoint(1,m_ltx,pointy);
break;
case 3:
SetPoint(1,m_ltx,pointy);
SetPoint(2,pointx,m_rby);
break;
case 4:
SetPoint(2,pointx,m_rby);
break;
case 5:
SetPoint(2,pointx,pointy);
break;
case 6:
SetPoint(2,m_rbx,pointy);
break;
case 7:
SetPoint(1,pointx,m_lty);
SetPoint(2,m_rbx,pointy);
break;
case 8:
SetPoint(1,pointx,m_lty);
break;
case 9:
break;
}
//重新计算边界矩形
CalcBounds(pView);
//修改文档标志
m_pDocument->SetModifiedFlag();
}
// delta为逻辑坐标
void CRectObj::MoveTo(CPoint delta, CVisDrawView* pView)
{
ASSERT_VALID(this);
//把delta转化为世界坐标
double pointx,pointy;
pointx = pView->ClientToWorld(delta.x);
pointy = -pView->ClientToWorld(delta.y);
//修改矩形两顶点坐标
m_ltx = m_ltx + pointx;
m_lty = m_lty + pointy;
m_rbx = m_rbx + pointx;
m_rby = m_rby + pointy;
//重新计算边界矩形
CalcBounds(pView);
//修改文档标志
m_pDocument->SetModifiedFlag();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -