在 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 的每次迭代中递增。)

代码现在运行良好。

谢谢。