How to generate a dome by using points in MATLAB - matlab

I am trying to generate a semi ellipsoidal dome shape by using x, y, z values. In my code below, I define the x,y,z values but I am unable to assign those values to sphere.
How do I resolve this?
clc
x = [65 55.2125 50.8267 46.7398 42.9232 39.3476 35.9815 32.7882 29.7175 26.6833 23.4690 18.7605];
y = x;
z = [0.0,0.9,2.7,5.2,8.2,11.8,15.8,20.3,25.2,30.7,37.1,47.5]; % max height of dome is 47.5
[x,y,z] = sphere(20);
x = x(12:end,:);
y = y(12:end,:);
z = z(12:end,:);
r = 65; % radius of the dome
surf(r.*x,r.*y,r.*z);
axis equal;

It will be simpler or at least more elegant to use the parametric equations of an ellipsoide.
% semi axis parameters
a = 65; % x-axis
b = 65; % y-axis
c = 47.5; % z-axis
%% Parametrisation
%
% To reach each point of the ellipsoide we need two angle:
% phi ∈ [0,2𝜋]
% theta ∈ [0, 𝜋]
%
% But since we only need half of an ellipsoide we can set
% theta ∈ [0,𝜋/2]
[theta,phi] = ndgrid(linspace(0,pi/2,50),linspace(0,2*pi,50));
x = a*sin(theta).*cos(phi);
y = b*sin(theta).*sin(phi);
z = c*cos(theta);
%plot
surf(x,y,z)
axis equal
Result:

You can remove the bottom half of the sphere by assigning NaNs to the approptiate elements of x and y:
[x,y,z] = sphere(20);
I = (z<0);
x(I) = NaN;
y(I) = NaN;
surf(x,y,z)

Related

Would like to generate surface of revolution from bezier curve

I would like to generate surface of revolution from bezier curve. I have made bezier curve in MATLAB but beyond this point I am stuck and do not know how to proceed. Please help.
Below is the code that I have made.
clc
clear
close all
% Name : Savla Jinesh Shantilal
% Bits ID : 2021HT30609
%% Define inout parameters
B = [1,1; 2,3; 4,3; 3,1]; % Creating matrix for polygon vertices
[r,s] = size(B); % getting size of matrix in terms of rows and columns
n = r-1; % n+1 represents number of vertices of the polygon
np = 20; % represents number of equi-distance points on the bezier curve
t = linspace(0,1,np);
%% Plot polygon
for k = 1:n
plot([B(k,1),B(k+1,1)], [B(k,2),B(k+1,2)], 'r', 'LineWidth', 2)
hold on
grid on
end
%% Generate the points on the bezier curve
for j = 1:np
P = [0,0];
for i = 0:n
M(i+1) = (factorial(n)/(factorial(i)*factorial(n-i)))*((t(j))^i)*((1-t(j))^(n-i));
P = P + B(i+1,:)*M(i+1);
end
Q(j,:) = P;
end
%% Plot the bezier curve from the obtained points
for l = 1:np-1
plot([Q(l,1),Q(l+1,1)],[Q(l,2),Q(l+1,2)], '-- b', 'LineWidth', 2);
hold on
end
Usually one can use the built-in cylinder function for monotonically increasing x-values. Here, the bezier curve has non monotonic values from max(x) so we break it to two parts to parameterize it, and then add an angle rotation.
% first define the x and y coordinate from your Q info:
xx = Q(:,1);
yy = Q(:,2);
N = 1e2;
[~, id] = max(xx); % the position where we split
t = linspace(xx(1),xx(id),N);
% Parameterize the function:
t = linspace(0,2*(xx(id)-xx(1)),N);
x = zeros(1, N);
L = t <= ( xx(id)-xx(1) ); % the "Left" side of the curve
x(L) = t(L)+xx(1);
x(~L) = flip(x(L));
%define the r value
r = x;
r(L) = interp1(xx(1:id) ,yy(1:id) , x(L) ); % Left side
r(~L) = interp1(xx(id:end),yy(id:end), x(~L)); % right side (not left)
% define your x values
x = repmat(x', [1 N]);
% define the theta that will perform the rotation
theta = linspace(0,2*pi, N);
% initialize values for y and z
y = zeros(N);
z = zeros(N);
% calculate the y and z values
for i=1:N
y(i,:) = r(i) *cos(theta);
z(i,:) = r(i) *sin(theta);
end
%plot the surface of revolution and the original curve
s = surf(x,y,z);
alpha 0.4
hold on
plot(xx,yy,'k','LineWidth',3)

How to plot a point in some color based on the result of a comparaison, not using a loop?

I'm using random points to determine the area below a curve (Monte-Carlo):
X: 1xn vector of x values for the function
Y: 1xn vector of y = f(x)
RP: mxn matrix of m random y for each x
I would like to split RP into RPA and RPB depending on it being above or below the curve. The idea is then to plot RPA and RPB against X, in different colors. This code doesn't work because RPA and RPB number of columns is not the same than X:
clf
f = #(x) sin(x/10) + cos(x/60); % Function
xMin = 1; xMax = 100; % x interval
X = [xMin:xMax];
Y = f(X);
plot(X,Y), hold on % Plot function
yMin = min(Y); yMax = max(Y); % Axes limits
set(gca, 'xlim', [xMin, xMax], 'ylim', [yMin, yMax])
m = 20; % Random points per x value
RP = rand(m, columns(X)) .* (yMax-yMin) .+ yMin;
% Split points (doesn't work)
RPA = RP(RP>Y);
RPB = RP(RP<=Y);
br = size(RPB) / size(RP) % Ratio of points below
a = (xMax - xMin) * (yMax - yMin) * br % Area below
% Plot points
plot(X, RPA, 'r.') % Above
plot(X, RPB, 'g.') % Below
Is there a possibility to build RPA and RPB so that they are the same size than RP, with the excluded points y being NaN or something similar, which can be counted and plotted?
You gave a good answer yourself. You can build RPA and RPB with strategic NaNs:
% Split points (works!)
RPA = RP;
RPA(RP<=Y) = NaN;
RPB = RP;
RPB(RPB > Y) = NaN;
And than calculating the ration as the not-NaN:
br = sum(~isnan(RPB)) / sum(~isnan(RP)) % Ratio of points below
I get this nice image:

Graphing a Line given x,y, and z angle

I have this piece of MATLAB code that outputs x,y, and z angles and I would like draw a line using them. Can someone point me in the right direction on how to do this?
C = pi;
A = pi;
B = pi;
Z = [cos(C),-sin(C),0; sin(C),cos(C),0; 0,0,1];
X = [1,0,0;0,cos(A),-sin(A);0,sin(A),cos(A)];
Y = [cos(B),0,sin(B);0,1,0;-sin(B),0,cos(B)];
R =(X*Y)*Z;
yaw=atan2(R(2,1),R(1,1))
pitch=atan2(-R(3,1),sqrt(R(3,2)^2+R(3,3)^2))
roll=atan2(R(3,2),R(3,3))
X, Y, and Z are not angles, they are rotation matrices defined by the angles A, B, and C.
it's not clear what's the meaning of "draw a line using them", they are just used to rotate vectors in the 3D space.
here is an example of drawing a rotated vector with them:
% define rotation angles (around the axes)
C = pi/2;
A = pi/4;
B = pi/4;
% generate rotation matrices
Z = [cos(C),-sin(C),0; sin(C),cos(C),0; 0,0,1];
X = [1,0,0;0,cos(A),-sin(A);0,sin(A),cos(A)];
Y = [cos(B),0,sin(B);0,1,0;-sin(B),0,cos(B)];
R =(X*Y)*Z;
% generate a vector and rotate it
v = [1;1;1];
u = R*v;
% plot
quiver3(0,0,0,v(1),v(2),v(3));
hold on
quiver3(0,0,0,u(1),u(2),u(3));
xlim([-1 1]); ylim([-1 1]); zlim([-1 1])
axis square
legend('original','rotated')

Visualize conic with Matlab or Octave

I like to visualize conics with Matlab or Octave. The (general) conic is given by the equation 0 = ax² + bxy + cy² +dxz +eyz+f*z² for a point p=(x,y,z). How can I plot this with Matlab or octave if I know the parameters a,b,c,d,e and f? Or respectively, how can I find the points that satisfy this equation?
Since you are asking for the conics, I understand that you are probably referring to the 2D contours of the general conic equation. I will also cover how to visualize this equation in other different ways.
For all the following examples, I have set the conic constants so that I obtain a hiperboloid.
My code is written in MATLAB syntax. If you are using Octave, it might differ slightly.
Visualizing 2D Conics with CONTOUR
I have isolated z in terms of x and y, from the general conic equation:
z = (1/2)*(-d*x-e*y±sqrt(-4*a*f*x.^2-4*b*f*x.*y-4*c*f*y.^2+d^2*x.^2+2*d*e*x.*y+e^2*y.^2))/f;
Since z is a piecewise function due to (± sqrt), I need to make sure that I plot both hemispheres. I designate z1 for +sqrt, and z2 for -sqrt.
Finally, I plot the contours for z1 and z2 that will yield the set of conics in 2D. This conics will be circles of different radius.
Code:
clear all;
clc;
% Conic constants.
a = 1;
b = 0;
c = 1;
d = 0;
e = 0;
f = -1;
% Value for x and y domain.
v = 10;
% Domain for x and y.
x = linspace(-v,v);
y = linspace(-v,v);
% Generate a 2D mesh with x and y.
[x,y] = meshgrid(x,y);
% Isolate z in terms of x and y.
z1 = (1/2)*(-d*x-e*y+sqrt(-4*a*f*x.^2-4*b*f*x.*y-4*c*f*y.^2+d^2*x.^2+2*d*e*x.*y+e^2*y.^2))/f;
z2 = (1/2)*(-d*x-e*y-sqrt(-4*a*f*x.^2-4*b*f*x.*y-4*c*f*y.^2+d^2*x.^2+2*d*e*x.*y+e^2*y.^2))/f;
% Find complex entries in z.
i = find(real(z1)~=z1);
j = find(real(z2)~=z2);
% Replace complex entries with NaN.
z1(i) = NaN;
z2(j) = NaN;
figure;
subplot(1,2,1);
% Draw lower hemisphere.
contour(x,y,z1,'ShowText','on');
% Adjust figure properties.
title('2D Conics: Lower hemishphere');
xlabel('x-axis');
ylabel('y-axis');
axis equal;
grid on;
box on;
axis([-10 10 -10 10]);
subplot(1,2,2);
% Draw upper hemisphere.
contour(x,y,z2,'ShowText','on');
hold off;
% Adjust figure properties.
title('2D Conics: Upper hemishphere');
xlabel('x-axis');
ylabel('y-axis');
axis equal;
grid on;
box on;
axis([-10 10 -10 10]);
Output:
Visualizing 3D Conics with CONTOUR3
Same as on the previous example, but now we plot the set of conics in 3D.
Code:
clear all;
clc;
% Conic constants.
a = 1;
b = 0;
c = 1;
d = 0;
e = 0;
f = -1;
% Value for x and y domain.
v = 10;
% Domain for x and y.
x = linspace(-v,v);
y = linspace(-v,v);
% Generate a 2D mesh with x and y.
[x,y] = meshgrid(x,y);
% Isolate z in terms of x and y.
z1 = (1/2)*(-d*x-e*y+sqrt(-4*a*f*x.^2-4*b*f*x.*y-4*c*f*y.^2+d^2*x.^2+2*d*e*x.*y+e^2*y.^2))/f;
z2 = (1/2)*(-d*x-e*y-sqrt(-4*a*f*x.^2-4*b*f*x.*y-4*c*f*y.^2+d^2*x.^2+2*d*e*x.*y+e^2*y.^2))/f;
% Find complex entries in z.
i = find(real(z1)~=z1);
j = find(real(z2)~=z2);
% Replace complex entries with NaN.
z1(i) = NaN;
z2(j) = NaN;
% Lower hemisphere. Draw 20 conics.
contour3(x,y,z1,20);
hold on;
% Upper hemisphere. Draw 20 conics.
contour3(x,y,z2,20);
hold off;
% Adjust figure properties.
title('3D Conics');
xlabel('x-axis');
ylabel('y-axis');
zlabel('z-axis');
axis equal;
grid on;
box on;
axis([-10 10 -10 10 -10 10]);
Output:
Visualizing Quadrics with ISOSURFACE
I have isolated f in terms of x, y and z, from the general conic equation, and renamed it to f_eq:
f_eq = -(a*x.^2+b*x.*y+c*y.^2+d*x.*z+e*y.*z)./z.^2;
Finally, I obtain the set of points that satisfy the equation f_eq = f, which is in fact an isosurface that yields a quadric; in this example a hiperboloid.
Code:
clear all;
clc;
% Conic constants.
a = 1;
b = 0;
c = 1;
d = 0;
e = 0;
f = -1;
% Value for x, y and z domain.
v = 10;
% Domain for x ,y and z.
x = linspace(-v,v);
y = linspace(-v,v);
z = linspace(-v,v);
% Generate a 3D mesh with x, y and z.
[x,y,z] = meshgrid(x,y,z);
% Evaluate function (3D volume of data).
f_eq = -(a*x.^2+b*x.*y+c*y.^2+d*x.*z+e*y.*z)./z.^2;
% Draw the surface that matches f_eq = f.
p = patch(isosurface(x,y,z,f_eq,f));
isonormals(x,y,z,f_eq,p)
p.FaceColor = 'red';
p.EdgeColor = 'none';
% Adjust figure properties.
title('Quadric');
xlabel('x-axis');
ylabel('y-axis');
zlabel('z-axis');
axis equal;
grid on;
box on;
axis([-10 10 -10 10 -10 10]);
camlight left;
lighting phong;
Output:

how to produce this particular 3D graph from scalar data in Matlab?

I am trying to produce this graph using Matlab. The built-in ellipsoid function is confusing. For this problem I have two variables ( width and length ) and a constant height.
to make it very simple I want to show that the width is changing while we approach the tip but height is constant. w,x,h are the variables shown in the graph.
I would really appreciate it if someone can help.
The following code gets you a long way, I think. See example output:
I added enought comments that you should be able to take it from here...
% plot ellipsoid in 3D
% height and width of ellipsoid:
e_h = 10;
e_w = 3;
% position where the "quivers" (arrows) go:
q_offset = 2; % distance from axis
q_scale = 0.5; % multiplier to give parabola some size
q_spacing = 0.5; % distance between arrows
q_height = 2.5; % height above XY plane where arrows are drawn
N = 1000; % number of points for drawing
theta = linspace(0, 2*pi, N); % parameter to help drawing ellipse
zerov = zeros(1, N); % array of zeros that I will need
% coordinates of main ellipse:
x = e_w * sin(theta);
y = zeros(size(x));
z = e_h * cos(theta);
% plot main ellipse:
figure;
plot3(x, y, z)
% secondary plot
y2 = q_scale*(e_w.^2 - x.^2) + 2; % offset parabola - what your plot looked like...
hold on
plot3(x, y2, zerov+q_height); % plotting the parabola in the XY plane at height
axis equal % make the plot dimensions isotropic
% add quivers
q_base = -e_w:q_spacing:e_w; % x coordinate; y and z are fixed
q_length = (e_w.^2 - q_base.^2)*q_scale; % length of quiver - just an equation I chose
q0 = zeros(size(q_base)); % another vector I will need multiple times
q1 = ones(size(q_base)); % ditto
% plot the arrows: the "-1" argument means "don't scale"
quiver3(q_base, q0+q_offset, q_height*q1, q0, q_length, q0, -1)