【问题标题】:Closest point projection of a 3D point to 3D triangles with numpy/scipy使用 numpy/scipy 将 3D 点的最近点投影到 3D 三角形
【发布时间】:2015-11-27 08:09:30
【问题描述】:

如何使用 numpy/scipy 计算一个点到 N 个三角形的最近投影?

现在我将创建一个函数来计算对单个三角形basically this 的投影,然后遍历整个三角形数组。但在我开始这样做之前,我想知道是否已经有一个内置于 scipy 的解决方案。比如:

# DREAMY PSEUDOCODE
import numpy as np
N_TRIANGLES = 1000

point = np.random.rand(3) * 100 #random 3d point
triangles = np.random.rand(N_TRIANGLES,3,3) * 100 #array of triangles

from scipy.spatial import pointToTriangles
projections = pointToTriangles(point,triangles)

这是一张帮助您形象化的图片:

在上图中,中间的红点是我的查询“点”,蓝点是“三角形”np.array() 中定义的每个三角形的顶点。绿点代表我想要的结果。它们是“点”在已定义三角形上的最接近投影,我希望将此信息作为点数组返回。

干杯!

【问题讨论】:

  • 你能澄清你的要求吗?在您的示例中,projections 应该包含什么?
  • 我仍然不明白您所说的“点”到三角形表面的投影是什么意思。如果我在 3D 空间中有一个点和一个三角形,那么我可以绘制无限多条线,将点连接到三角形的表面。你能找到/画一个图表,或者至少举一个实数的例子吗?
  • @ali_m 抱歉,我正在寻找最接近三角形点的投影。
  • 您可以将点投影到每个三角形的平面上,这是您想要的吗?或者您是否还想在三角形中找到距该投影点最近的点?
  • 嗯,投影通常沿着明确定义的方向发生。如果不是三角形的平面法线,则需要定义要沿哪个平面投影,否则您的问题未定义。

标签: python math numpy scipy geometry


【解决方案1】:

这是我想出的代码。我在 scipy 中找不到任何可以直接帮助我的东西,而且这个解决方案比查询 CGAL 快大约 2 倍。它不处理折叠的三角形,但可以通过检查边长来解决这个问题,并返回最长边上的最近点。

import numpy as np
from numpy.core.umath_tests import inner1d

def pointsToTriangles(points,triangles):

    with np.errstate(all='ignore'):

        # Unpack triangle points
        p0,p1,p2 = np.asarray(triangles).swapaxes(0,1)

        # Calculate triangle edges
        e0 = p1-p0
        e1 = p2-p0
        a = inner1d(e0,e0)
        b = inner1d(e0,e1)
        c = inner1d(e1,e1)

        # Calculate determinant and denominator
        det = a*c - b*b
        invDet = 1. / det
        denom = a-2*b+c

        # Project to the edges
        p  = p0-points[:,np.newaxis]
        d = inner1d(e0,p)
        e = inner1d(e1,p)
        u = b*e - c*d
        v = b*d - a*e

        # Calculate numerators
        bd = b+d
        ce = c+e
        numer0 = (ce - bd) / denom
        numer1 = (c+e-b-d) / denom
        da = -d/a
        ec = -e/c


        # Vectorize test conditions
        m0 = u + v < det
        m1 = u < 0
        m2 = v < 0
        m3 = d < 0
        m4 = (a+d > b+e)
        m5 = ce > bd

        t0 =  m0 &  m1 &  m2 &  m3
        t1 =  m0 &  m1 &  m2 & ~m3
        t2 =  m0 &  m1 & ~m2
        t3 =  m0 & ~m1 &  m2
        t4 =  m0 & ~m1 & ~m2
        t5 = ~m0 &  m1 &  m5
        t6 = ~m0 &  m1 & ~m5
        t7 = ~m0 &  m2 &  m4
        t8 = ~m0 &  m2 & ~m4
        t9 = ~m0 & ~m1 & ~m2

        u = np.where(t0, np.clip(da, 0, 1), u)
        v = np.where(t0, 0, v)
        u = np.where(t1, 0, u)
        v = np.where(t1, 0, v)
        u = np.where(t2, 0, u)
        v = np.where(t2, np.clip(ec, 0, 1), v)
        u = np.where(t3, np.clip(da, 0, 1), u)
        v = np.where(t3, 0, v)
        u *= np.where(t4, invDet, 1)
        v *= np.where(t4, invDet, 1)
        u = np.where(t5, np.clip(numer0, 0, 1), u)
        v = np.where(t5, 1 - u, v)
        u = np.where(t6, 0, u)
        v = np.where(t6, 1, v)
        u = np.where(t7, np.clip(numer1, 0, 1), u)
        v = np.where(t7, 1-u, v)
        u = np.where(t8, 1, u)
        v = np.where(t8, 0, v)
        u = np.where(t9, np.clip(numer1, 0, 1), u)
        v = np.where(t9, 1-u, v)


        # Return closest points
        return (p0.T +  u[:, np.newaxis] * e0.T + v[:, np.newaxis] * e1.T).swapaxes(2,1)

一些测试数据将 100 个点投影到 10k 个三角形:

    import numpy as np
    import cProfile

    N_TRIANGLES = 10**4 # 10k triangles
    N_POINTS    = 10**2 # 100 points
    points      = np.random.random((N_POINTS,3,)) * 100
    triangles   = np.random.random((N_TRIANGLES,3,3,)) * 100

    cProfile.run("pointsToTriangles(points,triangles)") # 54 function calls in 0.320 seconds

这很快就会占用内存,因此在处理大型数据集时,最好一次迭代一个点或三角形。

【讨论】:

  • 这段代码是大致遵循geometrictools.com/Documentation/DistancePoint3Triangle3.pdf 中描述的算法,还是有所不同? [编辑:我现在看到它是,但在许多输入三角形上矢量化] 输入的形状是什么?
  • 我对代码进行了一些调整,以便它可以处理投影在三角形数组上的点数组。如果您查看更新后的示例,您将看到输入形状。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 1970-01-01
  • 2015-05-14
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
相关资源
最近更新 更多