While drawing a simple unit sphere, I want to rotate it continuously and smoothly.
If we use camorbit or camroll, it actually, rotates then takes a pause, which is not a smooth and continuous rotation.
Any suggestions how to achieve that,
Example:
a simple sphere
figure
sphere
axis equal
for i = 1: 100
camorbit(-5, 0);
% pause(0.01);
drawnow;
end
This is a pretty simple example, however if we use a large data set like wrapping an image data on this sphere and rotate along its axis, it takes some time to render it.
I tired using OpenGL or auto renderer as well as pause (0.01), still it didn't make much difference.
The figure looks like it stops for a while and then moves to the next, which clearly isn't a continuous spherical rotation.
This works decently for me:
figure
sphere
axis equal
axis off
axis vis3d
h_plot = gca;
set(gcf, 'Renderer', 'zbuffer')
while ishandle(h_plot)
camorbit(-5, 0);
drawnow;
end
Related
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
Is there some way of using the surf() style data format to create a heat map?
I have a bunch of scattered data of the form z=f(x,y) (so I used TriScatteredInterp to make it work with meshgrid) and I'd like to visualize z with a heat map. surf already does something similar to what I want, except you have to manually rotate the graph so the view is top down looking at the XY plane.
Basically, I'd like something similar to this:
But surf gives you this by default:
Although the answers here already show how to do this with surf, rendering the 3d surface feels a little like overkill...
pcolor creates the required images directly
(with slightly better results -surf has a gap next to the axes)
code
figure(1)
pcolor(peaks)
figure(2)
surf(peaks)
view(2)
results
pcolor
surf
Adding to Ben's answer, you can use the view command. view allows you to rotate your plot to whatever camera angle you wish.
In general, you call the command like so:
view(AZ, EL);
AZ is the azimuth or horizontal rotation, while EL is the vertical elevation. These are both in degrees.
In your case, once you plot your surf plot, use view(0, 90); before you go to the next subplot. view(0, 90); is the default 2-D view, and this looks directly overhead.
By doing this, you avoid having to rotate your plot manually, then using campos to determine what the camera position is at given your plot. view(0, 90); should give you what you need.
Sidenote
Doing view(2); also gives you the default 2D view, which is equal to view(0, 90); as we talked about. By doing view(3);, this gives you the default 3D view as seen in your plots. FWIW, the default azimuth and elevation for a 3D plot is AZ = -37.5, EL = 30, in degrees of course.
Rotate the view to what you want. Then type campos in the terminal. This shows you the camera position. You can then use campos( your_desired ) to set the camera position for future plots.
For example, the x, y view is usually:
campos([4.0000 2.5000 86.6025])
I have used isosurface function as follows:
isosurface(data);
grid on; axis equal;
colormap copper;
alpha(0.1);
hold on;
How do I make the object rotate on its own?
I'm thinking about two possible solutions:
First, you could redraw the surface a number of times, each time incrementing by a small angle the position. Something like:
for i=1:length_of_animation
[theta,phi,r] = cart2sph(x,y,z);
[x,y,z] = sph2cart(theta+small_angle, phi, r);
delete(h);
h = isosurface(x,y,z)
end
Second, you could move the camera around the plot using the campos function. see mathworks details. This will not make the surface rotate, but will make the view point rotate. Playing with the camera could be a little tricky tho.
I have obtained an x-y plot in Matlab of the sine curve and I wish to rotate this plot by 90 degrees counter clockwise. How do I do this?
In the figure you have plotted, click 'View'->'Camera Toolbar'. Use the Roll Camera icon, and that should allow you to rotate your plot.
EDIT: You can also use the camroll function to do this programatically
camroll(90)
Note, this actually rotates the camera looking at the plot clockwise, not the plot itself. So if you want to rotate the plot 90 degrees counter-clockwise, you will need to rotate the camera 90 degrees clockwise.
Another solution is function view:
view([90 90])
In my opinion this is better solution because there is a problem with labels when one uses camroll function. See code below:
y = rand(1,10);
subplot(211)
plot(1:10,y)
xlabel('x')
ylabel('y')
view([-90 90])
subplot(212)
plot(1:10,y)
xlabel('x')
ylabel('y')
camroll(90)
The best way is to use view([az,el]) that works also for 3d plots.
plot your graph using surf, mesh, etc. and put the graph manually in the desired position using the interactive rotate 3d tool at the tool bar. You see at the left side bottom of the plot the values for the horizontal rotation (azimuth, az) and the vertical elevation (el).
Note the values for az and el and use view([az,el]) to plot.
(When choosing az and el manually it seems like it gives only 2d-plots since the parameters are to be set correctly. Values like [0,1], [0,1], ... normally not work.)
I have an image loaded from disk as a texture, and a same-sized matrix d which has the corresponding depths.
How can I use surf to show me the image as a 3d-model? Simply taking
surf(depthMatrix, img);
doesn't give a nice result since
the camera looks not from the x-y plane in z-direction
It looks fairly black
It doesn't look that smooth although my depth matrix is actually smoothed out when I show it using imshow(depthMatrix, []);
You can use texture mapping to display your image on your surface like so:
surf(depthMatrix,img,... %# depthMatrix is z data, img is an image
'FaceColor','texturemap',... %# Use texture mapping
'EdgeColor','none'); %# Turn off edge coloring
And to address your 3 points:
You can adjust your camera angle with the mouse by pressing the button on the figure, which turns on interactive 3-D rotation. You can also turn interactive rotation on using the function ROTATE3D, or you can change the camera view without the mouse using the function VIEW.
Your plot was looking black because edges are drawn as black lines by default, and there were probably a lot of them.
You can adjust the axis scaling and limits to make your surface appear smoother. For example, axis equal will make data units the same for all 3 axes, so your z axis (which ranges from 0 to 25) will be flattened significantly since your other two axes span ranges in the hundreds. Alternatively, in your call to SURF you can specify x and y data to use for the values on those axes, which can ultimately help you to better adjust the relative scaling between those axes and the z axis.