How to place a geographical map underneath a surf plot in Matlab? - matlab

If there is an easier way to do this in general any suggestions would be appreciated.
I have imported a .nc file into Matlab and currently have a surface plot created from the interpolated matrix of data which corresponds to longitudes and latitudes. An alpha scale has been applied to add opacity and now I would like to place a map of said longs and lats beneath it so that it acts as an overlay.
here is the code used to plot where xq,yq is the mesh longitude and latitude grid and newMatrix is the interpolated version of the original matrix. Attached is the top view surf plot which I would like a map of long lat restricted x,y axis beneath (line style or topographic)
f = figure;
ax = axes('Parent',f);
h = surf(xq,yq,newMatrix,'Parent',ax);
set(h, 'edgecolor','none');
view(ax,[0,90]);
alpha color
alpha scaled
grid off
colorbar;
I'm aware of geomap but I'm not sure how it can be used in this way without causing the axis to misalign or just not be applied correctly. Before I was using a contour plot but found it easier to interpolate and plot with surf as per this post: Matlab how to make smooth contour plot?

Related

How do I calculate the area of a projection created by the command "view"?

How do I calculate the area of a projection? For example, using the following code, I get a projection on the X-Z plane.
[x,y,z]=peaks;
surf(x,y,z);
xlabel('x');ylabel('y');zlabel('z')
view([0,0])
X-Z Plane Projection
I want to be able to determine the area of the projection of any surf plot that I create. Is there a command or function for this?
Short answer
polyarea(x(1,:),max(z))+polyarea(x(1,:),min(z))
Explanation
The plot you want to calculate its area is,
In area calculation you need only the borders of the projection,
plot(x(1,:),max(z))
hold on
plot(x(1,:),min(z),'r')
and the output is,
The total area is the summation of both areas (upper border to x axis and lower border to x axis),
>> polyarea(x(1,:),max(z))+polyarea(x(1,:),min(z))
>> 28.5947
If you want to get the projection area at an arbitrary view angle, you can use the viewmtx function to project the surface onto the viewing plane, and then use boundary and polyarea to extract the boundary and calculate the area. Something like this:
% draw your surface
[x,y,z]=peaks;
surf(x,y,z);
xlabel('x');ylabel('y');zlabel('z')
axis equal;
%extract the viewing angle, and calculate the resulting transformation matrix
[az,el]=view(gca);
T= viewmtx(az,el);
% transform the surface points by this transformation matrix
pts= [x(:),y(:),z(:),ones(numel(x),1)]';
tpts= T*pts;
tpts=(tpts(1:3,:))';
% now "tpts" has the surface points projected onto the viewing plane
figure, plot( tpts(:,1), tpts(:,2), 'bo'); axis equal;
% calculate the border of this region, and calculate its area.
border = boundary(tpts(:,1), tpts(:,2));
projectedArea = polyarea(tpts(border,1), tpts(border,2));
This approach is based off of the help for viewmtx.

MATLAB - Plotting a smooth volume from 3D scatter plot data

So I have data in the form [x y z intensity] that I plot on a scatter3 figure with xyz axes. The colour of the data is used to dictate the intensity value. Problem is, using a scatter plot means the data points show up as discrete points. What I need, is a smooth shape - so I guess I need some kind of interpolation between the points?
I've tried using trisurf, but the problem with this one is that it interpolates between points that it shouldn't. So where I should have 'gaps' in my surface, it joins up the edges instead so it fills in the gaps. See the attached pics for clarification.
Does anyone have any suggestions?
The code I use is as below (the commented out scatter3 is what does the scatter plot, the rest does the trisurf):
% Read in data
dataM = csvread('3dDispersion.csv');
% scatter3(dataM(:,1), dataM(:,2), dataM(:,3), 5, dataM(:,4),'filled');
% Plot
hold on;
x = dataM(:,1);
y = dataM(:,2);
freq = dataM(:,3);
tri = delaunay(x,y);
h = trisurf(tri, x, y, freq);
% Make it pretty
% view(-45,30);
view(3);
axis vis3d;
lighting phong;
shading interp;
Use the boundary function in Matlab. This will apply a mesh similar to shrinkwrap over your points. In order to reduce the "gap closers", you will want to increase the "shrink factor".
Try K = boundary(X,Y,Z,0.9)
Where X, Y & Z are the vectors of your data points
https://www.mathworks.com/help/matlab/ref/boundary.html
You can then use trimesh or related surface plotting functions depending on how you want to display it.

Matlab: How can I control the color of a streamtube plot?

I am currently trying to plot 3D streamtubes. I want the tubes to be colored corresponding to their respective velocity (e.g. slow = blue, fast = red).
To be more exact, I have three 3D-matrices containing the velocity in x, y and z direction. The color of the streamtubes should be sqrt(vx^2+vy^2+vz^2). When using streamtube(x,y,z,vx,vy,vz,sx,sy,sz) the tubes are colored according to their z-coordinate which is useless because it's a 3D plot anyway.
Well this wasn't easy (it ought to be a builtin option), but by modifying the CData of each tube (they are each their own graphics object), you can achieve the desired result. Here's an example
load wind
[sx,sy,sz] = meshgrid(80,20:10:50,0:5:15);
h=streamtube(x,y,z,u,v,w,sx,sy,sz);
drawnow
view(3)
axis tight
shading interp;
This gives this picture:
but then doing this:
vel=sqrt(u.^2+v.^2+w.^2); %// calculate velocities
for i=1:length(h)
%// Modify the colour data of each tube
set(h(i),'CData',interp3(x,y,z,vel,get(h(i),'XData')...
,get(h(i),'YData'),get(h(i),'ZData'),'spline'))
end
drawnow
view(3)
axis tight
shading interp;
gives this result
NOTES:
1) I don't know if this is fully correct, I don't know how to test it
2) You have to interpolate the velocity data from the points where it's known onto the vertices of the streamtubes
3) I found the spline interpolation option to work best, but the other options might work better in other cases

Surface plot on top of colour image (x-y plane)

I guess, I've got an colormap issue with Matlab2013. I plot a 3d surface plot with colormap hot and I would like to have in the same plot an bitmap (8bit colour image) on the x-y plane. Plotting both separately from each other works fine but as soon as I plot them in one figure the first surface plot is only black. I guess it is because the RGB image on the x-y plane uses a different colour map. Is there an option in Matlab to plot two different type of images in the same plot?
surf(X,Y,density,'FaceColor','texturemap','Edgecolor','none')
colormap hot
...
%// define the location of the bitmap
xImage = [miX maX; miX maX]; %// The y data for the image corners
yImage = [miY miY; maY maY]; %// The x data for the image corners
zImage = [zDist zDist; zDist zDist]; %// The z data for the image corners
surf(xImage,yImage,zImage,... %// Plot the surface
'CData',RGBImage,...
'FaceColor','texturemap');
Thanks!
Durin
I think this is an issue with the relative scaling of density and zImage. I can replicate this by doing the following:
1) Plot a surf where the third input is n x m which is scaled like some real data (-0.2 to +0.2, for example). This responds to changes in colormap as you'd expect.
2) After hold on, plot another surf where the third input is n x m x 3, like a RGB image, double values scaled between 0 and 1.
This causes the first image to go "dark" (or whatever the lowest color in that particular colormap is). The issue is that they share their CLim, being in the same axis, although the RGBImage doesn't, in fact, reference the colormap.
This is "fixable" by scaling/normalising the first plot (your density values) to be between 0 and 1 (in this case) - although this quick fix is going to give you issues if you then want to add a colorbar. Alternatively, first grab the "CLim" from your axis after plotting the first surf:
trueC = get(gca,'CLim');
Then set it back after you plot the image:
set(gca,'CLim',trueC)

Need help in 3D plot using MATLAB (X,Y,Z,V)

I need to ask help in plotting a 3D volume in MATLAB. My data set includes the X, Y, Z coordinate and corresponding intensity value, V.
I was using pcolor (X,Y,V) and shading interp while i was doing the 2D images but then I got stuck when I am about to create the 3D images. I have tried scatter3, smooth3 and slice but it seems it does not fit the function I need.
My goal is to plot the 3D grid with the corresponding intensity value per coordinate and apply shading interp between these points.
I am really new in 3D plotting and I would really appreciate any help in achieving my goal. Thank you so much!
Here are some example of images that I am trying to create
(source: ndt.net)
(source: www.bam.de)
I have a solution for your first example, in which you show three cross-sections of the volume data. With this solution you can essentially plot several pcolor with different orientations, in one same 3D figure.
First, you need the data for the different slices. This is exactly what you had when you did pcolor(X,Y,V) to plot the cross section in 2D, where X, Y and V are two dimensional matrices. You will also need to create a matrix Z with the z-position of the slice (e.g. Z = zeros(size(X)) + z0). Then you use the command surface(X,Y,Z,V) to plot the cross section image in 3D, where X,Y,Z are the positions, and V is the color (value of the function).
Repeat this procedure for all the other slices, using appropriate X,Y,Z,V matrices for each slice. For slices oriented on other axes you will have to define X,Y,Z accordingly. Remember to use "hold on" after the first surface command, so that all the slices are plotted.
Example:
surface(X1,Y1,Z1,V1); shading interp; hold on
surface(X2,Y2,Z2,V2); shading interp;
surface(X3,Y3,Z3,V3); shading interp;
colormap(jet(2048)); caxis([0,3]); % color axis colormap and scaling
axis equal; xlabel('X'); ylabel('Y'); zlabel('Z') % X,Y,Z scaling and label
Result figure here: