Rotate linear array into an interpolated circle on a 2D plane?

7 visualizzazioni (ultimi 30 giorni)
I have a 1x9 array (x).
I also have a 9x9 2D matrix (v).
I can easily plot the 1x9 array horizontally and vertically (pictured).
Now, I want to either interpolate or rotate the horizontal/vertical array to have a circle.
The picture below shows what I desire, approximately. This is my best attempt on helping visualize what I want but the result may be slightly different based on the resultant correct code.
The reason I simply can't "fill in the spots" is that I am applying this problem on a much larger scale. For example, instead of a 9x9 matrix, imagine applying this problem to a 200x200 matrix.
My current code is listed here:
v = zeros(9,9);
x = [1 2 3 4 5 4 3 2 1];
v(5,:) = x;
v(:,5) = x';
imagesc(v); colormap jet;

Risposta accettata

Jan
Jan il 15 Nov 2017
n = 200;
x = randperm(n, n); % Arbitrary [1 x n] vector
k = -n/2:n/2; % n+1 values!
k2 = k .^ 2
M = sqrt(k2 + k2.'); % Auto-expand: >= R2016b
% Older versions:
% M = sqrt(bsxfun(@plus, k2, k2.'));
Now M is a matrix with data of a circular shape with values. Now all you have to do is to map the values from 0 (at the center) to n^2/sqrt(2) to your values of x. I assume you do not want all x, but the half only, when the output should be symmetric.
MM = 0.5 * n * M / (n^2 / sqrt(2)) + 1;
Well, then I'm struggling currently, because I cannot try it. You have to subtract a value such that MM has values from 1 to n/2. Then use round() to make them integers, which can be used as indices of x. The values in the corners must be outside the valid range, because the colors are defined for n values only, but the diagonal of the square is longer.
Perhaps you get the rest by your own.

Più risposte (2)

Ashwin Singh
Ashwin Singh il 4 Mag 2020
Here's a super fast way to do it. It's all about reshaping the 2D array into a 1D array, interpolating in 1D, and then reshaping back into a 2D array.
This method generalises well into many dimensions. Here the input is ee and the output is ee_rs, I was trying to interpolate a matrix function of t down rows and r across columns into one with t down rows, x across columns and y into planes.
%% t indep case
r = linspace(0,10,100); %starts at zero, faster to just interp first quadrant then concatenate
input = 95*exp(-(abs(r)/2).^4);
% make array
M = sqrt(r.^2+r'.^2); %dummy matrix of different radii from origin
M = reshape(M, [1,length(r)^2]); %make into 1D list
output = interp1(r, input, M,'spline',0); %interpolate onto 1D list
output = reshape(output, [length(r),length(r)]); %make back into array
%put into all four quadrants
output = [rot90(output); output];
output = [rot90(rot90(output)) output];
%% multidimensional case
ress = [16, 32, 64, 128, 256]; %resolutions
times = []; %for plotting runtime against resolution
for res = ress
%setup
tic
r = linspace(0,10,res);
t = linspace(-4,4,round(res/2));
w = 2;
n_hyps = 10;
amp = 100;
ee = amp*exp(-(abs(r)/w).^n_hyp-t'.^2);
%matrix of plane
M = sqrt(r.^2+r'.^2);
M = reshape(M, [length(r)^2,1]);%reshape
ee_rs = interp1(r', ee', M,'spline',0)';%inerpolate
ee_rs = reshape(ee_rs, [length(t),length(r),length(r)]);%reshape back
times = [times toc];
end
%getting ready for plotting
ee_rs = permute(ee_rs, [3,2,1]);
cen_t = round(length(t)/2);
%concatenating with other quadrants
ee_rs = [rot90(ee_rs); ee_rs];
ee_rs = [rot90(rot90(ee_rs)) ee_rs];
figure
contourf(ee_rs(:,:,cen_t))
%plot runtimes
figure
loglog(ress, times)

Gabriel Parkinson
Gabriel Parkinson il 9 Apr 2020
I was trying to do something very similar. This is how I managed to do it.
It's horribly optimised, but is fine for small datasets, and even something of around 500 by 500 runs in a reasonable amout of time.
If your data doesn't vary around zero, I suggest you apply some check to change all the values outside R so that you can see the relevant data.
close all; clear; clc;
size = 11; %desired dimensions of your output array
radius = 5; %real world size of the array
%define two arrays for x and y positions
x = linspace(-radius,radius,size);
y = linspace(-radius,radius,size);
%combine x and y into a meshgrid for surf function
[X,Y] = meshgrid(x,y);
Z = zeros(size,size); %preallocate the Z array
n1 = 5; %define the size of your data array
n2 = 10001; %define the size of the interpolated array
r = 4;
data = [5 4 3 2 1];%your data
arrayn1 = linspace(0,n1,n1); %
arrayn2 = linspace(0,n1,n2);
thesize = linspace(-r,r,n2);
matr = interp1(arrayn1,data,arrayn2);
disp('Start loop')
for nx = 1:size
for ny = 1:size
for run = 1:n2
if X(nx,ny)^2 + Y(nx,ny)^2 > thesize(run)^2 - 0.01 && X(nx,ny)^2 + Y(nx,ny)^2 < thesize(run)^2 + 0.01
%change the tolerance here depending on the spacing of your original dataset
Z(nx,ny) = matr(run);
end
end
end
disp(['Iteration ',num2str(nx)])
end
plot(arrayn2,matr)
figure
imagesc(Z)
xlabel('X')
ylabel('Y')

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by