基于OpenCL的二维图形变换与裁剪实验
- 格式:docx
- 大小:390.23 KB
- 文档页数:45
实验报告学院:计算机学号:姓名:实验四 二维图形的基本几何变换一、实验目的1.掌握二维图形基本的几何变换原理及变换矩阵; 2.掌握矩阵运算的程序设计。
二、实验内容实现二维图形的基本变换,包括平移、旋转、比例、对称变换。
三、实验环境硬件平台:PC运行环境: Windows 平台,Visual C++四、算法描述二维图形齐次坐标变换矩阵一般表达式 T = 这 3×3 矩阵中各元素功能一共可分成四块,即a 、b 、c 、d 四项用于图形的比例、对称、错切、旋转等基本变换; k 、m 用于图形的平移变换;p 、q 用于图形的透视变换; s 用于图形的全比例变换。
平移变换 旋转变化放缩变换五、实验过程5.1打开Visualc++6.0程序5.2新建一个C++项目⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡s m kq dc p b a ⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡''1),(110010011y x t t T y x t t y x y x y x 记为⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡-=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡''1)(11000cos sin 0sin cos 1y x R y x y x θθθθθ记为⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡''1),(11000001y x s s S y x s s y x y x y x记为5.3单击完成,双击源文件里的二维图形几何变换View.cpp,出现下图5.5找到其中的OnDraw函数,并将其改成如下,使其实现了一条直线的平移。
void C二维图形几何变换View::OnDraw(CDC* pDC){C二维图形几何变换Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// TODO: 在此处为本机数据添加绘制代码int a[3][3];int i,j;for(i=0;i<3;i++)for(j=0;j<3;j++)a[i][j]=0;for(i=0;i<3;i++)a[i][i]=1;int x0=80,x1=350,y0=120,y1=120;pDC->MoveTo(x1,y1);E:\c++6.0安装\MSDev98\MyProjects\pDC->LineTo(x0,y0);a[2][0]=80;//使直线在行方向上平移了80个单位a[2][1]=50;//使直线在列方向上平移了50个单位x0=x0*a[0][0]+y0*a[1][0]+a[2][0];y0=x0*a[0][1]+y0*a[1][1]+a[2][1];x1=x1*a[0][0]+y1*a[1][0]+a[2][0];y1=x1*a[0][1]+y1*a[1][1]+a[2][1];pDC->MoveTo(x1,y1);pDC->LineTo(x0,y0);}5.6单击运行程序并有如下结果5.7找到其中的OnDraw函数,并将其改成如下,使其实现了一条直线的平移和缩放。
《计算机图形学实验》报告任课教师:钱文华2016年春季学期实验:梁友栋裁剪实验时间:2016年11月17日实验地点:信息学院2204实验目的:掌握梁友栋裁剪程序代码:#include <stdio.h>#include <glut.h>#include <stdlib.h>#include <math.h>class wcPt2D{public:GLfloat x,y;void setCoords(GLfloat xCoord,GLfloat yCoord){x=xCoord;y=yCoord;}GLfloat getx() const{return x;}GLfloat gety() const{return y;}};inline GLint round(const GLfloat a){return GLint(a+0.5);}void setPixel(int x,int y){glBegin(GL_POINTS);glVertex2i(x,y);glEnd();}void init(){glClearColor(1.0,1.0,1.0,0.0);glMatrixMode (GL_PROJECTION);gluOrtho2D(-200.0,200.0,-200.0,200.0);}void lineBres(GLfloat x0,GLfloat y0,GLfloat xEnd,GLfloat yEnd){ int dx = fabs(xEnd - x0),dy = fabs(yEnd - y0);int p = 2*dy - dx;int twoDy = 2*dy,twoDyMinusDx = 2*(dy - dx);int x,y;if(x0>xEnd){x = xEnd;y = yEnd;xEnd = x0;}else{x = x0;y = y0;}setPixel(x,y);while(x<xEnd){x++;if(p<0)p+=twoDy;else{y++;p+=twoDyMinusDx;}setPixel(x,y);}}GLint clipTest(GLfloat p,GLfloat q,GLfloat *u1,GLfloat *u2){ GLfloat r;GLint returnValue = true;if(p<0.0){r = q/p;if(r>*u2)returnValue = false;elseif(r>*u1)*u1 = r;}elseif(p>0.0){r = q/p;if(r<*u1)returnValue = false;else if(r<*u2)*u2 = r;}elseif(q<0.0)returnValue = false;return(returnValue);}void lineClipLiangBarsk(wcPt2D winMin,wcPt2D winMax,wcPt2D p1,wcPt2D p2){GLfloat u1 = 0.0,u2 = 1.0,dx = p2.getx()-p1.getx(),dy;GLfloat x1 = p1.getx(),y1 = p1.gety();GLfloat x2 = p2.getx(),y2 = p2.gety();if(clipTest(-dx,p1.getx()-winMin.getx(),&u1,&u2))if(clipTest(dx,winMax.getx()-p1.getx(),&u1,&u2)){dy = p2.gety()-p1.gety();if(clipTest(-dy,p1.gety()-winMin.gety(),&u1,&u2)){if(clipTest(dy,winMax.gety()-p1.gety(),&u1,&u2)){if(u2<1.0){p2.setCoords(p1.getx()+u2*dx,p1.gety()+u2*dy);}if(u1>0.0){p1.setCoords(p1.getx()+u1*dx,p1.gety()+u1*dy);}glColor3f(0.0,0.0,0.0);lineBres(x1,y1,p1.getx(),p1.gety());lineBres(p2.getx(),p2.gety(),x2,y2);glColor3f(1.0,0.0,0.0);lineBres(p1.getx(),p1.gety(),p2.getx(),p2.gety());}}else{glColor3f(0.0,0.0,0.0);lineBres(x1,y1,x2,y2);}}}void displayliangyoudongcaijian(){glClear(GL_COLOR_BUFFER_BIT);glLineWidth(5.0);glColor3f(0.0,0.0,0.0);glBegin(GL_LINE_LOOP);glVertex2i(100,100);glVertex2i(100,-100);glVertex2i(-100,-100);glVertex2i(-100,100);glEnd();glPointSize(4);wcPt2D test1[4] = {{-100.0,-100.0},{100.0,100.0},{-150.0,-200.0},{200.0,120.0}};wcPt2D test2[4] = {{-100.0,-100.0},{100.0,100.0},{-150.0,-120.0},{0.0,0.0}};wcPt2D test3[4] = {{-100.0,-100.0},{100.0,100.0},{-50.0,50.0},{150.0,150.0}};wcPt2D test4[4] = {{-100.0,-100.0},{100.0,100.0},{-50.0,0.0},{60.0,50.0}};wcPt2D test5[4] = {{-100.0,-100.0},{100.0,100.0},{-170.0,-200.0},{200.0,-120.0}};lineClipLiangBarsk(test1[0],test1[1],test1[2],test1[3]);lineClipLiangBarsk(test2[0],test2[1],test2[2],test2[3]);lineClipLiangBarsk(test3[0],test3[1],test3[2],test3[3]);lineClipLiangBarsk(test4[0],test4[1],test4[2],test4[3]);lineClipLiangBarsk(test5[0],test5[1],test5[2],test5[3]);glFlush();}void main(int argc, char* argv[]){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(50,100);glutInitWindowSize(400,300);glutCreateWindow("梁友栋裁剪算法");init();glutDisplayFunc(displayliangyoudongcaijian);glutMainLoop();}实验结果:。
实验五二维图形的裁剪和变换一.实验目的:1.理解二维图形变换的含义。
2.掌握二维平移变换的实现。
3.掌握二维旋转变换的实现。
4.掌握二维比例变换的实现。
5.掌握二维平移变换的实现。
二.实验内容:1.分别实现二维图形变换,并测试你的算法。
三.实验过程#include <graphics.h>#include <stdio.h>#define LEFT 1#define RIGHT 2#define BOTTOM 4#define TOP 8int encode(float x,float y,float XL,float XR,float YB,float YT){int c=0;if(x<XL)c|=LEFT;if(x>XR)c|=RIGHT;if(y<YB)c|=BOTTOM;if(y>YT)c|=TOP;return c;}void CS_LineClip(x1,y1,x2,y2,XL,XR,YB,YT)float x1,y1,x2,y2,XL,XR,YB,YT;{int code1,code2,code;float x,y;code1=encode(x1,y1,XL,XR,YB,YT); code2=encode(x2,y2,XL,XR,YB,YT); while((code1!=0 )||(code2!=0)){if((code1&code2)!=0)return;if(code1!=0)code=code1;elsecode=code2;if((LEFT&code)!=0){x=XL;y=y1+(y2-y1)*(XL-x1)/(x2-x1);}else if((RIGHT&code)!=0){x=XR;y=y1+(y2-y1)*(XR-x1)/(x2-x1);}else if((BOTTOM & code )!=0){y=YB;x=x1+(x2-x1)*(YB-y1)/(y2-y1);}else if((TOP & code) !=0){y=YT;x=x1+(x2-x1)*(YT-y1)/(y2-y1);}if(code==code1){x1=x;y1=y;code1=encode(x1,y1,XL,XR,YB,YT);}else{x2=x;y2=y;code2=encode(x2,y2,XL,XR,YB,YT);}}setcolor(255);line(x1,y1,x2,y2);}main(){int graphdriver=DETECT,graphmode;int x1,y1,x2,y2;initgraph( &graphdriver, &graphmode,"\TC\Turboc 2");line(45,15,45,200);line(45,15,400,15);line(45,200,400,200);line(400,15,400,200);CS_LineClip(20.0,30.0,200.0,400.0,45.0,400.0,15.0,200.0); outtextxy(x1,y1,"start point");outtextxy(x2,y2,"end point");getch();closegraph();}。
专业班级:学号:姓名:一、试验名称:二维裁剪二、试验目的:在二维观察中,需要在观察坐标系下对窗口进行裁剪,即只保留窗口内的那部分图形,去掉窗口外的图形。
二维裁剪是用计算机生成图形最基本的技能,通过本实验使学生掌握如何用计算机进行二维裁剪并熟悉开发环境。
三、实验原理:算法源代码:void CMyView::OnDraw(CDC* pDC){CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data herePoint FrameLT,FrameRB;Point P[5];FrameLT.x=150;FrameLT.y=150;FrameRB.x=320;FrameRB.y=320;pDC->Rectangle((int)FrameLT.x,(int)FrameLT.y,(int)FrameRB.x,(int)FrameRB. y);for(int i = 0; i < 5; i++){P[i].x = (float)(260 + 150*cos(72*i*PI/180) +0.5);P[i].y = (float)(260 + 150*sin(72*i*PI/180) +0.5);}专业班级:学号:姓名:pDC->MoveTo((int)P[0].x,(int)P[0].y);pDC->LineTo((int)P[2].x,(int)P[2].y);pDC->LineTo((int)P[4].x,(int)P[4].y);pDC->LineTo((int)P[1].x,(int)P[1].y);pDC->LineTo((int)P[3].x,(int)P[3].y);pDC->LineTo((int)P[0].x,(int)P[0].y);}void CMyView::Code(Point FrameLT,Point FrameRB,Point P,unsigned char *Flag){unsigned char flag=0;if(P.x<FrameLT.x) flag+=1;if(P.x>FrameRB.x) flag+=2;if(P.y>FrameRB.y) flag+=4;if(P.y<FrameLT.y) flag+=8;(*Flag)=flag;}void CMyView::Clipping(Point FrameLT,Point FrameRB,Point LineSP,Point LineEP){CClientDC dc(this);unsigned char flagSP,flagEP,flagAND,flagOR;double k=(LineEP.y-LineSP.y)/(LineEP.x-LineSP.x);Code(FrameLT,FrameRB,LineSP,&flagSP);Code(FrameLT,FrameRB,LineEP,&flagEP);专业班级:学号:姓名:flagAND=flagSP & flagEP;if(flagAND!=0)return;while(flagSP!=0||flagEP!=0){flagOR=flagSP|flagEP;if((flagOR&0x01)==1){if((flagSP&0x01)==1){LineSP.y=(float)(LineSP.y+k*(FrameLT.x-LineSP.x)); LineSP.x=FrameLT.x;Code(FrameLT,FrameRB,LineSP,&flagSP);}else{LineEP.y=(float)(LineEP.y+k*(FrameLT.x-LineEP.x)); LineEP.x=FrameLT.x;Code(FrameLT,FrameRB,LineEP,&flagEP);}}if((flagOR&0x02)==2){if((flagSP&0x02)==2){LineSP.y=(float)(LineSP.y+k*(FrameRB.x-LineSP.x)); LineSP.x=FrameRB.x;专业班级:学号:姓名:Code(FrameLT,FrameRB,LineSP,&flagSP);}else{LineEP.y=(float)(LineEP.y+k*(FrameRB.x-LineEP.x)); LineEP.x=FrameRB.x;Code(FrameLT,FrameRB,LineEP,&flagEP);}}if((flagOR&0x04)==4){if((flagSP&0x04)==4){LineSP.x=(float)(LineSP.x+(FrameRB.y-LineSP.y)/k); LineSP.y=FrameRB.y;Code(FrameLT,FrameRB,LineSP,&flagSP);}else{LineEP.x=(float)(LineEP.x+(FrameRB.y-LineEP.y)/k); LineEP.y=FrameRB.y;Code(FrameLT,FrameRB,LineEP,&flagEP);}}if((flagOR&0x08)==8){专业班级:学号:姓名:if((flagSP&0x08)==8){LineSP.x=(float)(LineSP.x+(FrameLT.y-LineSP.y)/k); LineSP.y=FrameLT.y;Code(FrameLT,FrameRB,LineSP,&flagSP);}else{LineEP.x=(float)(LineEP.x+(FrameLT.y-LineEP.y)/k); LineEP.y=FrameLT.y;Code(FrameLT,FrameRB,LineEP,&flagEP);}flagAND=flagSP&flagEP;if(flagAND!=0)return;}dc.MoveTo((int)LineSP.x,(int)LineSP.y);dc.LineTo((int)LineEP.x,(int)LineEP.y);}}void CMyView::OnCut() //裁剪{// TODO: Add your command handler code hereCClientDC dc(this);CPen pen(PS_SOLID,1,RGB(255,255,255));CPen *pOldpen = dc.SelectObject(&pen);专业班级:学号:姓名:CBrush*pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));dc.SelectObject(pBrush);Point FrameLT,FrameRB;Point P[5];FrameLT.x=150;FrameLT.y=150;FrameRB.x=320;FrameRB.y=320;dc.Rectangle((int)FrameLT.x,(int)FrameLT.y,(int)FrameRB.x,(int)FrameR B.y);for(int i = 0; i < 5; i++){P[i].x = (float)(260 + 150*cos(72*i*PI/180) +0.5);P[i].y = (float)(260 + 150*sin(72*i*PI/180) +0.5);}dc.MoveTo((int)P[0].x,(int)P[0].y);dc.LineTo((int)P[2].x,(int)P[2].y);dc.LineTo((int)P[4].x,(int)P[4].y);dc.LineTo((int)P[1].x,(int)P[1].y);dc.LineTo((int)P[3].x,(int)P[3].y);dc.LineTo((int)P[0].x,(int)P[0].y);dc.SelectObject(pOldpen);专业班级:学号:姓名:dc.Rectangle((int)FrameLT.x,(int)FrameLT.y,(int)FrameRB.x,(int)FrameR B.y);Clipping(FrameLT,FrameRB,P[0],P[2]);Clipping(FrameLT,FrameRB,P[2],P[4]);Clipping(FrameLT,FrameRB,P[4],P[1]);Clipping(FrameLT,FrameRB,P[1],P[3]);Clipping(FrameLT,FrameRB,P[3],P[0]);}四、实验总结:裁剪处理的主要步骤是:①图元关于窗口内外关系的判别;②图元与窗口的求交。
基于OpenCL的并行计算在图像处理中的应用研究一、引言随着计算机技术的不断发展,图像处理在各个领域中扮演着越来越重要的角色。
而并行计算作为一种提高计算效率的重要手段,被广泛应用于图像处理领域。
OpenCL作为一种开放的并行计算框架,具有跨平台、高性能等优势,因此在图像处理中得到了广泛的应用。
本文将探讨基于OpenCL的并行计算在图像处理中的应用研究。
二、OpenCL简介OpenCL(Open Computing Language)是一种开放的并行计算框架,由Khronos Group组织制定并维护。
它允许开发人员利用多核CPU、GPU等异构设备进行并行计算,从而加速应用程序的运行速度。
OpenCL 具有跨平台、高性能、灵活性强等特点,适用于各种类型的并行计算任务。
三、图像处理中的并行计算图像处理是一种对图像进行获取、存储、传输和呈现等操作的技术,广泛应用于医学影像、数字摄影、视频处理等领域。
在图像处理过程中,往往需要对大量的像素数据进行处理,这就需要高效的计算方法来提高处理速度。
而并行计算正是能够满足这一需求的技术之一。
四、基于OpenCL的图像处理算法1. 图像滤波图像滤波是图像处理中常见的操作,可以用于去噪、平滑、锐化等目的。
基于OpenCL的并行计算可以加速图像滤波算法的执行,提高处理效率。
2. 图像分割图像分割是将图像划分为若干个具有独立特征的区域的过程,常用于目标检测、边缘检测等领域。
通过利用OpenCL进行并行计算,可以加快图像分割算法的运行速度。
3. 特征提取在图像处理中,特征提取是一项重要任务,可以帮助识别目标、分类等。
基于OpenCL的并行计算可以加速特征提取算法的执行,提高准确性和效率。
五、案例分析以某医学影像处理项目为例,该项目需要对大量医学影像数据进行处理和分析。
通过采用基于OpenCL的并行计算技术,可以显著提高影像处理速度,缩短诊断时间,提高工作效率。
六、未来展望随着硬件技术的不断进步和OpenCL框架的不断完善,基于OpenCL的并行计算在图像处理领域将有更广阔的应用前景。
基于OpenCL的尺度不变特征变换算法的并行设计与论文第1篇:基于OpenCL的尺度不变特征变换算法的并行设计与论文针对尺度不变特征变换(sift)算法实时*差的问题,提出了利用开放式计算语言(opencl)并行优化的sift算法。
首先,通过对原算法各步骤进行组合拆分、重构特征点在内存中的数据索引等方式对原算法进行并行化重构,使得计算机网络算法的中间计算结果能够完全在显存中完成交互;然后,采用复用全局内存对象、共享局部内存、优化内存读取等策略对原算法各步骤进行并行设计,提高数据读取效率,降低传输延时;最后,利用opencl语言在图形处理单元(gpu)上实现了sift算法的细粒度并行加速,并在*处理器(cpu)上完成了移植。
与原sift算法配准效果相近时,并行化的算法在gpu和cpu平台上特征提取速度分别提升了10.51~19.33和2.34~4.74倍。
实验结果表明,利用o 未完,继续阅读 >第2篇:基于遗传算法的优化设计论文1数学模型的建立影响抄板落料特*的主要因素有:抄板的几何尺寸a和b、圆筒半径R、圆筒的转速n、抄板安装角β以及折弯抄板间的夹角θ等[4,9]。
在不同的参数a、β、θ下,抄板的安装会出现如图1所示的情况。
图1描述了不同参数组合下抄板的落料特*横截面示意图。
其中,图1(a)与图1(b)、图1(c)、图1(d)的区别在于其安装角为钝角。
当安装角不为钝角且ob与oc的夹角σ不小于od与oc夹角ψ时(即σ≥ψ),会出现图1(b)所示的安装情况;当σ<ψ时,又会出现图1(c)与图1(d)所示的情况,而两者区别在于,η+θ是否超过180°,若不超过,则为图1(c)情况,反之则为图1(d)情况。
其中,点a为抄板上物料表面与筒壁的接触点或为物料表面与抄板横向长度b边的交点;点b为抄板的顶点;点c为抄板折弯点;点d为抄板边与筒壁的交点;点e为ob连线与圆筒内壁面的交点;点f为oc连线与圆筒内壁面的交点。
实验3OpenGL几何变换1.实验目的理解并掌握O penGL二维平移、旋转、缩放变换的方法。
2.实验内容(1)阅读实验原理,运行示范实验代码,掌握0penGL程序平移、旋转、缩放变换的方法。
(2)根据示范代码,完成实验作业。
3.实验原理(1)OpenGL下的几何变换在OpenGL的核心库中,每一种几何变换都有一个独立的函数,所有变换都在三维空间中定义。
平移矩阵构造函数为glTranslate<f,d>(t x,ty,tz),作用是把当前矩阵和一一个表示移动物体的矩阵相乘。
t x、 ty、 tz指定这个移动物体的矩阵,它们可以是任意的实数值,后缀为f (单精度浮点fl oat)或d(双精度浮点double),对于二维应用来说, tz=0.0。
旋转矩阵构造函数为glRotate<f,d>(theta, vx, vy, vz),作用是把当前矩阵和一个表示旋转物体的矩阵相乘。
theta, vx, vy, vz指定这个旋转物体的矩阵,物体将围绕(0,0,0)到(x,y,z) 的直线以逆时针旋转, 参数theta表示旋转的角度.向量 v=(v x,vy,vz)的分量可以是任意的实数值,该向量用于定义通过坐标原点的旋转轴的方向,后缀为 f(单精度浮点f l oat)或d (双精度浮点double),对于二维旋转来说, vx=0.0, vy=0.0, vz=1.0。
缩放矩阵构造函数为glScale<f,d>(sx, sy, sz),作用是把当前矩阵和一个表示缩放物体的矩阵相乘。
sx, sy, sz指定这个缩放物体的矩阵,分别表示在x, y, z方向上的缩放比例, 它们可以是任意的实数值,当缩放参数为负值时,该函数为反射矩阵,缩放相对于原点进行,后缀为 f(单精度浮点fl oat)或d(双精度浮点double)。
注意这里都是说“把当前矩阵和一个表示移动<旋转, 缩放>物体的矩阵相乘”, 而不是直接说“这个函数就是旋转”或者“这个函数就是移动”,这是有原因的, 马上就会讲到。
西北农林科技大学实习报告学院名称:理学院专业班级:姓名:学号:课程:计算机图形学实验报告日期:第十五周实验四二维图形的裁剪一、实验目的1)加深直线段的剪裁算法的理解。
2)熟练掌握一种裁剪算法的编程方法。
二、实验步骤1)分析直线段和矩形窗口的位置关系,选定比较合理算法流程。
2)画出程序流程图。
3)编写程序的源程序。
4)编辑源程序并进行调试。
5)进行特殊模式的运行测试,并结合情况进行调整。
三、实验内容1)在编码算法、中点分割算法、Liang-Barsky算法三种中任选一种作为编程模型。
2)编写直线段裁剪的源程序。
3)建议有能力的学生编写多边形裁剪程序。
4)在计算机上编辑编译运行,实现直线段的裁剪。
原理1.直线和窗口的关系:直线和窗口的关系可以分为如下3类:(1)整条直线在窗口内。
此时,不需剪裁,显示整条直线。
(2)整条直线在窗口外,此时,不需剪裁,不显示整条直线。
(3)部分直线在窗口内,部分直线在窗口外。
此时,需要求出直线与窗框的交点,并将窗口外的直线部分剪裁掉,显示窗口内的直线部分。
直线剪裁算法有两个主要步骤。
首先将不需剪裁的直线挑出,即删去在窗外的直线。
然后,对其余直线,逐条与窗框求交点,并将窗口外的部分删去。
2.Cohen-Sutherland直线剪裁算法:(1)输入直线段的两端点坐标p1(x1,y1),p2(x2,y2),以及窗口的4条边界坐标,y wt ,y wb,y wl,y wr.(2)对p1,p2进行编码,点p1的编码为code1,点p2的编码为code2.(3)若code1| code2=0,对直线p1p2“简取”之,转(6);否则,若code1& code2≠0,对直线段“简弃”之,转(7);当上述两条均不满足时,进行步骤(4)。
(4)确保p1在窗口外部。
若p1在窗口内,则交换p1和p2的坐标值和编码。
(5)根据p1编码从低位开始寻找值为1的地方,从而确定p1在窗口外的哪一侧,然后求出直线段与相应窗口边界的交点S,并用交点S的坐标值替换p1的坐标值,即在交点S处把线段一分为二,因此可以去掉p1S。
二维图形变换与裁剪实验目录1.实验目的 (3)2.实验内容 (3)2.1 实验内容 (3)2.2 实验任务 (3)3.实验过程 (3)3.1 创建基类 (3)3.2 程序分析 (5)3.2.1 数据结构设计 (6)3.3 过程描述 (6)3.3.1 添加线段类CLine (6)3.3.1.1 CLine类的定义 (6)3.1.1.2线段的绘制 (7)3.3.1.3 线段的平移算法 (8)3.3.1.4 线段的旋转算法 (9)3.3.1.5 线段缩放算法 (10)3.3.1.6 线段裁剪算法 (11)3.3.2 添加圆类CCircle (16)3.3.2.1 CCircle类的定义 (16)3.3.2.2 圆的绘制算法 (17)3.3.2.3 圆的平移算法 (18)3.3.2.4 圆的旋转算法 (19)3.3.2.4 圆的缩放算法 (19)3.3.3 添加矩形类CTrangle (20)3.3.3.1 CTrangle类的定义 (20)3.3.3.2 矩形的绘制算法 (21)3.3.3.3 矩形的平移算法 (22)3.3.3.4 矩形旋转算法 (23)3.3.3.5 矩形缩放算法 (24)3.3.4 添加多边形类CPolygn (25)3.3.4.1 CPolygon类的定义 (25)3.3.4.2 多边形绘制算法 (26)3.3.4.3 多边形平移算法 (27)3.3.3.4 多边形旋转算法 (27)3.3.3.5 多边形缩放算法 (28)3.3.3.6 多边形裁剪算法 (29)3.4 菜单事件 (35)3.4.1 消息映射 (35)3.4.2 事件实现 (36)3.5 整体运行效果截图 (44)4.实验体会 (44)实验题目:基本图形生成算法实验1.实验目的1)掌握图形几何变换实现原理,基本几何、复合等;2)掌握二维图形观察流程及变换。
3)掌握图形裁剪算法(二维线段、多边)的原理与实现方。
4)掌握面向对象知识实现图形类的编写方法,实现二维图形的变换换与裁剪。
2.实验内容2.1 实验内容二维图形变换与裁剪实验目的是掌握基本几何、复合二维图形变换与裁剪、窗口视图变换、图形裁减算法等,实验内容包括基于面向对象的方法建立图形类层次结构(如图形基类、点、线段、圆、多边形等),实现几种图形的表示、绘制、序列化(持久保存到磁盘文件)等,实现图形的几何变换(平移、旋转、缩放、复合变换);实现直线段缩放、复合变换);实现直线段缩放、复合变换);实现直线段缩放、复合变换);实现直线段裁剪(三选一:编码裁减算法、中点分割剪算法、Liang -Barsky算法)、多边形裁剪(二选一:多边形Sutherland -Hodgman裁剪算法、Weiler-Atherton裁剪算法)。
在一个程序框架下实现,提交3次程序, 1份实验报告。
2.2 实验任务1)使用Visual C++建立一个单文档程序,建立图形对象相关的基本图形类层次结构。
在程序中增加图形变换菜单(各基本变换对应菜单项),图形的参数通过对话框提供(设计变换参数的对话框,如平移、旋转比例等),实现二维图形的变换。
(提示:在各类中增加相应成员函数实现对象的几何变换;菜单选择变换弹出对应变换的参数对话框,对话框中提供参数后取出参数传递给图形对象,或基于鼠标交互通过调用图形变换成员函数实现对象的换)。
2)图形裁剪能用对话框或鼠标在视口中拖动形成矩裁剪窗,然后裁剪文档中已有的图形对象,显示本次裁剪结果。
测试图形应包含直线段、多边形。
3.实验过程3.1 创建基类1. 创建CShape类,添加平移,旋转,缩放和剪切的虚函数,被所有图形类继承,序列化时通过向上转型和多态机制使用基类的方法绘制所有图形和执行相应操作,CShape类的定义如下:class CShape : public CObject{DECLARE_SERIAL(CShape)//序列号public://序列化void Serialize(CArchive &ar);//构造函数CShape();CShape(int w, int s, COLORREF c);CShape(CShape &s);/******************添加虚函数*********************///绘制virtual void Draw(CDC *pDC);//平移virtual void Translate(int tx, int ty);//缩放virtual void Scale(int px,int py,float xr, float yr);//旋转virtual void Rotate(float angle, int xr, int yr);//裁剪virtual void Tailor(int cx1,int cy1,int cx2, int cy2);//获取图形类型virtual int getType();virtual ~CShape();protected:int width;int style;COLORREF color;int type;//图像类型};由于图形绘制过程中需要用到保存文件和打开保存文件的功能,因此在基类中需要添加序列化函数。
基类序列化函数的定义如下://序列化函数实现void CShape::Serialize(CArchive &ar){CObject::Serialize(ar);if(ar.IsStoring()){ar<<width<<style<<color;}else{ar>>width>>style>>color;}}执行图形变换时,希望是对一类或者一个图形进行绘制,因此,在基类中还添加了类型号type属性和获取类型号的函数,函数如下:int CShape::getType(){return type;}3.2 程序分析所有图形和变换方式都通过菜单来绘制或执行操作,另外,涉及到图形的保存和文件的打开,因此对所有的图形类进行序列化,并在文档类中添加一个CObject类的数组,如下:public:CObArray all;//画图序列,存储对象指针序列化过程如下:void CCG201611245504_02Doc::Serialize(CArchive& ar){all.Serialize(ar);//对象数组序列化if (ar.IsStoring()){// TODO: add storing code hereall.Serialize(ar);}else{// TODO: add loading code hereall.Serialize(ar);}}每绘制一个图像时,都将图形对象的指针添加到数组中,如添加一个圆:all.Add(new CCircle(dlg.m_cx,dlg.m_cy,dlg.m_radius));绘制all中的图形对象,通过在视图类的OnDrow中获取文档序列,绘制all中所有的对象,实现如下:void CCG201611245504_02View::OnDraw(CDC* pDC){CCG201611245504_02Doc* pDoc = GetDocument();ASSERT_V ALID(pDoc);//获取队列文档// TODO: add draw code for native data hereint count = pDoc->all.GetSize();//获取文档序列中的图形对象数量for(int i=0;i<count;i++){((CShape *)(pDoc->all.GetAt(i)))->Draw(pDC);//向上转型,并调用Draw函数画出图形对象}}除此之外,每添加一个对象或执行一次操作,都要调用Ondraw方法对all中的对象进行重绘,达到刷新的效果。
绘制图形时,通过对话框来获取绘制该图形所需要的参数。
但是由于多边形的顶点数量具有不确定性,为了绘制方便,对多边形进行静态绘制。
3.2.1 数据结构设计1)、用结构体存储点坐标,并能够赋值给其他坐标的结构体//点的坐标结构体struct Point{double x;double y;Point operator = (const Point other){this->x = other.x;this->y = other.y;return *this;}};3.3 过程描述3.3.1 添加线段类CLine3.3.1.1 CLine类的定义class CLine : public CShape{DECLARE_SERIAL(CLine)//序列号public:CLine();virtual ~CLine();CLine(int x1,int y1,int x2,int y2);CLine(CLine &c);//序列化void Serialize(CArchive &ar);virtual void Draw(CDC *pDC);virtual void Translate(int tx, int ty);virtual void Scale(int px,int py,float xr, float yr);virtual void Rotate(float angle, int xr, int yr);virtual void Tailor(int wbx, int wby, int wtx, int wty);int code(int x, int y, int x1, int y1, int x2, int y2);//获取图形类型virtual int getType();public:int x1,y1,x2,y2;};3.1.1.2线段的绘制void CLine::Draw(CDC *pDC){CPen p(style, width,color);CPen *old = pDC->SelectObject(&p);pDC->MoveTo(x1,y1);pDC->LineTo(x2,y2);pDC->SelectObject(old);//画笔还原}图1. 绘制线段3.3.1.3 线段的平移算法//tx和ty为平移的距离void CLine::Translate(int tx, int ty){x1 = x1 + tx;y1 = y1 + ty;x2 = x2 + tx;y2 = y2 + ty;}图2. 线段平移3.3.1.4 线段的旋转算法//angle为旋转角,xr和yr和为旋转中心void CLine::Rotate(float angle,int xr, int yr){this->Translate(-xr,-yr);int tempx = x1,tempy = y1;float rangle = (angle/180.0) * 3.1415926;x1 = tempx*cos(rangle) - tempy*sin(rangle);y1 = tempx*sin(rangle) + tempy*cos(rangle);tempx = x2;tempy = y2;x2 = tempx*cos(rangle) - tempy*sin(rangle);y2 = tempx*sin(rangle) + tempy*cos(rangle);this->Translate(xr,yr);}图3. 线段旋转3.3.1.5 线段缩放算法//px,py为缩放中心,xr,yr分别为横向和纵向的缩放比例void CLine::Scale(int px,int py,float xr, float yr){int dx1 = x1 - px;int dx2 = x2 - px;int dy1 = y1 - py;int dy2 = y2 - py;dx1 = dx1 * xr;dx2 = dx2 * xr;dy1 = dy1 * yr;dy2 = dy2 * yr;x1 = px + dx1;x2 = px + dx2;y1 = py + dy1;y2 = py + dy2;}图4. 线段缩放3.3.1.6 线段裁剪算法//cx1,cx2,cy1,cy2为裁剪框左上和右下两点坐标void CLine::Tailor(int cx1,int cy1,int cx2, int cy2){//a为线段的斜率int temp;if(x1>x2){temp = x1; x1 = x2; x2 = temp;temp = y1; y1 = y2; y2 = temp;}if(cx1>cx2){temp = cx1; cx1 = cx2; cx2 = temp;}if(cy1>cy2){temp = cy1; cy1 = cy2; cy2 = temp;}if((x2-x1) != 0){float a = (y2-y1)/((float)(x2-x1));float b = y1 - a*x1;//y = a*x + b为线段方程//ca为矩形框对角线的斜率float ca = (cy2-cy1)/((float)(cx2-cx1));float b1 = cy1 - ca*cx1;float b2 = cy2 + ca*cx1;//y = ca*x + b1 为左上右下对角线的方程//y = -ca*x + b2为左下右上对角线的方程if(x2<=cx1 || x1>=cx2){x1 = y1 = x2 = y2 = 0;return;}if(y1<y2){if(y1>=cy2 || y2<=cy1){x1 = y1 = x2 = y2 = 0;return;}}else{if(y2>=cy2 || y1<=cy1){x1 = y1 = x2 = y2 = 0;return;}}if(a>0){if((cy2 - a*cx1 - b)<=0 || (cy1 - a*cx2 - b)>=0){x1 = y1 = x2 = y2 = 0;return;}//把线段的左端点带入,判断在是在直线上方还是下方//下方if((y1-ca*x1-b1)<0 && y1<cy1){y1 = cy1;x1 = (y1 - b)/a;}//上方if((y1-ca*x1-b1)>0 && x1<cx1){x1 = cx1;y1 = a*x1+b;}if((y1-ca*x1-b1)==0 && x1<cx1){x1 = cx1;y1 = cy1;}//把线段的右端点带入,判断在是在直线上方还是下方//下方if((y2-ca*x2-b1)<0 && x2>cx1){x2 = cx2;y2 = a*x2+b;}//上方if((y2-ca*x2-b1)>0 && y2>cy2){y2 = cy2;x2 = (y2 - b)/a;}if((y2-ca*x2-b1)==0 && x2>cx2){x2 = cx2;y2 = cy2;}}if(a<0){if((cy1 - a*cx1 - b)>=0 || (cy2 - a*cx2 - b)<=0){x1 = y1 = x2 = y2 = 0;return;}//把线段的左端点带入,判断在是在直线上方还是下方//x1在上方(正确)if((y1+ca*x1-b2)<0 && x1<cx1){x1 = cx1;y1 = a*x1+b;}//x1在下方if((y1+ca*x1-b2)>0 && y1>cy2){y1 = cy2;x1 = (y1 - b)/a;}if((y1+ca*x1-b2)==0 && y1>cy2){x1 = cx1;y1 = cy1;}//把线段的右端点带入,判断在是在直线上方还是下方if((y2+ca*x2-b2)>0 && x2>cx2){x2 = cx2;y2 = a*x2+b;}if((y2+ca*x2-b2)<0 && y2<cy1){y2 = cy1;x2 = (y2 - b)/a;}if((y2+ca*x2-b2)==0 && x2>cx2){x2 = cx2;y2 = cy1;}}if(a == 0){if(x1 < cx1){x1 = cx1;}if(x2 > cx2){x2 = cx2;}}}else{if(x2<=cx1 || x1>=cx2){x1 = y1 = x2 = y2 = 0;return;}if(y1<y2){if(y1>=cy2 || y2<=cy1){x1 = y1 = x2 = y2 = 0;return;}}else{if(y2>=cy2 || y1<=cy1){x1 = y1 = x2 = y2 = 0;return;}}if(y1>y2){temp = y1; y1 = y2;y2 = temp;}if(y1<cy1)y1 = cy1;if(y2>cy2)y2 = cy2;}}图5. 线段裁剪3.3.2 添加圆类CCircle3.3.2.1 CCircle类的定义class CCircle : public CShape{DECLARE_SERIAL(CCircle)//序列号public:CCircle();CCircle(int x,int y,int r);CCircle(CCircle &c);virtual ~CCircle();//序列化void Serialize(CArchive &ar);virtual void Draw(CDC *pDC);virtual void Translate(int tx, int ty);virtual void Scale(int px,int py,float xr, float yr);virtual void Rotate(float angle, int xr, int yr);//获取图形类型virtual int getType();public:int xc,yc,radiusx,radiusy;};3.3.2.2 圆的绘制算法void CCircle::Draw(CDC *pDC){CPen p(style, width,color);CPen *old = pDC->SelectObject(&p);pDC->Ellipse(xc-radiusx,yc-radiusy,xc+radiusx,yc+radiusy);pDC->SelectObject(old);//画笔还原}图6. 绘制圆3.3.2.3 圆的平移算法void CCircle::Translate(int tx, int ty){xc = xc + tx;yc = yc + ty;}图7. 圆的平移3.3.2.4 圆的旋转算法void CCircle::Rotate(float angle, int xr, int yr){float rangle = (angle/180.0) * 3.1415926;this->Translate(-xr,-yr);int tempx = xc;int tempy = yc;xc = tempx*cos(rangle) - tempy*sin(rangle);yc = tempx*sin(rangle) + tempy*cos(rangle);this->Translate(xr,yr);}图8. 圆的旋转3.3.2.4 圆的缩放算法void CCircle::Scale(int px,int py,float xr, float yr){int x1 = xc - radiusx;int x2 = xc + radiusx;int y1 = yc - radiusy;int y2 = yc + radiusy;int dx1 = x1 - px;int dx2 = x2 - px;int dy1 = y1 - py;int dy2 = y2 - py;dx1 = dx1 * xr;dx2 = dx2 * xr;dy1 = dy1 * yr;dy2 = dy2 * yr;x1 = px + dx1;x2 = px + dx2;y1 = py + dy1;y2 = py + dy2;radiusx = (x2 - x1)/2;radiusy = (y2 - y1)/2;xc = x1 + radiusx;yc = y1 + radiusy;}图9. 圆的缩放3.3.3 添加矩形类CTrangle3.3.3.1 CTrangle类的定义class CTrangle : public CShape{DECLARE_SERIAL(CTrangle)//序列号public:CTrangle();virtual ~CTrangle();CTrangle(int x1,int y1,int x2,int y2);CTrangle(CTrangle &c);//序列化void Serialize(CArchive &ar);virtual void Draw(CDC *pDC);virtual void Translate(int tx, int ty);virtual void Scale(int px,int py,float xr, float yr);virtual void Rotate(float angle, int xr, int yr);//获取图形类型virtual int getType();public:int x1,y1,x2,y2,x3,y3,x4,y4;};3.3.3.2 矩形的绘制算法void CTrangle::Draw(CDC *pDC){CPen p(style, width,color);CPen *old = pDC->SelectObject(&p);pDC->MoveTo(x1,y1);pDC->LineTo(x2,y2);pDC->LineTo(x3,y3);pDC->LineTo(x4,y4);pDC->LineTo(x1,y1);//pDC->Rectangle(x1,y1,x2,y2);pDC->SelectObject(old);//画笔还原}图10. 绘制矩形3.3.3.3 矩形的平移算法void CTrangle::Translate(int tx, int ty){x1 = x1 + tx;y1 = y1 + ty;x2 = x2 + tx;y2 = y2 + ty;x3 = x3 + tx;y3 = y3 + ty;x4 = x4 + tx;y4 = y4 + ty;}图11. 矩形平移3.3.3.4 矩形旋转算法void CTrangle::Rotate(float angle, int xr, int yr){this->Translate(-xr,-yr);int tempx = x1,tempy = y1;float rangle = (angle/180.0) * 3.1415926;x1 = tempx*cos(rangle) - tempy*sin(rangle);y1 = tempx*sin(rangle) + tempy*cos(rangle);tempx = x2;tempy = y2;x2 = tempx*cos(rangle) - tempy*sin(rangle);y2 = tempx*sin(rangle) + tempy*cos(rangle);tempx = x3;tempy = y3;x3 = tempx*cos(rangle) - tempy*sin(rangle);y3 = tempx*sin(rangle) + tempy*cos(rangle);tempx = x4;tempy = y4;x4 = tempx*cos(rangle) - tempy*sin(rangle);y4 = tempx*sin(rangle) + tempy*cos(rangle);this->Translate(xr,yr);}图12. 矩形旋转3.3.3.5 矩形缩放算法void CTrangle::Scale(int px,int py,float xr, float yr){int dx1 = x1 - px;int dx2 = x2 - px;int dy1 = y1 - py;int dy2 = y2 - py;dx1 = dx1 * xr;dx2 = dx2 * xr;dy1 = dy1 * yr;dy2 = dy2 * yr;x1 = px + dx1;x2 = px + dx2;y1 = py + dy1;y2 = py + dy2;int dx3 = x3 - px;int dx4 = x4 - px;int dy3 = y3 - py;int dy4 = y4 - py;dx3 = dx3 * xr;dx4 = dx4 * xr;dy3 = dy3 * yr;dy4 = dy4 * yr;x3 = px + dx3;x4 = px + dx4;y3 = py + dy3;y4 = py + dy4;}图13. 矩形缩放3.3.4 添加多边形类CPolygn3.3.4.1 CPolygon类的定义class CPolygon : public CShape{DECLARE_SERIAL(CPolygon)//序列号public:CPolygon();virtual ~CPolygon();CPolygon(POINT points[], int n);CPolygon(CPolygon &c);//序列化void Serialize(CArchive &ar);virtual void Draw(CDC *pDC);virtual void Translate(int tx, int ty);virtual void Scale(int px,int py,float xr, float yr);virtual void Rotate(float angle, int xr, int yr);virtual void Tailor(int cx1,int cy1,int cx2, int cy2);//获取图形类型virtual int getType();int Tailorside(int start,int end,int n,POINT *point2,int cx1,int cy1,int cx2, int cy2);protected:int n;POINT points[MAX_CTRL_POINT];};3.3.4.2 多边形绘制算法void CPolygon::Draw(CDC *pDC){CPen p(style, width,color);CPen *old = pDC->SelectObject(&p);//POINT point[5] = {{10,10},{110,10},{110,110},{60,60},{10,110}};//this->points = point;pDC->Polygon(points,n);pDC->SelectObject(old);//画笔还原}图14. 多边形绘制3.3.4.3 多边形平移算法void CPolygon::Translate(int tx, int ty){for(int i=0;i<this->n;i++){points[i].x = points[i].x + tx;points[i].y = points[i].y + ty;}}图15. 多边形平移3.3.3.4 多边形旋转算法void CPolygon::Rotate(float angle, int xr, int yr){this->Translate(-xr,-yr);int tempx,tempy;float rangle = (angle/180.0) * 3.1415926;for(int i=0;i<n;i++){tempx = points[i].x;tempy = points[i].y;points[i].x = tempx*cos(rangle) - tempy*sin(rangle);points[i].y = tempx*sin(rangle) + tempy*cos(rangle);}this->Translate(xr,yr);}图16. 多边形旋转3.3.3.5 多边形缩放算法void CPolygon::Scale(int px,int py,float xr, float yr){int dx,dy;for(int i=0;i<n;i++){dx = points[i].x - px;dy = points[i].y - py;dx = xr * dx;dy = yr * dy;points[i].x = px + dx;points[i].y = py + dy;}}图17. 多边形缩放3.3.3.6 多边形裁剪算法//start为points中某一条边的起始点下标,end为结束点下标,n为保存的另个一个CPOINT数组的当前位置下标//返回nint CPolygon::Tailorside(int start,int end,int n,POINT *point2,int cx1,int cy1,int cx2, int cy2){int x1 = points[start].x;int y1 = points[start].y;int x2 = points[end].x;int y2 = points[end].y;int temp;int flag = 0;if(x1>x2){temp = x1; x1 = x2; x2 = temp;temp = y1; y1 = y2; y2 = temp;}if(cx1>cx2){temp = cx1; cx1 = cx2; cx2 = temp;}if(cy1>cy2){temp = cy1; cy1 = cy2; cy2 = temp;}if((x2-x1) != 0){float a = (y2-y1)/((float)(x2-x1));float b = y1 - a*x1;//y = a*x + b为线段方程//ca为矩形框对角线的斜率float ca = (cy2-cy1)/((float)(cx2-cx1));float b1 = cy1 - ca*cx1;float b2 = cy2 + ca*cx1;//y = ca*x + b1 为左上右下对角线的方程//y = -ca*x + b2为左下右上对角线的方程if(x2<=cx1 || x1>=cx2){x1 = y1 = x2 = y2 = 0;return n;}if(y1<y2){if(y1>=cy2 || y2<=cy1){x1 = y1 = x2 = y2 = 0;return n;}}else{if(y2>=cy2 || y1<=cy1){x1 = y1 = x2 = y2 = 0;return n;}}if(a>0){if((cy2 - a*cx1 - b)<=0 || (cy1 - a*cx2 - b)>=0){x1 = y1 = x2 = y2 = 0;return n;}//把线段的左端点带入,判断在是在直线上方还是下方//下方if((y1-ca*x1-b1)<0 && y1<cy1){y1 = cy1;x1 = (y1 - b)/a;}//上方if((y1-ca*x1-b1)>0 && x1<cx1){x1 = cx1;y1 = a*x1+b;}if((y1-ca*x1-b1)==0 && x1<cx1){x1 = cx1;y1 = cy1;}//把线段的右端点带入,判断在是在直线上方还是下方//下方if((y2-ca*x2-b1)<0 && x2>cx1){x2 = cx2;y2 = a*x2+b;}//上方if((y2-ca*x2-b1)>0 && y2>cy2){y2 = cy2;x2 = (y2 - b)/a;}if((y2-ca*x2-b1)==0 && x2>cx2){x2 = cx2;y2 = cy2;}}if(a<0){if((cy1 - a*cx1 - b)>=0 || (cy2 - a*cx2 - b)<=0){x1 = y1 = x2 = y2 = 0;return n;}//把线段的左端点带入,判断在是在直线上方还是下方//x1在上方(正确)if((y1+ca*x1-b2)<0 && x1<cx1){x1 = cx1;y1 = a*x1+b;}//x1在下方if((y1+ca*x1-b2)>0 && y1>cy2){y1 = cy2;x1 = (y1 - b)/a;}if((y1+ca*x1-b2)==0 && y1>cy2){x1 = cx1;y1 = cy1;}//把线段的右端点带入,判断在是在直线上方还是下方if((y2+ca*x2-b2)>0 && x2>cx2){x2 = cx2;y2 = a*x2+b;}if((y2+ca*x2-b2)<0 && y2<cy1){y2 = cy1;x2 = (y2 - b)/a;}if((y2+ca*x2-b2)==0 && x2>cx2){x2 = cx2;y2 = cy1;}}if(a == 0){if(x1 < cx1){x1 = cx1;}if(x2 > cx2){x2 = cx2;}}}else{if(x2<=cx1 || x1>=cx2){x1 = y1 = x2 = y2 = 0;return n;}if(y1<y2){if(y1>=cy2 || y2<=cy1){x1 = y1 = x2 = y2 = 0;return n;}}else{if(y2>=cy2 || y1<=cy1){x1 = y1 = x2 = y2 = 0;return n;}}if(y1>y2){temp = y1; y1 = y2;y2 = temp;}if(y1<cy1)y1 = cy1;if(y2>cy2)y2 = cy2;}if(flag == 1){point2[n].x = x2;point2[n].y = y2;n = n+1;point2[n].x = x1;point2[n].y = y1;n = n+1;}else{point2[n].x = x1;point2[n].y = y1;n = n+1;point2[n].x = x2;point2[n].y = y2;n = n+1;}return n;}//基于边的多边形裁剪void CPolygon::Tailor(int cx1,int cy1,int cx2, int cy2){int num = 0;int i;POINT point2[MAX_CTRL_POINT];for(i=0; i<this->n ;i++){if((i+1)!=this->n)num = Tailorside(i,i+1,num,point2,cx1,cy1,cx2,cy2);elsenum = Tailorside(i,0,num,point2,cx1,cy1,cx2,cy2);}this->n = num;for(i=0; i<this->n; i++){this->points[i].x = point2[i].x;this->points[i].y = point2[i].y;}}图18. 多边形裁剪3.4 菜单事件3.4.1 消息映射protected://{{AFX_MSG(CCG201611245504_02Doc)afx_msg void OnDrawcircle();afx_msg void OnTranslatecircle();afx_msg void OnDrawline();afx_msg void OnTranslateline();afx_msg void OnDrawpolygon();afx_msg void OnTranslatepolygon();afx_msg void OnDrawtrangle();afx_msg void OnTranslatetrangle();afx_msg void OnScalecircle();afx_msg void OnScaleline();afx_msg void OnScalepolygon();afx_msg void OnScaletrangle();afx_msg void OnRomatecircle();afx_msg void OnRomaeline();afx_msg void OnRomatepolygon();afx_msg void OnRomatetragle();afx_msg void OnTranslateall();afx_msg void OnRomateall();afx_msg void OnScaleall();afx_msg void OnTailline();//}}AFX_MSGDECLARE_MESSAGE_MAP()3.4.2 事件实现void CCG201611245504_02Doc::OnDrawcircle(){// TODO: Add your command handler code hereCDialog_DrawCircle2 dlg;if(dlg.DoModal() == IDOK){all.Add(new CCircle(dlg.m_cx,dlg.m_cy,dlg.m_radius));this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnTranslatecircle(){// TODO: Add your command handler code hereCDialog_Translate dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 1)shape->Translate(dlg.m_tx, dlg.m_ty);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnDrawline(){// TODO: Add your command handler code hereCDialog_DrawLine dlg;if(dlg.DoModal() == IDOK){all.Add(new CLine(dlg.start_x,dlg.start_y,dlg.end_x,dlg.end_y));this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnTranslateline(){// TODO: Add your command handler code hereCDialog_Translate dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 2)shape->Translate(dlg.m_tx, dlg.m_ty);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnDrawpolygon(){// TODO: Add your command handler code here//CDialog_DrawPolygon dlg;//if(dlg.DoModal() == IDOK)//{POINT points[5] = {{310,310},{410,310},{410,410},{360,360},{310,410}};//POINT points[4] = {{310,310},{410,310},{410,410},{310,410}};all.Add(new CPolygon(points,5));this->UpdateAllViews(NULL);//刷新,执行绘制//}}void CCG201611245504_02Doc::OnTranslatepolygon(){// TODO: Add your command handler code hereCDialog_Translate dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 3)shape->Translate(dlg.m_tx, dlg.m_ty);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnDrawtrangle(){// TODO: Add your command handler code hereCDialog_DrawLine dlg;if(dlg.DoModal() == IDOK){all.Add(new CTrangle(dlg.start_x,dlg.start_y,dlg.end_x,dlg.end_y));this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnTranslatetrangle(){// TODO: Add your command handler code hereCDialog_Translate dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 4)shape->Translate(dlg.m_tx, dlg.m_ty);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnScalecircle(){// TODO: Add your command handler code hereCDialog_Scale dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 1)shape->Scale(dlg.m_px, dlg.m_py,dlg.m_rx, dlg.m_ry);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnScaleline(){// TODO: Add your command handler code hereCDialog_Scale dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 2)shape->Scale(dlg.m_px, dlg.m_py,dlg.m_rx, dlg.m_ry);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnScalepolygon(){// TODO: Add your command handler code hereCDialog_Scale dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 3)shape->Scale(dlg.m_px, dlg.m_py,dlg.m_rx, dlg.m_ry);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnScaletrangle(){// TODO: Add your command handler code hereCDialog_Scale dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 4)shape->Scale(dlg.m_px, dlg.m_py,dlg.m_rx, dlg.m_ry);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnRomatecircle(){// TODO: Add your command handler code hereCDialog_Romate dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 1)shape->Rotate(dlg.m_angle,dlg.m_px,dlg.m_py);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnRomaeline(){// TODO: Add your command handler code hereCDialog_Romate dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 2)shape->Rotate(dlg.m_angle,dlg.m_px,dlg.m_py);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnRomatepolygon(){// TODO: Add your command handler code hereCDialog_Romate dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 3)shape->Rotate(dlg.m_angle,dlg.m_px,dlg.m_py);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnRomatetragle(){// TODO: Add your command handler code hereCDialog_Romate dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){//((CShape *)(all.GetAt(i)))->Translate(dlg.m_tx, dlg.m_ty);shape = (CShape *)(all.GetAt(i));if(shape->getType() == 4)shape->Rotate(dlg.m_angle,dlg.m_px,dlg.m_py);}this->UpdateAllViews(NULL);//刷新,执行绘制}}void CCG201611245504_02Doc::OnTranslateall(){// TODO: Add your command handler code hereCDialog_Translate dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){shape = (CShape *)(all.GetAt(i));shape->Translate(dlg.m_tx, dlg.m_ty);}}this->UpdateAllViews(NULL);//刷新,执行绘制}void CCG201611245504_02Doc::OnRomateall(){// TODO: Add your command handler code hereCDialog_Romate dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){shape = (CShape *)(all.GetAt(i));shape->Rotate(dlg.m_angle, dlg.m_px, dlg.m_py);}}this->UpdateAllViews(NULL);//刷新,执行绘制}void CCG201611245504_02Doc::OnScaleall(){// TODO: Add your command handler code hereCDialog_Scale dlg;if(dlg.DoModal() == IDOK){CShape *shape;int count = all.GetSize();for(int i=0; i<count; i++){shape = (CShape *)(all.GetAt(i));shape->Scale(dlg.m_px, dlg.m_py,dlg.m_rx, dlg.m_ry);}}this->UpdateAllViews(NULL);//刷新,执行绘制}void CCG201611245504_02Doc::OnTailline(){// TODO: Add your command handler code hereCDialog_DrawLine dlg;if(dlg.DoModal() == IDOK){CShape *shape;。