How to bring trisurf plot to 'bottom' and other plots to 'top'? - matlab

In the following snippet, I try to bring the trisurf plot in the background, so the black lines of plot(x,y,':','color','k') are not hidden anymore. I tried uistack(heatmap,'bottom'), but the trisurf plot seemed unimpressed. May anybody provide a hint, how to solve this problem? Thank you and have a nice day! :)
close all;
figure;
hold;
x = [0.1567 0.2334 0.3098 0.3846 0.4138 0.4585 0.5183 0.1605 0.2398 0.3182 0.3952 0.4718 0.5487 0.5789 0.1629 0.2434 0.3236 0.4024 0.4814 0.5595];
x = x.';
y = [78.2114 85.3144 91.3028 95.9450 97.4787 99.4758 101.3201 88.1143 96.4935 103.4136 108.4151 112.5280 115.3430 116.3878 96.3760 105.0047 112.7581 119.3596 124.1293 128.1137];
y = y.';
z = [0.4250 0.5307 0.5916 0.6210 0.6285 0.6276 0.6251 0.4155 0.5185 0.5978 0.6350 0.6510 0.6596 0.6529 0.4024 0.5072 0.5823 0.6274 0.6415 0.6423];
z = z.';
f = #(X,Y) X;
dt = delaunayTriangulation(x,y);
P = dt.Points;
heatmap = trisurf(dt.ConnectivityList, ...
P(:,1), P(:,2), f(P(:,1),P(:,2)), ...
'EdgeColor', 'none', ...
'FaceColor', 'interp', ...
'FaceLighting', 'phong');
for i=1:10:100
x = 0.15:0.01:0.6;
y = i*x+80;
plot(x,y,'--','color','k') % <- these plots should not be hidden by trisurf plot
end
Example for hidden black plot lins with 'FaceAlpha' = 1.0 of trisurf plot
Example for visible black plot lines, because 'FaceAlpha' of trisurf plot was reduced to 0.5.

As I understand you may just use plot3 function instead of plot:
plot3(x,y,ones(size(x)),'--','color','k') % <- these plots should not be hidden by trisurf plot

Related

How to combine a 3D surf plot and a comet3 plot in MATLAB?

I'm writing a code to plot the circular orbit of a satellite (created using comet3() function) around a 3d model of the Earth (created using surf() and set() functions). The problem is that I can't seem to find a way to get them together in the same plot. I have tried using hold on and hold off but that doesn't seem to work either. I'm pasting the MATLAB code below for reference.
Edit: All the other functions like sv_from_coe(), odeset, etc. are working perfectly, the only place I'm facing issue is combining the plots from comet3() and set().
G = 6.67E-11;
Me = 5.976E24;
coe = [6776, 0.0005638, 2.0543, 0.9, 5.549, 0];
[r, v] = sv_from_coe(coe);
rv = [r v];
opt = odeset('RelTol', 1e-6, 'AbsTol', 1e-6);
[t,X] = ode45(#rate, [0 2*1.5*3600], rv, opt);
[x,y,z] = sphere;
r_earth = 6378*1000;
figure
hs1 = surf(x*r_earth,y*r_earth,-z*r_earth);
cdata = imread('1024px-Land_ocean_ice_2048.jpg');
alpha = 1;
hold on
axis equal
comet3(X(:,1), X(:,2), X(:,3))
set(hs1, 'FaceColor', 'texturemap', 'CData', cdata, 'FaceAlpha', alpha, 'EdgeColor', 'none')
You just have to reverse the order, first plot the earth and set the texture. Then use comet3 to animate the trajectory:
% earth
[x,y,z] = sphere;
r_earth = 6378*1000;
% some simple trajectory
phi = 0:0.01:2*pi;
r_orbit = r_earth + 408*1e3; % ISS orbit height
xv = r_orbit * cos(phi);
yv = r_orbit * sin(phi);
zv = zeros(size(yv));
% draw figure
figure(1); clf;
ax = axes;
% first plot the earth and set texture
hs1 = surf(x*r_earth,y*r_earth,-z*r_earth);
alpha = 1;
cdata = imread("Land_ocean_ice_2048.jpg");
set(hs1, 'FaceColor', 'texturemap', 'CData', cdata, 'FaceAlpha', alpha, 'EdgeColor', 'none')
hold on
axis equal
% finally, animate using comet3
comet3(xv,yv,zv)

Matlab Contour Plot Legend in R2014b different from previous versions

I have a matlab script such as this:
x = linspace(-2*pi,2*pi);
y = linspace(0,4*pi);
[X,Y] = meshgrid(x,y);
Z = sin(X)+cos(Y);
Z1 = cos(.5*X) + sin(2*Y);
figure
[c h] = contour(X,Y,Z, '-r')
hold on
[c1 h2] = contour(X,Y,Z1, '-b')
legend('test1', 'test2')
I have two contour plots on the same plot, one shown in red, the other shown in blue. The problem is that the legend doesn't show up in the red and blue colors. In an older version of matlab this worked just fine, but how are you supposed to define the legend in R2014b so that it has red contours next to 'test 1' and blue contours next to 'test 2'?
Someone else had a very similar question on mathcentral but it didn't get answered: http://www.mathworks.com/matlabcentral/answers/164210-how-does-the-contour-plot-with-r2014b-work.
Thanks!
According to the documentation, in R2014b "Colorbar and legend have new properties and do not support some axes properties". As the handle returned by contour is now a Contour object, there is little you can do.
Still, to get the desired behavior you have this awfully ugly hack:
x = linspace(-2*pi,2*pi);
y = linspace(0,4*pi);
[X,Y] = meshgrid(x,y);
Z = sin(X)+cos(Y);
Z1 = cos(.5*X) + sin(2*Y);
figure
hold on
[~, h1] = contour(X,Y,Z, '-r');
h1_ = plot(NaN, '-r');
[~, h2] = contour(X,Y,Z1, '-b');
h2_ = plot(NaN, '-b');
L = legend([h1_ h2_], 'test 1', 'test 2');

how to get vertical gradient fill in matlab plot

I have a function y=x^2 to plot and I would like to fill the area bound by this curve with gradient color from black to red along the y direction. I found the color online
x = linspace(-3, 3, 20)';
f = x.^2;
M = f.^2;
N = length(x);
verts = [x(:), f(:)-max(f); x(:) zeros(N,1)];
q = (1:N-1)';
faces = [q, q+1, q+N+1, q+N];
p = patch('Faces', faces, 'Vertices', verts, 'FaceVertexCData', [M(:); M(:)], 'FaceColor', 'interp', 'EdgeColor', 'none')
This code show me the area bound with the curve to the xaxis, like
But what I want to fill is the WHITE area. So I modify the code as follows
x = linspace(-3, 3, 20)';
f = x.^2;
M = f.^2;
N = length(x);
verts = [x(:), f(:)-max(f); x(:) zeros(N,1)];
q = (1:N-1)';
faces = [q, q+1, q+N+1, q+N];
p = patch('Faces', faces, 'Vertices', verts, 'FaceVertexCData', [M(:); M(:)], 'FaceColor', 'interp', 'EdgeColor', 'none')
this gives me something like the following
it fill the right area but two issues:
the whole image shifted to negative y axis by 9 units
the gradient color was fill from left to right but I want it to fill from bottom to top (vertically)
the colormap was not defined as black to red (I can change that manually though)
The vertical shift happened because of the line
verts = [x(:), f(:)-max(f); x(:) zeros(N,1)];
where f(:) - max(f) is always <=0 . I think you just need to use f(:) to solve that problem.
As for the direction of the shading, since you are defining your patches as vertical strips, they will be colored as vertical strips. If you want horizontal shading, you need to define horizontal patches. Can you figure that out, or do you need help?
EDIT - this code does what you are asking:
figure;
x=linspace(-3, 3, 200);
f = x.^2;
plot(x, f, 'r'); hold on % you could leave this line out... then there is no curve
N = numel(x);
for ii = ceil(N/2):N-1
ix = [ii ii+1 N-ii N-ii+1];
disp(ix)
patch(x(ix), f(ix), f(ii)*256/max(f(:)),'edgecolor', 'none');
end
Here is the output:
One more problem - you are defining the color M as f.^2 - isn't that one round of squaring too many? I think you meant it to be x.^2 (or just F)?
There is a possibly much easier way to achieve almost the same thing... draw the picture as follows:
cplot = repmat(1:256, [256 1])'; % create a 256 square horizontal gradient
xv = linspace(-3, 3, 256); % range of x values
yv = linspace(0, 9, 256); % range of y values
cplot(repmat(xv.^2, [256 1])>repmat(yv', [1 256]))=255; % set area below the curve to white
figure
imagesc(xv, yv, cplot);
Now all you have to do is fix the color scale... you will want the color 255 to be white...

3D body plot in matlab ( volume visualization )

I have little or no experience with volumetric data in MATLAB,
I need to complete next task:
I have 3 vectors ( rows ):
x_ = vector(1:smpl:max_row,1);
y_ = vector(1:smpl:max_row,2);
z_ = vector(1:smpl:max_row,3);
that are samples from large 3 columns array vector with height max_row.
x_ , y_ , z_ are points of 3D figure - surface points of the figure ( volume ). They represent 3D body that should be drawn in matlab.
I created linear grid:
%linear grid
a = -1.1:step:(-1.1+step*(length(x_)-1));
b = -1.1:step:(-1.1+step*(length(y_)-1));
c = -1.1:step:(-1.1+step*(length(z_)-1));
[x,y,z] = meshgrid(-1.1:step:(-1.1+step*(length(x_)-1)));
and also I create array v length(x_)*length(x_)*length(x_) that contains '1' in cells that are of 3D body representation function points and '0' another.
I tryied to make interpolation:
vi = interp3(x,y,z,v,x,y,z,'nearest');
but then vi = v that I've already created.
Now I need to plot the v array on 3D and form 3D body like in
http://www.mathworks.com/help/techdoc/ref/isonormals.html
for example.
I make that next way:
%plotting:
figure
p = patch(isosurface(x,y,z,v,1e-5,'verbose'),'FaceColor','green','EdgeColor','none');
grid on;
isonormals(v,p);
daspect([1 1 1])
view(3);
axis tight;
camproj perspective;
camlight
lighting gouraud
colormap(hsv)
but I get then only small rectangles in place of function '1' that are not connected like in picture that is attached.
I expect solid body enclosed by that points to be plotted.
Does anybody know what is the problem , how to draw 3D body from the x,y,z,v arrays ?
Thanks in advance.
image:
http://imgur.com/Ulegj
Try this, which will be a nice plot (it interpolates a bit though):
x = vector(1:smpl:max_row,1);
y = vector(1:smpl:max_row,2);
z = vector(1:smpl:max_row,3);
% Settings
displaySurface = 1;
displayPoints = 0;
xres = 800; % Resolution, the higher, the smoother
yres = 800;
cm = 'default'; % Colormap
% Axes Limits
xmin = min(x);
ymin = min(y);
xmax = max(x);
ymax = max(y);
xi = linspace(xmin, xmax, xres);
yi = linspace(ymin, ymax, yres);
% Figure
myfig = figure('Position', [200 200 800 600]);
rotate3d off
[XI, YI] = meshgrid(xi, yi);
ZI = griddata(x, y, z, XI, YI, 'cubic');
mesh(XI,YI,ZI);
colormap(cm)
if(displaySurface == 1)
hold on;
surf(XI, YI, ZI, 'EdgeColor', 'none');
end
hold on;
xlabel('x');
ylabel('y');
zlabel('z');
title('Title', 'FontWeight', 'bold');
xlim([xmin xmax])
ylim([ymin ymax])
grid off;
if(displayPoints == 1)
hold on
plot3(x, y, z,'marker','p','markerfacecolor','w','linestyle','none')
hidden off
end

Plot outside axis in Matlab

How to plot something outside the axis with MATLAB? I had like to plot something similar to this figure;
Thank you.
Here is one possible trick by using two axes:
%# plot data as usual
x = randn(1000,1);
[count bin] = hist(x,50);
figure, bar(bin,count,'hist')
hAx1 = gca;
%# create a second axis as copy of first (without its content),
%# reduce its size, and set limits accordingly
hAx2 = copyobj(hAx1,gcf);
set(hAx2, 'Position',get(hAx1,'Position').*[1 1 1 0.9], ...
'XLimMode','manual', 'YLimMode','manual', ...
'YLim',get(hAx1,'YLim').*[1 0.9])
delete(get(hAx2,'Children'))
%# hide first axis, and adjust Z-order
axis(hAx1,'off')
uistack(hAx1,'top')
%# add title and labels
title(hAx2,'Title')
xlabel(hAx2, 'Frequency'), ylabel(hAx2, 'Mag')
and here is the plot before and after:
You can display one axis with the scale you want, then plot your data on another axis which is invisible and large enough to hold the data you need:
f = figure;
% some fake data
x = 0:20;
y = 23-x;
a_max = 20;
b_max = 23;
a_height = .7;
%% axes you'll see
a = axes('Position', [.1 .1 .8 a_height]);
xlim([0 20]);
ylim([0 20]);
%% axes you'll use
scale = b_max/a_max;
a2 = axes('Position', [.1 .1 .8 scale*a_height]);
p = plot(x, y);
xlim([0 20]);
ylim([0 b_max]);
set(a2, 'Color', 'none', 'Visible', 'off');
I had similar problem and I've solved it thanks to this answer. In case of bar series the code is as follows:
[a,b] = hist(randn(1000,1)); % generate random data and histogram
h = bar(b,a); % plot bar series
ylim([0 70]) % set limits
set(get(h,'children'),'clipping','off')% turn off clippings