MATLAB - 获取点阵列之间的角度
MATLAB - get angle between arrays of points
为了照明分析,基于this document,我试图确定一组灯光和固体表面上一系列点的三件事:
(图片重点:蓝色大点是显示光照方向的灯,小点是我表面的点)
- 1) 每个灯和每个点之间的距离,
- 2) 每个光所面对的方向与所有点的法向量之间的角度:
请注意,在此图像中,我复制了法线向量并将其移动以更清楚地显示角度。
- 3) 每个光所面对的方向与从该光到实体上所有点的矢量之间的角度:
最初我嵌套了 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
的内置角度?
感谢大家的帮助,对于油漆图像感到抱歉!
上下文:这张图片显示了我的灯光(大蓝点)、灯光朝向(黑色小痕迹)和我的模型。
根据MathWorks,没有built-in函数来计算向量之间的角度。但是,您可以使用三角函数来计算角度。
输入
很遗憾,由于您没有详细解释您的输入数据,我将假设您有一个矩阵 Lmat
,每行包含一个光源的位置向量和一个矩阵 Dmat
包含光源的方向向量,大小均为 n×3,其中 n 是光源的数量现场.
矩阵Omega
和Nmat
的大小应该是m×3,包含所有的位置向量和法向量m 个曲面点。想要的结果是所有光线方向向量和表面法线向量之间的夹角,其中有n⋅m,光线之间的夹角方向向量和连接光线到表面上每个点的向量,其中有n⋅m
要获得所有光源和表面点组合的结果,必须垂直重复输入矩阵:
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;
要计算 light-to-point 向量与方向向量之间的角度,只需将 Nmat
替换为 Omega - Lmat
。
使用向量积/叉积
mentioned 上述方法在非常小的 (θ ≈ 0°) 或非常大的 (θ ≈ 180°) 角度时会出现精度问题。建议的解决方案是使用叉积和内积计算角度。
两个向量的向量积的范数是
可以结合上面定义的内积得到
显然可以重新排序为:
相应的 MATLAB 代码如下所示:
normCross = sqrt(sum(cross(Dmat,Nmat,2).^2,2));
anglesInDegrees = atan2(normCross,dot(Dmat.',Nmat.')') * 180/pi;
为了照明分析,基于this document,我试图确定一组灯光和固体表面上一系列点的三件事:
(图片重点:蓝色大点是显示光照方向的灯,小点是我表面的点)
- 1) 每个灯和每个点之间的距离,
- 2) 每个光所面对的方向与所有点的法向量之间的角度:
请注意,在此图像中,我复制了法线向量并将其移动以更清楚地显示角度。
- 3) 每个光所面对的方向与从该光到实体上所有点的矢量之间的角度:
最初我嵌套了 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
的内置角度?
感谢大家的帮助,对于油漆图像感到抱歉!
上下文:这张图片显示了我的灯光(大蓝点)、灯光朝向(黑色小痕迹)和我的模型。
根据MathWorks,没有built-in函数来计算向量之间的角度。但是,您可以使用三角函数来计算角度。
输入
很遗憾,由于您没有详细解释您的输入数据,我将假设您有一个矩阵 Lmat
,每行包含一个光源的位置向量和一个矩阵 Dmat
包含光源的方向向量,大小均为 n×3,其中 n 是光源的数量现场.
矩阵Omega
和Nmat
的大小应该是m×3,包含所有的位置向量和法向量m 个曲面点。想要的结果是所有光线方向向量和表面法线向量之间的夹角,其中有n⋅m,光线之间的夹角方向向量和连接光线到表面上每个点的向量,其中有n⋅m
要获得所有光源和表面点组合的结果,必须垂直重复输入矩阵:
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;
要计算 light-to-point 向量与方向向量之间的角度,只需将 Nmat
替换为 Omega - Lmat
。
使用向量积/叉积
mentioned 上述方法在非常小的 (θ ≈ 0°) 或非常大的 (θ ≈ 180°) 角度时会出现精度问题。建议的解决方案是使用叉积和内积计算角度。
两个向量的向量积的范数是
可以结合上面定义的内积得到
显然可以重新排序为:
相应的 MATLAB 代码如下所示:
normCross = sqrt(sum(cross(Dmat,Nmat,2).^2,2));
anglesInDegrees = atan2(normCross,dot(Dmat.',Nmat.')') * 180/pi;