旋转、缩放和平移2D坐标?

5

我目前正在从事一个项目,试图使用Python Imaging Library创建Hilbert曲线。我已经创建了一个函数,通过每次迭代生成新的曲线坐标,并将它们放入各个列表中,然后我希望能够移动、旋转和缩放它们。我想知道是否有人可以给我一些提示或方法来做到这一点,因为我完全不知道该怎么做。目前仍在努力编写大部分代码。

#! usr/bin/python
import Image, ImageDraw
import math

# Set the starting shape
img = Image.new('RGB', (1000, 1000))
draw = ImageDraw.Draw(img)

curve_X = [0, 0, 1, 1]
curve_Y = [0, 1, 1, 0]

combinedCurve = zip(curve_X, curve_Y)
draw.line((combinedCurve), fill=(220, 255, 250))
iterations = 5

# Start the loop
for i in range(0, iterations):
    # Make 4 copies of the curve

    copy1_X = list(curve_X)
    copy1_Y = list(curve_Y)

    copy2_X = list(curve_X)
    copy2_Y = list(curve_Y)

    copy3_X = list(curve_X)
    copy3_Y = list(curve_Y)

    copy4_X = list(curve_X)
    copy4_Y = list(curve_Y)

    # For copy 1, rotate it by 90 degree clockwise
    # Then move it to the bottom left
    # For copy 2, move it to the top left
    # For copy 3, move it to the top right
    # For copy 4, rotate it by 90 degrees anticlockwise
    # Then move it to the bottom right

    # Finally, combine all the copies into a big list
    combinedCurve_X = copy1_X + copy2_X + copy3_X + copy4_X
    combinedCurve_Y = copy1_Y + copy2_Y + copy3_Y + copy4_Y

# Make the initial curve equal to the combined one
curve_X = combinedCurve_X[:]
curve_Y = combinedCurve_Y[:]

# Repeat the loop

# Scale it to fit the canvas
curve_X = [x * xSize for x in curve_X]
curve_Y = [y * ySize for y in curve_Y]
# Draw it with something that connects the dots
curveCoordinates = zip(curve_X, curve_Y)
draw.line((curveCoordinates), fill=(255, 255, 255))

img2=img.rotate(180)
img2.show()

请查看标题为“Python函数用于旋转2D对象”的问题的答案(https://dev59.com/2mIj5IYBdhLWcg3wpmsH)以及我对问题“给定两个顶点,围绕中心点旋转线”的答案(https://dev59.com/m2Uq5IYBdhLWcg3wC8BQ#14842362)。 - martineau
1个回答

8
这里有一个解决方案适用于矩阵(因为这种类型的计算是有意义的,在最后,2D坐标是只有1列的矩阵!),
缩放非常容易,只需要将矩阵的每个元素乘以比例因子即可:
scaled = copy.deepcopy(original)
for i in range(len(scaled[0])):
    scaled[0][i]=scaled[0][i]*scaleFactor
    scaled[1][i]=scaled[1][i]*scaleFactor

移动非常简单,您只需要将偏移量添加到矩阵的每个元素中即可。以下是使用矩阵乘法的方法:

import numpy as np
# Matrix multiplication
def mult(matrix1,matrix2):
    # Matrix multiplication
    if len(matrix1[0]) != len(matrix2):
        # Check matrix dimensions
        print 'Matrices must be m*n and n*p to multiply!'
    else:
        # Multiply if correct dimensions
        new_matrix = np.zeros(len(matrix1),len(matrix2[0]))
        for i in range(len(matrix1)):
            for j in range(len(matrix2[0])):
                for k in range(len(matrix2)):
                    new_matrix[i][j] += matrix1[i][k]*matrix2[k][j]
        return new_matrix

然后创建您的翻译矩阵。
import numpy as np
TranMatrix = np.zeros((3,3))
TranMatrix[0][0]=1
TranMatrix[0][2]=Tx
TranMatrix[1][1]=1
TranMatrix[1][2]=Ty
TranMatrix[2][2]=1

translated=mult(TranMatrix, original)

最后,旋转会有点棘手(您知道旋转角度吗?):
import numpy as np
RotMatrix = np.zeros((3,3))
RotMatrix[0][0]=cos(Theta)
RotMatrix[0][1]=-1*sin(Theta)
RotMatrix[1][0]=sin(Theta)
RotMatrix[1][1]=cos(Theta)
RotMatrix[2][2]=1

rotated=mult(RotMatrix, original)

以下是我所做的一些进一步阅读:

所以,基本上,如果你在代码中插入这些操作,通过旋转/平移矩阵将向量乘以它们,就可以实现它。

编辑

我刚刚发现了这个Python库,它似乎提供了所有类型的变换:http://toblerity.org/shapely/index.html


如果你发现程序运行太慢了,可以考虑使用copy.deepcopy(original)中的deepcopy进行检查。在过去,我曾经运行过类似的代码,结果发现deepcopy比自定义的copy()方法要慢得多。 - rubenafo
你能编辑一下导入 zero 函数所需的库吗?是用的 numpy 吗? - sapo_cosmico
@ sapo_cosmico 说实话,我不记得我用的是什么了。我已经使用numpy进行了更新;有关更多选项,请参见此问题:https://dev59.com/GWw15IYBdhLWcg3wWqf- - 7hibault
我认为在else语句中仍然存在问题: new_matrix = zero(len(matrix1),len(matrix2[0])) - sapo_cosmico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接