用python在3D numpy数组中绘制三角形

用python在3D numpy数组中绘制三角形,python,arrays,numpy,3d,Python,Arrays,Numpy,3d,假设我有一个具有某种形状的3D数组(矩形长方体),例如(48、32、64)。我在这个立方体中有3个点和一些坐标。 x1=(10,20,30) x2=(21,15,34) x3=(33,1,62) 我需要在这个受点限制的3D数组中绘制填充平面,例如,在3D数组中绘制三角形。在2D情况下,我们可以使用openCV执行此操作: 但在3D情况下,最简单的方法是什么?为了渲染3D三角形,您必须将其投影到2d,或者使用一些现成的解决方案,例如mplot3d,或者您可以手动将3D数据投影到2d 最简单的投影

假设我有一个具有某种形状的3D数组(矩形长方体),例如(48、32、64)。我在这个立方体中有3个点和一些坐标。 x1=(10,20,30) x2=(21,15,34) x3=(33,1,62)

我需要在这个受点限制的3D数组中绘制填充平面,例如,在3D数组中绘制三角形。在2D情况下,我们可以使用openCV执行此操作:


但在3D情况下,最简单的方法是什么?

为了渲染3D三角形,您必须将其投影到2d,或者使用一些现成的解决方案,例如
mplot3d
,或者您可以手动将3D数据投影到2d

最简单的投影是正交投影。您可以通过忽略数据的z维度来实现这一点

对于透视投影,将3d数据除以z值:

import numpy as np

p1 = (10, 20, 30)
p2 = (21, 15, 34)
p3 = (33, 1, 62)

tri3d = np.array([p1, p2, p3])
ortho2d = tri3d[:, :2]
proj2d = tri3d[:, :2] / tri3d[:, 2:]

print(tri3d)
print(ortho2d)
print(proj2d)
结果:

[[10 20 30]
 [21 15 34]
 [33  1 62]]
[[10 20]
 [21 15]
 [33  1]]
[[0.33333333 0.66666667]
 [0.61764706 0.44117647]
 [0.53225806 0.01612903]]
然后,您可以使用您在问题中提到的相同三角形填充。一些注意事项是您所在空间的边界,以及任何投影三角形的比例。请注意,投影坐标都非常小。在这种情况下,您可能会将它们按一定的比例放大(相当于相机校准矩阵中的焦距)。

编辑过:我以前忘记了包含
完整三角形的代码()


假设你有一个画线的算法,比如,假设它可以推广到N-dim的情况

幸运的是,该软件包具有Bresenham算法的N-dim实现

(免责声明:我是该软件包的主要作者。)

设A,B,C为三角形ABC顶点的坐标


如果您只需要绘制外部形状,您可以使用算法使用各种点的组合来形成直线:AB、BC、CA

在代码中,这仅仅是:

import numpy as np
import raster_geometry as rg


a, b, c = (1, 1), (3, 7), (6, 4)
coords = set(rg.bresenham_lines((a, b, c), closed=True))
print(coords)
# {(1, 2), (6, 4), (3, 2), (4, 6), (5, 5), (2, 2), (2, 3), (3, 6), (2, 4), (4, 3), (3, 7), (2, 5), (1, 1), (5, 3)}
arr = rg.render_at((10, 10), coords)
print(arr.astype(int))
# [[0 0 0 0 0 0 0 0 0 0]
#  [0 1 1 0 0 0 0 0 0 0]
#  [0 0 1 1 1 1 0 0 0 0]
#  [0 0 1 0 0 0 1 1 0 0]
#  [0 0 0 1 0 0 1 0 0 0]
#  [0 0 0 1 0 1 0 0 0 0]
#  [0 0 0 0 1 0 0 0 0 0]
#  [0 0 0 0 0 0 0 0 0 0]
#  [0 0 0 0 0 0 0 0 0 0]
#  [0 0 0 0 0 0 0 0 0 0]]
如果需要绘制完整的三角形,可以执行以下操作:

  • 从点a到点B画一条线
  • 为直线上的每个点,从C到AB线中的一点绘制一条直线
虽然这可能不是最有效的方法,但它将相当有效。 顶点附近的某些点可能会丢失。 在这种情况下,通过所有三个顶点重复相同的过程就足够了

在代码中,这可以是:

import numpy as np
import raster_geometry as rg


def full_triangle(a, b, c):
    ab = rg.bresenham_line(a, b, endpoint=True)
    for x in set(ab):
        yield from rg.bresenham_line(c, x, endpoint=True)


a, b, c = (1, 1), (3, 7), (6, 4)
coords = set(full_triangle(a, b, c))
print(coords)
# {(1, 2), (6, 4), (5, 4), (3, 2), (3, 3), (5, 5), (4, 6), (4, 5), (4, 4), (1, 1), (2, 3), (4, 3), (2, 2), (3, 6), (3, 7), (2, 5), (5, 3), (3, 4), (2, 4), (3, 5)}
arr = rg.render_at((10, 10), coords)
print(arr.astype(int))
# [[0 0 0 0 0 0 0 0 0 0]
#  [0 1 1 0 0 0 0 0 0 0]
#  [0 0 1 1 1 1 0 0 0 0]
#  [0 0 1 1 1 1 1 1 0 0]
#  [0 0 0 1 1 1 1 0 0 0]
#  [0 0 0 1 1 1 0 0 0 0]
#  [0 0 0 0 1 0 0 0 0 0]
#  [0 0 0 0 0 0 0 0 0 0]
#  [0 0 0 0 0 0 0 0 0 0]
#  [0 0 0 0 0 0 0 0 0 0]]

请注意,虽然示例是2D,但它们适用于N-dim。 例如,您所追求的三维三角形可以通过以下方式生成:

x1 = (10, 20, 30)
x2 = (21, 15, 34)
x3 = (33, 1, 62)
coords = set(full_triangle(x1, x2, x3))
arr = rg.render_at((48, 32, 64), coords)

我不确定你是否正确理解了这个问题。在输出上,我必须有相同形状的3D数组,其中点(体素)标记为1,以便绘制trainagle。啊,可以渲染为三角形定义的体素。。。为此,需要找到三角形体素交点。这里有一个很好的答案:。Plotly具有显示体素的方法:
x1 = (10, 20, 30)
x2 = (21, 15, 34)
x3 = (33, 1, 62)
coords = set(full_triangle(x1, x2, x3))
arr = rg.render_at((48, 32, 64), coords)