二维几何变换有如下几种:平移变换、比例变换、对称变换、旋转变换、错切变换
本文会给出:平移变换、旋转变换、比例变换、相对任意参考点的二维变换的算法和代码实现
平移变换
平移是指将物体沿直线路径从一个坐标位置 ( x 1 , y 1 ) (x1,y1) (x1,y1)移动到另一个坐标位置 ( x 2 , y 2 ) (x2,y2) (x2,y2)的变换。设 t x t_x tx为沿X轴的平移量, t y t_y ty为沿Y轴的平移量。
平移变换的二维表示为:
{ x 2 = x 1 + t x y 2 = y 1 + t y \begin{cases}x_2=x_1+t_x\\ y_2=y_1+t_y\end{cases} {x2=x1+txy2=y1+ty
平移变换的齐次表示为:
[ x 2 y 2 1 ] = [ x 1 y 1 1 ] [ 1 0 0 0 1 0 t x t y 1 ] \begin{gathered} \begin{bmatrix} x_2 & y_2 & 1\end{bmatrix}= \begin{bmatrix} x_1 & y_1 & 1\end{bmatrix} \begin{bmatrix} 1 & 0 & 0\\0 & 1 & 0\\t_x & t_y & 1 \end{bmatrix} \end{gathered} [x2y21]=[x1y11]⎣⎡10tx01ty001⎦⎤
代码实现
def translate(p_list, dx, dy):
"""
:param p_list:(list of lsit of int:[[x0,x1], [x1,y1], ...]) point set of p
:param dx: (int) delta x
:param dy: (int) delta y
:result: (list of list of int:[[x0, y0], [x1, y1], ...])
"""
n = len(p_list)
result = []
for i in range(0, n):
x2 = p_list[i][0] + dx
y2 = p_list[i][1] + dy
result.append([x2, y2])
return result
旋转变换
二维旋转是将物体沿着xy平面内的圆弧路径重定位。旋转角 θ \theta θ取值逆时针为正,顺时针为负
旋转变换的二维表示
如图所示:
显见有如下关系:
{
x
2
=
r
∗
c
o
s
(
α
+
θ
)
=
r
∗
c
o
s
α
∗
c
o
s
θ
−
r
∗
s
i
n
α
∗
s
i
n
θ
y
2
=
r
∗
s
i
n
(
α
+
θ
)
=
r
∗
c
o
s
α
∗
s
i
n
θ
+
r
∗
s
i
n
α
∗
c
o
s
θ
\begin{cases} x_2=r*cos(\alpha+\theta)=r*cos\alpha*cos\theta-r*sin\alpha*sin\theta\\ y_2=r*sin(\alpha+\theta)=r*cos\alpha*sin\theta+r*sin\alpha*cos\theta \end{cases}
{x2=r∗cos(α+θ)=r∗cosα∗cosθ−r∗sinα∗sinθy2=r∗sin(α+θ)=r∗cosα∗sinθ+r∗sinα∗cosθ
又因为有 x 1 = r ∗ c o s α , y 1 = r ∗ s i n α x_1=r*cos\alpha,y_1=r*sin\alpha x1=r∗cosα,y1=r∗sinα,所以有
{ x 2 = r ∗ c o s ( α + θ ) = x 1 ∗ c o s θ − y 1 ∗ s i n θ y 2 = r ∗ s i n ( α + θ ) = x 1 ∗ s i n θ + y 1 ∗ c o s θ \begin{cases} x_2=r*cos(\alpha+\theta)=x_1*cos\theta-y_1*sin\theta\\ y_2=r*sin(\alpha+\theta)=x_1*sin\theta+y_1*cos\theta \end{cases} {x2=r∗cos(α+θ)=x1∗cosθ−y1∗sinθy2=r∗sin(α+θ)=x1∗sinθ+y1∗cosθ
旋转变换的齐次表示
[ x 2 y 2 1 ] = [ x 1 y 1 1 ] [ c o s θ s i n θ 0 − s i n θ c o s θ 0 0 0 1 ] \begin{gathered} \begin{bmatrix} x_2 & y_2 & 1\end{bmatrix}= \begin{bmatrix} x_1 & y_1 & 1\end{bmatrix} \begin{bmatrix} cos\theta & sin\theta & 0\\-sin\theta & cos\theta & 0\\0 & 0 & 1 \end{bmatrix} \end{gathered} [x2y21]=[x1y11]⎣⎡cosθ−sinθ0sinθcosθ0001⎦⎤
代码实现
def rotate(p_list, x, y, r):
"""
:param p_list:(list of lsit of int:[[x0,x1], [x1,y1], ...]) point set of p
:param x: (int) coordinate x
:param y: (int) coordinate y
:param r: (float) degree
:result: (list of list of int:[[x0, y0], [x1, y1], ...])
"""
n = len(p_list)
sin = math.sin(math.radians(r))
cos = math.cos(math.radians(r))
result = []
for x1, y1 in p_list:
x2 = int(x1 * cos - y1 * sin)
y2 = int(x1 * sin + y1 * cos)
result.append([x2, y2])
return result
比例变换
二维比例变换改变物体的尺寸。通过顶点值 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)乘以比例系数 S x S_x Sx和 S y S_y Sy得到变换的坐标 ( x 2 , y 2 ) (x_2,y_2) (x2,y2);
比例系数 S x S_x Sx为在x方向对物体的缩放, S y S_y Sy在y方向的缩放。比例系数可以赋予任何正数,小于1缩小,大于1则放大;若 S x = S y S_x=S_y Sx=Sy为等比例变换,若 S x ≠ S y S_x\neq S_y Sx=Sy则是非均匀比例变换。
比例变换的二维表示为:
{ x 2 = x 1 ∗ S x y 2 = y 1 ∗ S y \begin{cases}x_2=x_1*S_x\\ y_2=y_1*S_y\end{cases} {x2=x1∗Sxy2=y1∗Sy
比例变换的齐次表示为:
[ x 2 y 2 1 ] = [ x 1 y 1 1 ] [ S x 0 0 0 S y 0 0 0 1 ] \begin{gathered} \begin{bmatrix} x_2 & y_2 & 1\end{bmatrix}= \begin{bmatrix} x_1 & y_1 & 1\end{bmatrix} \begin{bmatrix} S_x & 0 & 0\\0 & S_y & 0\\0 & 0 & 1 \end{bmatrix} \end{gathered} [x2y21]=[x1y11]⎣⎡Sx000Sy0001⎦⎤
代码实现
def scale(p_list, x, y, s):
"""
:param p_list:(list of lsit of int:[[x0,x1], [x1,y1], ...]) point set of p
:param x: (int) coordinate x
:param y: (int) coordinate y
:param s: (float) times
:result: (list of list of int:[[x0, y0], [x1, y1], ...])
"""
n = len(p_list)
result = []
for i in range(0, n):
x2 = int(p_list[i][0] + s)
y2 = int(p_list[i][1] + s)
result.append([x2, y2])
return result
相对任意参考点的二维变换
如果要对某参考点(x,y)作二维几何变换,比如比例变换,旋转变换等。变换过程如下:
- 将参考点移至坐标原点
- 对原点进行二维几何变换
- 进行反平移,将参考点移回原来的位置