在 MATLAB 中的大立方体中构造多条路径
Constructing multiple paths inside a big cube in MATLAB
我有一个大立方体,里面装满了很多小立方体。我想通过小立方体制作 4 条相连的路径,每条路径都有不同的颜色。我们最终会在立方体内部得到不同的颜色区域。我有一些来自之前问题的代码 ( AND )。该代码可以构建任意长度的路径 <= 小立方体的数量,我刚刚对其进行了一些调整并且它运行良好。我现在要做的就是重复这 4 次,每个区域一次。我添加了一个 for 循环来执行此操作,并指定了每条路径中的立方体数量。但它不起作用!好像只构造了第一条路径。这是我如何构建路径的快速解释,
从任何随机立方体开始,用某种颜色(它的区域颜色)给它上色,找到它的邻居,选择它的任何邻居,然后给那个邻居上色。然后对于这个当前 selected 的邻居,我们重复相同的过程,我们查看它的邻居和 select 他们中的任何一个作为路径中的下一步。如果一个立方体的邻居都被访问过(属于某个路径),该算法将 select 任何未访问的立方体并移动到它,只要它不会使路径断开连接。这是通过检查要 selected 的未访问立方体是否有一些访问过的邻居来实现的,如果有,那么我们可以移动到它,因为路径将被连接。构建一个区域的代码运行良好,我只想将此过程进行四次,但这是行不通的。这是代码,
%%
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
getNeighbourIndex = @(idx) iNeighbour(idx,~isnan(iNeighbour(idx,:))) ;
%set(hcube,'Visible','off') %// turn off all small cubes
%CubeOfInterest = 32 ; %// 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)
%% // Random path
rng(1) %// set that if you want reproducible results, otherwise comment it
set(hcube,'Visible','off')
startCubeIndex = randi([1 numel(hcube)],1) ; %// random starting cube
%// startCubeIndex = 1 ; %// or fixed one
maxPathLength = 0 ; %// maximum length of path
maxPathLength= maxPathLength+1;
path_terminated = false ; %// condition to get out of loop
path_visited = [] ; %// store the generated path (visited cubes)this to be checked in case 2 as well.
ptIndex = 1 ;
path_visited(1) = startCubeIndex ;
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1)
availableAll =[1:125];
for i=1:4
if (i==1)
path_visited(1) = startCubeIndex ;
maxPathLength=60;
elseif (i==2)
ptIndex= ptIndex+1;
path_visited(ptIndex) = randi([1 max(availableAll)],1) ;
maxPathLength=30;
elseif (i==3)
ptIndex= ptIndex+1;
path_visited(ptIndex) = randi([1 max(availableAll)],1) ;
maxPathLength=20;
elseif (i==4)
ptIndex= ptIndex+1;
path_visited(ptIndex) = randi([1 max(availableAll)],1) ;
maxPathLength=15;
end
disp (maxPathLength)
while ~path_terminated
available_next = getNeighbourIndex( path_visited(ptIndex) ) ; %// get all the neighbours
[~,~,ib] = intersect(path_visited,available_next) ; %// check if we already went through some
if ~isempty(ib)
available_next(ib) = [] ; %// remove visited cube from "available" list
end
nAvail = numel(available_next) ; %// number of actually available neighbour
if nAvail == 0 %// Exit loop if no neighbour available
msgTerm = 'Path blocked. No other neighbour available.' ; %// Reason for terminating path
%//path_terminated = true ;
%//here I want to make the modification.
looping=true; %//To keep looping until we find the correct next move.
counter=0; %//to iterate through the cubes which are not visisted.
while looping==true
counter= counter+1;
jump= availableAll (counter); %//select the first available cube and check if it is suitable or not
if (~isempty (intersect(getNeighbourIndex(jump), path_visited))) %// if the selcted cube has a visited neighbor, it means it is suitable. The path will stay connected.
%good we found it.
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = jump ; %//add the selected cube to the path.
availableAll (availableAll==jump)= []; %//remove the selected cube from the list of available cubes.
looping= false; %//stop looping.
end
%continue
end
else
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
availableAll (availableAll==path_visited(ptIndex))= []; %//remove the selected cube from the list of available cubes.
end
if ptIndex >= maxPathLength %// exit loop if we reached the max number of elements
msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue;
end
%// choose one neighbour randomly among the available ones
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1) %// highlight new cube
set(hcube( path_visited(1:ptIndex-1) ) ,'Visible','on','FaceColor','g','FaceAlpha',.2) %// shade old cubes
pause(0.05) %// just for intermediate display, you can comment these 2 lines
drawnow %// just for intermediate display, you can comment these 2 lines
end
disp(msgTerm)
end
上面的部分代码是从我链接的问题中获得的。我已经添加了 for 循环,以及在访问邻居的情况下移动到未访问的多维数据集的部分(代码在注释 "here I want to make the modification." 下)。 如果删除 for 循环,代码将在 1 个区域正常工作。请注意,我还没有为不同的区域着色,现在重要的是如何为 4 个区域重复相同的路径构建方法。
谁能告诉我我犯了什么错误,以及如何解决?
谢谢。
我明白了。在这里,
if ptIndex >= maxPathLength %// exit loop if we reached the max number of elements
msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue;
end
ptIndex
将在构建第一个区域后的所有 3 个区域中大于 maxPathLength
。这是因为每次访问多维数据集时 ptIndex
都会递增。假设我们在第一个区域访问了 60 个立方体,那么 ptIndex
将等于 60。现在,第二个区域的 maxPathLength
是 30。因此,ptIndex
> 30 这将导致在不构建第二个区域的情况下退出的代码。因此,就好像我们只是在构建第一个区域,然后就停止了。为了解决这个问题,我将每个区域的步数与该区域的 maxPathLength
进行了比较,如下所示,
if steps==maxPathLength %// exit loop if we reached the max number of elements
% msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue;
end
其中 steps
从 0 开始并增长到每个区域的 maxPathLength
(我们在第二个 while 之前将其初始化为 0 并在第二个 while 的每次迭代中递增。)
代码现在运行良好。
谢谢。
我有一个大立方体,里面装满了很多小立方体。我想通过小立方体制作 4 条相连的路径,每条路径都有不同的颜色。我们最终会在立方体内部得到不同的颜色区域。我有一些来自之前问题的代码 (
从任何随机立方体开始,用某种颜色(它的区域颜色)给它上色,找到它的邻居,选择它的任何邻居,然后给那个邻居上色。然后对于这个当前 selected 的邻居,我们重复相同的过程,我们查看它的邻居和 select 他们中的任何一个作为路径中的下一步。如果一个立方体的邻居都被访问过(属于某个路径),该算法将 select 任何未访问的立方体并移动到它,只要它不会使路径断开连接。这是通过检查要 selected 的未访问立方体是否有一些访问过的邻居来实现的,如果有,那么我们可以移动到它,因为路径将被连接。构建一个区域的代码运行良好,我只想将此过程进行四次,但这是行不通的。这是代码,
%%
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
getNeighbourIndex = @(idx) iNeighbour(idx,~isnan(iNeighbour(idx,:))) ;
%set(hcube,'Visible','off') %// turn off all small cubes
%CubeOfInterest = 32 ; %// 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)
%% // Random path
rng(1) %// set that if you want reproducible results, otherwise comment it
set(hcube,'Visible','off')
startCubeIndex = randi([1 numel(hcube)],1) ; %// random starting cube
%// startCubeIndex = 1 ; %// or fixed one
maxPathLength = 0 ; %// maximum length of path
maxPathLength= maxPathLength+1;
path_terminated = false ; %// condition to get out of loop
path_visited = [] ; %// store the generated path (visited cubes)this to be checked in case 2 as well.
ptIndex = 1 ;
path_visited(1) = startCubeIndex ;
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1)
availableAll =[1:125];
for i=1:4
if (i==1)
path_visited(1) = startCubeIndex ;
maxPathLength=60;
elseif (i==2)
ptIndex= ptIndex+1;
path_visited(ptIndex) = randi([1 max(availableAll)],1) ;
maxPathLength=30;
elseif (i==3)
ptIndex= ptIndex+1;
path_visited(ptIndex) = randi([1 max(availableAll)],1) ;
maxPathLength=20;
elseif (i==4)
ptIndex= ptIndex+1;
path_visited(ptIndex) = randi([1 max(availableAll)],1) ;
maxPathLength=15;
end
disp (maxPathLength)
while ~path_terminated
available_next = getNeighbourIndex( path_visited(ptIndex) ) ; %// get all the neighbours
[~,~,ib] = intersect(path_visited,available_next) ; %// check if we already went through some
if ~isempty(ib)
available_next(ib) = [] ; %// remove visited cube from "available" list
end
nAvail = numel(available_next) ; %// number of actually available neighbour
if nAvail == 0 %// Exit loop if no neighbour available
msgTerm = 'Path blocked. No other neighbour available.' ; %// Reason for terminating path
%//path_terminated = true ;
%//here I want to make the modification.
looping=true; %//To keep looping until we find the correct next move.
counter=0; %//to iterate through the cubes which are not visisted.
while looping==true
counter= counter+1;
jump= availableAll (counter); %//select the first available cube and check if it is suitable or not
if (~isempty (intersect(getNeighbourIndex(jump), path_visited))) %// if the selcted cube has a visited neighbor, it means it is suitable. The path will stay connected.
%good we found it.
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = jump ; %//add the selected cube to the path.
availableAll (availableAll==jump)= []; %//remove the selected cube from the list of available cubes.
looping= false; %//stop looping.
end
%continue
end
else
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
availableAll (availableAll==path_visited(ptIndex))= []; %//remove the selected cube from the list of available cubes.
end
if ptIndex >= maxPathLength %// exit loop if we reached the max number of elements
msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue;
end
%// choose one neighbour randomly among the available ones
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1) %// highlight new cube
set(hcube( path_visited(1:ptIndex-1) ) ,'Visible','on','FaceColor','g','FaceAlpha',.2) %// shade old cubes
pause(0.05) %// just for intermediate display, you can comment these 2 lines
drawnow %// just for intermediate display, you can comment these 2 lines
end
disp(msgTerm)
end
上面的部分代码是从我链接的问题中获得的。我已经添加了 for 循环,以及在访问邻居的情况下移动到未访问的多维数据集的部分(代码在注释 "here I want to make the modification." 下)。 如果删除 for 循环,代码将在 1 个区域正常工作。请注意,我还没有为不同的区域着色,现在重要的是如何为 4 个区域重复相同的路径构建方法。
谁能告诉我我犯了什么错误,以及如何解决?
谢谢。
我明白了。在这里,
if ptIndex >= maxPathLength %// exit loop if we reached the max number of elements
msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue;
end
ptIndex
将在构建第一个区域后的所有 3 个区域中大于 maxPathLength
。这是因为每次访问多维数据集时 ptIndex
都会递增。假设我们在第一个区域访问了 60 个立方体,那么 ptIndex
将等于 60。现在,第二个区域的 maxPathLength
是 30。因此,ptIndex
> 30 这将导致在不构建第二个区域的情况下退出的代码。因此,就好像我们只是在构建第一个区域,然后就停止了。为了解决这个问题,我将每个区域的步数与该区域的 maxPathLength
进行了比较,如下所示,
if steps==maxPathLength %// exit loop if we reached the max number of elements
% msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue;
end
其中 steps
从 0 开始并增长到每个区域的 maxPathLength
(我们在第二个 while 之前将其初始化为 0 并在第二个 while 的每次迭代中递增。)
代码现在运行良好。
谢谢。