How to plot 2 surfaces and their intersection curve in MATLAB? - matlab

I have the equations of two surfaces and I want to plot both of them and highlight their intersection
My code looks like this
t=linspace(-1,1,100);
x=t;
y=t;
z=cos(t.^8+12);
plot3(x,y,z,'g-','linewidth',3)
hold on
[x,y]=meshgrid(-2:2,-2:2);
surf(x,y,z)
And that gives me the plot for the surface z = f(x,y) but I can not figure out how to plot the plane x=y

Subject to editing upon further question details.
Here might be an interesting starting point. Below is a script that uses the patch() function to create the rectangle plane x = y. The patch function takes corner coordinates of a rectangle to plot in the 3D case (x,y,z) coordinates. Unfortunately, I was unable to get the surface plot from the above code. So the intersection discussion is a story for another time.
Function Call:
patch(X_Coordinates,Y_Coordinates,Z_Coordinates,Colour);
%***************************************************%
%3D line plot%
%***************************************************%
x = linspace(-1,1,100);
y = linspace(-1,1,100);
z = cos(x.^8+12);
plot3(x,y,z,'g-','linewidth',3)
%***************************************************%
%3D surface plot%
%***************************************************%
hold on
[x,y] = meshgrid(-2:0.01:2,-2:0.01:2);
z = cos(x.^8+12);
% surf(x,y,z);
%***************************************************%
%Plotting the xy-plane%
%***************************************************%
Plane_Top = 255;
Plane_Bottom = -255;
Plane_Width = 4;
%Using plane attributes to set patch points%
X = [-Plane_Width/2 -Plane_Width/2 Plane_Width/2 Plane_Width/2];
Y = [-Plane_Width/2 -Plane_Width/2 Plane_Width/2 Plane_Width/2];
Z = [Plane_Bottom Plane_Top Plane_Top Plane_Bottom];
%Plotting characteristics%
Colour = [252/255 148/255 3/255];
patch(X,Y,Z,Colour);
view(3);
grid on;
xlabel("X-Axis"); ylabel("Y-Axis");
title("Plotting the XY-Plane and Line Function");
Using MATLAB version: R2019b

Related

How to 3D plot a parametric curve WITH orthographic projections?

How to generate a 3D plot of a parametric curve with the orthographic projections on the inside walls of the 3D plot, as shown in this video?
I can generate a 3D plot of the curve using the plot3 function but I am lost how to create the blue orthographic projections on the inner walls of the cube ...and the red dashed lines.
P.S.
Also, how to generate the 3 separate "Coordinate Functions" plots (not shown on the diagram above but shown in the video) ...and how to synchronize them together during the animation?
Well, this took a lot of time to write.
clear;clc;close all
t = 0:0.01:6;
x = cos(5*t);
y = sin(5*t);
z = t;
%for x,y,z as as general function of t
xmin = min(x);
xmax = max(x);
ymin = min(y);
ymax = max(y);
zmin = min(z);
zmax = max(z);
orangeColorRGB = [0.8500 0.3250 0.0980];
%3D plot
plot3DSubplot = subplot(3,2,[1 3 5]);
view(3)
grid on
title('Parametric curve in R^3')
xlabel('x(t)')
ylabel('y(t)')
zlabel('z(t)')
xyProjectionOffset = -0.5;
xzProjectionOffset = 1.5;
yzProjectionOffset = 1.5;
xlim([xmin max(xmax, yzProjectionOffset)])
ylim([ymin max(ymax, xzProjectionOffset)])
zlim([min(zmin ,xyProjectionOffset) zmax])
curve3D_marker = animatedline(plot3DSubplot,x(1),y(1),z(1),'Marker','o','Color','magenta'); %marker in 3D
curve3D = animatedline(plot3DSubplot, x(1),y(1),z(1),'Color','magenta','LineStyle','-','LineWidth',2); %3D curve
curve3D_projectedToXY = animatedline(plot3DSubplot,x(1),y(1),xyProjectionOffset,'Color','blue','LineStyle','-','LineWidth',2); %projection on xy
curve3D_projectionStraightLineToXY = animatedline(plot3DSubplot,x(1),y(1),z(1),'Color',orangeColorRGB,'LineStyle','--','LineWidth',2); %projection on xy
curve3D_projectedToXZ = animatedline(plot3DSubplot,x(1),xzProjectionOffset,z(1),'Color','blue','LineStyle','-','LineWidth',2); %projection on xz
curve3D_projectionStraightLineToXZ = animatedline(plot3DSubplot,x(1),y(1),z(1),'Color',orangeColorRGB,'LineStyle','--','LineWidth',2); %projection on xy
curve3D_projectedToYZ = animatedline(plot3DSubplot,yzProjectionOffset,y(1),z(1),'Color','blue','LineStyle','-','LineWidth',2); %projection on yz
curve3D_projectionStraightLineToYZ = animatedline(plot3DSubplot,x(1),y(1),z(1),'Color',orangeColorRGB,'LineStyle','--','LineWidth',2); %projection on xy
%x plot
xPlot = subplot(3,2,2);
grid on
title('Coordinates')
ylabel('cos(5t)')
xlim([t(1) t(end)])
ylim([xmin xmax])
xCoordinate = animatedline(xPlot,t(1),x(1),'Color','blue');
xCoordinate_projectedValue = animatedline(xPlot,t(1),x(1),'Color',orangeColorRGB,'LineStyle','--');
xCoordinateMarker = animatedline(xPlot,t(1),x(1),'Color','blue','Marker','o');
%y plot
yPlot = subplot(3,2,4);
grid on
ylabel('sin(5t)')
xlim([t(1) t(end)])
ylim([ymin ymax])
yCoordinate = animatedline(yPlot,t(1),y(1),'Color','blue');
yCoordinate_projectedValue = animatedline(yPlot,t(1),y(1),'Color',orangeColorRGB,'LineStyle','--');
yCoordinateMarker = animatedline(yPlot,t(1),y(1),'Color','blue','Marker','o');
%z plot
zPlot = subplot(3,2,6);
grid on
ylabel('t')
xlim([t(1) t(end)])
ylim([zmin zmax])
zCoordinate = animatedline(zPlot,t(1),z(1),'Color','blue');
zCoordinate_projectedValue = animatedline(zPlot,t(1),z(1),'Color',orangeColorRGB,'LineStyle','--');
zCoordinateMarker = animatedline(zPlot,t(1),z(1),'Color','blue','Marker','o');
for i=2:length(t)
% 3D plot & projections
addpoints(curve3D,x(i),y(i),z(i))
clearpoints(curve3D_marker)
addpoints(curve3D_marker,x(i),y(i),z(i))
%XY projection
addpoints(curve3D_projectedToXY,x(i),y(i),xyProjectionOffset)
clearpoints(curve3D_projectionStraightLineToXY)
addpoints(curve3D_projectionStraightLineToXY,[x(i) x(i)],[y(i) y(i)],[xyProjectionOffset z(i)])
%XZ projection
addpoints(curve3D_projectedToXZ,x(i),xzProjectionOffset,z(i))
clearpoints(curve3D_projectionStraightLineToXZ)
addpoints(curve3D_projectionStraightLineToXZ,[x(i) x(i)],[xzProjectionOffset y(i)],[z(i) z(i)])
%YZ projection
addpoints(curve3D_projectedToYZ,1.5,y(i),z(i))
clearpoints(curve3D_projectionStraightLineToYZ)
addpoints(curve3D_projectionStraightLineToYZ,[yzProjectionOffset x(i)],[y(i) y(i)],[z(i) z(i)])
%2D x plot
addpoints(xCoordinate,t(i),x(i))
clearpoints(xCoordinate_projectedValue)
addpoints(xCoordinate_projectedValue,[t(1) t(i)],[x(i) x(i)])
clearpoints(xCoordinateMarker)
addpoints(xCoordinateMarker,t(i),x(i))
%2D y plot
addpoints(yCoordinate,t(i),y(i))
clearpoints(yCoordinate_projectedValue)
addpoints(yCoordinate_projectedValue,[t(1) t(i)],[y(i) y(i)])
clearpoints(yCoordinateMarker)
addpoints(yCoordinateMarker,t(i),y(i))
%2D z plot
addpoints(zCoordinate,t(i),z(i))
clearpoints(zCoordinate_projectedValue)
addpoints(zCoordinate_projectedValue,[t(1) t(i)],[z(i) z(i)])
clearpoints(zCoordinateMarker)
addpoints(zCoordinateMarker,t(i),z(i))
drawnow
end
Outside the for-loop:
Define your subplots.
Define your lines in a somewhat object-oriented approach. Define lines with animatedline
including their
properties
(color, linewidth etc).
Define lines with animatedline with the intention to use only the marker.
Inside the for-loop:
Add the new points to those lines using addpoints.
Regarding the projections to the xy,yz,xz planes:
The projection of a point (x0,y0,z0) to the xy plane defined by z = -2 is (x0,y0,-2). Therefore when you have a point (x,y,z) you project to the correct plane in the same way.
For the vertical lines that connect the current point to the projection, at every update to the plot remove previous points and redraw them. That's why I first call
clearpoints
to remove any previous points and then addpoints to add 2 points for a straight line from the projection to the actual (x,y,z) point.
For the "marker-lines", again clearpoints and then add the new point.
After adding the points to all the lines, call
drawnow
before the next loop iteration for all lines to be updated at the same time (and for the updates to appear synchronized).

Matlab - Subtracting two 3D figures with surf and min function

I'm trying to make a surf plot that looks like:
So far I have:
x = [-1:1/100:1];
y = [-1:1/100:1];
[X,Y] = meshgrid(x,y);
Triangle1 = -abs(X) + 1.5;
Triangle2 = -abs(Y) + 1.5;
Z = min(Triangle1, Triangle2);
surf(X,Y,Z);
shading flat
colormap winter;
hold on;
[X,Y,Z] = sphere();
Sphere = surf(X, Y, Z + 1.5 );% sphere with radius 1 centred at (0,0,1.5)
hold off;
This code produces a graph that looks like :
A pyramid with square base ([-1,1]x[-1,1]) and vertex at height c = 1.5 above the origin (0,0) is erected.
The top of the pyramid is hollowed out by removing the portion of it that falls within a sphere of radius r=1 centered at the vertex.
So I need to keep the part of the surface of the sphere that is inside the pyramid and delete the rest. Note that the y axis in each plot is different, that's why the second plot looks condensed a bit. Yes there is a pyramid going into the sphere which is hard to see from that angle.
I will use viewing angles of 70 (azimuth) and 35 (elevation). And make sure the axes are properly scaled (as shown). I will use the AXIS TIGHT option to get the proper dimensions after the removal of the appropriate surface of the sphere.
Here is my humble suggestion:
N = 400; % resolution
x = linspace(-1,1,N);
y = linspace(-1,1,N);
[X,Y] = meshgrid(x,y);
Triangle1 = -abs(X)+1.5 ;
Triangle2 = -abs(Y)+1.5 ;
Z = min(Triangle1, Triangle2);
Trig = alphaShape(X(:),Y(:),Z(:),2);
[Xs,Ys,Zs] = sphere(N-1);
Sphere = alphaShape(Xs(:),Ys(:),Zs(:)+2,2);
% get all the points from the pyramid that are within the sphere:
inSphere = inShape(Sphere,X(:),Y(:),Z(:));
Zt = Z;
Zt(inSphere) = nan; % remove the points in the sphere
surf(X,Y,Zt)
shading interp
view(70,35)
axis tight
I use alphaShape object to remove all unwanted points from the pyramid and then plot it without them:
I know, it's not perfect, as you don't see the bottom of the circle within the pyramid, but all my tries to achieve this have failed. My basic idea was plotting them together like this:
hold on;
Zc = Zs;
inTrig = inShape(Trig,Xs(:),Ys(:),Zs(:)+1.5);
Zc(~inTrig) = nan;
surf(Xs,Ys,Zc+1.5)
hold off
But the result is not so good, as you can't really see the circle within the pyramid.
Anyway, I post this here as it might give you a direction to work on.
An alternative to EBH's method.
A general algorithm from subtracting two shapes in 3d is difficult in MATLAB. If instead you remember that the equation for a sphere with radius r centered at (x0,y0,z0) is
r^2 = (x-x0)^2 + (y-y0)^2 + (z-z0)^2
Then solving for z gives z = z0 +/- sqrt(r^2-(x-x0)^2-(y-y0)^2) where using + in front of the square root gives the top of the sphere and - gives the bottom. In this case we are only interested in the bottom of the sphere. To get the final surface we simply take the minimum z between the pyramid and the half-sphere.
Note that the domain of the half-sphere is defined by the filled circle r^2-(x-x0)^2-(y-y0)^2 >= 0. We define any terms outside the domain as infinity so that they are ignored when the minimum is taken.
N = 400; % resolution
z0 = 1.5; % sphere z offset
r = 1; % sphere radius
x = linspace(-1,1,N);
y = linspace(-1,1,N);
[X,Y] = meshgrid(x,y);
% pyramid
Triangle1 = -abs(X)+1.5 ;
Triangle2 = -abs(Y)+1.5 ;
Pyramid = min(Triangle1, Triangle2);
% half-sphere (hemisphere)
sqrt_term = r^2 - X.^2 - Y.^2;
HalfSphere = -sqrt(sqrt_term) + z0;
HalfSphere(sqrt_term < 0) = inf;
Z = min(HalfSphere, Pyramid);
surf(X,Y,Z)
shading interp
view(70,35)
axis tight

Plot 3D line on top of surface plot in Octave

I have plotted a surface from some data. In the same plot I want to have a 3D line (I have the [x,y,z] values for the line I want to plot). When I try to do this using plot3(x,y,z) in the same figure, the line is always below the surface.
Is there any way to fix this? I don't know if this problem appears in Matlab as well.
Minimal example:
figure;
hold all;
y = x = 0:35;
z = ones(1,36).*0.5;
plot3(x,y,z);
[X,Y] = meshgrid(-8:.5:8);
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
surf(Z);
The result (the blue line is below the surface):
To answer part of your question, you don't get this problem in MATLAB with the following code:
figure;
hold all;
x = 0:35;
y = x;
z = ones(1,36).*0.5;
plot3(x,y,z);
[X,Y] = meshgrid(-8:.5:8);
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
surf(Z);
I also had this problem with surf in Octave, so I used the mesh function instead. It is not as pretty, and has different parameters but does allow lines to overlay it:
I created that with the same code as above but replacing surf with:
mesh ((X+8)*2.2, (Y+8)*2.2, Z);
Because mesh needed its parameters to be scaled up. The result is roughly the same.

Interpolate surface of 3D cylinder in Matlab

I have a dataset that describes a point cloud of a 3D cylinder (xx,yy,zz,C):
and I would like to make a surface plot from this dataset, similar to this
In order to do this I thought I could interpolate my scattered data using TriScatteredInterp onto a regular grid and then plot it using surf:
F = TriScatteredInterp(xx,yy,zz);
max_x = max(xx); min_x = min(xx);
max_y = max(yy); min_y = min(yy);
max_z = max(zz); min_z = min(zz);
xi = min_x:abs(stepSize):max_x;
yi = min_y:abs(stepSize):max_y;
zi = min_z:abs(stepSize):max_z;
[qx,qy] = meshgrid(xi,yi);
qz = F(qx,qy);
F = TriScatteredInterp(xx,yy,C);
qc = F(qx,qy);
figure
surf(qx,qy,qz,qc);
axis image
This works really well for convex and concave objects but ends in this for the cylinder:
Can anybody help me as to how to achieve a nicer plot?
Have you tried Delaunay triangulation?
http://www.mathworks.com/help/matlab/ref/delaunay.html
load seamount
tri = delaunay(x,y);
trisurf(tri,x,y,z);
There is also TriScatteredInterp
http://www.mathworks.com/help/matlab/ref/triscatteredinterp.html
ti = -2:.25:2;
[qx,qy] = meshgrid(ti,ti);
qz = F(qx,qy);
mesh(qx,qy,qz);
hold on;
plot3(x,y,z,'o');
I think what you are loking for is the Convex hull function. See its documentation.
K = convhull(X,Y,Z) returns the 3-D convex hull of the points (X,Y,Z),
where X, Y, and Z are column vectors. K is a triangulation
representing the boundary of the convex hull. K is of size mtri-by-3,
where mtri is the number of triangular facets. That is, each row of K
is a triangle defined in terms of the point indices.
Example in 2D
xx = -1:.05:1; yy = abs(sqrt(xx));
[x,y] = pol2cart(xx,yy);
k = convhull(x,y);
plot(x(k),y(k),'r-',x,y,'b+')
Use plot to plot the output of convhull in 2-D. Use trisurf or trimesh to plot the output of convhull in 3-D.
A cylinder is the collection of all points equidistant to a line. So you know that your xx, yy and zz data have one thing in common, and that is that they all should lie at an equal distance to the line of symmetry. You can use that to generate a new cylinder (line of symmetry taken to be z-axis in this example):
% best-fitting radius
% NOTE: only works if z-axis is cylinder's line of symmetry
R = mean( sqrt(xx.^2+yy.^2) );
% generate some cylinder
[x y z] = cylinder(ones(numel(xx),1));
% adjust z-range and set best-fitting radius
z = z * (max(zz(:))-min(zz(:))) + min(zz(:));
x=x*R;
y=y*R;
% plot cylinder
surf(x,y,z)
TriScatteredInterp is good for fitting 2D surfaces of the form z = f(x,y), where f is a single-valued function. It won't work to fit a point cloud like you have.
Since you're dealing with a cylinder, which is, in essence, a 2D surface, you can still use TriScatterdInterp if you convert to polar coordinates, and, say, fit radius as a function of angle and height--something like:
% convert to polar coordinates:
theta = atan2(yy,xx);
h = zz;
r = sqrt(xx.^2+yy.^2);
% fit radius as a function of theta and h
RFit = TriScatteredInterp(theta(:),h(:),r(:));
% define interpolation points
stepSize = 0.1;
ti = min(theta):abs(stepSize):max(theta);
hi = min(h):abs(stepSize):max(h);
[qx,qy] = meshgrid(ti,hi);
% find r values at points:
rfit = reshape(RFit(qx(:),qy(:)),size(qx));
% plot
surf(rfit.*cos(qx),rfit.*sin(qx),qy)

matlab 3d mesh and line plotting

I need help plotting a spiral helix on a cone. For the helix:
x = tsin(6t)
y = tcos(6t)
z = t/3
...and this helix lies on the cone:
z = sqrt(x^2+y^2)/3
I need to plot the mesh plot of the cone and the 3D line plot of the helix on the same
chart.
I think you want a surface plot of the cone first. Try
[X Y] = meshgrid(-1:.01:1);
Z = sqrt(X.^2 + Y.^2)/3;
Then, plot this surface with the surf function, and set some sort of shading and transparency
surf(X,Y,Z), caxis([-1 1]), shading flat, alpha(.5);
This should make a cone shape (you can play with the colors).
Now for the helix, define the vectors as you did
t = 0:.01:1;
x = t.*cos(6*t);
y = t.*sin(6*t);
z = t/3;
Then do
hold on;
This makes it so any other plotting you do will appear on the same figure.
Then finally,
plot3(x,y,z);