vectores una recorrer programacion multiplicacion matriz matrices llenar imprimir extraer elementos ejemplos datos almacenar arrays matlab loops matrix

arrays - una - recorrer un vector en matlab



Bucle espiral en una matriz desde un punto (2)

Tengo una grilla 2D como sigue y quiero comenzar desde X, Y y guardar la esquina de una ventana (W) y la superposición de (OP). He intentado estos códigos, pero ninguno de ellos se ajusta a mi propósito.

Como se demuestra, quiero comenzar desde un punto al azar (celda negra) y guardar las ubicaciones de las esquinas (mostradas por círculos negros) de cada nueva ventana en un ciclo en espiral. El algoritmo debe usarse para cualquier tamaño de cuadrícula (no necesariamente cuadrada) y cualquier ubicación de punto de inicio.

Matlab también tiene una función (espiral) que es similar a la que yo quiero, pero no requiere una cuadrícula, tamaño de ventana y superposición (OP).

Espero tener la siguiente salida para esta figura: (8,12) (11,12) (11,9) (8,9) (4,9) (4,12) (4,15) ...

Estoy usando los siguientes códigos que comienzan desde una esquina y llenan la matriz paso a paso usando el tamaño W, OP y Matrix definido:

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;

Entonces, de una manera más clara, ¿cómo debería cambiar el código "arriba" para comenzar desde una ubicación (x, y) y llenar en espiral toda la matriz de acuerdo con W, OP y el tamaño (M).

¡Gracias!


Aquí hay un fragmento de código que produce el resultado esperado. Allí donde solo hay cambios menores en el spiral_generic necesarios para satisfacer sus requisitos:

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


El problema básico

Deje que los datos se definan como:

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

Entonces las coordenadas de la espiral se pueden obtener como valores en el plano complejo de la siguiente manera :

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

Por supuesto, las coordenadas xey son entonces

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

Con los valores de ejemplo dados anteriormente, el plot(z,''o-'') (o la plot(x,y,''o-'') ) produce el gráfico

La clave fue generar la secuencia 1,2,3,3,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,8... Estoy en deuda con OEIS por resolver esa parte . La secuencia resulta ser la parte entera de la raíz cuadrada de 4n + 1, para n = 1,2,3, ...

Cómo incluir la superposición y el tamaño de la ventana

Para tener en cuenta la superposición, siguiendo la sugerencia de Daniel , reste su valor del step .

Para considerar el tamaño de ventana, N debe ser lo suficientemente grande para que la espiral llegue a algún punto fuera del límite de la ventana; y luego solo se mantendrían los puntos precedentes.

Dado que es difícil calcular de antemano qué tan grande debe ser N , un posible enfoque es aumentar exponencialmente N en un bucle hasta que sea lo suficientemente grande. El aumento exponencial asegura que el número de iteraciones de bucle será pequeño. El siguiente código usa potencias de 2 para 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);

Con los datos indicados en el código, el gráfico obtenido es el siguiente. Tenga en cuenta que el último punto es (38,0). El siguiente punto sería (38, -2), que está fuera del límite de la ventana.