为了照明分析,基于this document,我试图确定一组灯光和固体表面上的一系列点的三个东西:
(图像键:大蓝点是显示照明方向的灯,小点是我表面上的点)
请注意,在此图像中,我复制了法线向量并移动它以更清晰地显示角度。
最初我有嵌套for
循环遍历实体上的所有灯光和点,但现在我正在尽力用真实的MATLAB样式和矩阵进行:
我找到了pdist2
函数的所有点之间的距离,但没有设法找到类似的方法来找到灯光和所有点之间的角度,也没有找到灯光和法线向量要点。我更喜欢用矩阵方法而不是像我一直使用的那样迭代。
考虑到我已经设置了数据,Lmat
的每一列都有我的x,y,z
我的灯光位置矢量; Dmat
给出每个光的x,y,z
个方向,因此来自这两个矩阵的每一行的组合完全定义了光和它所面对的方向。同样,Omega
和nmat
对表面上的点也是如此。
我相当确定要获得角度我想做的事情是:
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
的内置角度?
感谢所有人的帮助,并对油漆图片感到抱歉!
答案 0 :(得分:1)
根据MathWorks,没有内置函数来计算向量之间的角度。但是,您可以使用三角学来计算角度。
由于您遗憾地没有详细解释您的输入数据,我将假设您有一个矩阵find
,其中包含每行中光源的位置矢量和矩阵{{1包含光源的方向向量,大小 n ×3,其中 n 是场景中光源的数量。
矩阵Lmat
和Dmat
据说大小 m ×3,包含所有 m 曲面点的位置矢量和法线矢量。所需的结果是所有光方向矢量和表面法向量之间的角度,其中有 n ⋅ m ,以及光方向矢量和连接矢量之间的角度光到表面上的每个点,其中还有 n ⋅ m 。
要获得光源和曲面点的所有组合的结果,输入矩阵必须垂直重复:
Omega
两个向量的内积的定义是
其中θ是两个向量之间的角度。重新排序等式得出
因此,您可以计算方向向量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°)的角度下会出现精度问题。建议的解决方案是使用叉积和内积来计算角度。
两个载体的载体产物的范数是
您可以将此与内部产品的上述定义结合起来
显然可以重新排序:
相应的MATLAB代码如下所示:
Nmat