在MATLAB中用小方块填充整个立方体的体积

Dan*_*nia 4 3d graphics matlab matrix nearest-neighbor

我在MATLAB中构建了一个空心立方体,我想用小立方体完全填充其体积.然后我想找到一种方法来访问这些立方体并通过它们制作路径,即如果当前访问了立方体x,应该有一种方法可以知道它的右边,左边,顶边,底边,前面和后面最近的邻居是什么(最近邻居=直接在当前立方体旁边的立方体).我想我们有6个邻居,因为我们有6个不同的立方体面.

通过知道每个方向上最近的立方体,可以将通过立方体的路径定义为一系列步骤(例如,右,左,左,顶,右,前).我认为能够访问每个小立方体并移动到附近我们需要在矩阵中表示小立方体(可能是3D),如果一个小立方体在其右边有一个邻居立方体x,那么在矩阵中,x将出现在小立方体的当前列旁边的列中.此外,如果在另一深度层存在直接邻居(相同的x,y坐标但不同的z坐标,例如,前邻居和后邻居),则应指示.是否有更简单的方法来识别邻居?

我已经通过rayryeng获得了一个代码(构建一个空心立方体并在MATLAB中用小立方体填充)以在大的立方体中随机填充许多小立方体并构建一个3D矩阵,其中矩阵的每个切片(深度)代表一个小立方体以及每个切片(8行和3列)的行和列表示每个小立方体的顶点的xyz坐标.请查看我提供的问题链接以查看代码.

我想对代码进行两次修改,

1-以有组织的方式用小立方体填充大立方体,而不是随机.

2-调整3D矩阵以表示小立方体如何彼此相邻.

我试图调整链接问题中的代码以有组织的方式填充多维数据集.这是我的试用版(我在for循环中添加了if else),

   clf;
figure(1);
format compact 
h(1) = axes('Position',[0.2 0.2 0.6 0.6]);

%These are the different 8 vertices of the cube, each is defined by its 3 x
%y z coordinates:
vert = [1 1 -1; 
        -1 1 -1; 
        -1 1 1; 
        1 1 1; 
        -1 -1 1;
        1 -1 1; 
        1 -1 -1;
        -1 -1 -1];
%These are the 6 faces of the cube, each is defined by connecting 4 of the
%available vertices:
fac = [1 2 3 4; 
       4 3 5 6; 
       6 7 8 5; 
       1 2 8 7; 
       6 7 1 4; 
       2 3 5 8];

% I defined a new cube whose length is 1 and centers at the origin.
vert2 = vert * .05;  
fac2 = fac;


patch('Faces',fac,'Vertices',vert,'Facecolor', 'w');  % patch function for the first big cube. 
axis([-1, 1, -1, 1, -1, 1]);
axis equal;

hold on;

patch('Faces', fac2, 'Vertices', vert2, 'FaceColor', 'r', 'EdgeColor', 'none');
material metal;
alpha('color');
alphamap('rampdown');
%view(3);


hold on;
rng(123); %// Set seed for reproducibility
num_squares = 1000; %// Set total number of squares

%// New - to store the coordinates
coords = [];

%// For remembering the colours
colors = [];
%// For each square...

for idx = 1 : num_squares


    %// Take the base cube and add an offset to each coordinate
    %// Each coordinate will range from [-1,1]
    if (idx==1)
    vert_new = bsxfun(@plus, vert2, [.01 .01 .01]);

    else 
    vert_new = bsxfun (@plus, vert_new,[.01 .01 .01] );
    end
    %// New - For the coordinates matrix
    coords = cat(3, coords, vert_new);

    %// Generate a random colour for each cube
    color = rand(1,3);

    %// New - Save the colour
    colors = cat(1, colors, color);

    %// Draw the cube
    patch('Faces', fac, 'Vertices', vert_new, 'FaceColor', color,'EdgeColor', 'none');
end




%// Post processing
material metal;
alpha('color');
alphamap('rampdown');
view(3);
Run Code Online (Sandbox Code Playgroud)

但我得到的结果如下图所示,

在此输入图像描述

任何人都可以告诉我如何解决这个问题,并建立3D矩阵(或任何其他更简单的方式来代表每个立方体的邻居)?

编辑:详细说明小立方体邻居问题.考虑在大立方体内的任何地方都有一个立方体C. 让立方体位置为(.5,.5,.5),我们可以将其视为立方体的中心.然后,这个立方体将有6个相邻的立方体(直接位于它旁边),每个轴有2个邻居.所以,对于我们有的立方体(.5,.5,.5),

x轴右边的x轴(.5 +偏移,.5,.5)

x轴左边的x轴(.5 -offset,.5,.5)

y轴邻居到C的顶部(.5,.5 +偏移,.5)

y轴邻居到C的底部(.5,.5-偏移,.5)

z轴邻近C之后的一个深度(.5,.5,.5 +偏移)

z轴邻近C之前的一个深度(.5,.5,.5-偏移)

其中偏移可以看作立方体的中心与其任何面之间的距离.这只是澄清这个想法的解释,它不需要以同样的方式实现.我希望这很清楚,我将非常感谢构建这个邻域矩阵的任何帮助.

谢谢.

Hok*_*oki 7

同样的原则,我们在角落里建造一个大的立方体,然后是一个小立方体,然后我们用一个小的偏移量重复小立方体建筑,直到我们满了.与旧代码的主要区别在于,这次控制每个坐标集的阶跃变化(x,y,z小立方体坐标的函数)而不是随机的.

buildcube

%%
clf; figure(1); format compact 
h(1) = axes('Position',[0.2 0.2 0.6 0.6]);

%These are the different 8 vertices of the cube, each is defined by its 3 x y z coordinates:
vert = [ 1  1 -1; -1  1 -1; -1  1  1; 1  1  1; -1 -1  1; 1 -1  1; 1 -1 -1; -1 -1 -1];

%These are the 6 faces of the cube, each is defined by connecting 4 of the available vertices:
fac = [1 2 3 4; 4 3 5 6; 6 7 8 5; 1 2 8 7; 6 7 1 4; 2 3 5 8];

%// How many small cube do we want
MainCubeSide = 2 ;              %// dimension of the side of the main cube
nCubeOnSide = 5 ;               %// number of small cube in one "row/column" of the main cube
nCubesTotal = nCubeOnSide^3  ;  %// total number of small cube

% define the Main container cube
MainCube.Vertices = vert *(2/MainCubeSide) ; %// because the cube as defined above has already a side=2
MainCube.Faces = fac ;
MainCube.FaceColor = 'w' ;

hMainCube = patch(MainCube);  %// patch function for the first big cube. 
axis([-1, 1, -1, 1, -1, 1]);
axis equal;
hold on;
material metal;
alpha('color');
alphamap('rampdown');
view(138,24)
%view(3);


%% // generate all the coordinates of each cube first
dstep = MainCubeSide / nCubeOnSide ;                                                 %// step size for small cube vertices
vElem = bsxfun(@plus, vert / nCubeOnSide , -( MainCubeSide/2 - dstep/2)*[1 1 1] )  ; %// elementary cube vertices

%%
hold on;
coords = zeros( size(vElem,1),size(vElem,2), nCubesTotal ) ;  %// To store the coordinates
colors = zeros( nCubesTotal , 3 ) ;                           %// To store the colours
hcube  = zeros( nCubesTotal , 1 ) ;                           %// To store the handles of the patch objects

iNeighbour = zeros( nCubesTotal , 6 ) ;   %// To save the index of the neighbours
idc = permute( reshape(1:nCubesTotal,nCubeOnSide,nCubeOnSide,nCubeOnSide) , [3 2 1] ) ;

%// For each cube ...
iCube = 0 ;
for iline=1:nCubeOnSide         %// Lines
    for icol=1:nCubeOnSide      %// Columns
        for ih=1:nCubeOnSide    %// Slice (height)
            iCube = iCube + 1 ;

            %// Take the base corner coordinates and add an offset to each coordinate
            coords(:,:,iCube) = bsxfun(@plus, vElem , dstep*[(iline-1) (icol-1) (ih-1)]);

            %// Save the colour
            colors(iCube,:) = rand(1,3) ; 

            %// Draw the cube
            hcube(iCube) = patch('Faces', fac, 'Vertices', coords(:,:,iCube), 'FaceColor', colors(iCube,:) ) ;

            drawnow     %// just for intermediate display, you can comment these 2 lines
            pause(0.05) %// just for intermediate display, you can comment these 2 lines

            %// save adjacent cubes indices
            ixAdj = [iline-1 iline+1 icol-1 icol+1 ih-1 ih+1] ;  %// indices of adjacent cubes
            idxFalse = (ixAdj<1) | (ixAdj>nCubeOnSide) ;  %// detect cube which would be "out" of the main cube
            ixAdj(idxFalse) = 1 ;                                %// just to not get an "indexing" error at this stage
            iNeighbour(iCube,:) = [idc(ixAdj(1),icol,ih)    idc(ixAdj(2),icol,ih) ...
                                   idc(iline,ixAdj(3),ih)   idc(iline,ixAdj(4),ih) ...
                                   idc(iline,icol,ixAdj(5)) idc(iline,icol,ixAdj(6)) ] ;
            iNeighbour(iCube,idxFalse) = NaN ;
        end
    end
end
Run Code Online (Sandbox Code Playgroud)

此代码将每个多维数据集的句柄保存在变量中,hcube因此您可以根据需要在所有多维数据集上批量分配属性.例如,delete(hcube)将一次删除所有小立方体,或set(hcube,'Facealpha',0.5)将使所有立方体半透明.

您还可以仅在其中的一部分上设置/更改属性hcube(idx_subset) = ....这是通过索引了解相邻立方体可能有用的地方,但您的邻接问题尚未完全定义.


编辑:我在主循环中添加了邻居跟踪.它可能不是最有效的方法,但它确实保留了每个基本多维数据集的所有邻居的索引.的iNeighbour变量(尺寸:nCubesx6)保持每个邻居(6楼可能的邻居)的手柄索引.当邻居不存在时,我选择放置一个NaN.为了在没有NaNs的情况下直接检索邻居的索引,我定义了一个帮助程序匿名函数:

getNeighbourIndex = @(idx) iNeighbour(idx,~isnan(iNeighbour(idx,:))) ;
Run Code Online (Sandbox Code Playgroud)

现在可以帮助您跟踪给定多维数据集的所有邻居.例如:

set(hcube,'Visible','off')  %// turn off all small cubes
CubeOfInterest = 111 ;      %// select one cube
%// display the main cube of interest, and it's neighbours in transparency
set(hcube(CubeOfInterest),'Visible','on','FaceColor','r','FaceAlpha',1) 
set(hcube(getNeighbourIndex(CubeOfInterest)),'Visible','on','FaceColor','g','FaceAlpha',.05)
Run Code Online (Sandbox Code Playgroud)

立方体

如你所见,所有邻居都在那里,无论我们是否靠近墙壁.

  • 那是你在那里建造的一个困难的5x5魔方:-) (2认同)