matlab - 提取 8 个点/顶点内的体素

标签 matlab geometry box normals vertices

事情是这样的:我在 3D 体积中有 8 个点/顶点。 我想知道点 x 是否包含在其顶点由 8 个点给出的盒子内。

此外,我知道有 4 个点位于与 y 轴平行的平面(我们称之为 A)上,另外 4 个点也位于与 y 轴平行的另一个平面(B)上。

给定 A 和 B,它们是顶点的 4x3 矩阵。

我计算连接两对顶点的线,位于盒子的边界超平面上

    LinesJoiningVertices = 
            [A(2,:) - A(1,:), B(1,:) - A(1,:);
             A(1,:) - A(1,:), A(4,:) - A(1,:);
             A(3,:) - A(4,:), B(4,:) - A(4,:);
             A(2,:) - B(2,:), B(3,:) - B(2,:);
             B(2,:) - B(1,:), B(4,:) - B(1,:);
             A(1,:) - B(1,:), B(4,:) - B(1,:)]

我计算每个边界超平面的法线

   for i = 1:6
       normals(i,:) = cross(LinesJoiningVertices(i,1:3), LinesJoiningVertices(i,4:6))
   end

理论上,盒子内的点 x 与每个法线的点积应该为负(不是吗?)。 实际上,这是行不通的。我取一个我知道位于框内的点 x,对于第一个、第三个和第五个法线,答案大于 0。

我的代码有错误吗? 我的数学有错误吗?

最佳答案

  • 首先,让我告诉你一些事情。

对于两个平行平面,任何包含位于这两个平面之一上的四个点的两个子集的三维多边形只能用6个点来识别,其中每3个可以代表该平面包含该多边形的一个面。

对于与{B_0,B_1,B_2}构成的平面平行的平面上的任意6个点{A_0,A_2,A_3},需要满足其余两个点存在多边形的条件,否则,我们可以面对任何不一致分布的坐标,这些坐标形成随机的非线性形状或圆形或任何东西。 this illustration显示哪些两乘二相同颜色的线一定是平行的,以将剩余的点作为这些线的交点。

  • Sencondo,让我们继续计算给定的最后信息作为背景。

首先,点的坐标可以由系统生成:

syms x y z
P = [x,y,z]
left_x=0;right_x=4;

for j=0:1, for k=0:1, A((j)*2+k+1,1:3)=[left_x;floor(10*rand());floor(10*rand())];end,end
for j=0:1, for k=0:1, B((j)*2+k+1,1:3)=[right_x;floor(10*rand());floor(10*rand())];end,end

或者,手动输入

syms x y z
P = [x,y,z]


left_x=input('enter first x ');
for j=0:1, for k=0:1*~j,  A((j)*2+k+1,1:3)=[left_x;input(['print y' char((j)*2+k+49) ' ']);input(['print z' char((j)*2+k+49) ' '])];end,end,
right_x=input('enter second x ');
for j=0:1, for k=0:1*~j,  B((j)*2+k+1,1:3)=[right_x;input(['print y' char((j)*2+k+49) ' ']);input(['print z' char((j)*2+k+49) ' '])];end,end,

2-现在我们计算这些点中哪些点离y轴较近(近),哪些点离x轴较近(下),求出每3个点构成的4个虚拟平面的方程。

close_right_point=B((B(:,3)==min(B(:,3))),:)

far_right_point=B((B(:,3)==max(B(:,3))),:)

if(numel(close_right_point(:,1))==1)
temp=B((B(:,3)==min(B(B(:,3)~=min(B(:,3)),3))) ,:);
middler_points(2,:)=temp(1,:);
else
middler_points(2,:)=close_right_point(2,:);
end




closer_point=middler_points(middler_points(:,3)==min(middler_points(1,3),middler_points(2,3)),:)
if(numel(closer_point(:,1))==1)
further_point=middler_points(middler_points(:,3)==max(middler_points(1,3),middler_points(2,3)),:)
else
further_point=closer_point(2,:)
end


close_normal = cross(closer_point(1,:)-close_right_point(1,:), closer_point(1,:)-close_left_point(1,:))

close_plane=dot(close_normal,P-closer_point)



far_normal = cross(further_point-far_right_point(1,:), further_point-far_left_point(1,:))

far_plane=dot(far_normal,P-further_point)









low_left_point=A((A(:,2)==min(A(:,2))),:)


if(numel(low_left_point(:,1))==1)
temp=A((A(:,2)==min(A(A(:,2)~=min(A(:,2)),2))),:);
average_points(1,:)=temp(1,:);
else
average_points(1,:)=low_left_point(2,:);
end

high_left_point=A((A(:,2)==max(A(:,2))),:)




low_right_point=B((B(:,2)==min(B(:,2))),:)

high_right_point=B((B(:,2)==max(B(:,2))),:)


if(numel(low_right_point(:,1))==1)
temp=B((B(:,2)==min(B(B(:,2)~=min(B(:,2)),2))),:);
average_points(2,:)=temp(1,:);
else
average_points(2,:)=low_right_point(2,:);
end



lower_point=average_points(average_points(:,2)==min(average_points(1,2),average_points(2,2)),:)
if(numel(lower_point(:,1))==1)
higher_point=average_points(average_points(:,2)==max(average_points(1,2),average_points(2,2)),:)
else
higher_point=lower_point(2,:);
end



low_normal = cross( lower_point(1,:)-low_right_point(1,:), lower_point(1,:)-low_left_point(1,:))

low_plane=dot(low_normal,P-lower_point)



high_normal = cross( higher_point-high_right_point(1,:), higher_point-high_left_point(1,:))

high_plane=dot(high_normal,P-higher_point)

请注意,法线是与其所代表的平面垂直的向量,任何平面的方程都是从法线向量中提取的。

enter image description here

this如图所示,查看足以构成任何 3D 多边形的平行平面和 6 个动态点。

3-差不多完成了,继续进入下一阶段,我们通过用户输入接收所需点的坐标:

X=input('enter X ')
Y=input('enter Y ')
Z=input('enter Z ')

然后,检查该点是否超出相对于 y 轴的两个平行平面的最右端或最左端

if (X>right_x)
'out-bounds'
return;
end


if (X<left_x)
'out-bounds'
return;
end

然后,在平行于y轴绘制一条穿过该点的虚拟线之后,我们确保该点始终位于该线与较高和较低虚拟平面相交所形成的线段之间,如 this simulation shows

if Z> str2num(char(regexp(evalc(['x=' num2str(X) ';y=' num2str(Y) ';' char(solve(far_plane,z))]),'(\d+.\d*)','match')))
'out-bounds'
return;
end


if Z< str2num(char(regexp(evalc(['x=' num2str(X) ';y=' num2str(Y) ';' char(solve(close_plane,z))]),'(\d+.\d*)','match')))
'out-bounds'
return;
end


if Y> str2num(char(regexp(evalc(['x=' num2str(X) ';z=' num2str(Z) ';' char(solve(high_plane,y))]),'(\d+.\d*)','match')))
'out-of-bounds'
return;
end


if Y< str2num(char(regexp(evalc(['x=' num2str(X) ';z=' num2str(Z) ';' char(solve(low_plane,y))]),'(\d+.\d*)','match')))
'out-of-bounds'
return;
end

4-完成这一切,您可以使用此数据输入集检查该解决方案的有效性

0
0
0
6
5.6
0
5.05
4
0
0
6.51
-0.16
6.33
3.59

然后是 float

1
2
3

成功!,您可以使用此simulation查看/修改/检查结果通过单击任意点,然后使用任意参数更改定义文本字段,您也可以拖动点。

关于matlab - 提取 8 个点/顶点内的体素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32778353/

相关文章:

algorithm - 通过增加 A 的大小来测量求解线性系统 Ax=b 的计算复杂度

java - 如何在Java 3D API中将不同的图像设置为3D立方体的面/边?

c# - 从 ASP.NET 应用程序获取 Box API 的访问 token ?

html - 黑盒位置练习

c++ - 如何像在matlab中一样将实部和虚部放入一个变量中

matlab - 以 2 为底的矩阵对数

MATLAB 计时器对象陷阱和不良使用

geometry - 是否可以在不生成线的情况下测试像素是否在 bresenham 生成的线上?

c - 如何变换 glOrtho 剪裁平面?

python - 箱线图 X 值出现多次