Draw circle on surface map Matlab - matlab

I have a surface map created from Northing (X), Easting (y), and Elevation (z) data. I would like to draw a circle around a specific point of a specific radius (say 400 m). The circle has to show up on the surface map. Below is my code for creating the surface map. Any help would be greatly appreciated.
% load the map data
x = elevgrid(:,4); % northing
y = elevgrid(:,5); % easting
z = elevgrid(:,3); % elevation
% Put data onto a grid
[qx,qy] = meshgrid(linspace(min(x),max(x)),linspace(min(y),max(y)));
F = TriScatteredInterp(x,y,z);
qz = F(qx,qy);
% plot in matrix form
surf(qx,qy,qz)
EDIT
Here is a link to a text file of sample data - format being longtitude, latitiude, elevation.

You should be able to do this with plot3 quite easily. See code below for a modified version of your posted code.
I'm not sure about how your sample data is represented (to avoid problems in the future, please try to brew your question down to just the bare essentials, with inputs included).
clear;clc
% create data
xy = -2.5 + 5*gallery('uniformdata',[200 2],0);
x = xy(:,1);
y = xy(:,2);
z = x.*exp(-x.^2-y.^2);
% Put data onto a grid
[qx,qy] = meshgrid(linspace(min(x),max(x)),linspace(min(y),max(y)));
F = scatteredInterpolant(x,y,z);
qz = F(qx,qy);
% plot in matrix form
mesh(qx,qy,qz)
% Plot circle
hold on
r = 0.6;
xp = 0.4;
yp = -1.2;
t = linspace(0,2*pi);
Xp = r*sin(t)+xp;
Yp = r*cos(t)+yp;
plot3(Xp,Yp,F(Xp,Yp))
hold off
BR Magnus

Related

Suppress opening a MATLAB figure

How can I prevent MATLAB from plotting an object and it's transformation? I am trying to rotate a surface and am using a transformation matrix to do it, but I don't want the surface to be plotted at any point, How can I stop it?
% Defines the input variables for the SC at the orbital point.
FoV = deg2rad(FoV);
dist = sqrt(xp^2 + yp^2 + zp^2);
xp = 168.820350140000;
yp = 22703.2636668300
zp = 40331.2908433900
% Generates a line from the orbit point to the centre of the Earth.
xl = linspace(0,xp);
yl = linspace(0,yp);
zl = linspace(0,zp);
% Plots the orbits, orbit point, and Earth object onto the same plot.
plot3(xl,yl,zl);
hold on
scatter3(xp,yp,zp,100,'x','blue')
% Creates a cone for the FoV of the SC that targets the Earth's centre.
[x,y,z] = cylinder([dist*tan(FoV) 0],100);
h = surface(y,dist*z,x);
t = hgtransform('Parent',ax);
set(h,'Parent',t);
x_temp = get(h,'xdata');y_temp = get(h,'ydata');z_temp = get(h,'zdata'); % Duplicates data.
% Determines the coordinate rotations needed to align the cone with the
% orbit point and transforms the cone using object R.
% This if loop calibrates the cone for the 4 quadrants of 2 tangents.
xa = atan(yp/xp);
za = atan(zp/sqrt(xp^2+yp^2));
if xp>0
xa = xa-pi/2;
else
xa = xa+pi/2;
end
R = makehgtform('zrotate',xa,'xrotate',za);
set(t,'Matrix',R);
% Performs the same numerical transformation of the duplicate data and
% creates a sew sets of coordinates that match the transformation.
for i = 1:101
new_first_row(i,:) = (R * [x_temp(1,i);y_temp(1,i);z_temp(1,i);1])';
new_second_row(i,:) = (R * [x_temp(2,i);y_temp(2,i);z_temp(2,i);1])';
end
xr = new_first_row(:,1)'; % Transformed x data.
xr(2,:) = new_second_row(:,1)';
yr = new_first_row(:,2)'; % Transformed y data.
yr(2,:) = new_second_row(:,2)';
zr = new_first_row(:,3)'; % Transformed z data.
zr(2,:) = new_second_row(:,3)';
I want xr, yr, and zr to be calculated, but don't want any plots to be created from this specific script. I later want to create a different plot using this data. If there are any other ways of doing this, please let me know.
As Ander Biguri already said, there are probably better ways than to cram a round peg into a square hole.
As to the question itself: figure visibility is controlled through figure('Visible', 'off'), where 'on' is obviously the default. Don't forget to close your figure though:
fig = figure('Visible', 'off'); % Create invisible figure with handle
h = surface(...); % Your plot
% (...) your other processing
close(fig); % Close figure to save RAM

Matlab: patch area between two curves which depend on the curves values

I'm trying to fill an area between two curves with respect to a function which depends on the values of the curves.
Here is the code of what I've managed to do so far
i=50;
cc = #(xx,x,y) 1./(1+(exp(-xx)/(exp(-x)-exp(-y))));
n_vec = 2:0.1:10;
x_vec = linspace(2,10,length(n_vec));
y_vec = abs(sin(n_vec));
N=[n_vec,fliplr(n_vec)];
X=[x_vec,fliplr(y_vec)];
figure(1)
subplot(2,1,1)
hold on
plot(n_vec,x_vec,n_vec,y_vec)
hp = patch(N,X,'b')
plot([n_vec(i) n_vec(i)],[x_vec(i),y_vec(i)],'linewidth',5)
xlabel('n'); ylabel('x')
subplot(2,1,2)
xx = linspace(y_vec(i),x_vec(i),100);
plot(xx,cc(xx,y_vec(i),x_vec(i)))
xlabel('x'); ylabel('c(x)')
This code produces the following graph
The color code which I've added represent the color coding that each line (along the y axis at a point on the x axis) from the area between the two curves should be.
Overall, the entire area should be filled with a gradient color which depends on the values of the curves.
I've assisted the following previous questions but could not resolve a solution
MATLAB fill area between lines
Patch circle by a color gradient
Filling between two curves, according to a colormap given by a function MATLAB
NOTE: there is no importance to the functional form of the curves, I would prefer an answer which refers to two general arrays which consist the curves.
The surf plot method
The same as the scatter plot method, i.e. generate a point grid.
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px = linspace(min(n_vec), max(n_vec), resolution(1));
py = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px, py);
Generate a logical array indicating whether the points are inside the polygon, but no need to extract the points:
in = inpolygon(px, py, N, X);
Generate Z. The value of Z indicates the color to use for the surface plot. Hence, it is generated using the your function cc.
pz = 1./(1+(exp(-py_)/(exp(-y_vec(i))-exp(-x_vec(i)))));
pz = repmat(pz',1,resolution(2));
Set Z values for points outside the area of interest to NaN so MATLAB won't plot them.
pz(~in) = nan;
Generate a bounded colourmap (delete if you want to use full colour range)
% generate colormap
c = jet(100);
[s,l] = bounds(pz,'all');
s = round(s*100);
l = round(l*100);
if s ~= 0
c(1:s,:) = [];
end
if l ~= 100
c(l:100,:) = [];
end
Finally, plot.
figure;
colormap(jet)
surf(px,py,pz,'edgecolor','none');
view(2) % x-y view
Feel free to turn the image arround to see how it looks like in the Z-dimention - beautiful :)
Full code to test:
i=50;
cc = #(xx,x,y) 1./(1+(exp(-xx)/(exp(-x)-exp(-y))));
n_vec = 2:0.1:10;
x_vec = linspace(2,10,length(n_vec));
y_vec = abs(sin(n_vec));
% generate grid
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px_ = linspace(min(n_vec), max(n_vec), resolution(1));
py_ = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px_, py_);
% extract points
in = inpolygon(px, py, N, X);
% generate z
pz = 1./(1+(exp(-py_)/(exp(-y_vec(i))-exp(-x_vec(i)))));
pz = repmat(pz',1,resolution(2));
pz(~in) = nan;
% generate colormap
c = jet(100);
[s,l] = bounds(pz,'all');
s = round(s*100);
l = round(l*100);
if s ~= 0
c(1:s,:) = [];
end
if l ~= 100
c(l:100,:) = [];
end
% plot
figure;
colormap(c)
surf(px,py,pz,'edgecolor','none');
view(2)
You can use imagesc and meshgrids. See comments in the code to understand what's going on.
Downsample your data
% your initial upper and lower boundaries
n_vec_long = linspace(2,10,1000000);
f_ub_vec_long = linspace(2, 10, length(n_vec_long));
f_lb_vec_long = abs(sin(n_vec_long));
% downsample
n_vec = linspace(n_vec_long(1), n_vec_long(end), 1000); % for example, only 1000 points
% get upper and lower boundary values for n_vec
f_ub_vec = interp1(n_vec_long, f_ub_vec_long, n_vec);
f_lb_vec = interp1(n_vec_long, f_lb_vec_long, n_vec);
% x_vec for the color function
x_vec = 0:0.01:10;
Plot the data
% create a 2D matrix with N and X position
[N, X] = meshgrid(n_vec, x_vec);
% evaluate the upper and lower boundary functions at n_vec
% can be any function at n you want (not tested for crossing boundaries though...)
f_ub_vec = linspace(2, 10, length(n_vec));
f_lb_vec = abs(sin(n_vec));
% make these row vectors into matrices, to create a boolean mask
F_UB = repmat(f_ub_vec, [size(N, 1) 1]);
F_LB = repmat(f_lb_vec, [size(N, 1) 1]);
% create a mask based on the upper and lower boundary functions
mask = true(size(N));
mask(X > F_UB | X < F_LB) = false;
% create data matrix
Z = NaN(size(N));
% create function that evaluates the color profile for each defined value
% in the vectors with the lower and upper bounds
zc = #(X, ub, lb) 1 ./ (1 + (exp(-X) ./ (exp(-ub) - exp(-lb))));
CData = zc(X, f_lb_vec, f_ub_vec); % create the c(x) at all X
% put the CData in Z, but only between the lower and upper bound.
Z(mask) = CData(mask);
% normalize Z along 1st dim
Z = normalize(Z, 1, 'range'); % get all values between 0 and 1 for colorbar
% draw a figure!
figure(1); clf;
ax = axes; % create some axes
sc = imagesc(ax, n_vec, x_vec, Z); % plot the data
ax.YDir = 'normal' % set the YDir to normal again, imagesc reverses it by default;
xlabel('n')
ylabel('x')
This already looks kinda like what you want, but let's get rid of the blue area outside the boundaries. This can be done by creating an 'alpha mask', i.e. set the alpha value for all pixels outside the previously defined mask to 0:
figure(2); clf;
ax = axes; % create some axes
hold on;
sc = imagesc(ax, n_vec, x_vec, Z); % plot the data
ax.YDir = 'normal' % set the YDir to normal again, imagesc reverses it by default;
% set a colormap
colormap(flip(hsv(100)))
% set alpha for points outside mask
Calpha = ones(size(N));
Calpha(~mask) = 0;
sc.AlphaData = Calpha;
% plot the other lines
plot(n_vec, f_ub_vec, 'k', n_vec, f_lb_vec, 'k' ,'linewidth', 1)
% set axis limits
xlim([min(n_vec), max(n_vec)])
ylim([min(x_vec), max(x_vec)])
there is no importance to the functional form of the curves, I would prefer an answer which refers to two general arrays which consist the curves.
It is difficult to achieve this using patch.
However, you may use scatter plots to "fill" the area with coloured dots. Alternatively, and probably better, use surf plot and generate z coordinates using your cc function (See my seperate solution).
The scatter plot method
First, make a grid of points (resolution 500*500) inside the rectangular space bounding the two curves.
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px = linspace(min(n_vec), max(n_vec), resolution(1));
py = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px, py);
figure;
scatter(px(:), py(:), 1, 'r');
The not-interesting figure of the point grid:
Next, extract the points inside the polygon defined by the two curves.
in = inpolygon(px, py, N, X);
px = px(in);
py = py(in);
hold on;
scatter(px, py, 1, 'k');
Black points are inside the area:
Finally, create color and plot the nice looking gradient colour figure.
% create color for the points
cid = 1./(1+(exp(-py)/(exp(-y_vec(i))-exp(-x_vec(i)))));
c = jet(101);
c = c(round(cid*100)+1,:); % +1 to avoid zero indexing
% plot
figure;
scatter(px,py,16,c,'filled','s'); % use size 16, filled square markers.
Note that you may need a fairly dense grid of points to make sure the white background won't show up. You may also change the point size to a bigger value (won't impact performance).
Of cause, you may use patch to replace scatter but you will need to work out the vertices and face ids, then you may patch each faces separately with patch('Faces',F,'Vertices',V). Using patch this way may impact performance.
Complete code to test:
i=50;
cc = #(xx,x,y) 1./(1+(exp(-xx)/(exp(-x)-exp(-y))));
n_vec = 2:0.1:10;
x_vec = linspace(2,10,length(n_vec));
y_vec = abs(sin(n_vec));
% generate point grid
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px_ = linspace(min(n_vec), max(n_vec), resolution(1));
py_ = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px_, py_);
% extract points
in = inpolygon(px, py, N, X);
px = px(in);
py = py(in);
% generate color
cid = 1./(1+(exp(-py)/(exp(-y_vec(i))-exp(-x_vec(i)))));
c = jet(101);
c = c(round(cid*100)+1,:); % +1 to avoid zero indexing
% plot
figure;
scatter(px,py,16,c,'filled','s');

Plot quiver polar coordinates

I want to plot the field distribution inside a circular structure with radius a.
What I expect to see are circular arrows that from the centre 0 go toward a in the radial direction like this
but I'm obtaining something far from this result. I wrote this
x_np = besselzero(n, p, 1); %toolbox from mathworks.com for the roots
R = 0.1:1:a; PHI = 0:pi/180:2*pi;
for r = 1:size(R,2)
for phi = 1:size(PHI,2)
u_R(r,phi) = -1/2*((besselj(n-1,x_np*R(1,r)/a)-besselj(n+1,x_np*R(1,r)/a))/a)*cos(n*PHI(1,phi));
u_PHI(r,phi) = n*(besselj(n,x_np*R(1,r)/a)/(x_np*R(1,r)))*sin(PHI(1,phi));
end
end
[X,Y] = meshgrid(R);
quiver(X,Y,u_R,u_PHI)
where u_R is supposed to be the radial component and u_PHI the angular component. Supposing the formulas that I'm writing are correct, do you think there is a problem with for cycles? Plus, since R and PHI are not with the same dimension (in this case R is 1x20 and PHI 1X361) I also get the error
The size of X must match the size of U or the number of columns of U.
that I hope to solve it if I figure out which is the problem with the cycles.
This is the plot that I get
The problem has to do with a difference in co-ordinate systems.
quiver expects inputs in a Cartesian co-ordinate system.
The rest of your code seems to be expressed in a polar co-ordinate system.
Here's a snippet that should do what you want. The initial parameters section is filled in with random values because I don't have besselzero or the other details of your problem.
% Define initial parameters
x_np = 3;
a = 1;
n = 1;
% Set up domain (Cartesian)
x = -a:0.1:a;
y = -a:0.1:a;
[X, Y] = meshgrid(x, y);
% Allocate output
U = zeros(size(X));
V = zeros(size(X));
% Loop over each point in domain
for ii = 1:length(x)
for jj = 1:length(y)
% Compute polar representation
r = norm([X(ii,jj), Y(ii,jj)]);
phi = atan2(Y(ii,jj), X(ii,jj));
% Compute polar unit vectors
rhat = [cos(phi); sin(phi)];
phihat = [-sin(phi); cos(phi)];
% Compute output (in polar co-ordinates)
u_R = -1/2*((besselj(n-1, x_np*r/a)-besselj(n+1, x_np*r/a))/a)*cos(n*phi);
u_PHI = n*(besselj(n, x_np*r/a)/(x_np*r))*sin(phi);
% Transform output to Cartesian co-ordinates
U(ii,jj) = u_R*rhat(1) + u_PHI*phihat(1);
V(ii,jj) = u_R*rhat(2) + u_PHI*phihat(2);
end
end
% Generate quiver plot
quiver(X, Y, U, V);

Plotting a 3D graph of normalized prices in MatLab

I'm doing Gaussian processes and I calculated a regression per year from a given matrix where each row represents a year , so the code is:
M1 = MainMatrix; %This is the given Matrix
ker =#(x,y) exp(-1013*(x-y)'*(x-y));
[ns, ms] = size(M1);
for N = 1:ns
x = M1(N,:);
C = zeros(ms,ms);
for i = 1:ms
for j = 1:ms
C(i,j)= ker(x(i),x(j));
end
end
u = randn(ms,1);
[A,S, B] = svd(C);
z = A*sqrt(S)*u; % z = A S^.5 u
And I wanna plotting each regression in a Graph 3D as the below:
I know that plot is a ribbon, but I have not idea how can I do that
The desired plot can be generated without the use of ribbon. Just use a surf-plot for all the prices and a fill3-plot for the plane at z=0. The boundaries of the plane are calculated from the actual limits of the figure. Therefore we need to set the limits before plotting the plane. Then just some adjustments are needed to generate almost the same appearance.
Here is the code:
% generate some data
days = (1:100)';
price = days*[0.18,-0.08,0.07,-0.10,0.12,-0.08,0.05];
price = price + 0.5*randn(size(price));
years = 2002+(1:size(price,2));
% prepare plot
width = 0.6;
X = ones(size(price,1),1)*0.5;
X = [-X,X]*width;
figure; hold on;
% plot all 'ribbons'
for i = 1:size(price,2)
h = surf([days,days],X+years(i),[price(:,i),price(:,i)]);
set(h,'MeshStyle','column');
end
% set axis limits
set(gca,'ZLim',[-20,20]);
% plot plane at z=0
limx = get(gca,'XLim');
limy = get(gca,'YLim');
fill3(reshape([limx;limx],1,[]),[flip(limy),limy],zeros(1,4),'g','FaceAlpha',0.2)
% set labels
xlabel('Day of trading')
ylabel('Year')
zlabel('Normalized Price')
% tweak appearance
set(gca,'YTick',years);
set(gca,'YDir','reverse');
view([-38,50])
colormap jet;
grid on;
%box on;
This is the result:
That's a ribbon plot with an additional surface at y=0 which can be drawn with fill3

examples to convert image to polar coordinates do it explicitly - want a slick matrix method

I am trying to convert an image from cartesian to polar coordinates.
I know how to do it explicitly using for loops, but I am looking for something more compact.
I want to do something like:
[x y] = size(CartImage);
minr = floor(min(x,y)/2);
r = linspace(0,minr,minr);
phi = linspace(0,2*pi,minr);
[r, phi] = ndgrid(r,phi);
PolarImage = CartImage(floor(r.*cos(phi)) + minr, floor(r.sin(phi)) + minr);
But this obviously doesn't work.
Basically I want to be able to index the CartImage on a grid.
The polar image would then be defined on the grid.
given a matrix M (just a 2d Gaussian for this example), and a known origin point (X0,Y0) from which the polar transform takes place, we expect that iso-intensity circles will transform to iso-intensity lines:
M=fspecial('gaussian',256,32); % generate fake image
X0=size(M,1)/2; Y0=size(M,2)/2;
[Y X z]=find(M);
X=X-X0; Y=Y-Y0;
theta = atan2(Y,X);
rho = sqrt(X.^2+Y.^2);
% Determine the minimum and the maximum x and y values:
rmin = min(rho); tmin = min(theta);
rmax = max(rho); tmax = max(theta);
% Define the resolution of the grid:
rres=128; % # of grid points for R coordinate. (change to needed binning)
tres=128; % # of grid points for theta coordinate (change to needed binning)
F = TriScatteredInterp(rho,theta,z,'natural');
%Evaluate the interpolant at the locations (rhoi, thetai).
%The corresponding value at these locations is Zinterp:
[rhoi,thetai] = meshgrid(linspace(rmin,rmax,rres),linspace(tmin,tmax,tres));
Zinterp = F(rhoi,thetai);
subplot(1,2,1); imagesc(M) ; axis square
subplot(1,2,2); imagesc(Zinterp) ; axis square
getting the wrong (X0,Y0) will show up as deformations in the transform, so be careful and check that.
I notice that the answer from bla is from polar to cartesian coordinates.
However the question is in the opposite direction.
I=imread('output.png'); %read image
I1=flipud(I);
A=imresize(I1,[1024 1024]);
A1=double(A(:,:,1));
A2=double(A(:,:,2));
A3=double(A(:,:,3)); %rgb3 channel to double
[m n]=size(A1);
[t r]=meshgrid(linspace(-pi,pi,n),1:m); %Original coordinate
M=2*m;
N=2*n;
[NN MM]=meshgrid((1:N)-n-0.5,(1:M)-m-0.5);
T=atan2(NN,MM);
R=sqrt(MM.^2+NN.^2);
B1=interp2(t,r,A1,T,R,'linear',0);
B2=interp2(t,r,A2,T,R,'linear',0);
B3=interp2(t,r,A3,T,R,'linear',0); %rgb3 channel Interpolation
B=uint8(cat(3,B1,B2,B3));
subplot(211),imshow(I); %draw the Original Picture
subplot(212),imshow(B); %draw the result