How do I plot a triangle in three dimensions? [duplicate] - matlab

This question already has answers here:
How can I plot a 3D-plane in Matlab?
(4 answers)
Closed 8 years ago.
I would like to draw different triangles by using MATLAB shown in the figure below. Suppose that I have 3 vectors V1=[1 1 1], V2=[-1 1 1], v3=[-2 -2 -2].
How can I draw triangle with these vectors in 3D?
![enter image description here][1]

You can use plot3() like this:
v1=[1 1 1]; v2=[-1 1 1]; v3=[-2 -2 -2];
triangle = [v1(:), v2(:), v3(:), v1(:)];
plot3(triangle(1, :), triangle(2, :), triangle(3, :))
xlabel('x'); ylabel('y'); zlabel('z');
This is the output:
Edit:
This is in order to plot axis:
val = 5; %// Max value of axis
axX = [0 0 0; val 0 0];
axY = [0 0 0; 0 val 0];
axZ = [0 0 0; 0 0 val];
plot3(axX(:, 1), axX(:, 2), axX(:, 3), 'k');
plot3(axY(:, 1), axY(:, 2), axY(:, 3), 'k');
plot3(axZ(:, 1), axZ(:, 2), axZ(:, 3), 'k');
text(val, 0, 0, 'x')
text(0, val, 0, 'y')
text(0, 0, val, 'z')
view(3)
In addition you can make the plot look like your reference image, adding these commands to above code:
set(gca,'xtick',[], 'xcolor', 'w')
set(gca,'ytick',[], 'ycolor', 'w', 'YDir','reverse')
set(gca,'ztick',[], 'zcolor', 'w')
view(45, 30)
This is the result:

Related

How do I resolve this issue with 3D image visualization?

I have this 3D image data that I need to visualize. I have been able to visualize it with 2D slices using imshow3D, but I would like to see the image data in 3D space.
The code I used is as follows (courtesy: How do i create a rectangular mask at known angles?), but I can't tell why it isn't displaying:
% create input image
imageSizeX = 120;
imageSizeY = 200;
imageSizeZ = 50
% generate 3D grid
[columnsInImage, rowsInImage, pagesInImage] = meshgrid(1:imageSizeX, 1:imageSizeY, 1:imageSizeZ);
% create the sphere in the image.
centerY = imageSizeY/2;
centerX = imageSizeX/2;
centerZ = imageSizeZ/2;
diameter = 56;
radius = diameter/2;
sphereVoxels = (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 = 60;
% 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(y0:y, 1:width, 1:page)=3;
% figure, imshow3D(Img);
% axis on;
% grid on;
% display it using an isosurface
fv = isosurface(Img, 0);
patch(fv,'FaceColor',[0 0 .7],'EdgeColor',[0 0 1]); title('Binary volume of a sphere');
view(45,45);
axis tight;
grid on;
xlabel('x-axis [pixels]'); ylabel('y-axis [pixels]'); zlabel('z-axis [pixels]')
Although, the solid bar is not diagonal as the figure attached below, I would expect the image to be something similar to this:
I do not know exactly what I am doing wrong here.
With regard to the problem in your code, it appears that you set points inside the sphere to 1, then set all the remaining points outside the sphere to 2, then a section through the y plane to 3. There is no value of 0 in the volume in this case, so trying to get an isosurface at the value of 0 isn't going to find anything.
However, if you'd rather create a "voxelated" Minecraft-like surface, like in your sample image showing the facets of your voxels, then I have another option for you...
First, I created a set of volume data as you did in your example, with the exception that I omitted the for loop that sets values to 2, and instead set the values of the solid bar to 2.
Next, I made use of a function build_voxels that I've used in a few 3D projects of mine:
function [X, Y, Z, C] = build_voxels(roiMask)
maskSize = size(roiMask);
% Create the ROI surface patches pointing toward -x:
index = find(diff(padarray(roiMask, [1 0 0], 'pre'), 1, 1) > 0);
[X1, Y1, Z1, C1] = make_patches([-1 -1 -1 -1], [1 1 -1 -1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward +x:
index = find(diff(padarray(roiMask, [1 0 0], 'post'), 1, 1) < 0);
[X2, Y2, Z2, C2] = make_patches([1 1 1 1], [-1 -1 1 1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward -y:
index = find(diff(padarray(roiMask, [0 1 0], 'pre'), 1, 2) > 0);
[X3, Y3, Z3, C3] = make_patches([-1 -1 1 1], [-1 -1 -1 -1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward +y:
index = find(diff(padarray(roiMask, [0 1 0], 'post'), 1, 2) < 0);
[X4, Y4, Z4, C4] = make_patches([1 1 -1 -1], [1 1 1 1], [-1 1 1 -1]);
% Create the ROI surface patches pointing toward -z:
index = find(diff(padarray(roiMask, [0 0 1], 'pre'), 1, 3) > 0);
[X5, Y5, Z5, C5] = make_patches([1 1 -1 -1], [-1 1 1 -1], [-1 -1 -1 -1]);
% Create the ROI surface patches pointing toward +z:
index = find(diff(padarray(roiMask, [0 0 1], 'post'), 1, 3) < 0);
[X6, Y6, Z6, C6] = make_patches([-1 -1 1 1], [-1 1 1 -1], [1 1 1 1]);
% Collect patch data:
X = [X1 X2 X3 X4 X5 X6];
Y = [Y1 Y2 Y3 Y4 Y5 Y6];
Z = [Z1 Z2 Z3 Z4 Z5 Z6];
C = [C1 C2 C3 C4 C5 C6];
function [Xp, Yp, Zp, Cp] = make_patches(Xo, Yo, Zo)
[Xp, Yp, Zp] = ind2sub(maskSize, index);
Xp = bsxfun(#plus, Xp, Xo./2).';
Yp = bsxfun(#plus, Yp, Yo./2).';
Zp = bsxfun(#plus, Zp, Zo./2).';
Cp = index(:).';
end
end
This function accepts a 3D matrix, ideally a logical mask of the volume region(s) to create a surface for, and returns 4 4-by-N matrices: X/Y/Z matrices for the voxel face patches and an index matrix C that can be used to get values from the volume data matrix for use in coloring each surface.
Here's the code to render the surfaces:
[X, Y, Z, C] = build_voxels(Img > 0);
rgbData = reshape([1 0 0; 1 1 0], [2 1 3]);
hSurface = patch(X, Y, Z, rgbData(Img(C), :, :), ...
'AmbientStrength', 0.5, ...
'BackFaceLighting', 'unlit', ...
'EdgeColor', 'none', ...
'FaceLighting', 'flat');
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');
And here's the plot:
Note that the sphere and bar surfaces are colored differently since they are labeled with values 1 and 2, respectively, in the volume data Img. These values are extracted from Img using C and then used as an index into rgbData, which contains red (first row) and yellow (second row) RGB triplets. This will create an N-by-1-by-3 matrix of polygon face colors.

How to link plotted positions on a 2-D graph

I have the following code to plot some points on a 2-D x,y coordinate plane:
A=[1, 1; 1, 5; 3, 9; 4, 2; 4, 6; 6, 2; 7, 6; 6, 9; 9, 9];
figure
plot(A(:,1),A(:,2),'r.','LineWidth',2,'MarkerSize',10);
axis([0 10 0 10]);
str=num2str(A);
text(A(:,1)*1.02,A(:,2)*1.02,str);
However, my problem is I will like to link each point to every other point, to form a mesh.
Can anyone please assist with this problem.
You can double loop through the rows of A and draw a line between each pair. If you add these lines to the end of your code:
hold on
for ii = 1:(size(A, 1) - 1)
for jj = (ii + 1):size(A, 1)
line([A(ii, 1), A(jj, 1)], [A(ii, 2), A(jj, 2)])
end
end
You will get the plot with each point connected to all the other points:

Filling an area above a curve with many colors (matlab, surf)

I'm trying to create a figure in matlab that looks like this:
desired figure
I am doing so by: (i) assigning value points to each x,y coordinate, (ii) plotting a surf, and (iii) change the view point so the third axis is not seen. Here is the code:
x = linspace(0, 1, 10);
y = linspace(0, 1, 10);
z = linspace(0, 1, 10);
z = repmat(z, 10, 1);
z = flipud(triu(z));
z(z==0) = nan;
hold off
surf(x, y, z, 'linestyle', 'none')
colormap([linspace(0.39, 1, 20)',linspace(0.58, 0.25, 20)', linspace(0.93, 0.25, 20)']);
colorbar
xlim([x(1) x(end)])
shading interp
view([90 -90])
hold on
plot(x, 1-y, 'linewidth', 2)
I get the following figure: matlab figure I get
As you can see, there a lot of white spaces above the line which I would like to be in color as well. Unfortunately, I cannot add any more grid points as calculating the actual value of the points takes a lot of time (unlike the example above).
Is there a way to have matlab draw colors in those white spaces as well?
Thanks!
You can try to use patch function to create filled polygon.
See http://www.mathworks.com/help/matlab/ref/patch.html
Try the following code:
vert = [0 1;1 1;1 0]; % x and y vertex coordinates
fac = [1 2 3]; % vertices to connect to make triangle
fvc = [1 0 0; 1 1 1; 0 0 1];
patch('Faces',fac,'Vertices',vert,'FaceVertexCData',fvc,'FaceColor','interp');
Result is close:
I was managed to get closer to the desired figure:
close all
x = linspace(0, 1, 10);
y = linspace(0, 1, 10);
%colorbar
xlim([x(1) x(end)])
%Fill rectangle.
vert = [0 0; 1 0; 1 1; 0 1]; % x and y vertex coordinates
fac = [1 2 3 4]; % vertices to connect to make squares
%patch('Faces',fac,'Vertices',vert,'FaceColor','red')
fvc = [1 0 0; 0.6 0.7 1; 0.6 0.7 1; 1 0 0]; %Color of vertices (selected to be close to example image).
patch('Faces',fac,'Vertices',vert,'FaceVertexCData',fvc,'FaceColor','interp')
hold on
%Fill lower triangle with white color.
vert = [0 0;0 1;1 0]; % x and y vertex coordinates
fac = [1 2 3]; % vertices to connect to make triangle
fvc = [1 1 1; 1, 1, 1; 1, 1, 1]; %White color
patch('Faces',fac,'Vertices',vert,'FaceVertexCData',fvc,'FaceColor','interp');
plot(x, 1-y, 'linewidth', 2)
set(gca,'Xtick',[],'Ytick',[]); %Remove tick marks
Result:
Thank you Rotem! I wasn't aware of the patch function and indeed it solved the issue!
The colors on the actual figure I'm trying to achieve are not linear, so I just used patch for all the empty triangles. Here is the adjusted code I use for the simple example (again, this is just a bit more general just to be able to have non linear colors in the area above the curve):
x = linspace(0, 1, 10);
y = linspace(0, 1, 10);
z = linspace(0, 1, 10);
z = repmat(z, 10, 1)+0.1;
z = flipud(triu(z));
z(z==0) = nan;
z = z-0.1;
hold off
surf(x, y, z, 'linestyle', 'none')
colormap([linspace(0.39, 1, 20)',linspace(0.58, 0.25, 20)', linspace(0.93, 0.25, 20)']);
colorbar
xlim([x(1) x(end)])
shading interp
view([90 -90])
hold on
patch_cor_y = kron((length(y):-1:1)', ones(3, 1));
patch_cor_x = kron((1:length(x))', ones(3, 1));
patch_cor = [y(patch_cor_y(2:end-2))', x(patch_cor_x(3:end-1))'];
patch_path = reshape(1:length(patch_cor),3, length(patch_cor)/3)';
patch_col = z(sub2ind(size(z), patch_cor_x(3:end-1), patch_cor_y(2:end-2)));
patch('Faces',patch_path,'Vertices',patch_cor,'FaceVertexCData',patch_col,'FaceColor','interp', 'EdgeColor', 'none');
plot(x, 1-y, 'linewidth', 2)
The figure achieved: figure

matlab plot the matrix with custom colors

Is there a way to specify the colors of the lines when plotting the matrix.
For instance:
// here is my matrix A
A = [13, 3, 4;19, 0, 1;18, 0, 2;19, 0, 1;19, 0, 1];
// when I am plotting it I am not in control of what color each line will be
plot(A)
Using
plot(A, 'r')
just colors everything in red (which is expected)
When trying something like
plot(A, ['r', 'g','b'])
or
plot(A, 'rgb')
does not work (which is not surprising)
So is there any way to specify color for each line?
You can change the color afterwards:
A = [13 3 4;
19 0 1;
18 0 2;
19 0 1;
19 0 1];
p=plot(A);
clrs = jet(numel(p)); % just a Nx3 array of RGB values
for ii=1:numel(p)
set(p(ii),'color',clrs(ii,:));
end
Example:
A=sin(repmat(linspace(0,2*pi,200),20,1)'*diag(linspace(1,2,20)));
% same thing as above
The plot function doesn't provide a way to do it as concisely as in your example. Instead, you can try:
plot(A(:, 1), 'r', A(:, 2), 'g', A(:, 3), 'b');

MatLab - understanding input of plot3

I have a brief question regarding the plot3 function in MatLab.
Say I write the following:
x = [1 1 -1 1];
y = [4 4 4 4];
z = [-1 1 1 -1];
plot3(x,y,z)
Why does MatLab then draw a triangle with vertices in (-1,4-1), (1, 4, -1) and (1,4,1) instead of just plotting the points (-1, 4, -1), (1, 4, -1) and (1, 4, 1)?
The default line style for plot and plot3 is a line, not just points. If you want to plot just the points, use a different style:
plot3(x,y,z,'or'); #% plots red circles at each point