计算机图形学-二维变换与二维观察

几何变换: 

图形的几何变换指对图形的几何信息经过平移、比例、旋转等变换后产生新的图形;即图形在方向尺寸和形状方面的变换,需要改变图形对象的坐标描述。

齐次坐标

n维→n+1维

用(n+1)维向量表示n维向量,ex:二维平面上的点P(x,y)表示为(hx,hy,h);h≠0.n维空间类推;

n维空间用非齐次坐标表示的向量坐标值唯一,齐次坐标表示不唯一(因为有比例系数);

规范化齐次坐标:

即h = 1.规范化齐次坐标提供了用矩阵运算将二/三/n维空间中的一个点集从一个坐标系变换到另一个坐标系的方法。

二维变换矩阵(T₂D)

二维空间中的点变换可以看作点的齐次坐标与T相乘

设T:\begin{bmatrix} a &b&p \\ c & d&q\\ l & m&s \end{bmatrix} ,将其分为四个子矩阵:

T₁:   \begin{bmatrix} a &b \\ c& d \end{bmatrix} ,比例,旋转,对称,错切

T₂:\begin{bmatrix} l&m\\ \end{bmatrix} ,平移

T₃:\begin{bmatrix} p\\ q \end{bmatrix} ,投影变换;

T4:\begin{bmatrix} s \end{bmatrix} ,整体比例变换.

将T定义为单位矩阵则表示二维空间中的直角坐标系,可看做三个行向量:

第一行:\begin{bmatrix} 1&0 &0 \end{bmatrix}\\ ,x轴上的无穷远点;

第二行:\begin{bmatrix} 0 &1 &0 \end{bmatrix} ,y轴上的无穷远点;

第三行:\begin{bmatrix} 0 &0 & 1 \end{bmatrix} ,坐标原点。

基本几何变换

平移:

二维变换矩阵T:\begin{bmatrix} 1&0 &0 \\ 0& 1& 0\\ Tx&Ty & 1 \end{bmatrix} ,

坐标矩阵:\begin{bmatrix} x' &y' &1 \end{bmatrix} = \begin{bmatrix} x+Tx&y+Ty &1 \end{bmatrix} ;

比例:

二维变换矩阵T:\begin{bmatrix} Sx &0 &0 \\ 0& Sy &0 \\ 0& 0 & 1 \end{bmatrix} ,

坐标矩阵:\begin{bmatrix} x'&y' &1 \end{bmatrix} = \begin{bmatrix} xSx & ySy &1 \end{bmatrix} ;

旋转:

二维变换矩阵T:\begin{bmatrix} cos& sin &0 \\ -sin & cos &0 \\ 0 & 0 & 1 \end{bmatrix}

在xOy平面上,二维图形绕原点逆时针旋转θ角

顺时针:将θ换成-θ;上式中的sin取负

对称

即旋转→关于x/y轴对称→旋转

错切:

用于产生弹性物体的变形处理;

若变换矩阵中非对角线元素不为零,则会起到把图形沿X或Y轴错切的作用;

二维变换矩阵T:\begin{bmatrix} 1& b &0 \\ c& 1&0 \\ 0& 0 & 1 \end{bmatrix} ,

坐标矩阵\begin{bmatrix} x' & y' & 1\\ \end{bmatrix} = \begin{bmatrix} x+cy & y+bx & 1\\ \end{bmatrix} ;

错切参数方程:

沿x方向错切:  \left\{\begin{matrix} x' = x+cy \\ y' = y \end{matrix}\right. ,

沿y方向错切:  \left\{\begin{matrix} x' = x & \\ y' = y+bx \end{matrix}\right. ,

沿两个方向错切:\left\{\begin{matrix} x' = x+cy & \\ y' = y+bx \end{matrix}\right. ;

关于相对参考点的错切变换 以及对x,y变化的理解——参考两个tan值

二维几何变换的计算

点、线、多边形:

将表示图形的n个顶点依次写在n×3矩阵中,再乘以变换矩阵T,得到变换后的点矩阵

曲线:一般是将每一个点都依次变换;部分特殊的可以近似分割为多边形再进行平移旋转等基本组合

复合变换:图形做一次以上的变换;看做基本几何变换的组合

复合变换的变换矩阵

复合平移变换:\begin{bmatrix} 1 &0 &0 \\ 0& 1& 0\\ Tx1+Tx2&Ty1+Ty2 &1 \end{bmatrix} ;

复合比例变换:\begin{bmatrix} Sx1Sx2 &0 & 0\\ 0& Sy1Sy2 &0 \\ 0& 0 & 1 \end{bmatrix} ;

复合旋转变换:原来的θ换成(θ₁+θ₂),记作R = Rθ₁Rθ₂ = R(θ₁+θ₂)

旋转变换可以看作比例变换和错切变换的综合

二维复合变换中的矩阵相乘要注意顺序除平移、旋转、比例等特殊变换外矩阵的相乘顺序不可以改变.

变换时,矩阵的顺序是正常的变换顺序,代码的顺序与变换的顺序相反。

相对关系的几何变换

相对参考点:平移至原点→作变换→平移回参考点

相对方向:旋转至与某坐标轴重合作变换旋转回原参考方向

#关于任意方向对称#

1.平移——平移对称轴至与原点相交

2.旋转——旋转使对称轴与坐标轴重合

3.对称——关于坐标轴的对称图形

4.反向旋转——转回原方向

5.反向平移——平移回原位置

图示:

(坐标系之间的变换:坐标系的变换)

光栅变换:直接对帧缓存中像素点进行操作。

将图像信息以像素点的形式储存在帧缓存中;从光栅帧缓存中读出指定像素块的内容,然后将像素块的内容复制到另一光栅区域,随后擦除原光栅区域中的像素内容.

二维仿射变换:

平移、比例、旋转、错切、反射

关于二维观察中的各种窗口:

窗口:世界坐标系中的一个矩形区域

视区:(规格化)设备坐标系上指定的一个矩形区域,显示窗口内的图形。

开窗口:将图形关于窗口进行裁剪,然后将裁剪后的保留在窗口内的图形, 变换成显示器屏幕上指定视区内的图形(取景变换:裁剪运算和窗口到视区的变换)

二维观察的实质

裁剪:在观察坐标系下对窗口进行裁剪

内容:

·判断图形元素与窗口区域之间的关系

·求出窗口内的部分图形

以下是一些常见的矩形窗口裁剪算法,矩形窗口边界:

上Ywt,下Ywb,左Xwl,右Xwr

直线段的裁剪:

1.Cohen-Sutherland(编码裁剪算法)

#关于编码的规则:四位编码,依次是 上-下-右-左 ;当点在边界线上时,对应编码取0#

设线段的两个端点为P₁(x₁,y₁),P₂(x₂,y₂),编码为code1 code2

情况一:判断P₁P₂完全在窗口内,“简取”;条件是code1|code2=0(按位或等于零,即两个编码的每一位都是0)

情况二:判断P₁P₂完全在窗口外且是同一外侧(即x/y坐标值均小于/大于同一窗口边界所在直线),“简弃”;条件是code1&code2≠0(按位与不等于零,即至少有一位都是1)

情况三:前两者均不符合,直线有可能与窗口相交,此时对直线进行分段,再进行上述处理:

关于求交:

检查P1,在窗口外或与P2交换使其在窗口外;根据值为1的编码确定具体的相交边界,求出交点代替P1,然后用新的P1P2重新进行上述步骤的判断。(求交点:利用关系k=(y2-y1)/(x2-x1) )

 优缺点:

优:编码实现对完全可见/不可见线段的快速选择

缺:过程复杂冗余,有浮点运算

2.中点分割算法(用二分逼近计算交点)

“求最远点”

令P1在窗口外:

S1-判断P2:测试P2是否在窗口内。若是, 则P2就是离P1最远的可见点, 结束; 否则, 进行下一步

S2-判断简弃:对P1、P2的区域码作逻辑与,若结果不为0,表明P1、P2是在窗外同侧,线段P1P2全部不可见, 弃之,结束;否则, 进行下一步

S3-取中点,判断和替换:Pm.若Pm可见,则Pm代替P1,重复步骤(3);若Pm不可见, 则需要判断Pm和P2的关系

        如果Pm和P2在窗口的同侧外面(即Pm、P2的区域码逻辑与不为0),则Pm代替P2,重复步骤3;

        如果Pm和P2不在窗口的同侧外面(即Pm、P2的区域码逻辑与为0),则Pm代替P1,重复步骤3;

S4-结束条件:进行到分点与线段端点距离达到分辨率精度为止

只运用加法和位移,便于实现。

3.Liang-Barsky算法(梁友栋-Brasky算法)P109

#基于矩形窗口#

基本出发点:参数方程

假设直线段的端点为(x₁, y₁),(x₂, y₂),则直线的参数方程:

\left\{\begin{matrix} x = x1 + u(x2 - x1)\\ y = y1 + u(y2 - y1) \end{matrix}\right.

其中0≤u≤1.

先求出8个参数

Δx = x₂ - x₁, Δy = y₂ - y₁;

p1 = -Δx , p2 = Δx , p3 = -Δy , p4 = Δy ;

q1 = x1 - Xwl , q2 = Xwr - x1,

q3 = y1 - Ywb , q4 = Ywt - y1;

(中左 右中 中下 上中)

逻辑过程

S1:输入端点坐标和窗口边界参数

S2:若p1 = p2 = 0,直线与左右边界平行,此时若(q1 < 0 || q2 < 0)则说明直线在窗口外,转S7;否则有(q1 ≥ 0 && q2 ≥ 0 ),求值并判断:

uk = \frac{qk}{pk},pk \neq 0,k = 3,4

\\Umax = max(0,Uk|p<0) \\Umin = min( Uk|p>0,1)

求出两个u值u3、u4;再求出Umax和Umin

S3: 若p3 = p4 = 0,直线与上下边界平行,此时若(q3 < 0 || q4 < 0)则说明直线在窗口外,转S7;否则有(q1 ≥ 0 && q2 ≥ 0 ):

uk = \frac{qk}{pk},pk\neq 0,k = 1,2

\\Umax = max(0,Uk|p<0) \\Umin = min( Uk|p>0,1)

求出两个u值u1、u2;再求出Umax和Umin

S4:上述两条均不满足:pk ≠ 0(k = 1,2,3,4);此时计算:

uk = \frac{qk}{pk},pk \neq 0,k = 1,2,3,4

\\Umax = max(0,Uk|p<0,Uk|p<0) \\Umin = min(Uk|p>0,Uk|p>0,1)

求出四个u值u1、u2、u3、u4;再求出Umax和Umin

S5:求出Umax和Umin后判断:

若Umax>Umin,线段在窗口外,转至S7;

若Umax≤Umin,将其代入参数方程求出端点(x₁,y₁) , (x₂,y₂);

S6:画线;

S7:算法结束.

多边形的裁剪

直接使用直线段的裁剪会获得一组不相连的离散直线段。

构造能产生n个封闭区域的多边形裁剪算法。多边形裁剪算法的输出为给出裁剪后的多边形边界的顶点序列。

1.Sutherland-Hodgeman多边形裁剪

多边形的边界是一个整体,用窗口的边界对多边形进行裁剪,用窗口边框补缺口

原理:窗口各边界进行裁剪,存储输入与输出顶点表;每次裁剪去边界外不可见的顶点,保留边界内可见顶点多边形与边界的交点。裁剪顺序为左-下-上-右

例:

 注:适合于凸多边形。对于凹多边形,最后一个顶点总是连着第一个顶点:

 

2.Weiler-Atherton多边形裁剪

原理:

假设顺时针处理顶点:

对于由外到内的保留沿多边形边界方向在内部的线段;

对于由内到外的保留内部线段和沿顺时针方向上的边框部分线段。

例:

 

步骤:

1.建立主多边形(被裁减)和裁剪多边形(裁剪边框)的顶点表(外:逆时针;内:顺时针)

2.求出主多边形和裁剪多边形的交点,将其按顺时针插入顶点表中,在两多边形顶点表中的相同交点间建立双向指针

 3.裁剪:如果存在没有被跟踪过的交点,则执行以下步骤:

a)建立空的裁剪结果多边形的顶点表;

b)选取任一个没有被跟踪过的交点为起点,将其输出到裁剪结果多边形的顶点表;

c)如果该交点是进点,则跟踪主多边形边界;否则跟踪裁剪多边形边界;

d)跟踪多边形边界,每遇到多边形顶点,将其输出到裁剪结果多边形的顶点表中,直至遇到新的交点;

e)将该交点输出到裁剪结果多边形的顶点表中,并通过链接该交点的双向指针,改变跟踪方向;

f)重复d)、e),直至回到起点为止。    

其他裁剪

文字裁剪:串精度裁剪&字符精度裁剪&笔划、像素精度裁剪

 

 外部裁剪(空白裁剪):保留外部,留下内部的裁剪

OpenGL的基本变换和二维观察

指定当前的投影矩阵堆栈:glMatrixMode(GL_PROJECTION);

初始化当前的栈顶矩阵为单位矩阵:glLoadIdentity();

定义二维裁剪窗口 gluOtho2D(xwmin, xwmax, ywmin, ywmax);//左右下上;默认为±1

指定视区:glViewPort(xvmin,yvmin,vpWidth,vpHeighht);

xvmin,yvmin:对应屏幕显示窗口的矩形视区的左下角坐标

vpWidth,vpHeighht:视区的高和宽

默认的视区大小和位置与显示窗口保持一致

——————2021-11-01-14:57-图书馆—————— 

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用 Python 和 Pygame 库实现图形的二维变换的示例代码: ```python import pygame import math # 定义颜色 BLACK = (0, 0, 0) WHITE = (255, 255, 255) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) # 初始化 Pygame pygame.init() # 设置窗口尺寸 size = (700, 500) screen = pygame.display.set_mode(size) # 设置窗口标题 pygame.display.set_caption("2D Transformations") # 设置字体 font = pygame.font.SysFont('Calibri', 25, True, False) # 定义几何图形 triangle = [(100, 100), (150, 150), (50, 150)] square = [(300, 100), (400, 100), (400, 200), (300, 200)] pentagon = [(550, 150), (600, 100), (650, 125), (625, 175), (575, 175)] # 定义变换矩阵 translation_matrix = lambda x, y: [[1, 0, x], [0, 1, y], [0, 0, 1]] rotation_matrix = lambda theta: [[math.cos(theta), -math.sin(theta), 0], [math.sin(theta), math.cos(theta), 0], [0, 0, 1]] scaling_matrix = lambda sx, sy: [[sx, 0, 0], [0, sy, 0], [0, 0, 1]] # 定义变换操作 def translate(points, x, y): matrix = translation_matrix(x, y) return [tuple(matrix @ (p[0], p[1], 1))[:2] for p in points] def rotate(points, theta): matrix = rotation_matrix(theta) return [tuple(matrix @ (p[0], p[1], 1))[:2] for p in points] def scale(points, sx, sy): matrix = scaling_matrix(sx, sy) return [tuple(matrix @ (p[0], p[1], 1))[:2] for p in points] # 定义变量 angle = 0 scale_factor = 1 tx = 0 ty = 0 # 游戏循环 done = False while not done: # 处理事件 for event in pygame.event.get(): if event.type == pygame.QUIT: done = True elif event.type == pygame.KEYDOWN: # 处理按键事件 if event.key == pygame.K_LEFT: tx -= 10 elif event.key == pygame.K_RIGHT: tx += 10 elif event.key == pygame.K_UP: scale_factor *= 2 elif event.key == pygame.K_DOWN: scale_factor /= 2 elif event.key == pygame.K_SPACE: angle += math.pi / 4 # 清屏 screen.fill(WHITE) # 应用变换 transformed_triangle = scale(rotate(translate(triangle, tx, ty), angle), scale_factor, scale_factor) transformed_square = scale(rotate(translate(square, tx, ty), angle), scale_factor, scale_factor) transformed_pentagon = scale(rotate(translate(pentagon, tx, ty), angle), scale_factor, scale_factor) # 绘制几何图形 pygame.draw.polygon(screen, RED, transformed_triangle, 2) pygame.draw.polygon(screen, GREEN, transformed_square, 2) pygame.draw.polygon(screen, BLUE, transformed_pentagon, 2) # 显示变换信息 text1 = font.render("LEFT/RIGHT: Translate", True, BLACK) text2 = font.render("UP/DOWN: Scale", True, BLACK) text3 = font.render("SPACE: Rotate", True, BLACK) screen.blit(text1, [10, 10]) screen.blit(text2, [10, 40]) screen.blit(text3, [10, 70]) # 更新屏幕 pygame.display.flip() # 退出 Pygame pygame.quit() ``` 在这个示例中,我们使用了 Pygame 库来创建一个窗口,并绘制三个几何图形:三角形、正方形和五边形。我们定义了三个变换操作:平移、旋转和缩放,并使用这些操作来对几何图形进行变换。我们使用了三个变量来控制变换:平移量 `tx` 和 `ty`、缩放因子 `scale_factor` 和旋转角度 `angle`。我们在游戏循环中不断更新这些变量,并重新计算变换后的几何图形。我们还使用 Pygame 的文本渲染功能来显示变换信息。最后,我们使用 `pygame.display.flip()` 方法更新屏幕。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值