如何在Python中高效地对大量点应用3D变换?

huangapple go评论70阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年8月8日 19:47:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76859263.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定