《计算机图形学》实验报告——区域填充和剪裁

合集下载

实验报告格式9区域填充

实验报告格式9区域填充

学号
天津城建大学
计算机图形学实验报告
实验九区域填充
学生姓名
专业、班级
指导教师任丽敏
成绩
计算机与信息工程学院
2013 年月日
天津城建大学
设计性实验任务书
计算机与信息工程学院专业班姓名学号:
课程名称:计算机图形学
设计题目:多边形填充
完成期限:自2013 年11月8 日至2013 年11 月18 日
设计依据、要求及主要内容(可另加附页):
1设计依据:
本课程设计是依据教材<<计算机计算机图形学>>一书的第5章图形算法为设计依据, 用扫描线填充算法制作多边形填充的程序。

2设计要求:
用扫描线填充多边形
基本要求:
(1)数据输入项为:多边形的顶点数、各顶点x,y坐标。

对于扫描线填充算法要输入扫描线间距。

(2)填充区域输出在PictureBox控件中。

附加要求:(1)填充区中可内嵌多个多边形。

(2)对于扫描线填充算法使用一定距离的字符填充。

指导教师:任丽敏
实验目的:题目:
设计思想:原程序:运行结果:体会:。

计算机图形学实验报告材料三图形裁剪算法

计算机图形学实验报告材料三图形裁剪算法

实验题目:实验三图形裁剪算法1.实验目的:理解区域编码(Region Code,RC)设计Cohen-Sutherland直线裁剪算法编程实现Cohen-Sutherland直线裁剪算法2.实验描述:设置裁剪窗口坐标为:wxl=250;wxr=850;wyb=250;wyt=450;裁剪前如下图所示:裁剪后结果为:3.算法设计:Cohen-Sutherland 直线裁剪算法:假设裁剪窗口是标准矩形,由上(y=wyt)、下(y=wyb)、左(x=wxl)、右(x=wxr)四条边组成,如下图所示。

延长窗口四条边形成 9个区域。

根据被裁剪直线的任一端点 P(x,y)所处的窗口区域位置,可以赋予一组4位二进制区域码C4C3C2C1。

编码定义规则:第一位C1:若端点位于窗口之左侧,即 X<Wxl,则 C1=1,否则 C1=0。

第二位C2:若端点位于窗口之右侧,即 X>Wxr,则 C2=1,否则 C2=0。

第三位C3:若端点位于窗口之下侧,即 Y<Wyb,则 C3=1,否则 C3=0。

第四位C4:若端点位于窗口之上侧,即 Y>Wyt,则 C4=1,否则 C4=0。

裁剪步骤:1. 若直线的两个端点的区域编码都为0,即 RC1|RC2=0(二者按位相或的结果为0,即 RC1=0 且RC2=0),说明直线两端点都在窗口内,应“简取”。

2. 若直线的两个端点的区域编码都不为0,即 RC1&RC2≠0(二者按位相与的结果不为0,即 RC1≠0且 RC2≠0,即直线位于窗外的同一侧,说明直线的两个端点都在窗口外,应“简弃”。

3. 若直线既不满足“简取”也不满足“简弃”的条件,直线段必然与窗口相交,需要计算直线与窗口边界的交点。

交点将直线分为两段,其中一段完全位于窗口外,可“简弃”。

对另一段赋予交点处的区域编码,再次测试,再次求交,直至确定完全位于窗口内的直线段为止。

4. 实现时,一般按固定顺序左(x=wxl)、右(x=wxr)、下(y=wyb)、上(y=wyt)求解窗口与直线的交点。

计算机图形学图形区域填充效果

计算机图形学图形区域填充效果
CFill.cpp参考代码:
// Fill.cpp : implementation file
#include "stdafx.h"
#include "FloodFill.h"
#include "Fill.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
(1)种子填充算法原理
在多边形内部找到一个已知的象素点作为种子点,由此开始,利用区域的连通性找到多边形内部的 其它所有象素点进行填充。
(i)四向连通区域
①四向连通区域概念:从区域上任一点出发,在不超出区域边界的前提下,可通过4个方向:上、下、左、右的移动组合到达区域中的任意象素点,称此区域为四向连通区域。
{
//有需要填充的区域
if(spanNeedFill==FALSE)
{
spanNeedFill = TRUE;
}
x++;
}
if(spanNeedFill)
{
CPoint rightp(x-1,y);
stack.Push(x-1);
stack.Push(y);
spanNeedFill = FALSE;
virtual ~CStack();
};
#endif // !defined(AFX_STACK_H__D198F788_4ED1_4C09_98E5_433BAB24D864__INCLUDED_)
CStack.cpp参考代码:
// Stack.cpp: implementation of the CStack class.
#if !defined(AFX_STACK_H__D198F788_4ED1_4C09_98E5_433BAB24D864__INCLUDED_) #define AFX_STACK_H__D198F788_4ED1_4C09_98E5_433BAB24D864__INCLUDED_

计算机图形学 实验三 二维图形的区域填充

计算机图形学 实验三 二维图形的区域填充

西北农林科技大学实习报告学院名称:理学院专业班级:姓名:学号:课程:计算机图形学实验报告日期:第十四周实验三二维图形的区域填充一、实验目的1)加深对填充算法的理解,分析比较种子填充和边缘填充的差异。

2)掌握二维图形区域种子填充的原理和算法。

二、实验步骤1)对任意多边形的几何形状进行分析,选定比较合适的算法模型。

2)画出程序流程图;3)编写程序的源程序;4)编辑源程序并进行调试;5)进行特殊模式的运行测试,并结合情况进行调整。

三、实验内容用种子填充算法编写程序实现区域填充,并能在计算机上编译运行,正确地实现任意多边形边界的单色填充。

原理边界填充算法可以让用户首先勾画图的轮廓,选择填充颜色和填充模式,然后拾取内部点,系统就可以自动给图的内部涂上所需要的颜色和图案。

该算法的输入是种子点坐标 ( x , y )、填充色和边界颜色。

算法从( x , y )开始检测相邻位置是否是边界颜色,若不是,就用填充色着色,并检测其相邻位置。

该过程延续到已经检测完区域边界颜色范围内的所有像素为止。

使用栈结构来实现4-连通边界填充算法的算法步骤如下:(1)种子像素入栈。

(2)执行如下三步操作:1 栈顶像素出栈。

2 将出栈像素置成填充色。

3 检查出栈像素的4-邻接点,若其中某个像素不是边界色且未置成多边形色,则把该像素入栈。

(3)检查栈是否为空,若栈非空重复执行步骤(2),若栈为空则结束。

边界填充算法可以用于填充带有内孔的平面区域。

其缺点是把太多的像素压入堆栈,有些像素甚至会入栈多次,这样一方面降低了算法的效率,另一方面还要求很大的存储空间以实现栈结构。

将之改进,可构造沿扫描线填充水平像素段的4-连通边界填充算法,其算法步骤如下:(1)种子像素入栈。

(2)执行如下三步操作:1 栈顶元素出栈。

2 填充出栈元素所在扫描行的连续像素段,从出栈的像素开始沿扫描线向左和向右填充,直到遇到边界像素为止,即每出栈一个像素,就对包含该像素的整个扫描线区间进行填充,并且记录下此时扫描线区间的x坐标范围[ x1, x2 ]。

实验二:图形填充算法实验报告

实验二:图形填充算法实验报告

《计算机图形学》实验报告(实验二:图形填充算法)一、实验目的及要求用两种方法做图形的填充算法!二、理论基础1.边填充算法对于每一条扫描线和每条多边形的交点(x1,y1),将该扫描线上的交点右方的所有像素取补。

2.种子填充算法利用栈来实现种子填充算法。

种子像素入栈,当栈非空时重复执行如下步骤:将栈顶像素出栈,将出栈像素置成多边形色,按左,上,右,下顺序检查与出栈像素相邻的四个像素,若其中某个像素不再边界且未置成多边形,则把该像素入栈!三、算法设计与分析1、边填充算法void CEdge_mark_fillView::OnDraw(CDC* pDC){CEdge_mark_fillDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);int d[500][500]={0};int inside;int x,y;Bresenham(80,101,100,400,d);Bresenham(100,300,290,400,d);Bresenham(292,400,382,50,d);Bresenham(380,50,202,150,d);Bresenham(200,150,82,101,d);for(y=0;y<500;y++){inside=0;for(x=0;x<500;x++){if(d[x][y]==1)if(d[x+1][y]!=1){inside=!(inside);}if(inside!=0)pDC->SetPixel(x,y,12);}}}2、种子填充int x=299,y=51;COLORREF oldcolor;COLORREF newcolor;oldcolor=RGB(256,256,256);newcolor=RGB(123,123,123);pDC->MoveTo (40,40);pDC->LineTo (80,40);pDC->LineTo (70,80);pDC->LineTo (40,40);FloodFill(51,51,RGB(255,255,255),RGB(0,0,255));pDC->LineTo (40,40);void CMyView::FloodFill(int x,int y,COLORREF oldcolor,COLORREF newcolor) {CDC* pDC;pDC=GetDC();if(pDC->GetPixel(x,y)==oldcolor){pDC->SetPixel(x,y,newcolor);FloodFill(x,y-1,oldcolor,newcolor);FloodFill(x,y+1,oldcolor,newcolor);FloodFill(x-1,y,oldcolor,newcolor);FloodFill(x+1,y,oldcolor,newcolor);}四、程序调试及结果的分析1、2、四、实验心得及建议由于很多不会,所以这次没能按时当堂完成,下来花了不少时间才弄出来,第二种尤其比较麻烦,在同学的帮助下才做出来了。

计算机图形学--填充报告2

计算机图形学--填充报告2

计算机图形学课程名称多边形填充实验名称一、实验目的及要求软件环境:Microsoft studio visual C++ 6.0 MFC硬件:计算机(1)理解窗口到视区的变换(2)学习使用MFC的图形编程(3)实现五角多边形的填充二、实验内容仿照Windows的附件程序“画图”, 用C++语言编制一个具有交互式绘制和编辑多种图元功能的程序“Mini-Painter”,实现以下功能对应的设计内容:(1) 能够以交互方式在图形绘制区绘制填充多边形(2) 设置线条的颜色、线型和线条宽度,对绘制的图元进行线条和填充属性的修改;三、实验步骤1.新建MFC应用程序(a)新建工程。

运行VC++6.0,新建一个MFC AppWizard[exe]工程,并命名为“多边形”,选择保存路径,确定。

(b)详细步骤不再细述,接下来如图(c)在view.cpp中输入代码并编译运行无误得到结果三、实验内容// 多边形View.cpp : implementation of the CMyView class//#include "stdafx.h"#include "多边形.h"#include "多边形Doc.h"#include "多边形View.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CMyViewIMPLEMENT_DYNCREATE(CMyView, CView)BEGIN_MESSAGE_MAP(CMyView, CView)//{{AFX_MSG_MAP(CMyView)ON_COMMAND(ID_DUOBIANXING, OnDuobianxing)//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)END_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CMyView construction/destructionCMyView::CMyView(){// TODO: add construction code here}CMyView::~CMyView(){}BOOL CMyView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}///////////////////////////////////////////////////////////////////////////// // CMyView drawingvoid CMyView::OnDraw(CDC* pDC){CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// Circle(100,RGB(0,168,168),pDC) ;// TODO: add draw code for native data here}///////////////////////////////////////////////////////////////////////////// // CMyView printingBOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CMyView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add extra initialization before printing}void CMyView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add cleanup after printing}///////////////////////////////////////////////////////////////////////////// // CMyView diagnostics#ifdef _DEBUGvoid CMyView::AssertValid() const{CView::AssertValid();}void CMyView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CMyDoc* CMyView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));return (CMyDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CMyView message handlersvoid CMyView::OnDuobianxing(){// TODO: Add your command handler code here//CMyDoc* pDoc = GetDocument();//ASSERT_VALID(pDoc);CDC *pDC=GetDC();const int POINTNUM=10; //多边形点数.typedef struct XET{float x;float dx,ymax;XET* next;}AET,NET;struct point{float x;float y;}polypoint[POINTNUM]={200,150,350,50,350,400,250,250,100,350,200,200,300,200,400,200};//多边形顶点int MaxY=0;int i;for(i=0;i<POINTNUM;i++)if(polypoint[i].y>MaxY)MaxY=polypoint[i].y;AET *pAET=new AET;pAET->next=NULL;NET *pNET[1024];for(i=0;i<=MaxY;i++){pNET[i]=new NET;pNET[i]->next=NULL;}for(i=0;i<=MaxY;i++){for(int j=0;j<POINTNUM;j++)if(polypoint[j].y==i){if(polypoint[(j-1+POINTNUM)%POINTNUM].y>polypoint[j].y){NET *p=new NET;p->x=polypoint[j].x;p->ymax=polypoint[(j-1+POINTNUM)%POINTNUM].y;p->dx=(polypoint[(j-1+POINTNUM)%POINTNUM].x-polypoint[j].x)/(polypoint[(j-1+POINTNUM)%POINTN UM].y-polypoint[j].y);p->next=pNET[i]->next;pNET[i]->next=p;}if(polypoint[(j+1+POINTNUM)%POINTNUM].y>polypoint[j].y){NET *p=new NET;p->x=polypoint[j].x;p->ymax=polypoint[(j+1+POINTNUM)%POINTNUM].y;p->dx=(polypoint[(j+1+POINTNUM)%POINTNUM].x-polypoint[j].x)/(polypoint[(j+1+POINTNUM)%POINTN UM].y-polypoint[j].y);p->next=pNET[i]->next;pNET[i]->next=p;}}}for(i=0;i<=MaxY;i++){NET *p=pAET->next;while(p){p->x=p->x + p->dx;p=p->next;}//断表排序,不再开辟空间AET *tq=pAET;p=pAET->next;tq->next=NULL;while(p){while(tq->next && p->x >= tq->next->x)tq=tq->next;NET *s=p->next;p->next=tq->next;tq->next=p;p=s;tq=pAET;}//(改进算法)先从AET表中删除ymax==i的结点AET *q=pAET;p=q->next;while(p){if(p->ymax==i){q->next=p->next;delete p;p=q->next;}else{q=q->next;p=q->next;}}//将NET中的新点加入AET,并用插入法按X值递增排序p=pNET[i]->next;q=pAET;while(p){while(q->next && p->x >= q->next->x)q=q->next;NET *s=p->next;p->next=q->next;q->next=p;p=s;q=pAET;}//配对填充颜色p=pAET->next;while(p && p->next){for(float j=p->x;j<=p->next->x;j++)pDC->SetPixel(static_cast<int>(j),i,RGB(168,255,55));p=p->next->next;//考虑端点情况}}ReleaseDC(pDC);}四、实验结果五、实验总结分析做这个实验要借助数组链表和指针的用法,通过研究,更熟练了用指针进行扫描来绘制圆,通过做这实验,也提升了我对这门课的兴趣。

计算机图形学实验(3-6)

计算机图形学实验(3-6)

实验三:区域填充一、实验目的区域填充是指先将区域内的一点(常称为种子点)赋予给定颜色,然后将这种颜色扩展到整个区域内的过程。

区域填充技术广泛应用于交互式图形、动画和美术画的计算机辅助制作中。

本实验采用递归填充算法或扫描线算法实现对光栅图形的区域填充。

通过本实验,可以掌握光栅图形编程的基本原理和方法。

二、实验内容掌握光栅图形的表示方法,实现种子算法或扫描线算法。

通过程序设计实现上述算法。

建议采用VC++实现OpenGL程序设计。

三、实验原理、方法和手段递归算法在要填充的区域内取一点(X,Y)的当前颜色记为oldcolor,用要填充的颜色newcolor去取代,递归函数如下:procedure flood-fill(X,Y,oldcolor,newcolor:integer);beginif getpixel(framebuffer,x,y)=oldcolorthen beginsetpixel(framebuffer,x,y,newcolor);flood-fill(X,Y+1,oldcolor,newcolor);flood-fill(X,Y-1,oldcolor,newcolor);flood-fill(X-1,Y,oldcolor,newcolor);flood-fill(X+1,Y,oldcolor,newcolor);endend扫描线算法扫描线算法的效率明显高于递归算法,其算法的基本思想如下:(1)(初始化)将算法设置的堆栈置为空,将给定的种子点(x,y)压入堆栈。

(2)(出栈)如果堆栈为空,算法结束;否则取栈顶元素(x,y)作为种子点。

(3)(区段填充)从种子点(x,y)开始沿纵坐标为y的当前扫描线向左右两个方向逐个象素进行填色,其值置为newcolor,直到抵达边界为止。

(4)(定范围)以x left和x right分别表示在步骤3中填充的区段两端点的横坐标。

(5)(进栈)分别在与当前扫描线相邻的上下两条扫描线上,确定位于区间[x left,x right]内的给定区域的区段。

计算机图形学实验四 区域填充算法的实现

计算机图形学实验四   区域填充算法的实现

实验四区域填充算法的实现班级 08信计2班学号 20080502082 姓名分数一、实验目的和要求:1、理解区域的表示和类型。

2、能正确区分四连通和八连通的区域3、了解区域填充的实验原理。

4、利用C++实现区域填充的递归算法。

二、实验内容:1假设在多边形内有一像素已知,由此出发利用连通性找到区域内所有像素。

2 取(x,y)为种子点将整个区域填充为新的颜色。

3 进行递归填充。

三、实验结果分析区域填充属性包括填充样式,填充颜色和填充图案的类型。

C语言中定义了某种图形后,即可调用-floodfill函数,对指定区域进行填充. 程序代码#define pi 3.141592#define MAX(a,b) (a>b)? a:b#define MIN(a,b) (a<b)? a:b#include "graphics.h"#include "math.h"struct edge {int ymax;float x;float delat;struct edge * pedge; };struct point{int x;int y;} ;struct et { struct edge * pedge;int n;};struct edge g_aet[10];struct edge dge[10];struct et g_et[10];struct point point1,point2;int ZUO(float x){ if((int)x==x)return (int)x;return (int)x+1;}int YOU(float x){ if((int)x==x)return (int)x-1;return (int)x;}int k=400,l=0;void draw1(){int i,t,j,a,c,p,z; float b;struct edge temp;for(i=k;i<=l;i++){a=0;for(t=0;t<=9;t++){ if(g_et[t].n==i) break;}for(j=0;j<=9;j++){ if(g_aet[j].ymax==0) break;}if(t!=10){ g_aet[j].ymax=g_et[t].pedge->ymax;g_aet[j].x=g_et[t].pedge->x;g_aet[j].delat=g_et[t].pedge->delat;if(g_et[t].pedge->pedge!=0){g_aet[j+1].ymax=g_et[t].pedge->pedge->ymax;g_aet[j+1].x=g_et[t].pedge->pedge->x;g_aet[j+1].delat=g_et[t].pedge->pedge->delat; }}for(j=0;j<=9;j++){ if(g_aet[j].ymax==0) break; }j--;for(t=0;t<=j;t++){ for(z=0;z<=j-1;z++){if(g_aet[z].x>g_aet[z+1].x){ temp.ymax=g_aet[z].ymax;temp.x=g_aet[z].x;temp.delat=g_aet[z].delat;g_aet[z].ymax=g_aet[z+1].ymax;g_aet[z].x=g_aet[z+1].x;g_aet[z].delat=g_aet[z+1].delat;g_aet[z+1].ymax=temp.ymax;g_aet[z+1].x=temp.x;g_aet[z+1].delat=temp.delat;}}}for(j=0;j<=9;j++){ if(g_aet[j].ymax==0) break; }j--;for(p=0;p<=j;p++){ a++;if(a%2!=0)b=g_aet[p].x;else{for(c=ZUO(b);c<=YOU(g_aet[p].x);c++)putpixel(c,i,2);}}for(t=0;t<=j;t++){ if(g_aet[t].ymax==(i+1)){ g_aet[t].ymax=0;g_aet[t].x=0;g_aet[t].delat=0;}g_aet[t].x+=g_aet[t].delat;}for(t=0;t<=j;t++){ for(z=0;z<=j-1;z++){if(g_aet[z].x<g_aet[z+1].x){ temp.ymax=g_aet[z].ymax;temp.x=g_aet[z].x;temp.delat=g_aet[z].delat;g_aet[z].ymax=g_aet[z+1].ymax;g_aet[z].x=g_aet[z+1].x;g_aet[z].delat=g_aet[z+1].delat;g_aet[z+1].ymax=temp.ymax;g_aet[z+1].x=temp.x;g_aet[z+1].delat=temp.delat;}}}}}void generate(){int i,y,n=1,m,q,p;float x;for(i=0;i<=9;i++){if(n==1){ point2.x=point1.x=300;point2.y=point1.y=200;n++;}else{ if(n%2==0){ x=40*cos(i*pi/5)+200;y=40*sin(i*pi/5)+200;}else{ x=100*cos(i*pi/5)+200;y=100*sin(i*pi/5)+200;}if(point1.y==y) { n++; continue;}m=MIN(point1.y,y);if(x==point1.x){ dge[i-1].delat=0;dge[i-1].ymax=MAX(point1.y,y);dge[i-1].x=x;dge[i-1].pedge=0;for(q=0;q<=9;q++){ if(g_et[q].n==m) break;}if(q==10){g_et[i-1].pedge=&dge[i-1];g_et[i-1].n=m;}else{g_et[q].pedge->pedge=&dge[i-1];g_et[i-1].n=0;}}else{dge[i-1].delat=(float)(x-point1.x)/(y-point1.y);dge[i-1].ymax=MAX(point1.y,y);if(point1.y>y) dge[i-1].x=x;else {dge[i-1].x=point1.x; }dge[i-1].pedge=0;for(q=0;q<=9;q++){ if(g_et[q].n==m) break;}if(q==10){ g_et[i-1].pedge=&dge[i-1];g_et[i-1].n=m;}else{g_et[q].pedge->pedge=&dge[i-1];g_et[i-1].n=0;}}p=MAX(point1.y,y);k=MIN(k,m);l=MAX(l,p);point1.x=x;point1.y=y;n++;}}if(point1.y==point2.y) return;else{if(point2.x==point1.x){dge[i-1].delat=0;dge[i-1].ymax=MAX(point1.y,point2.y);dge[i-1].x=point2.x;}else{ dge[i-1].ymax=MAX(point1.y,point2.y);if(point1.y>point2.y) dge[i-1].x=point2.x;else {dge[i-1].x=point1.x;}dge[i-1].delat=(float)(point2.x-point1.x)/(point2.y-point1.y);}}m=MIN(point1.y,point2.y);k=MIN(k,m);l=MAX(l,dge[i-1].ymax);g_et[i-1].n=m;g_et[i-1].pedge=&dge[i-1];}void main(){ int driver=DETECT,mode; int i; registerbgidriver(EGA VGA_driver);initgraph(&driver,&mode,"\\tc");initgraph(&driver,&mode,"\\tc");for(i=0;i<=9;i++){ g_aet[i].ymax=0; g_aet[i].x=0; g_aet[i].delat=0;g_et[i].pedge=0;}generate();draw1();circle(200,200,100); circle(200,200,40);getch();closegraph();}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验报告模板
《计算机图形学》实验报告
区域填充算法、裁剪算法
一、实验目的及要求
上机用所学的算法来填充多边形区域,在所给的区域里面剪裁所给出的线段。

二、理论基础
区域填充:区域填充所采用的算法是种子天填充算法。

算法的主要思想是在所给定的区域类取一点作为种子,然后向种子坐标的上下左右,或者上下左右,左上,左下,右上,右下八个方向进行填充,从而达到填充整个区域的目地。

但是由于在上述的算法中其他的新种子呀进行入栈,就会使得很多用过的种子从新入栈,使效率不高。

所以重新设计了一下算法,采用取一点先横向填充,即(x0,y0)y0,不变x0++或者x0--,在所给定的范围之类填充完了之后再采用y+1,y-1.上下两个方向进行填充。

剪裁:选用了Cohe-SutherLand算法,剪裁算法的主体思想是先将整个区域分成9个区域。

如图所示
1001 1000 1010
0001 0000 0010
0101 0100 0110
其中0000里面是所需要的剪裁的部分。

在一条直线在这个区域里面。

它的两个端点将会落在上面的区域中的任何一个区域中。

1) 当线段完全在框里面,取这个两个端点;2) 当这条直线明显在区域外面,则抛弃;3) 如果不满足上面的2个条件,则把线段分成两段,其中一段在外面,则放弃,在里面则保留。

通过上面的标记来判断端点是否在区域里面。

三、算法设计与分析
剪裁:
void COpenglForMFCView::OnAreaCut()
{
// TODO: Add your command handler code here
m_bClip = !m_bClip ;
if( !m_bClip )
return ;
// 直线端点集合数组一定为端点对偶数个点坐标和裁剪准备时数据一致
int nvLines[8][2] = {{0,0},{100,100},{10,201},{-200,-50},{-50,-140},{-50,140},{-80,10},{240,270}};
// 裁剪窗口边界坐标上下左右
int nvClip[4] = {100,-100,-100,100};
// 加入裁剪代码得到最终的直线端点代码存入裁剪后数据集
// 存入的数据位nvLineFinal
int nvLineFinal[8][2] ; //存入最终的剪裁的坐标
// 处理过程
// AfxMessageBox(_T("Please Insert The Clip Code!") );
// 保存过程
vLineFinal.clear() ;
int i = 0 ;
int nValidLineNum = 0 ; // 有效直线端点对数目根据实际情况修改有效坐标Point2D oPtTmp ;
////////////////////////算法填写位置///////////////////////////////////////////////
float x0,y0,x1,y1,left,right,bottom,top,x,y;
int code1,code2,code;
//将存入边界的上下左右的信息
top = nvClip[0];
bottom =nvClip[1];
left = nvClip[2];
right = nvClip[3];
for (i=0;i<8;i+=2)
{
x0 = nvLines[i][0]; //存入任意直线的起点与终点坐标
y0 = nvLines[i][1];
x1 = nvLines[i+1][0];
y1 = nvLines[i+1][1];
encode(x0,y0,&code1,top,right,bottom,left);
encode(x1,y1,&code2,top,right,bottom,left);
while(code1<<1>0||code2<<1>0)
{
if ((code1&code2)<<1>0) break;
code = code1;
if(code1==0) code = code2;
if ((1&code)<<1>0) //1是左边线段与左边界相交
{
x = left;
y = y0 + (y1 - y0)*(left - x0)/(x1-x0);
}
else if((2&code)<<1>0) //2是右边界线段与右边界相交
{
x = right;
y = y0 + (y1 - y0)*(right - x0)/(x1-x0);
}
else if ((4&code)<<1>0) //4是底边界线段与底边界相交
{
y = bottom;
x = x0 + (x1-x0)*(bottom - y0)/(y1-y0);
}
else if ((8&code)<<1>0) //8是顶边界线段与顶边界相交
{
y = top;
x = x0 + (x1-x0)*(top - y0)/(y1-y0);
}
if (code == code1)
{
x0 = x;
y0 = y;
encode(x0,y0,&code1,top,right,bottom,left);
}
else
{
x1 = x;
y1 = y;
encode(x1,y1,&code2,top,right,bottom,left);
}
}
/*oPtTmp.x=x0;
oPtTmp.y=y0;
vLineFinal.push_back(oPtTmp) ;
oPtTmp.x=x1;
oPtTmp.y=y1;
vLineFinal.push_back(oPtTmp) ; */
//if
((x0>left&&x0<right)&&(x1>left&&x1<right)&&(y0>bottom&&y0<top)&&(y1>bottom&&y1<top) )
{
nvLineFinal[nValidLineNum][0] = x0; //将最终的坐标存入数组
nvLineFinal[nValidLineNum][1] = y0;
nvLineFinal[nValidLineNum+1][0] = x1;
nvLineFinal[nValidLineNum+1][1] = y1;
nValidLineNum += 2;
}
}
/////////////////////////////////////////////////////////////////////////////
for( i = 0 ; i < nValidLineNum ; ++i )
{
oPtTmp.x = nvLineFinal[i][0] ;
oPtTmp.y = nvLineFinal[i][1] ;
vLineFinal.push_back(oPtTmp) ;
}
// 将裁剪窗口边界信息保存
vClipWnd.clear() ;
// 左上
oPtTmp.x = nvClip[2] ;
oPtTmp.y = nvClip[0] ;
vClipWnd.push_back(oPtTmp) ;
// 左下
oPtTmp.y = nvClip[1] ;
vClipWnd.push_back(oPtTmp) ;
// 右下
vClipWnd.push_back(oPtTmp) ;
oPtTmp.x = nvClip[3] ;
vClipWnd.push_back(oPtTmp) ;
// 右上
vClipWnd.push_back(oPtTmp) ;
oPtTmp.y = nvClip[0] ;
vClipWnd.push_back(oPtTmp) ;
// 左上
vClipWnd.push_back(oPtTmp) ;
oPtTmp.x = nvClip[2] ;
vClipWnd.push_back(oPtTmp) ;
return ;
}
四、程序调试及结果的分析
五、实验心得及建议
在实验过程中,将画线分成了几个部分。

分别是k为无穷的时候,0<k<=1,k>1,-1<=k<0,k<-1.这几种情况。

采用了分而治之的思想,各个击破。

但是在算法实现中还是遇到了一些困难。

例如对c++的不了解,花费了大量的时间在阅读程序上,还有就不问题考虑的不过全面。

花费了很多时间去了调试,另一个是在细节方面处理得不够好,所画的直线有些地方还是有“折”样。

评语:。

相关文档
最新文档