I have two points in my coordinate system (x,y) that I want to know the angle of their line and x-axis.
I use swift for solving this but I can't get the angle.
I need this angle in radians to use it in the following equation:
(x0 + r cos theta, y0 + r sin theta)
r : radius of circle
If you have two points, (x0, y0) and (x1, y1), then the angle of the line joining them (relative to the X axis) is given by:
theta = atan2((y1 - y0), (x1 - x0))
The angle between a line, for reference, let's call this A, defined by two points p1=(x1,y1),p2=(x2, y2) and the x-axis is related to finding the slope/ gradient of the line, A.
# To solve a problem you sometimes have to simplify it and then work up to the full solution"
Let's start by obtaining the gradient of the line A.
The gradient of line A:
slope = (y2 - y1)/(x2 - x1)
for a straight line, that makes an angle theta with the x-axis
tan(theta) = slope = (change in y) / (change in x)
Therefore, theta = tan_inverse (slope)
theta = atan(slope)
Related
I have data which produces a polar plot
where I want to obtain the ratio of the x and y data points (x/y) at each angle then plot the ratio (x/y) versus the angle theta (0,...,360). What is the best way to achieve this?
If you have the rho and theta coordinates for each data point in the plot, you can easily obtain the (x,y) coordinates.
Assuming your polar coordinates are stored in two separate vectors of the same length, 'rho' and 'theta', you could use the following code to extract the respective x and y coordinates:
% theta is expressed in radians
x = rho .* cos(theta) ;
y = rho .* sin(theta) ;
and then compute the ratio as follows:
x_over_y = x ./ y ;
Alternatively, you could do everything in one step, like so:
% theta is expressed in radians
x_over_y = (rho .* cos(theta)) ./ (rho .* sin(theta)) ;
Once you have x_over_y, you can plot it against the theta values:
% theta is expressed in radians
plot(theta*180/pi, x_over_y) ;
Start of line (yellow) and axes are at [xc,yc,zc]
End of line is at [xp,yp,zc].
a,b, c are the angles which line makes in space.
What I need are the angles which line's projections (black line) create on xy,yz and xz planes.
A_y_to_z: Projected line's angle from y axis to z axis on xz plane.
A_z_to_x: Angle from z to x axis on zx plane.
A_x_to_y: Angle from x to y axis on xy plane.
Writing code on Matlab
You can calculate the projection angle to any plane by:
Obtaining the direction of the line, d = (xp - xc, yp - yc, zp - zc)
Normalizing d
Calculating the dot-product with the normal of the plane, dot(d, n) = d.x * n.x + d.y * n.y + d.z * n.z
Calculating the angle to the normal by a = acos(dot(d, n))
Finally obtaining the angle to the plane by taking b = 90 - a (assuming units in degrees - NB most math library functions use radians)
Special case: if dot(d, n) < 0, then the angle a will be greater than 90 degrees. In this case if you only want the acute angle, do b = a - 90 instead of 90 - a.
e.g. To calculate the angle to the xy plane, use n = (0, 0, 1), i.e. the z-axis, which is the normal to that plane.
I want to plot a two-dimensional function of the polar coordinates r and theta in three-dimensional cartesian coordinates. I have that (sorry about bad maths formatting, LaTeX not compatible, it seems)
f(r,theta) = r/2 * (cos(theta - pi/4) + sqrt(1 + 1/2 * cos(2*theta)))
Converting r and theta to cartesian coordinates
x = r * cos(theta), y = r * sin(theta)
Further, the domain is -1<r<1 and 0<theta<2 * pi, which I define by
r = -1:2/50:1;
and
theta = 0:2*pi/50:2*pi;
giving me two vectors of the same dimensions.
I can define the x and y values used for plotting as row vectors by
x = r. * cos(theta);
and
y = r. * sin(theta);
So now I need to define the z values, which will depend on the values of x and y. I thought I should make a 101x101 where each matrix element contains a data point of the final surface. But how should I do this? I thought about using a double for loop:
for i=1:numel(r)
for j=1:numel(theta)
z(i,j) = r(i)/2 .* cos(theta(j) - pi/4) + r(i).*sqrt(1 + 1/2 * cos(2.*theta(j)));
end
end
Then simply surf(z)
While this definitely gives me a surface, it gives me the incorrect surface! I don't know what is happening here. The incorrect surface is given in Figure 1, while the correct one is given in Figure 2. Can anyone help me out? For reference, the correct surface was plotted with GeoGebra, using
A = Function[<expression 1>, <Expresison 2>, <Expression 3>, <var 1>, <start>, <stop>, <var 2>, <start>, <stop>]
Figure 1. Incorrect surface.
Figure 2. Correct surface.
As others have said, you can use meshgrid to make this work.
Here's your example using gridded r and theta and an anonymous function to replace the double loop:
r = -1:2/50:1;
theta = 0:2*pi/50:2*pi;
% define anonymous function f(r,theta)
f = #(r,theta) r/2 .* (cos(theta - pi/4) + sqrt(1 + 1/2 .* cos(2.*theta)));
% generate grids for r and theta
[r, theta] = meshgrid(r,theta);
% calculate z from gridded r and theta
z = f(r,theta);
% convert r,theta to x,y and plot with surf
x = r.*cos(theta);
y = r.*sin(theta);
surf(x,y,z);
You need to use meshgrid to get matrix coordinates if you want to use surf. Taking your x and y (lower case), call
[X,Y] = meshgrid(x,y);
Then X and Y (upper case) will have the same values as you gave it, but laid out in the two-dimensional array as expected by surf. Loop over the indices here and compute your Z, which should have all(size(Z) == size(X)).
https://www.mathworks.com/help/matlab/ref/meshgrid.html
How can I plot a 3D-plane at specific point in Matlab?
Consider the plane equation
Z=(-a * X - b * Y)/c
with following coefficients:
a=0.01; b=0.03; c= 1; d=0.
I want to plot this plane around point (100,100) not at origin (0,0). How it possible to do that?
The code I used:
[X,Y] = meshgrid(x);
a=0.1;
b=0.2;
c=1;
d=0;
Z=(-a * X - b * Y)/c;
surf(X,Y,Z)
shading flat
xlabel('x')
ylabel('y')
zlabel('z')
surf() just plots whatever set of points you give it. To generate those points, you're evaluating the equation at a specific set of coordinates given by X and Y. Therefore you want those points to be centred around the region of interest:
[X, Y] = meshgrid(95:0.1:105); % e.g. +/-5 at resolution of 0.1
or, say, for arbitrary view coordinates m,n:
[X, Y] = meshgrid(m-20:m+20, n-20:n+20); % e.g. +/-20 at resolution of 1
That gives you the view around 100,100 of a plane centred at the origin, which I think is what you're asking for.
Alternatively if you want the plane itself centred at 100,100, then you need that offset in the equation:
Z=(-a * (X - 100) - b * (Y - 100))/c;
so then a view centred on the origin will be equivalent to viewing the original plane around -100,-100.
I have a problem which is twofold:
How do I plot a toroidal surface in MATLAB, given a major radius R and a minor radius a? To avoid confusion, it is the toroidal/poloidal coordinate system, illustrated in the picture below, that I'm talking about.
Now, in any point (phi, theta) on this surface, the minor radius will be distorted by some value that I have stored in a matrix. How do I plot this distorted surface? This might be easy once I have the answer to part 1, but this is my actual goal, so any solution to part 1 that cannot handle this is pretty useless to me.
If anyone can tell me how to make the image appear smaller here, please do =)
Addressing your first question: first you will need to define the coordinates of your torus in toroidal coordinates (seems natural!) and then convert to Cartesian coordinates, which is how MATLAB expects all plots to be constructed (unless you are making a polar plot, of course). So we start of by defining our toroidal coordinates:
aminor = 1.; % Torus minor radius
Rmajor = 3.; % Torus major radius
theta = linspace(-pi, pi, 64) ; % Poloidal angle
phi = linspace(0., 2.*pi, 64) ; % Toroidal angle
We just want a single surface of the torus, so the minor radius is a scalar. We now make a 2D mesh of these coordinates:
[t, p] = meshgrid(phi, theta);
and convert to 3D Cartesian coordinates using the formulas given on the Wikipedia page linked to in the question:
x = (Rmajor + aminor.*cos(p)) .* cos(t);
y = (Rmajor + aminor.*cos(p)) .* sin(t);
z = aminor.*sin(p);
Now we have our torus defined in 3D, we can plot it using surf:
surf(x, y, z)
axis equal
Edit: To address your second question, it depends how you have your distortions stored, but say you have a matrix defined at each toroidal and poloidal point, you will just have to multiply the constant that is the minor radius by the distortion. In the following I create a distortion matrix that is the same dimensions as my toroidal and poloidal angle coordinate matrices and that is normally distributed about a mean of 1 with a FWHM of 0.1:
distortion = 1. + 0.1 * randn(64, 64);
x = (Rmajor + aminor .* distortion .*cos(p)) .* cos(t);
y = (Rmajor + aminor .* distortion .* cos(p)) .* sin(t);
z = aminor.* distortion .* sin(p);
surf(x, y, z)
The result of which is:
You can do this with surf - just create matrices with the x,y,z coordinates. The page you linked to has the trig equations to do this (they are exactly what you'd come up with on your own - I wrote the code below before checking your link).
R = 10;
a = 3;
tx=nan(41,21);
ty=nan(41,21);
tz=nan(41,21);
for j=1:21
for i=1:41
phi = (i-1)*2*pi/40;
theta = (j-1)*2*pi/20;
tx(i,j)= cos(phi) * (R+cos(theta)*a);
ty(i,j)= sin(phi) * (R+cos(theta)*a);
tz(i,j)= sin(theta)*a;
end
end
figure
surf(tx,ty,tz)
axis equal
To distort the surface, replace the constant a with a matrix of the desired minor radius values, and index into that matrix - i.e. tz(i,j) = sin(theta)*distortion(i,j) (but in all dimensions, obviously).