同样的原理,我们先建造一个大立方体,然后在角落里建造一个小立方体,然后用一个小的偏移量重复建造小立方体,直到填满为止。与旧代码的主要区别在于,这次控制了每个坐标集的阶跃变化(功能
x,y,z
小立方体的坐标)而不是随机的。
%%
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
此代码将每个多维数据集的句柄保存在变量中
hcube
因此,如果需要,可以对所有立方体进行批量属性赋值。例如
delete(hcube)
将一次性删除所有小立方体,或
set(hcube,'Facealpha',0.5)
将使所有立方体半透明。
您还可以仅在其中的一个子集上设置/更改属性
hcube(idx_subset) = ...
这是通过索引知道相邻立方体可能有用的地方,但您的邻接问题尚未完全定义。
编辑:
我已经在主循环中添加了邻居跟踪。这可能不是最有效的方法,但它确实保留了每个基本立方体的所有邻居的索引。
这个
iNeighbour
变量(大小:
nCubesx6
)保持每个邻居(6个可能的邻居)的句柄索引。当邻居不存在时,我选择放置一个
NaN
相反
不使用
NaN公司
s、 我定义了一个助手匿名函数:
getNeighbourIndex = @(idx) iNeighbour(idx,~isnan(iNeighbour(idx,:))) ;
现在,它可以帮助您跟踪给定立方体的所有邻居。例如:
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)
正如你所看到的,所有的邻居都在那里,无论我们是否靠近墙。