确定具有已知法线的两个点是否彼此面对(matlab)

ThT*_*ThT 2 matlab space points normals

我正在尝试找到以下问题的解决方案,但尚不清楚如何解决。想象一下,我在空间中有以下几点,如下图所示:

在此处输入图片说明

如果我认为我唯一已知的信息是点位置及其法线,我想确定两个点(将第一个点的位置视为参考)是否彼此面对。例如从点以上图像abcde我有:

a面对点ce但不是点bd

b面对点de但不是点ac

c面对点a而不是点bde

d面对点be但不是点ac

最后

e面点abd而不是点c

我的第一个虽然是通过使用这里提出的解决方案来处理每对的两个法向量之间的带符号角,但这对某些对有效,而对其他对无效。关于两点彼此面对的想法是,如果我们将一个点视为原点,那么如果另一个点在原点的 180 度视场内并且其法向量向内(有点“朝向”)原点。

任何有帮助的想法。

谢谢。


更新:

尝试更清楚一点并回答下面的一些评论。原则上,它在空间中的点对应于人脸的质心。但是,我事先没有这些信息(即每个点对应于面的中心,或面及其顶点的列表)。所以在更高的层次上,如果我们处理人脸,问题将是如何确定两个人脸是否彼此可见,但正如我所说,我现在拥有的唯一信息是空间中的实际点及其法线.

在此处输入图片说明

样本点:

a = [26415.3720833199 11986.0504166605 739];
na = [0 0 1];

b = [27263.8100000023 11103.1983333336 1512.50000000021];
nb = [0.102791963903622 -0.994702876318771 0];

c = [28059.5700000001 11185.4316666667 962.499999999998];
nc = [-0.102791963903623 0.994702876318771 -9.06557542353252e-16];

d = [26606.7112499615 10390.7487916521 739];
nd = [0 0 1];

e = [27792.4499999996 9225.36499999984 2782];
ne = [0 0 -1];
Run Code Online (Sandbox Code Playgroud)

gno*_*ice 5

你可以用几个简单的点积来解决你的问题......

根据您的描述,如果(ie )的法线与从to 开始的向量之间的角度小于或等于 90 度,则该ba在另一个点的视场 (FOV) 内。如所描述的在这里,该角度可以通过取找到点积的和,通过分割长度的(并假设长度已经是1),并且取反余弦的结果的。把它放到一个匿名函数中,你有:anaabb-anab-ana

isInFOV = @(b, a, na) (acosd(dot(b-a, na)./norm(b-a)) <= 90);
Run Code Online (Sandbox Code Playgroud)

如果沿着从到的向量运行的(的法线)的分量是正的,则可以将一个点定义b为“指向”另一个点。如所描述的在这里,该组件可以通过采取找到点积的和,并通过分割长度的(并假设长度已经是1)。把它放到一个匿名函数中,你有:anbbbaa-bnba-bnb

isPointingToward = @(b, nb, a) (dot(a-b, nb)./norm(a-b) > 0);
Run Code Online (Sandbox Code Playgroud)

然后我们可以定义一个点a是否“面对”另一个点b

isFacing = @(a, na, b, nb) (isInFOV(b, a, na) && isPointingToward(b, nb, a));
Run Code Online (Sandbox Code Playgroud)

请注意,我使用了逻辑短路 AND 运算符, &&因为isPointingToward如果isInFOV已经评估为 ,则不需要评估false

矢量化

您可以使用类似的函数bsxfun或用dot标准矩阵运算替换对 的调用来重新表述上述等式以向量化运算。这将允许您检查给定点面对的集合中的哪些点。该函数的矢量化版本isFacing如下:

function index = isFacing(a, na, b, nb)

  V = bsxfun(@minus, b, a);                     % Compute b-a for all b
  V = bsxfun(@rdivide, V, sqrt(sum(V.^2, 2)));  % Normalize each row
  index = (acosd(V*na.') <= 90);                % Find points in FOV of a
  index(index) = (sum(V(index, :).*nb(index, :), 2) < 0);  % Of those points in FOV,
                                                           %   find those pointing
                                                           %   towards a

end
Run Code Online (Sandbox Code Playgroud)

例子

使用问题中的样本数据:

pointMat = [26415.3720833199 11986.0504166605 739; ...               % Point a
            27263.8100000023 11103.1983333336 1512.50000000021; ...  % Point b
            28059.5700000001 11185.4316666667 962.499999999998; ...  % Point c
            26606.7112499615 10390.7487916521 739];                  % Point d
normalMat = [0 0 1; ...
             0.102791963903622 -0.994702876318771 0; ...
             -0.102791963903623 0.994702876318771 -9.06557542353252e-16; ...
             0 0 1];
p = [27792.4499999996 9225.36499999984 2782];  % Point e
np = [0 0 -1];

>> isFacing(p, np, pointMat, normalMat)

ans =

  4×1 logical array

   1    % Facing a
   1    % Facing b
   0    % Not facing c
   1    % Facing d
Run Code Online (Sandbox Code Playgroud)