图形学_二维图形的剪裁_Sutherland-Hodgeman_Cohen—Sutherland

一、Cohen-Sutherland剪裁算法

1.基本思想

对于每条线段P1P2分为三种情况处理:

(1)若P1P2完全在窗口内,则显示该线段P1P2。

(2)若P1P2明显在窗口外,则丢弃该线段。

(3)若线段不满足(1)或(2)的条件,则在交点处把线段分为两段。其中一段完全在窗口外,可弃之。然后对另一段重复上述处理。

为快速判断,采用如下编码方法:

将窗口边线两边沿长,得到九个区域,每一个区域都用一个四位二进制数标识,直线的端点都按其所处区域赋予相应的区域码,用来标识出端点相对于裁剪矩形边界的位置

  • 任何位赋值为1,代表端点落在相应的位置上,否则该位为0。

  • 若端点在剪取矩形内,区域码为0000。

2.算法流程

  • 若P1P2完全在窗口内code1=0,且code2=0,则“取”

  • 若P1P2明显在窗口外code1&code2≠0,则“弃”

  • 在交点处把线段分为两段。其中一段完全在窗口外,可弃之。然后对另一段重复上述处理。

3.交点求取

计算线段P1(x1,y1)--P2(x2,y2)与窗口边界的交点

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);}

二、Sutherland-Hodgman剪裁算法

1.基本思想

分割处理策略:将多边形关于矩形窗口的裁剪分解为多边形关于窗口四边所在直线的裁剪。

流水线过程(左上右下):前边的结果是后边的输入。

  • 一次用窗口的一条边裁剪多边形。

  • 考虑窗口的一条边以及延长线构成的裁剪线,把平面分成两个部分:可见一侧;不可见一侧

  • 多边形的各条边的两端点S、P。它们与裁剪线的位置关系只有四种

  • 情况(1)仅输出顶点P;

  • 情况(2)输出0个顶点;

  • 情况(3)输出线段SP与裁剪线的交点I;

  • 情况(4)输出线段SP与裁剪线的交点I和终点P

三、 程序流程图

一、Cohen-Sutherland算法

二、Sutherland-Hodgman算法

 四、源程序

一、Cohen-Sutherland


  1 #include "easyx.h"
2 #include "math.h"
3 #include "windows.h"
4 #include "stdio.h"
5 #include "stdlib.h"
6 #include "conio.h"
7 #include "graphics.h"
8
9 #define left 1
10 #define right 2
11 #define bottom 8
12 #define top 4
13
14 int edge_x1,edge_x2,edge_y1,edge_y2; //全局变量,代表剪裁的边界
15
16 //画线算法
17 void dda(int x1,int y1,int x2,int y2,int color)
18 {
19 int steps;
20 double xin,yin,dx,dy,x,y;
21 dx = x2 - x1;
22 dy = y2 - y1;
23 if(fabs(dx) > fabs(dy))
24 steps = fabs(dx);
25 else
26 steps = fabs(dy);
27 xin = (double)(dx/steps);
28 yin = (double)(dy/steps); //possible loss of data
29 x = x1;
30 y = y1;
31 putpixel(x,y,color);
32 for(int i = 0;i <= steps;i ++)
33 {
34 x = x + xin;
35 y = y + yin;
36 putpixel(x,y,color);
37 }
38 }
39
40
41 //对输入的点进行编码
42 int coding(int x,int y)
43 {
44 int code;
45 if(y <= edge_y2 && y >= edge_y1)
46 {
47 if(x > edge_x2)
48 code = 2; //中右方
49 else if(x < edge_x1)
50 code = 1; //中左方
51 else
52 code = 0; //中心
53 }
54
55 else if(y > edge_y2)
56 {
57 if(x > edge_x2)
58 code = 6; //右下方
59 else if(x < edge_x1)
60 code = 5; //左下方
61 else
62 code = 4; //中下方
63 }
64 else
65 {
66 if(x > edge_x2)
67 code = 10; //右上方
68 else if(x < edge_x1)
69 code = 9; //左上方
70 else
71 code = 8; //中上方
72 }
73
74 return code;
75 }
76
77
78
79
80 //剪裁算法
81 int cutline(int x1,int y1,int x2,int y2)
82 {
83 int visible = 0,done = 1;
84 int c;
85 int c1,c2;
86 int x,y; //表示交点
87 c1 = coding(x1,y1);
88 c2 = coding(x2,y2); //将顶点进行编码
89 do
90 {
91 if(c1 == 0 && c2 == 0) //完全可见
92 {
93 visible = 1;
94 done = 0;
95 }
96 else if((c1 & c2) != 0) //完全不可见
97 {
98 done = 0;
99 }
100 else
101 {
102 ////////////////////////////
103 if(c1 != 0)
104 c = c1;
105 else
106 c = c2;
107 ////////////////////////////
108 if((left & c) != 0)
109 {
110 x = edge_x1;
111 y = y1 + (y2 - y1)*(edge_x1 - x1)/(x2-x1);
112 }
113 else if((right & c) != 0)
114 {
115 x = edge_x2;
116 y = y1 + (y2 - y1)*(edge_x2 - x1)/(x2-x1);
117 }
118 else if((bottom &c )!= 0)
119 {
120 y = edge_y1;
121 x = x1 + (x2 - x1)*(edge_y1 - y1)/(y2-y1);
122 }
123 else if((top & c )!= 0)
124 {
125 y = edge_y2;
126 x = x1 + (x2 - x1)*(edge_y2 - y1)/(y2-y1);
127 }
128 else
129 {}
130 //////////////////////////////////////
131 if(c = c1)
132 {
133 x1 = x;
134 y1 = y;
135 c1 = coding(x1,y1);
136 }
137 else
138 {
139 x2 = x;
140 y2 = y;
141 c2 = coding(x2,y2);
142 }
143 ///////////////////////////////////
144 }//else
145
146 }while(done); //while
147
148 dda(x1,y1,x2,y2,RGB(0,0,255)); //画线
149
150 return 0;
151 }
152
153
154 int main()
155 {
156 //硬件测试,将gd装入图形驱动器,gm置入最大图形模式。
157 int gd=DETECT,gm;
158 int x1,y1,x2,y2;
159 //输入X的边界
160 printf("请输入剪裁区域的横坐标边界\n");
161 printf("X1 = ");
162 scanf("%d",&edge_x1);
163 printf("\n");
164 printf("X2 = ");
165 scanf("%d",&edge_x2);
166 printf("\n\n");
167
168 //输入Y的边界
169 printf("请输入剪裁区域的纵坐标边界\n");
170 printf("Y1 = ");
171 scanf("%d",&edge_y1);
172 printf("\n");
173 printf("Y2 = ");
174 scanf("%d",&edge_y2);
175 printf("\n\n");
176
177 //输入直线端点
178 printf("请输入直线两个顶点的坐标");
179 scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
180
181 //图形初始化
182 initgraph(&gd,&gm,"c:\\tc");
183 //设置兰背景。
184 setbkcolor(WHITE);
185 cleardevice();
186
187 cutline(x1,y1,x2,y2); //进行剪裁
188
189 getch();
190 closegraph();
191 return 0;
192 }

二.Sutherland-Hodgman


  1 #include "easyx.h"
2 #include "math.h"
3 #include "windows.h"
4 #include "stdio.h"
5 #include "stdlib.h"
6 #include "conio.h"
7 #include "graphics.h"
8
9 int edge_x1,edge_x2,edge_y1,edge_y2; //全局变量,代表剪裁的边界
10
11 //画线算法
12 void dda(int x1,int y1,int x2,int y2,int color)
13 {
14 int steps;
15 double xin,yin,dx,dy,x,y;
16 dx = x2 - x1;
17 dy = y2 - y1;
18 if(fabs(dx) > fabs(dy))
19 steps = fabs(dx);
20 else
21 steps = fabs(dy);
22 xin = (double)(dx/steps);
23 yin = (double)(dy/steps); //possible loss of data
24 x = x1;
25 y = y1;
26 putpixel(int(x),int(y),color);
27 for(int i = 0;i <= steps;i ++)
28 {
29 x = x + xin;
30 y = y + yin;
31 putpixel(int(x),int(y),color);
32 }
33 }
34
35 //剪裁算法
36 int Surtherland_Hondgman(double p[][2],int n,int bound)
37 {
38 int sumpoint = 0; //新的顶点个数
39 double new_p[100][2]; //存放新的顶点序列
40 double sx = p[n-1][0],sy = p[n-1][1]; //将定点序列的最后一个顶点赋值给s
41 int flag;
42 if(sx > bound) //在内侧
43 flag = 0;
44 else
45 flag = 1;
46
47 for(int i = 0;i < n;i++)
48 {
49 if(p[i][0] > bound) //在内侧
50 {
51 if(flag != 0)
52 {
53 flag = 0;
54 //求交点并放入新的多边形顶点序列中;
55 new_p[sumpoint][0] = bound; //横坐标
56 new_p[sumpoint][1] = sy + (((p[i][1] - sy)/(p[i][0] - sx)) * (bound - sx)); //纵坐标
57 sumpoint++;
58 }
59 new_p[sumpoint][0] = p[i][0];
60 new_p[sumpoint][1] = p[i][1]; //将当前顶点放入新的多边形顶点序列new_p中
61 sumpoint++;
62 }
63 else
64 {
65 if(flag == 0)
66 {
67 flag = 1;
68 new_p[sumpoint][0] = bound; //横坐标
69 new_p[sumpoint][1] = sy + (((p[i][1] - sy)/(p[i][0] - sx)) * (bound - sx)); //纵坐标
70 sumpoint++;
71 }
72 }
73 sx = p[i][0];
74 sy = p[i][1];
75 }
76 for(int i = 0;i < sumpoint-1;i++)
77 dda(new_p[i][0],new_p[i][1],new_p[i+1][0],new_p[i+1][1],RGB(255,0,0));
78 dda(new_p[0][0],new_p[0][1],new_p[sumpoint-1][0],new_p[sumpoint-1][1],RGB(255,0,0));
79
80 return 0;
81 }
82
83
84 int main()
85 {
86 //硬件测试,将gd装入图形驱动器,gm置入最大图形模式。
87 int gd=DETECT,gm;
88 int n;
89 double p[10][2];
90 //输入X的边界
91 printf("请输入剪裁区域的左侧边界的横坐标\n");
92 printf("X1 = ");
93 scanf("%d",&edge_x1);
94
95 //dda(edge_x1,1,edge_x1,500,BLUE);
96
97 //输入直线端点
98 printf("请输入待剪裁多边形的边数:");
99 scanf("%d",&n);
100 printf("请输入待剪裁多边形的顶点序列:\n");
101 for(int i = 0;i < n;i ++)
102 scanf("%lf%lf",&p[i][0],&p[i][1]);
103
104
105 //图形初始化
106 initgraph(&gd,&gm,"c:\\tc");
107 //设置兰背景。
108 setbkcolor(WHITE);
109 cleardevice();
110
111 Surtherland_Hondgman(p,n,edge_x1); //先对左边界进行裁剪
112
113 getch();
114 closegraph();
115 return 0;
116 }

图形学_二维图形的剪裁_Sutherland-Hodgeman_Cohen—Sutherland,布布扣,bubuko.com

时间: 2024-08-02 02:39:29

图形学_二维图形的剪裁_Sutherland-Hodgeman_Cohen—Sutherland的相关文章

二维图形旋转公式的推导

关于二维图形旋转可能在非常多计算机图形学相关的书籍上都会介绍,然而真正理解公式推导过程的却讲得不多. 那么怎样推导出二维图形绕某一点旋转的公式呢?我在这里就将其推导过程简要的说明一下. 事实上推导过程比較简单,首先我们来看一幅图,看看怎样推导出二维图形绕原点进行旋转的公式. 上图画的比較粗略,只是能说明问题就够了.如果旋转前的点位于P处.旋转之后的点位于P'处. 怎样求旋转之后的点P'坐标? 在图中.旋转之前P的方向角是a,旋转之后P'的方向角就变为a+b,这里b就是旋转的角度.所谓方向角是改点

二维图形的矩阵变换(一)——基本概念

基本的二维变换可包括旋转.缩放.扭曲,和平移四种,              而这些几何运算则可以转换为一些基本的矩阵运算: 这几个变换都是线性的,但平移运算不是线性的,不能通过2*2矩阵运算完成.若要将点 (2, 1)在 x 方向将其平移 3 个单位,在 y 方向将其平移 4 个单位. 可通过先使用矩阵乘法再使用矩阵加法来完成此操作. 综合这几种基本运算,数学家们将其统一为一个3*3矩阵,存储形式如下: 由于表示仿射变换的矩阵的第三列总是(0,0,1),在存储矩阵的时候,大多只存成一个2*3的

二维图形的矩阵变换(三)——在WPF中的应用矩阵变换

UIElement和RenderTransform 首先,我们来看看什么样的对象可以进行变换.在WPF中,用于呈现给用户的对象的基类为Visual类,但是Visual对象并不具有变换功能,具有变换功能的是它的子类UIElement.这个类也是非常底层的类了,几乎我们所有的常用控件都是继承自它,也就是说,基本上所有的UI对象都是可以应用变换的. 然后,我们在再来看看UIElement中变换种类.UIElement支持两种变换:RenderTransform和LayoutTransform,其中La

二维图形的矩阵变换(二)——WPF中的矩阵变换基础

在前文二维图形的矩阵变换(一)——基本概念中已经介绍过二维图像矩阵变换的一些基础知识,本文中主要介绍一下如何在WPF中进行矩阵变换. Matrix结构 在WPF中,用Matrix结构(struct类型)表示二维变换矩阵,它是一个3*3的数组,结构如下, 由于第三列是常量0,0,1,因此并不作为公开属性,可见的只有剩余六个属性. 构造变换 虽然Matrix类公开了这六个属性让我们设置,但是靠直接设置这六个属性来实现平移.旋转等变换对于我们来说实在太困难了,因此又增加了如下许多函数来帮助我们实现这一

二维图形的几何变换【转】

转自:lab104_yifan http://blog.csdn.net/accelerator_/article/details/39253983 1.基本几何变换及变换矩阵 基本几何变换都是相对于坐标原点和坐标轴进行的几何变换,有平移.比例.旋转.反射和错切等. 1.1 平移变换 是指将p点沿直线路径从一个坐标位置移到另一个坐标位置的重定位过程.他是一种不产生变形而移动物体的刚体变换(rigid-body transformation),如下图所示. 图1-1 平移变换 推导: 求得平移变换

二维图形变换

5.1二维图形变化 一.向量 是具有长度和方向的实体 二.特殊的线性组合 (1)仿射组合 (2)凸组合(对仿射组合加以更多的限制) 三.向量的点积和叉积 (1)点积 两个向量夹角的余弦值等于两个单位向量的点积 (2)叉积 两个向量的叉积是另一个三维向量,且与两个向量均正交 利用叉积求平面的法向量,三点可确定一个平面 5.2 图形坐标系 1.世界坐标系 是一个公共坐标系,是现实中物体或场景的统一参考系 2.建模坐标系 又称局部坐标系,每个物体有自己的局部中心和坐标系 3.观察坐标系 从观察者的角度

YBT1540打鼹鼠_二维树状数组

1540:打鼹鼠_二维树状数组 时间限制: 1000 ms         内存限制: 524288 KB [题目描述] 这是一道模板题. 给出一个 n×m 的零矩阵 A,你需要完成如下操作: 1 x y k:表示元素 Ax,y自增 k: 2 a b c d:表示询问左上角为 (a,b),右下角为 (c,d) 的子矩阵内所有数的和. [输入] 输入的第一行有两个正整数 n,m: 接下来若干行,每行一个操作,直到文件结束. [输出] 对于每个 2 操作,输出一个整数,表示对于这个操作的回答. [输

[转]二维图形的矩阵变换(一)——基本概念

来源:http://www.cnblogs.com/TianFang/p/3920734.html 基本的二维变换可包括旋转.缩放.扭曲,和平移四种,              而这些几何运算则可以转换为一些基本的矩阵运算: 这几个变换都是线性的,但平移运算不是线性的,不能通过2*2矩阵运算完成.若要将点 (2, 1)在 x 方向将其平移 3 个单位,在 y 方向将其平移 4 个单位. 可通过先使用矩阵乘法再使用矩阵加法来完成此操作. 综合这几种基本运算,数学家们将其统一为一个3*3矩阵,存储形

openGL实现二维图形和三维图形

openGL是一个强大的底层图形库,其命令最初的时候使用C语言实现的.openGL定义了一个图形程序接口,常用于制作处理三维图像,功能强大,调用方便,在图像处理十分受欢迎. 实现图形主要使用的是openGL的一个工具包:GLUT. GLUT (pronounced like the glut in gluttony) is the OpenGL Utility Toolkit, a window system independent toolkit for writing OpenGL prog