英文:
How to Efficiently Apply 3D Transformations to a Large Number of Points in Python?
问题
我正在使用Python进行一个3D图形项目,我有一个包含数千个表示复杂对象的3D点的列表。我需要高效地对这些点执行多个变换(平移、旋转和缩放)。
我尝试使用循环来应用这些变换,但是当点的数量很大时,性能不理想。以下是我目前的做法(来自我最近的项目的片段):
import math
def transform_points(points, dx, dy, dz, rx, ry, rz, sx, sy, sz):
for point in points:
# 平移
point[0] += dx
point[1] += dy
point[2] += dz
# 绕X轴旋转
y = point[1] * math.cos(rx) - point[2] * math.sin(rx)
z = point[1] * math.sin(rx) + point[2] * math.cos(rx)
point[1] = y
point[2] = z
# 绕Y轴旋转
x = point[0] * math.cos(ry) + point[2] * math.sin(ry)
z = -point[0] * math.sin(ry) + point[2] * math.cos(ry)
point[0] = x
point[2] = z
# 绕Z轴旋转
x = point[0] * math.cos(rz) - point[1] * math.sin(rz)
y = point[0] * math.sin(rz) + point[1] * math.cos(rz)
point[0] = x
point[1] = y
# 缩放
point[0] *= sx
point[1] *= sy
point[2] *= sz
有没有更高效的方法来执行这些变换,可能使用库或内置功能?速度非常关键,因为这些变换将是实时渲染的一部分。
英文:
I am working on a 3D graphics project in Python, and I have a list of thousands of 3D points that represent a complex object. I need to perform multiple transformations (translation, rotation, and scaling) on these points efficiently.
I have tried using loops to apply the transformations, but the performance is not satisfactory with a large number of points. Here's what I've done so far (A snippet from my recent project)
import math
def transform_points(points, dx, dy, dz, rx, ry, rz, sx, sy, sz):
for point in points:
# Translate
point[0] += dx
point[1] += dy
point[2] += dz
# Rotate around X-axis
y = point[1] * math.cos(rx) - point[2] * math.sin(rx)
z = point[1] * math.sin(rx) + point[2] * math.cos(rx)
point[1] = y
point[2] = z
# Rotate around Y-axis
x = point[0] * math.cos(ry) + point[2] * math.sin(ry)
z = -point[0] * math.sin(ry) + point[2] * math.cos(ry)
point[0] = x
point[2] = z
# Rotate around Z-axis
x = point[0] * math.cos(rz) - point[1] * math.sin(rz)
y = point[0] * math.sin(rz) + point[1] * math.cos(rz)
point[0] = x
point[1] = y
# Scale
point[0] *= sx
point[1] *= sy
point[2] *= sz
Is there a more efficient way to perform these transformations, possibly using a library or built-in functionality? The speed is crucial, as these transformations will be part of real-time rendering.
答案1
得分: 1
这里的一个主要问题是,在每次迭代循环中,你都要计算每个值的cos和sin两次。
你可以将它们存储在一个变量中,这样就不需要每次都计算,因为知道cos和sin的计算成本相对较高。
例如:
def transform_points(points, dx, dy, dz, rx, ry, rz, sx, sy, sz):
cos_rx = math.cos(rx)
sin_rx = math.sin(rx)
cos_ry = math.cos(ry)
sin_ry = math.sin(ry)
cos_rz = math.cos(rz)
sin_rz = math.sin(rz)
for point in points:
# 平移
point[0] += dx
point[1] += dy
point[2] += dz
# 绕X轴旋转
y = point[1] * cos_rx - point[2] * sin_rx
z = point[1] * sin_rx + point[2] * cos_rx
point[1] = y
point[2] = z
# 绕Y轴旋转
x = point[0] * cos_ry + point[2] * sin_ry
z = -point[0] * sin_ry + point[2] * cos_ry
point[0] = x
point[2] = z
# 绕Z轴旋转
x = point[0] * cos_rz - point[1] * sin_rz
y = point[0] * sin_rz + point[1] * cos_rz
point[0] = x
point[1] = y
# 缩放
point[0] *= sx
point[1] *= sy
point[2] *= sz
这样,你只需要计算一次rx、ry和rz的sin和cos,而不是在每次迭代循环中每个值都计算两次,因此计算量为points.length * 6 * 2,如果点的数量增加,计算量可能会很大。
英文:
One of the main problem here is you are computing the cos and the sin twice in each iteration of the loop for each value.
One thing you could do is store them in a var, which would avoid to compute it every time, knowing that cos and sin are pretty expensive.
For example :
def transform_points(points, dx, dy, dz, rx, ry, rz, sx, sy, sz):
cos_rx = math.cos(rx)
sin_rx = math.sin(rx)
cos_ry = math.cos(ry)
sin_ry = math.sin(ry)
cos_rz = math.cos(rz)
sin_rz = math.sin(rz)
for point in points:
# Translate
point[0] += dx
point[1] += dy
point[2] += dz
# Rotate around X-axis
y = point[1] * cos_rx - point[2] * sin_rx
z = point[1] * sin_rx + point[2] * cos_rx
point[1] = y
point[2] = z
# Rotate around Y-axis
x = point[0] * cos_ry + point[2] * sin_ry
z = -point[0] * sin_y + point[2] * cos_ry
point[0] = x
point[2] = z
# Rotate around Z-axis
x = point[0] * cos_rz - point[1] * sin_rz
y = point[0] * sin_rz + point[1] * cos_rz
point[0] = x
point[1] = y
# Scale
point[0] *= sx
point[1] *= sy
point[2] *= sz
In this way, you would have to compute once the sin and cos for rx, ry and rz, so only 6 computations, instead of twice for each iteration of the loop for each value, so points.length * 6 * 2 ,which chan be big if the number of points increases.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论