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

extracting voxels within 8 points / 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。

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

你有你不同点的所有位置,还有点的位置x。想象一个中心点是 (0,0,0),你的点围绕它形成一个立方体。制作立方体的所有外表面,就像您使用 linesJoiningVertices 所做的那样,但使​​用 faces。你应该有 6 个外部 faces.

现在你必须检查你的 x 点是在立方体的每个 face 之前还是之后。如果该点在每个 face 之前,则它包含在立方体中。这也适用于非立方体。

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

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

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

  • 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)

注意,法线是垂直于它们所代表的平面的向量,任何平面的方程都是从法向量中提取出来的。

this是图的显示方式,看平行平面和6个动态点足以构成任何3D多边形

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

然后是浮点数

1
2
3

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