河南工业大学-图形学实验四
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验四:二维变换与裁剪算法的实现
一、实验目的
1、掌握平移变换、旋转变换和缩放变换方法;
2、达到掌握二维图形基本几何变换及运用几何变换快速方便生成图形的目的;
3、掌握图形裁剪算法。
二、实验要求
1. 在MFC单文档应用程序中,添加奇次二维坐标点类CP2,如图1.1 所示,参考图1.2部分代码,分别完成二维图形的平移、旋转和缩放。(注:变换参数可在程序内直接给出或用对话框等形式输入,简单二维图形经二维变换后可生成复杂图形。)
图1.1 CP2类定义
图1.2 部分二维变换参考代码
2. 利用Cohen-Sutherland端点编码算法编程实现任意线段的裁剪,要求自定义窗口区域和直线端点。(注:未被裁剪的线段及被裁剪的线段用不同的颜色显示出来。)
三、实验内容
一,二维图形的变换
○1菜单栏的建立
○2对话框的创建,
创建对应的类为dialog
○3为编辑框Edit添加成员变量:右键,建立类向导,选择Member Variables,双击
IDC_EDIT1(对应编辑框的ID),
Member variable name m_x1
Category Value
Variable type OK
○4新建两个类CCP2和TransForm,CCP2类用于将二维点坐标转换成齐次坐标,TransForm类是平移,旋转,缩放的具体实现。代码如下:
// CP2.h
#pragma once
class CP2
{
public:
CP2();
virtual ~CP2();
CP2(double x, double y);
//如果滚动条不能拉动,请启用宏。
○5在文件视图中找到test4View.h protected里面加入变量
CString x1,y1,x2,y2,translate,scale,rotate。用于在test4View.cpp中接收编辑框的值。
○6在test4View.cpp中加入#include “dialog.h”。在菜单栏中为“二维变换”建立类向导,为它添加消息。
void CTest4View::Onchange()
{
// TODO: Add your command handler code here
dialog dia;
if(dia.DoModal()==IDOK){ // dia.DoModal()显示一个模态对
//框,返回值为IDOK。
x1=dia.m_x1; //将编辑框的值赋给test4View中的变量
y1=dia.m_y1;
x2=dia.m_x2;
y2=dia.m_y2;
translate=dia.m_translate;
scale=dia.m_scale;
rotate=dia.m_rotate;
Invalidate(); //Invalidate()是强制系统进行重画}
}
○7建立一个Var类,用于将传递一个全局变量flag。flag的值为0,1,2,3分别实现画线,平移,旋转,缩放。
○8点击不同按钮修改flag的值执行不同的操作:
CDialog::OnOK()表示关闭对话框方式为OnOk()
○9在test4View.cpp中的OnDraw()函数里实现具体功能
○10实验结果展示
生成直线平移操作
旋转操作缩放操作
二,裁剪算法
○1基本思想:
对于每条待裁剪的线段P1P2分三种情况处理:
①若P1P2完全在窗口内,则显示该线段P1P2,简称“取”之;
②若P1P2完全在窗口外,则丢弃该线段,简称“舍”之;
③若线段既不满足“取”的条件,也不满足“舍”的条件,则求线段与窗口边界的交点,在交点处把线段分为两段,其中一段完全在窗口外,可舍弃之,然后对另一段重复上述处理。
○2算法步骤:
第一步判别线段两端点是否都落在窗口内,如果是,则线段完全可见;
否则进入第二步;
第二步判别线段是否为显然不可见,如果是,则裁剪结束;
否则进行第三步;
第三步求线段与窗口边延长线的交点,这个交点将线段分为两段,其中一段显然不可见,丢弃。
对余下的另一段重新进行第一步,第二步判断,直至结束。
○3新建类CP1,代码如下:
○4新建类LineClipping,代码如下:
○5为菜单项裁剪算法的响应事件添加代码。代码如下:
○6实验运行结果:
四、实验结果与总结
(列出实验过程中的收获和遇到的困难)
这次实验虽然做的是二维变换与裁剪算法的实现,但是大部分时间却花在了实现对话框输值,画布上画画的功能上,也算是弥补上一次实验吧。此次实验钻研了以下几个问题:
○1对比了博客上MFC对话框操作的两种方法。个人总结的区别有以下三点:首先,第
一种方法Category选择value,第二种选择Control。Value一般指字符串,各种数据类型(int等);Control一般指该控件对应的MFC类。如果为编辑框控件关联变量,如果是Value,那么该变量数据类型可以是CString,或int或float等数据类型;如果是control,那么该变量的数据类型只能是CEdit。其次,若选择是Control,还需要在dialog类里面定义自己的成员变量,在按钮的响应事件中通过this->GetDlgItemText();将编辑框中的值获取并赋给成员变量。最后,在...View类中复制的方法也不一样,第一种控件变量复制:
x1=dia.m_x1,第二种为成员变量:x1=dia.x1。
○2关于if(dlg.DoModal()==IDOK){…},当dlg.DoModal()后,显示一个模态对话框,此
时DoModal()函数并不返回,即并没有执行大括号内的内容,直到用户关闭此对话框时,DoModal才返回。如果用户点击了确定按钮,那么DoModal()函数就返回IDOK,此时进入if语句。IDOK是一个宏。当你CMyDlg dlg;时,对话框并没有显示,只是构造了一个CMyDlg 类型的对象而已,直到用户调用DoModal(),对话框才会显示出来。而且有意思的是DoModal()只有两个定义好的返回值IDOK和IDCANCLE,其实对应的就是默认的确认和取消,其他返回值需要自定义。这使我在点击不同按钮实现不同功能时碰到了困难,因为只有两个两个返回值,而我需要实现四个功能,对此我的解决方案是这样的,最初,只用一个IDOK返回值,没实现一个功能就换代码截完图,写完实验报告蒙混过关。接着,既然只用一个的话,为什么不在一个if(dlg.DoModal()==IDOK){}里把三个功能一起实现,在画布上把平移,旋转,缩放一同画出来。后来,好像全局变量可以解决这个问题诶,才有了之后的flag。