lua - 3d 中圆上的最近点。少了什么东西?

标签 lua collision-detection linear-algebra vectormath

我希望我能够清楚地解释这一点。我正在尝试计算 3D 圆上最近的点。我找到了以下解决方案: http://www.geometrictools.com/Documentation/DistancePoint3Circle3.pdf

我的代码如下(用Lua编写)。主要问题是投影Q似乎不正确,或者我不明白如何正确计算它。正如您在论文中所读到的那样,Q 应该是点在圆平面上的投影。

例如,圆的法线为{0,1,0},圆心位于{3,3,3}。我试图计算到圆的最近距离的点 (p) 位于 {6, 3, 2}。那么,在我的计算中,Q在圆平面上的投影是{6,0,2}。

为了使算法发挥作用,我似乎必须用平面的位置(例如法线方向上的圆心分量)来偏移 Q。在本例中,y 方向的值为 3。

我可以对正常的 {0,1,0} 进行破解,因为它很容易,但是一旦圆面临任何任意位置,我不知道如何计算它。

我错过了什么以及哪里出错了?

function calculatePointCircleDistance(p, circleCenter, circleNormal, circleRadius)
local C = circleCenter
local R = circleRadius
local Q = projectVectorOntoPlane(p, circleNormal)

-- I need to do a fix like this in order to get the calculations right
-- This for example only works with circleNormal {0,1,0}
-- Adding the y component of the circle position to the projection Q
Q[2] = C[2]

if vec3.equal(Q, C) == 1 then
    print("point exacly aligned with center circle")
    return vec3.mag(vec3.sub(C, p)), C
end

-- the following is calculating X=C+R (Q−C / |Q−C|)
local QminC = vec3.sub(Q, C)
local tmp = vec3.scale(vec3.div(QminC, vec3.mag(QminC)), R)
local X = vec3.add(C, tmp)

-- return distance as |X-p| as well as point X
return vec3.mag(vec3.sub(X, p)), X
end



function projectVectorOntoPlane(v, normal)
-- U = V - (V dot N)N
local vProjected = vec3.sub(v, vec3.scale(normal, vec3.dot(v, normal)))
return vProjected
end

最佳答案

我认为,您链接到的那篇论文使这次操作变得很重要。

您的问题是 projectVectorOntoPlane 实际上并未将矢量投影到您想要的平面上。它将矢量投影到与所需平面平行但穿过原点的另一个平面上。 (然后您尝试使用 Q[2] = C[2] 解决此问题,但这只会让事情变得更糟。)

平面可以由法线向量与平面上的某个点一起定义,因此您可以像这样编写 projectVectorOntoPlane 函数:

-- Project P onto the plane with normal n containing the point O.
function projectVectorOntoPlane(P, n, O)
    return vec3.sub(P, vec3.scale(n, vec3.dot(vec3.sub(P, O), n)))
end

但是,对于这个问题,最简单的方法是在基于圆心的坐标系中完成所有工作,因此我建议如下:

-- Return a point on the circle with center C, unit normal n and radius r
-- that's closest to the point P. (If all points are closest, return any.)
function pointCircleClosest(P, C, n, r)
    -- Translate problem to C-centred coordinates.
    local P = vec3.sub(P, C)

    -- Project P onto the plane containing the circle.
    local Q = vec3.sub(P, vec3.scale(n, vec3.dot(n, P)))

    -- If Q is at the centre, all points on the circle are equally close.
    if vec3.equal(Q, {0,0,0}) then
        Q = perpendicular(n)
    end

    -- Now the nearest point lies on the line through the origin and Q.
    local R = vec3.sub(P, vec3.scale(Q, r / vec3.mag(Q)))

    -- Return to original coordinate system.
    return vec3.add(R, C)
end

-- Return an arbitrary vector that's perpendicular to n.
function perpendicular(n)
    if math.abs(n[1]) < math.abs(n[2]) then
        return vec3.cross(n, {1,0,0})
    else
        return vec3.cross(n, {0,1,0})
    end
end

哦,您可能会发现使用更好的 vec3 类更方便,perhaps this one ,这样你就可以编写 P - C 而不是繁琐的 vec3.sub(P, C) 等等。

关于lua - 3d 中圆上的最近点。少了什么东西?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6571202/

相关文章:

if-statement - Lua elseif 无法正常工作

c++ - 如何推送现有/创建/实例化的类对象以在 Lua 脚本上使用?

javascript - 单击 Canvas 中的给定元素

Android Canvas 位图大小和测量

用于任意元素类型的 Haskell 线性代数矩阵库

algorithm - 大规模伪逆

lua - Corona sdk 在场景开始时延迟 EnterFrame 函数

c++ - 从 C++ 访问函数环境中的 Lua 变量

java - 矩形碰撞检测算法半工作

python - 矢量的二维正交投影到带有 numpy 的线上会产生错误的结果