📄 arctool.cpp
字号:
#include "StdAfx.h"
#include ".\arctool.h"
#include <math.h>
#include "arcobj.h"
#include "visdrawdoc.h"
#include "visdrawview.h"
CArcTool::CArcTool(void)
{
}
CArcTool::~CArcTool(void)
{
}
CArcTool::CArcTool(DrawShape drawShape)
: CDrawTool(drawShape)
{
pObj = NULL;
}
void CArcTool::OnLButtonDown(CVisDrawView* pView, UINT nFlags, const CPoint& point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CPoint dp;
double ptx, pty;
double nCenterPointx, nCenterPointy;
CPoint local = point;
//把设备坐标转化为逻辑坐标
pView->ClientToDoc(local);
//点point的世界坐标ptx,pty
pView->ClientToWorld(local, ptx,pty);
m_LMouseDownStep++;
//申请与视图窗口相关的设备描述表
CDC* dc=pView->GetDC();
//设定屏幕反色绘图模式
dc->SetROP2(R2_NOT);
//根据按下鼠标的次数执行不同的操作
switch(m_LMouseDownStep)
{
default:
ASSERT(FALSE);
case 1:
//第一次鼠标按下时创建CArcObj对象
pObj = new CArcObj(CRect(local, CSize(0, 0)));
//第一次按下鼠标时三种画弧工具的其他任务
switch(m_drawShape)
{
default:
break;
case tparcTool: //弧上三点画弧工具
case secarcTool: //起点、终点、圆心画弧工具
break;
case csearcTool: //圆心、起点、终点画弧工具
//把第一个点指定为圆心
pObj->SetCenterPoint(ptx,pty);
break;
}
//把CArcObj对象指针加到文档对象指针链表中
pView->GetDocument()->Add(pObj);
//记录辅助点
//第一次按下的设备坐标点
lastPoint = point;
prePoint = point;
oldPoint = point;
//第一次按下的逻辑坐标点
flocal = local;
break;
case 2:
//第二次按下鼠标时三种画弧工具的任务
switch(m_drawShape)
{
default:
break;
case tparcTool: //弧上三点画弧工具
//删除第一点到第二点之间的直线(在鼠标移动消息中绘制的)
dc->MoveTo(lastPoint);
dc->LineTo(prePoint);
break;
case secarcTool: //起点、终点、圆心画弧工具
//以第一点到第二点之间的距离为直径
dp = local - flocal;
double radium;
//计算逻辑半径
radium = sqrt((double)(dp.x*dp.x + dp.y*dp.y))/2.0;
//计算世界坐标下的半径
radium = pView->ClientToWorld(radium);
//设定圆弧对象半径
pObj->SetRadium(radium);
//以第一点和第二点的中点为圆心
dp.x = (flocal.x + local.x)/2;
dp.y = (flocal.y + local.y)/2;
//把圆心转化为世界坐标
pView->ClientToWorld(dp,nCenterPointx, nCenterPointy);
//设定圆弧对象圆心
pObj->SetCenterPoint(nCenterPointx, nCenterPointy);
//计算起点、终点弧度
pObj->SetStartAngle(pObj->CalcArcAngle(pView,flocal));
pObj->SetEndAngle(pObj->CalcArcAngle(pView,local));
break;
case csearcTool: //圆心、起点、终点画弧工具
//计算半径
pObj->SetRadium(pObj->CalcRadium(ptx,pty));
//计算起点弧度
pObj->SetStartAngle(pObj->CalcArcAngle(pView,local));
break;
}
prePoint = point;
oldPoint = point;
tlocal = local;
prelocal = local;
break;
case 3:
//第三次按下鼠标左键
switch(m_drawShape)
{
default:
break;
case tparcTool: //弧上三点画弧工具
//由弧上三点计算圆弧参数
pObj->CalculateArcParameterbytp(pView,flocal,tlocal,local);
// dc->SetROP2(R2_COPYPEN);
// DrawArc(pView, dc,pObj);
break;
case secarcTool: //起点、终点、圆心画弧工具
//第三点为圆心,为世界坐标
pView->ClientToWorld(local,nCenterPointx, nCenterPointy);
pObj->SetCenterPoint(nCenterPointx, nCenterPointy);
//圆心变化后需要重新计算起点和终点的弧度
//计算起点弧度
pObj->SetStartAngle(pObj->CalcArcAngle(pView,flocal));
//计算终点弧度
pObj->SetEndAngle(pObj->CalcArcAngle(pView,tlocal));
break;
case csearcTool: //圆心、起点、终点画弧工具
//删除从圆心到起点鼠标点之间的直线
// dc->MoveTo(lastPoint);
// dc->LineTo(oldPoint);
//计算终点弧度
pObj->SetEndAngle(pObj->CalcArcAngle(pView,local));
break;
}
//计算圆弧外接矩形
pObj->CalcBounds(pView);
//把鼠标按下次数标记置0
m_LMouseDownStep = 0;
//刷新视图
pView->Invalidate(TRUE);
//对象指针
pObj = NULL;
break;
}
//删除设备描述表
pView->ReleaseDC(dc);
}
void CArcTool::OnLButtonUp(CVisDrawView* pView, UINT nFlags, const CPoint& point)
{
}
void CArcTool::OnMouseMove(CVisDrawView* pView, UINT nFlags, const CPoint& point)
{
double nCenterPointx, nCenterPointy; //圆弧圆心
CPoint local = point;
//把设备坐标转化为逻辑坐标
pView->ClientToDoc(local);
if(!m_LMouseDownStep) return;
//申请与视图窗口相关的设备描述表
CDC* dc=pView->GetDC();
//用屏幕颜色的反色绘图
dc->SetROP2(R2_NOT);
switch(m_LMouseDownStep)
{
case 1:
//第一次按下鼠标时三种画弧工具的其他任务
switch(m_drawShape)
{
default:
break;
case tparcTool: //弧上三点画弧工具
//删除第一点到前一个鼠标位置点之间的直线
dc->MoveTo(lastPoint);
dc->LineTo(prePoint);
//绘制第一点到当前鼠标点位置的直线
dc->MoveTo(lastPoint);
dc->LineTo(point);
break;
case secarcTool: //起点、终点、圆心画弧工具
//删除第一点到前一个鼠标位置点之间的直线
dc->MoveTo(lastPoint);
dc->LineTo(prePoint);
//绘制起点到当前鼠标点位置的直线
dc->MoveTo(lastPoint);
dc->LineTo(point);
break;
case csearcTool: //圆心、起点、终点画弧工具
//删除第一点到前一个鼠标位置点之间的直线
dc->MoveTo(lastPoint);
dc->LineTo(prePoint);
//绘制起点到当前鼠标点位置的直线
dc->MoveTo(lastPoint);
dc->LineTo(point);
break;
}
break;
case 2:
//第一次按下鼠标时三种画弧工具的其他任务
switch(m_drawShape)
{
default:
break;
case tparcTool: //弧上三点画弧工具
//删除第二点与第三点重合时所画的圆弧
if(tlocal == prelocal)
{
pObj->CalculateArcParameterbytp(pView,flocal,tlocal,prelocal);
DrawArc(pView, dc,pObj);
}
//删除前经过前一个鼠标点的圆弧
pObj->CalculateArcParameterbytp(pView,flocal,tlocal,prelocal);
DrawArc(pView, dc,pObj);
//绘制经过当前鼠标点的圆弧
pObj->CalculateArcParameterbytp(pView,flocal,tlocal,local);
DrawArc(pView, dc,pObj);
break;
case secarcTool: //起点、终点、圆心画弧工具
///////////////////////////////////////////////////////////////////
//删除第一点到前一个鼠标位置点之间的直线
dc->MoveTo(lastPoint);
dc->LineTo(prePoint);
//绘制起点到当前鼠标点位置的直线
dc->MoveTo(lastPoint);
dc->LineTo(point);
//删除第一点到前一个鼠标位置点之间的直线
dc->MoveTo(oldPoint);
dc->LineTo(prePoint);
//绘制起点到当前鼠标点位置的直线
dc->MoveTo(oldPoint);
dc->LineTo(point);
/////////////////////////////////////////////////////////////////
//删除起点与终点重合时所画的圆弧
if(tlocal == prelocal)
{
//计算以前一个鼠标点为圆心的坐标
pView->ClientToWorld(prelocal,nCenterPointx, nCenterPointy);
pObj->SetCenterPoint(nCenterPointx, nCenterPointy);
//计算以前一个鼠标点为圆心的起点和重点弧度
//计算起点和终点弧度
pObj->SetStartAngle(pObj->CalcArcAngle(pView,flocal));
pObj->SetEndAngle(pObj->CalcArcAngle(pView,tlocal));
//删除以前一个鼠标点为圆心的圆弧
DrawArc(pView, dc,pObj);
}
/////////////////////////////////////////////////////////////////
//计算以前一个鼠标点为圆心的坐标
pView->ClientToWorld(prelocal,nCenterPointx, nCenterPointy);
pObj->SetCenterPoint(nCenterPointx, nCenterPointy);
//计算以前一个鼠标点为圆心的起点和重点弧度
//计算起点和终点弧度
pObj->SetStartAngle(pObj->CalcArcAngle(pView,flocal));
pObj->SetEndAngle(pObj->CalcArcAngle(pView,tlocal));
//删除以前一个鼠标点为圆心的圆弧
DrawArc(pView, dc,pObj);
//////////////////////////////////////////////////////////////
//计算以当前鼠标点为圆心的坐标
pView->ClientToWorld(local,nCenterPointx, nCenterPointy);
pObj->SetCenterPoint(nCenterPointx, nCenterPointy);
//计算以当前鼠标点为圆心的起点和重点弧度
//计算起点和终点弧度
pObj->SetStartAngle(pObj->CalcArcAngle(pView,flocal));
pObj->SetEndAngle(pObj->CalcArcAngle(pView,tlocal));
//绘制以当前鼠标点为圆心的圆弧
DrawArc(pView, dc,pObj);
break;
case csearcTool: //圆心、起点、终点画弧
//删除第一点到前一个鼠标位置点之间的直线
dc->MoveTo(lastPoint);
dc->LineTo(prePoint);
//绘制起点到当前鼠标点位置的直线
dc->MoveTo(lastPoint);
dc->LineTo(point);
//删除起点与终点重合时所画的圆弧
if(tlocal == prelocal)
{
pObj->SetEndAngle(pObj->CalcArcAngle(pView, prelocal));
DrawArc(pView, dc,pObj);
}
//删除以前一个鼠标点为终点的圆弧
pObj->SetEndAngle(pObj->CalcArcAngle(pView, prelocal));
DrawArc(pView, dc,pObj);
//画以当前鼠标点为终点的圆弧
pObj->SetEndAngle(pObj->CalcArcAngle(pView,local));
DrawArc(pView, dc,pObj);
break;
}
break;
case 3:
break;
}
//记录前一个鼠标点的逻辑坐标
prelocal = local;
//记录前一个鼠标点的设备坐标
prePoint = point;
pView->ReleaseDC(dc);
}
void CArcTool::OnLButtonDblClk(CVisDrawView* pView, UINT nFlags, const CPoint& point)
{
}
void CArcTool::CreateObj(CVisDrawView* pView, const CPoint& point)
{
}
//采用设备坐标绘制圆弧
void CArcTool::DrawArc(CVisDrawView* pView, CDC* dc,CArcObj* pObj)
{
double nCenterPointx, nCenterPointy;
double x1,y1,x2,y2;
CPoint nCenterPoint;
double nRadium;
double StartAngle,EndAngle;
//获得圆心世界坐标
pObj->GetCenterPoint(nCenterPointx, nCenterPointy);
//把圆心世界坐标转化为逻辑坐标
pView->WorldToClient(nCenterPoint,nCenterPointx, nCenterPointy);
//把圆心转化为设备坐标
pView->DocToClient(nCenterPoint);
//世界坐标下的圆弧半径
nRadium = pObj->GetRadium();
//圆弧起点、终点弧度
StartAngle = pObj->GetStartAngle();
EndAngle = pObj->GetEndAngle();
//得到起点坐标
x1=nCenterPointx +nRadium*cos(StartAngle);
y1=nCenterPointy +nRadium*sin(StartAngle);
//得到终点的坐标
x2=nCenterPointx +nRadium*cos(EndAngle);
y2=nCenterPointy +nRadium*sin(EndAngle);
//把起点、终点转化为逻辑坐标
CPoint nStart, nEnd;
pView->WorldToClient(nStart,x1,y1);
pView->WorldToClient(nEnd,x2,y2);
//把起点、终点转化为设备坐标
pView->DocToClient(nStart);
pView->DocToClient(nEnd);
//把半径转化为逻辑(设备)半径
nRadium = pView->WorldToClient(nRadium);
//采用设备坐标画圆弧
dc->Arc((nCenterPoint.x - (long)nRadium),(nCenterPoint.y + (long)nRadium),
(nCenterPoint.x + (long)nRadium),(nCenterPoint.y - (long)nRadium),
nStart.x,nStart.y,nEnd.x,nEnd.y);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -