Related
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
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).
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
I have a function and want to plot it on cylindrical coordinate.
w(z,theta)=sin(n.pi.z/a).sin(m.theta)
The limits of variables are: z=0..a , theta=0..theta_0 and radius of cylinder is R=1.
As a physical sense I can explain that if we in the Cartesian coordinate,
z & theta are x,y axis and w is surface on this rectangular domain. But in cylindrical coordinate z & theta restrict one cylindrical piece of cylinder with radius=1 that w is surface on this domain.
Plotting using cylindrical or spherical coordinates involves several steps:
Create vectors for theta and z:
theta = linspace(0,2*pi);
z = linspace(0,10);
Create a meshgrid from theta and z:
[TH,Z] = meshgrid(theta,z);
Write your function R(TH,Z):
R = sin(Z)+1+5*sin(TH); %// For cylinder it would be simply R = ones(size(Z));
Convert cylindrical coordinates to cartesian:
[x,y,z] = pol2cart(TH,R,Z);
Plot the result using surf, mesh or whatever:
mesh(x,y,z);
axis equal
This is the result you get:
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)