实现目标:
用一个左下角为(100,100),右上角为(800,400)的矩形做直线截取。有用户手动输入一个直线,将该直线在矩形内的部分截取,区域的部分消失。其中,用户绘制直线时,使用的是动态直线。
预备知识:
1)MFC编程相关知识
2)了解Cohen-Sutherland算法
3)了解橡皮线的绘制
过程描述:
1)在Ondraw函数中先画好矩形
2)由左键按下,鼠标移动,左键松开,三个函数,实现橡皮线,并且记录起点与终点的位置。到此完成程序的框架。下面实现具体的算法。橡皮线的实现使用 p->SetROP2(R2_NOT)函数。这是正规的橡皮线实现方法,想具体了解橡皮线的使用方法,可以百度该函数名加橡皮线即可
3)创建函数int CODE(CPoint p)用来传进来一个点坐标,返还一个四位二进制code值。该code值用于判断点的位置。直线的两个端点的编码表示出了线段的方位。对于任一点(x,y),根据其坐标所在的区域,赋予一个4位的二进制码D3D2D1D0。
编码规则如下:
(1)若x<wxl,D0=1,否则D0=0;
(2)若x>wxr,D1=1,否则D1=0;
(3)若y<wyb,D2=1,否则D2=0;
(4)若y>wyt,D3=1,否则D3=0。
4)在左键松开的函数中实现截取功能,
Step1 判断
裁剪一条线段时,先求出直线段端点p1和p2的编码code1和code2,然后:
a) 若code1|code2=0,对直线段简取之;
b) 若code1&code2≠0,对直线段简弃之;
Step2 裁剪
求直线和窗口边界的交点,对直线裁剪
确保p1位于窗口外;若p1在窗口内,则交换p1,p2。
根据p1的编码从低位开始找编码值为1的地方,确定要求交的窗口边界,求出直线段与相应窗口边界的交点,用交点代替p1.
重复上述过程
结果
遇到的问题
1、当画的直线斜率过大时,截取的直线只会从四个角作为起点。解决:之后将斜率的计算换成浮点计算就解决问题了。
2.由于使用橡皮线,直线的清除与重绘很麻烦。我直线截取的实现是通过用一条白色的线覆盖上一条线实现的。这个问题的解决占用了我很大一部分时间。
下面是代码
// 直线截取View.cpp: C直线截取View 类的实现
//
#include "stdafx.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "直线截取.h"
#endif
#include "直线截取Doc.h"
#include "直线截取View.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CPoint m_ptSpoint = CPoint(0, 0); //起始点
CPoint m_ptEpoint = CPoint(0, 0); //最终点
bool m_click;
float k = 0;
// C直线截取View
IMPLEMENT_DYNCREATE(C直线截取View, CView)
BEGIN_MESSAGE_MAP(C直线截取View, CView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &C直线截取View::OnFilePrintPreview)
ON_WM_CONTEXTMENU()
ON_WM_RBUTTONUP()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
// ON_WM_PAINT()
END_MESSAGE_MAP()
// C直线截取View 构造/析构
C直线截取View::C直线截取View() noexcept
{
// TODO: 在此处添加构造代码
}
C直线截取View::~C直线截取View()
{
}
BOOL C直线截取View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
<