在三维空间中,圆上最接近的点。有什么缺失的吗?

我希望我能够清楚地解释这个。我正在尝试计算三维圆上的最近点。我找到了以下解决方案: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)

--为了正确计算,我需要对它进行修正
--例如仅对circleNormal {0,1,0}有效
--在Q的投影中添加圆心位置的y分量
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

--以下计算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)

--作为|X-p|返回距离以及点X
return vec3.mag(vec3.sub(X,p)),X
end

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

原文链接 https://stackoverflow.com/questions/6571202

点赞
stackoverflow用户68063
stackoverflow用户68063

你提供的那篇论文在这个运算上有点夸张了,我认为。

你的问题在于 projectVectorOntoPlane 实际上并没有将向量投影到你想要的平面上。它将向量投影到另一个平面上,这个平面与你想要的平行,但是它通过原点。(你试图用 Q[2] = C[2] 来解决这个问题,但这只会让事情变得更糟。)

一个平面可以由法向量和平面上的某个点共同定义,所以你可以将 projectVectorOntoPlane 函数写成这样:

-- 将点 P 投影到法向量为 n、经过点 O 的平面上。
function projectVectorOntoPlane(P, n, O)
    return vec3.sub(P, vec3.scale(n, vec3.dot(vec3.sub(P, O), n)))
end

然而,对于这个问题,最简单的方法是在以圆心为基础的坐标系中全部工作,所以我建议这样做:

-- 返回圆心为 C、法向量为 n、半径为 r 且距离 P 最近的圆上的点。(如果所有的点到 P 的距离都相等,返回任何一个。)
function pointCircleClosest(P, C, n, r)
    -- 将问题转化到以 C 为中心的坐标系中。
    local P = vec3.sub(P, C)

    -- 将 P 投影到包含圆的平面上。
    local Q = vec3.sub(P, vec3.scale(n, vec3.dot(n, P)))

    -- 如果 Q 在圆心,所有点都与 P 最近。
    if vec3.equal(Q, {0,0,0}) then
        Q = perpendicular(n)
    end

    -- 接下来,最近的点在原点和 Q 通过的线上。
    local R = vec3.sub(P, vec3.scale(Q, r / vec3.mag(Q)))

    -- 返回到原始的坐标系中。
    return vec3.add(R, C)
end

-- 返回与 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 类更方便,就像这个,这样你可以写 P - C 而不是繁琐的 vec3.sub(P, C) 等等。

2011-07-04 15:17:51