Rotate 3D Surface until Level on MATLAB - matlab

I have yet to start creating the code because I am a little stuck and would like some help to guide me in the right direction. I have to use MATLAB to solve the following issue:
I am given the x,y,z of a 3D surface (about 300 points) that is tilted by an arbitrary angle theta about the x axis and tilted by an arbitrary angle alpha about the y axis. The goal is to tilt the surface so that all of the z values are the same, meaning that the surface is level.
I have tried using rotation matrices, but it has not worked out how I expected. Any suggestions and ideas are greatly appreciated.

It's not elegant, but you could try brute forcing the solution by rotating the graph in set increments about both the x and y axes. Then, simply take the solution where the maximum number of z-coordinates fall within a narrow range. This would mean that the surface is approximately level.

A similar approach but a bit more formal would be to calculated the vector parallel to the surface and knowing the direction of this vector, the rotation parameters got really easy to obtain by c=norm((a,b,c))*cos(angle).
If you have a plane-like surface, you could fit it the to a plane equation a*x+b*y+c*z+d=0 and the vector normal to plane is (a,b,c).
If you have another type of surface -- that is normally what one has -- you may still find the vector of the plane useful, as the plane may be parallel to the surface or may give the direction to compare to made the rotation.
Depending on how you implement it, it will just rotate having point of rotation at the origin (0,0,0). If you plane is far from the origin, both figures will be far from each other. A simple translation can solve it.
With some random point around a plane i got it:
With the code that i used.
n=300;
x= 20.*rand(n,1)-10; %interval
y= 20.*rand(n,1)-10; %interval
%if you want to plot a plane
z=(2*(y+rand(n,1)*0.3)+2*(x+rand(n,1)*0.3)-7)/.4+rand(n,1)*0.3;
figure()
plot3(x,y,z,'.')
hold on
%here i put the plane average data on zero
Centerplane=[mean(x) mean(y) mean(z)];
xc=x-mean(x);
yc=y-mean(y);
zc=z-mean(z);
%get the 'a' and 'b' component of the plane equation (z=a*x +b*y +d)
A=[xc yc]; B=zc;
r=A\B %%%Matlab!
r = vrrotvec( (([r(1) r(2) 1]/norm([r(1) r(2) 1]))),[0 0 1]);
RM=vrrotvec2mat(r); %get the rotation matrix
rdata=[xc,yc,zc]*RM; %rotate data
% put in the proper position back
rt_c_x=rdata(:,1)+mean(x);
rt_c_y=rdata(:,2)+mean(y);
rt_c_z=rdata(:,3)+mean(z);
%and plot
plot3(rt_c_x,rt_c_y,rt_c_z,'c.')
A=[x y]; B=z; %default data
r=A\B %%%Matlab!
r = vrrotvec( (([r(1) r(2) 1]/norm([r(1) r(2) 1]))),[0 0 1]);
RM=vrrotvec2mat(r); %get the rotation matrix
rdata2=[x,y,z]*RM; %rotate data
%and plot
plot3(rdata2(:,1),rdata2(:,2),rdata2(:,3),'g.')
xlabel('X')
ylabel('Y')
zlabel('Z')

Related

Quiver plot in X-Z plane instead of X-Y plane

In MATLAB, quiver will plot a vector field on the x-y plane by default. Is there a way to rotate the image so that is lies on the x-z plane?
I have tried creating a 3D matrix and using commands like streamslice and quiver3. However I have a large number of data points that are irregularly spaced so this results in some inaccurate interpolation and matrices that are too big.
It seems the easiest option would be to use a command like rotate, but that doesn't seem to work with quiver.
You should just use quiver3 and add zero-valued (or whatever constant y you want) inputs in the dimensions that you don't care about
[x,y] = meshgrid(0:0.2:2,0:0.2:2);
u = cos(x).*y;
v = sin(x).*y;
Q = quiver3(x, zeros(size(x)), y, u, zeros(size(u)), v);
axis equal

How can I create a slice of a surface plot to create a line? (Matlab)

Given some function z = f(x,y), I'm interested in creating a (1D) line plot along an arbitrary cutting plane in x,y,z. How do I do this in Matlab? Slice, for example, provides a higher dimensional version (colormap of density data) but this is not what I'm looking for.
E.g.:
z = peaks(50);
surf(z);
%->plot z along some defined plane in x,y,z...
This has been asked before, e.g. here, but this is the answer given is for reducing 3D data to 2D data, and there is no obvious answer on googling. Thanks.
If the normal vector of the plane you want to slice your surface will always lay in the xy plane, then you can interpolate the data over your surface along the x,y coordinates that are in the slicing line, for example, let the plane be defined as going from the point (0,15) to the point (50,35)
% Create Data
z=peaks(50);
% Create x,y coordinates of the data
[x,y]=meshgrid(1:50);
% Plot Data and the slicing plane
surf(z);
hold on
patch([0,0,50,50],[15,15,35,35],[10,-10,-10,10],'w','FaceAlpha',0.7);
% Plot an arbitrary origin axis for the slicing plane, this will be relevant later
plot3([0,0],[15,15],[-10,10],'r','linewidth',3);
Since it is a plane, is relatively easy to obtain the x,y coordinates alogn the slicing plane with linspace, I'll get 100 points, and then interpolate those 100 points into the original data.
% Create x and y over the slicing plane
xq=linspace(0,50,100);
yq=linspace(15,35,100);
% Interpolate over the surface
zq=interp2(x,y,z,xq,yq);
Now that we have the values of z, we need against what to plot them against, that's where you need to define an arbitrary origin axis for your splicing plane, I defined mine at (0,15) for convenience sake, then calculate the distance of every x,y pair to this axis, and then we can plot the obtained z against this distance.
dq=sqrt((xq-0).^2 + (yq-15).^2);
plot(dq,zq)
axis([min(dq),max(dq),-10,10]) % to mantain a good perspective

Plotting a rectangular matrix into a circle

I have generated a rectangular matrix with the azimouth angle changing with rows and the radius changing as you change column. These are meant to represent the relative velocities experienced by a rotating helicopter blade. This produces a matrix called Vmat. I want to plot this to appears in a circle (representing the rotation of the blade)
So far I have tried
[R,T] = meshgrid(r,az);
[x,y] = pol2cart(T,R);
surf(x,y,Vmat(r,az));
which should produce a contoured surface showing velocity as it changes with azimouth angle and radius but it comes up with dimension errors.
I don't mind if it is a 2d contour plot or 3d plot i guess both would be written in a similar way.
Thanks
James
The error is in writing Vmat(r,az), presuming that these are actual values of radius and azimuth, not indexes into your radius and azimuth. If you want to take only a subset of Vmat that's a slightly different matter, but this should work:
[R,T] = meshgrid(r,az); % creates a grid in polar coordinates
[x,y] = pol2cart(T,R); % changes those to cartesian for surf
surf(x,y,Vmat);
Alternatively you could do a contour plot:
h = polar([0 2*pi], [0 max(r)]); % set up polar axes with right scale
delete(h) % remove line
hold on
contour(x,y,Vmat);

Plotting characteristics of antenna radiation in matlab

I need to plot this function
theta = (-pi:0.01:pi);
f = 3*10^9;
c = 299792458;
da = 2;
Here's my code, but I'm not sure it's correct. I dont know where exactly dot mark should be. How to set X-Axis in degress?
beta = (2*pi*f)/c;
const= (da*beta)/2;
j= (cos(theta)+1).*(besselj(1,const*sin(theta))./(const*sin(theta)));
My another question is how to plot this function in polar coordinates.
I made something like this.
polar(theta,j);
Is it possible to rotate that function(by y-axis) to get 3D plot?
Things are quite right to me, although I wouldn't use the symbol j as a variable because (as i does) it is the symbol for the imaginary unit (sqrt(-1)). Doing so you are overriding it, thus things will work until you don't need complex numbers.
You should use element-wise operations such as (.*) when you aim at combining arrays entries element by element, as you correctly did to obtain F(\theta). In fact, cos(theta) is the array of the cosines of the angles contained in theta and so on.
Finally, you can rotate the plot using the command Rotate 3D in the plot window. Nonetheless, you have a 2D curve (F(\theta)) therefore, you will keep on rotating a 2D graph obtaining some kind of perspective view of it, nothing more. To obtain genuine information you need an additional dependent variable (Or I misunderstood your question?).
EDIT: Now I see your point, you want the Surface of revolution around some axis, which I suppose by virtue of the symmetry therein to be theta=0. Well, revolution surfaces can be obtained by a bit of analytic geometry and plotted e.g. by using mesh. Check this out:
% // 2D polar coordinate radius (your j)
Rad= (cos(theta)+1).*(besselj(1,const*sin(theta))./(const*sin(theta)));
Rad = abs(Rad); % // We need its absolute value for sake of clarity
xv = Rad .* cos(theta); % // 2D Cartesian coordinates
yv = Rad .* sin(theta); % // 2D Cartesian coordinates
phi = -pi:.01:pi; % // 3D revolution angle around theta = 0
% // 3D points of the surface
xf = repmat(xv',size(phi));
yf = yv' * cos(phi);
zf = yv' * sin(phi);
mesh(xf,yf,zf)
You can also add graphics effects
this is done via
mesh(xf,yf,zf,'FaceColor','interp','FaceLighting','phong')
camlight right
and a finer angular discretization (1e-3).

Creating a cylinder with axis centered differently

I know Matlab has a function called cylinder to create the points for a cylinder when number of points along the circumference, and the radius length. What if I don't want a unit cylinder, and also don't want it to center at the default axis (for example along z-axis)? What would be the easiest approach to create such a cylinder? Thanks in advance.
The previous answer is fine, but you can get matlab to do more of the work for you (because the results of cylinder separate x,y,z components you need to work a little to do the matrix multiplication for the rotation). To have the center of base of the cylinder at [x0 y0 z0], scaled by [xf yf xf] (use xf=yf unless you want an elliptic cylinder), use:
[x y z] = cylinder;
h=mesh(x*xf+x0,y*yf+y0,z*zf+z0)
If you also want to rotate it so it isn't aligned along the z-axis, use rotate. For example, to rotate about the x-axis by 90 degrees, so it's aligned along the y-axis, use:
rotate(h,[1 0 0],90)
Multiply the points by your favourite combination of a scaling matrix, a translation matrix, and a rotation matrix.