Plot 3D line on top of surface plot in Octave - matlab

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.

Related

How to plot 2 surfaces and their intersection curve in 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

Plotting Ellipse for complex values in matlab

I am trying to plot the elliptical trajectory of a particle, but my matlab code runs and gives me warning that I m trying to plot imaginary values. How can I remove this error?
My Matlab code is as follows:
% plot of trajectory of the particle in flexural gravity wave
U =5;
t=1;
y1=0;
h=50;
k=2*pi/100;
w=pi;
X= (-80*pi:pi:80*pi);
Y= (-80*pi:pi:80*pi);
H=1;
A= (H/2)*cosh(k*(h+y1))/sinh(k*h);
B= (H/2)*sinh(k*(h+y1))/sinh(k*h);
Y = B.* ((1-((X-U*t)./A).^2).^(1/2));
plot(X,Y);
xlabel('X');
ylabel('Y');
The warning matlab shows is:
Warning: Imaginary parts of complex X and/or Y arguments ignored
Please help me out with this.
If you want to plot imaginary number only,
Please change the code, plot(X,Y); as plot(X,imag(Y)).
In case of real value, plot(X,real(Y)).
If you are interested in magnitude of complex number, plot(X,abs(Y)).
I got the answer to my question.
I can plot it by using general coordinates of the ellipse, ie, using x=acos(t) and y=asin(t). and that really worked.
% plot of trajectory of the particle in flexural gravity wave
U = 5;
t = 1;
y1 = 0;
h = 50;
k = 2*pi/100;
w = pi;
x0 = U*t;
y0 = 0;
H = 1;
A = (H/2)*cosh(k*(h+y1))/sinh(k*h);
B = (H/2)*sinh(k*(h+y1))/sinh(k*h);
z = -2*pi:0.01:2*pi;
X = x0 + A*cos(z);
Y = y0 + B*sin(z);
plot(X,Y);
xlabel('X');
ylabel('Y');

Matlab overplot comet3 on a surf graph

I would like to overplot a comet3 plot over a surf plot, is this possible? hold on did not work.
It should work with the appropriate x,y and z values for the surface you are trying to display.
Simple example:
clc
clear
t = -2*pi:pi/100:2*pi;
x = (cos(2*t).^2).*sin(t);
y = (sin(2*t).^2).*cos(t);
%// Create x and y data for the surface plot
[xx,yy] = meshgrid(x,y);
zz = xx.^2 + yy.^2 - 7;
surf(xx,yy,zz)
hold on
comet3(x,y,t);
output:

How to plot symbolic graph on top of normal plot in Matlab

I've managed to plot on normal graph using the plot function in matlab. I then generated a symbolic function and I managed to plot that using ezplot. I would like to plot the two graphs into one set of x,y axis. I'm not sure how to do this... Here is the code:
a = [50; 100; 150;200;250;300;350];
b = [56;23;22;18;14;15;21];
plot(a,b);
y = polyfit(a,b,2);
syms x;
f = y(1)*x^2 + y(2)*x + y(3);
g = diff(f);
u = solve(g);
subplot(2, 2, 2);
ezplot(f);
Are you familiar with the hold command?
hold command

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)