3D body plot in matlab ( volume visualization ) - matlab

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

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)

Sphere with different capacities

I want to create a graphic representation. I have a sphere with radius of 50. I need to create two different filled capacities when it is one-fourth and three-fourths of its total capacity.
What I already have is this:
[x,y,z] = sphere();
r = 50;
surf( r*x, r*y, r*z ) % sphere with radius 50 centred at (0,0,0)
You could create the spere in two parts. Take a look at the following example:
% First part -- 0 to pi/2
theta = linspace(0,pi/2);
phi = linspace(-pi/2,pi/2);
[theta, phi] = meshgrid(theta, phi);
rho = 50;
[x, y, z] = sph2cart(theta, phi, rho);
surf(x,y,z, 'EdgeColor', 'b');
% Second part -- 90 to 360
hold on;
theta = linspace(pi/2,2*pi);
[theta, phi] = meshgrid(theta, phi);
[x, y, z] = sph2cart(theta, phi, rho);
surf(x,y,z, 'EdgeColor', 'r');
hold off;
It produces a graph like the following.

How do i obtain a cross section from a 3D volume?

I want to obtain a 2D slice from the 3D volume in the example (slightly modified) How do I resolve this issue with 3D image visualization? as follows:
% create input image
imageSizeX = 10;
imageSizeY = 10;
imageSizeZ = 10
% generate 3D grid using voxel size = 0.5
[Xq, Yq, Zq] = ndgrid(1:0.5:imageSizeX-1, 1:0.5:imageSizeY-1, 1:0.5:imageSizeZ-1);
% obtain coordinates of all internal vertices, faces, and edges
allCoords = [Xq(:), Yq(:), Zq(:)]; % i need this bit for something very important but not shown in the question.
% Re-generate 3D grid using voxel size = 1
[columnsInImage, rowsInImage, pagesInImage] = ndgrid(1: imageSizeX-1, 1: imageSizeY-1, 1: imageSizeZ-1);
% create the sphere in the image.
centerY = imageSizeY/2;
centerX = imageSizeX/2;
centerZ = imageSizeZ/2;
diameter = 4;
radius = diameter/2;
sphereVoxels = flipud((rowsInImage - centerY).^2 ...
+ (columnsInImage - centerX).^2 + (pagesInImage - centerZ).^2 <= radius.^2);
% change image from logical to numeric labels.
Img = double(sphereVoxels);
for ii = 1:numel(Img)
if Img(ii) == 0
Img(ii) = 2; % intermediate phase voxels
end
end
% specify the desired angle
angle = 30;
% specify desired pixel height and width of solid
width = imageSizeX;
height = imageSizeY;
page = imageSizeZ;
% Find the row point at which theta will be created
y = centerY - ( radius*cos(angle * pi/180) )
% determine top of the solid bar
y0 = max(1, y-height);
% label everything from y0 to y to be = 3 (solid)
Img(1:width, y0:y, 1:page)=3;
%%%%%% Plot the surfaces
[X, Y, Z, C] = build_voxels(Img > 0);
hSurface = patch(X, Y, Z, Img(C),...
'AmbientStrength', 0.5, ...
'BackFaceLighting', 'unlit', ...
'EdgeColor', 'none', ...
'FaceLighting', 'flat');
colormap([1 0 0; 1 1 0]);
axis equal;
axis tight;
view(45, 45);
grid on;
xlabel('x-axis (voxels)');
ylabel('y-axis (voxels)');
zlabel('z-axis (voxels)');
light('Position', get(gca, 'CameraPosition'), 'Style', 'local');
zoom on;
hold on;
Vq = griddata(columnsInImage, rowsInImage, pagesInImage, Img, Xq, Yq, Zq);
figure
h1 = slice(permute(Xq, [2 1 3]),permute(Yq, [2 1 3]),permute(Zq, [2 1 3]), Vq, 5,2,5);
When i run the code, i get an Error message:
"The number of data point locations should equal the number of data point values.
Error in griddata>useScatteredInterp (line 188)
F = scatteredInterpolant(inargs{1}(:),inargs{2}(:),inargs{3}(:), ..."
I want to believe this is so because the size of columnsInImage and size of pagesInImage are not equal to size(P,1) and size(P,3), respectively.
Nonetheless, I also tried to use a vector as follows:
figure
h1 = slice(Img(:,1), Img(:,2), Img(:,3), Img, 5,2,5);
I however still end up with the error message:
"Error using griddedInterpolant
The grid was created from grid vectors that were not strictly monotonic increasing.
Error in interp3 (line 142)
F = griddedInterpolant(X, Y, Z, V, method,extrap);"
Please, guys i need suggestions/ideas on how i could remedy these. Many thanks in advance!..

Multi dimensional (2d better 3d) scatter-plot with different errorbars in matlab

I am trying to program scatterplot with specific errorbars. The only build in function i found is
errorbar()
but this only enables me to make a 2d plot with errorbars in y direction. What i am asking for is a method to plot this with errorbars in x and y direction.
At the end my goal is to make a 3D-scatter-plot with 3 errorbars.
Perfect would be if the resulting image would be a 3d-plot with 3d geometric shapes (coordinate x,y,z with expansion in the dimension proportional to the errorbars) as 'marker'.
I found this page while searching the internet: http://code.izzid.com/2007/08/19/How-to-make-a-3D-plot-with-errorbars-in-matlab.html
But unfortunately they use only one errorbar.
My data is set of 6 arrays each containing either the x,y or z coordinate or the specific standard derivation i want to show as errorbar.
The code you posted looks very easy to adapt to draw all three error bars. Try this (note that I adapted it also so that you can change the shape and colour etc of the plots as you normally would by using varargin, e.g. you can call plot3d_errorbars(...., '.r'):
function [h]=plot3d_errorbars(x, y, z, ex, ey, ez, varargin)
% create the standard 3d scatterplot
hold off;
h=plot3(x, y, z, varargin{:});
% looks better with large points
set(h, 'MarkerSize', 25);
hold on
% now draw the vertical errorbar for each point
for i=1:length(x)
xV = [x(i); x(i)];
yV = [y(i); y(i)];
zV = [z(i); z(i)];
xMin = x(i) + ex(i);
xMax = x(i) - ex(i);
yMin = y(i) + ey(i);
yMax = y(i) - ey(i);
zMin = z(i) + ez(i);
zMax = z(i) - ez(i);
xB = [xMin, xMax];
yB = [yMin, yMax];
zB = [zMin, zMax];
% draw error bars
h=plot3(xV, yV, zB, '-k');
set(h, 'LineWidth', 2);
h=plot3(xB, yV, zV, '-k');
set(h, 'LineWidth', 2);
h=plot3(xV, yB, zV, '-k');
set(h, 'LineWidth', 2);
end
Example of use:
x = [1, 2];
y = [1, 2];
z = [1, 2];
ex = [0.1, 0.1];
ey = [0.1, 0.5];
ez = [0.1, 0.3];
plot3d_errorbars(x, y, z, ex, ey, ez, 'or')

Matlab Create 2d color graph from and interpolate 3d array

I have a matrix that stores x, y and z values as so:
{x1, y1, z1},
{x2, y2, z2},
{x3, y3, z3},
etc...
I need to interpolate the data, and plot in on a 2d graph, with color representing the z value. (example)
Any ideas?
Thanks!
Something like griddata might help you to interpolate:
x = vector(:,1);
y = vector(:,2);
z = vector(:,3);
% Settings
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);
than you just need to change the view of it to only display a certain plane for a fixed value of z
In addition to #Alexandrew answer you can use newer and faster TriScatteredInterp class instead of GRIDDATA. For your exampe you can use 2D IMAGESC instead of 3D MESH.
%# insert the code from #Alexandrew answer to generate meshgrid
[XI, YI] = meshgrid(xi, yi);
TSI = TriScatteredInterp(x,y,z);
ZI = TSI(XI,YI);
imagesc(ZI)
colorbar
If your input matrix is a cell array, you can convert it to a numeric matrix with a = cell2mat(a);