Spiral loop on a dot matrix

I have a 2D grid as shown below and you want to start with X, Y and keep the window corner (W) and overlap (OP). I tried these codes, but they do not suit me.

As shown, I want to start from a random point (black cell) and save the angular positions (shown in black circles) of each new window in a spiral loop. The algorithm should be used for any mesh size (not necessarily squares) and any points on the starting point.

Matlab also has a function (spiral) that is similar to what I want, but it does not accept grid, window size and overlap (OP).

I expect the following result for this figure: (8.12) (11.12) (11.9) (8.9) (4.9) (4.12) (4.15) ...

I use the following codes that start from the corner and fill the matrix step by step using specific sizes of W, OP and Matrix:

W = [10 12]; OP = [4 3]; M = zeros(100,110); for i=[1:W(1)-OP(1):size(M,1)-W(1), size(M,1)-W(1)+1] for j=[1:W(2)-OP(2):size(M,2)-W(2), size(M,2)-W(2)+1] block = rand(W(1),W(2)); M(i:i+W(1)-1, j:j+W(2)-1) = block; imagesc(M); axis equal tight xy pause(.1) end; end; 

So, in a more understandable way, how can I change the code β€œabove” to start with the location (x, y) and spiral fill the entire matrix according to W, OP and size (M).

Thanks!

+6
source share
2 answers

Here is a piece of code that gives the expected result. Where only minor changes to spiral_generic are needed to meet your requirements:

 function demo() spiral_generic([10,11],[3,4]) W = [10 12]; OP = [4 3]; %make sure your start point is really on the grid of r and c, this is not checked! start = [19,28]; M = zeros(100,110); r=[1:W(1)-OP(1):size(M,1)-W(1), size(M,1)-W(1)+1]; c=[1:W(2)-OP(2):size(M,2)-W(2), size(M,2)-W(2)+1]; startindex=[find(r==start(1),1,'first'),find(c==start(2),1,'first')]; A=spiral_generic([numel(r),numel(c)],startindex); [~,idx]=sort(A(:)); [ridx,cidx]=ind2sub(size(A),idx); %blocks contains the lower left corners in order of processing. blocks=[r(ridx);c(cidx)]; for blockindex=blocks block = rand(W(1),W(2)); M(blockindex(1):blockindex(1)+W(1)-1, blockindex(2):blockindex(2)+W(2)-1) = block; imagesc(M); pause(.1) end end function A = spiral_generic(n, P) % Makes NxN matrix filled up spirally starting with point P r = max([P - 1, n - P]); % Radius of the bigger matrix M = spiral(2 * r + 1); % Bigger matrix itself M = permute(M,[2,1]); % changing start direction of the spiral M = M(:,end:-1:1); % chaning spin orientation C = r + 1 - (P - 1); % Top-left corner of A in M A = M(C(1):C(1)+n(1)-1, C(2):C(2)+n(2)-1); % Get the submatrix [~, order] = sort(A(:)); % Get elements' order A(order) = 1:(n(1)*n(2)); % Fill with continous values end 
+3
source

Main problem

Let the data be defined as:

 step = 3; %// step size x0 = 8; %// x coordinate of origin y0 = 12; %// y coordinate of origin N = 32; %// number of steps 

Then the coordinates of the spiral can be obtained as values ​​in the complex plane as follows: † :

 z = x0+1j*y0 + step*cumsum([0 -1j.^(-floor(sqrt(4*(0:N)+1))-1)]); 

Of course, the x and y coordinates then

 x = real(z); y = imag(z); 

With the above examples, plot(z,'o-') values ​​(or plot(x,y,'o-') ) produces a graph

enter image description here

† The key was to generate the sequence 1,2,3,3,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,8... I must OEIS for solving this part . The sequence turns out to be the integer part of the square root of 4n + 1, for n = 1,2,3, ...

How to enable overlap and window size

To account for a match, following Daniel's suggestion , subtract its value from step .

To consider the size of the window, N must be large enough for the spiral to reach a point from the border of the window; and then only the previous points will be saved.

Since it is difficult to calculate in advance how large N , one possible approach is to exponentially increase N in the cycle until it becomes large enough. An exponential increase ensures that the number of iterations of the loop is small. The code below uses the values ​​2 for N

 %// Data step = 3; %// step size overlap = 1; %// overlap x0 = 20; %// x coordinate of origin y0 = 15; %// y coordinate of origin xmin = 0; %// window boundary: min x xmax = 40; %// window boundary: max x ymax = 30; %// window boundary: min y ymin = 0; %// window boundary: max y %// Computations stepov = step-overlap; N = 8; %// Initial value. Will be increased as needed done = false; while ~done z = x0+1j*y0 + stepov*cumsum([0 -1j.^(-floor(sqrt(4*(0:N)+1))-1)]); %// compute coordinates of N points ind = find(real(z)<xmin | real(z)>xmax | imag(z)<ymin | imag(z)>ymax, 1); %// find index of first z out of boundary, if any done = ~isempty(ind); %// exit if we have reached outside window boundary N = N*2; %// increase number of steps for next try end z = z(1:ind-1); %// only keep values that are within the boundary x = real(z); y = imag(z); 

With the data specified in the code, the resulting schedule is as follows. Note that the last point is (38.0). The next item will be (38, -2), which is outside the window border.

enter image description here

+9
source

Source: https://habr.com/ru/post/984725/


All Articles