MATLAB - 获取点阵列之间的角度

时间:2016-01-14 05:21:10

标签: arrays matlab matrix angle

为了照明分析,基于this document,我试图确定一组灯光和固体表面上的一系列点的三个东西:

(图像键:大蓝点是显示照明方向的灯,小点是我表面上的点)

  • 1)每个灯和每个点之间的距离,
  • 2)每个光面对的方向与所有点的法线向量之间的角度:

normal-normal

请注意,在此图像中,我复制了法线向量并移动它以更清晰地显示角度。

  • 3)每个光线面向的方向与从该光线到固体上所有点的矢量之间的角度:

normal-point

最初我有嵌套for循环遍历实体上的所有灯光和点,但现在我正在尽力用真实的MATLAB样式和矩阵进行:

我找到了pdist2函数的所有点之间的距离,但没有设法找到类似的方法来找到灯光和所有点之间的角度,也没有找到灯光和法线向量要点。我更喜欢用矩阵方法而不是像我一直使用的那样迭代。

考虑到我已经设置了数据,Lmat的每一列都有我的x,y,z我的灯光位置矢量; Dmat给出每个光的x,y,z个方向,因此来自这两个矩阵的每一行的组合完全定义了光和它所面对的方向。同样,Omeganmat对表面上的点也是如此。

我相当确定要获得角度我想做的事情是:

distMatrix = pdist2(Omega, Lmat);

LmatNew = zeros(numPoints, numLights, 3);
DmatNew = zeros(numPoints, numLights, 3);
OmegaNew = zeros(numPoints, numLights, 3);
nmatNew = zeros(numPoints, numLights, 3);
for i = 1:numLights
    LmatNew(:,i,1) = Lmat(i,1);
    LmatNew(:,i,2) = Lmat(i,2);
    LmatNew(:,i,3) = Lmat(i,3);

    DmatNew(:,i,1) = Dmat(i,1);
    DmatNew(:,i,2) = Dmat(i,2);
    DmatNew(:,i,3) = Dmat(i,3);
end

for j = 1:numPoints
    OmegaNew(j,:,1) = Omega(j,1);
    OmegaNew(j,:,2) = Omega(j,2);
    OmegaNew(j,:,3) = Omega(j,3);

    DmatNew(:,i,1) = Dmat(i,1);
    DmatNew(:,i,2) = Dmat(i,2);
    DmatNew(:,i,3) = Dmat(i,3);
end


angleMatrix = -dot(LmatNew-OmegaNew, DmatNew, 3);
angleMatrix = atand(angleMatrix);

angleMatrix = angleMatrix.*(angleMatrix > 0);

但是我在概念上陷入困境,试图让我的脑袋绕过我的点产品后做什么。

我是否在正确的轨道上?是否存在我忽略的pdist2的内置角度?

感谢所有人的帮助,并对油漆图片感到抱歉!

上下文:此图像显示我的灯光(大蓝点),灯光朝向的方向(黑色小痕迹)和我的模型。enter image description here

1 个答案:

答案 0 :(得分:1)

根据MathWorks,没有内置函数来计算向量之间的角度。但是,您可以使用三角学来计算角度。

输入

由于您遗憾地没有详细解释您的输入数据,我将假设您有一个矩阵find,其中包含每行中光源的位置矢量和矩阵{{1包含光源的方向向量,大小 n ×3,其中 n 是场景中光源的数量。

矩阵LmatDmat据说大小 m ×3,包含所有 m 曲面点的位置矢量和法线矢量。所需的结果是所有光方向矢量和表面法向量之间的角度,其中有 n m ,以及光方向矢量和连接矢量之间的角度光到表面上的每个点,其中还有 n m

要获得光源和曲面点的所有组合的结果,输入矩阵必须垂直重复:

Omega

使用内积/点积

两个向量的内积的定义是

inner product

其中θ是两个向量之间的角度。重新排序等式得出

theta

因此,您可以计算方向向量Nmat与法线向量Lmat = repmat(Lmat, size(Omega,1), 1); Dmat = repmat(Dmat, size(Omega,1), 1); Omega = repmat(Omega, size(Lmat,1), 1); Nmat = repmat(Nmat, size(Lmat,1), 1); 之间的角度,如下所示:

Dmat

要计算光点矢量和方向矢量之间的角度,只需将Nmat替换为normProd = sqrt(sum(Dmat.^2,2)).*sqrt(sum(Nmat.^2,2)); anglesInDegrees = acos(dot(Dmat.',Nmat.')' ./ normProd) * 180 / pi;

使用载体产品/杂交产品

已经mentioned上述方法在非常小(θ≈0°)或非常大(θ≈180°)的角度下会出现精度问题。建议的解决方案是使用叉积和内积来计算角度。

两个载体的载体产物的范数是

vector product

您可以将此与内部产品的上述定义结合起来

tan of vectors

显然可以重新排序:

enter image description here

相应的MATLAB代码如下所示:

Nmat