point projection into yx rotated plane - simulation

I want to simulate depth in a 2D space, If I have a point P1 I suppose that I need to project that given point P1 into a plane x axis rotated "theta" rads clockwise, to get P1'
It seems that P1'.x coord has to be the same as the P1.x and the P1'.y has to b shorter than P1.y. In a 3D world:
cosa = cos(theta)
sina = sin(theta)
P1'.x = P1.x
P1'.y = P1.y * cosa - P1.z * sina
P1'.z = P1.y * sina + P1.z * cosa
Is my P1.z = 0? I tried it and P1'.y = P1.y * cosa doesn't result as expected
Any response would be appreciated, Thanks!
EDIT: What I want, now I rotate camera and translate matrix
EDIT 2: an example of a single line with a start1 point and a end1 point (it's an horizontal line, result expected is a falling line to the "floor" as long as tilt angle increases)
I think it's a sign error or an offset needed (java canvas drawing (0,0) is at top-left), because my new line with a tilt of 0 is the one below of all and with a value of 90º the new line and the original one match

The calculation you are performing is correct if you would like to perform a rotation around the x axis clockwise. If you think of your line as a sheet of paper, a rotation of 0 degrees is you looking directly at the line.
For the example you have given the line is horizontal to the x axis. This will not change on rotation around the x axis (the line and the axis around which it is rotating are parallel to one another). As you rotate between 0 and 90 degrees the y co-ordinates of the line will decrease with P1.y*cos(theta) down to 0 at 90 degrees (think about the piece of paper we have been rotating around it's bottom edge, the x axis, at 90 degrees the paper is flat, and the y axis is perpendicular to the page, thus both edges of the page have the same y co-ordinate, both the side that is the "x-axis" and the opposite parallel side will have y=0).
Thus as you can see for your example this has worked correctly.
EDIT: The reason that multiplying by 90 degrees does not give an exactly zero answer is simply floating point rounding

Related

How can I use the rotation angle and axis to rotate a 3D plane?

I have two planes and know the planes' equations and normals. I want to rotate the points of the blue plane to the orange plane.
I use normals to get the rotation axis and rotation angle and use the Rodrigues' rotation formula to get the rotation matrix.
Multiplying the blue plane's normal by the rotation matrix, it works, the normal is equal to the normal of the orange plane. But when multiplying the points coordinates in the blue plane, the result is not I want. Which part did I ignore?
The blue and orange pane:
After rotation:
blue plane: 0.4273x-0.0075y-0.9041z+13.5950=0;
normal: [0.4273;-0.0075;-0.9041]
orange plane: -0.8111x+0.0019y-0.5849z+7.8024=0;
normal: [-0.811;0.0019;-0.5849]
theta = acos(dot(n_left,n_right)/(norm(n_left)*norm(n_right)));
theta = 1.3876;
axis = cross(n_left,n_right) / norm(cross(n_left,n_right));
axis = (-0.0062;-1.0000;0.0053);
C_matrix = [0 -axis(3) axis(2);
axis(3) 0 -axis(1);
-axis(2) axis(1) 0]; %cross product matrix
R = diag([1 1 1]) + (1-cos(theta))*C_matrix^2 + sin(theta)*C_matrix;
R = [0.1823,-0.0001,-0.9833;
0.0104,0.9999,0.0018;
0.9832,-0.0105,0.1822];
after_rotation = R*blue_points;
one point of blue plane: [-1.1056;-0.2270;14.8712]
after rotation: [14.8197;-0.4144;-1.6222]
one point of orange plane: [-0.2366;-0.4296;14.9292)]
I have a new question, like before. But I still cannot solve perfectly. Could you tell me which part should I fill?
left plane: 0.0456x+0.0016y-0.999z+1.1333=0;
normal: [0.0456,0.0016,-0.999]
right plane: -0.0174x+0.0037y-0.998z+0.9728=0;
normal: [-0.0174,0.0037,-0.9998]
rotation matrix:
R = [0.9980 -0.0001 0.0630
0.0003 1.0000 -0.0021
-0.0630 0.0021 0.9980]
one point on the left plane:[-2.4 -0.6446 1.0031]
after rotate: [-2.4012 -0.6446 0.9916]
one point on the right plane:[0.4095 -0.6447 0.9634]
Before rotation:
After rotation:
After rotation, I guess they are in the same plane, but they don't meet. What should I do to make the right side of the yellow plane to meet the left side of the blue plane? Which point should I rotate around? Origin? Thanks a lot for your answer!
Your current rotation performs the rotation about the origin.
If you want the planes to coincide, perform the rotation about a shared point between both planes (assuming the original planes were not parallel).
You can find a shared point from the 2 plane equations:
% Store data about plane
n_left = [0.43273 -0.0075 -0.9041];
n_left = n_left/norm(n_left);
b_left = -13.5950;
n_right = [-0.8111 0.0019 -0.5849];
n_right = n_right/norm(n_right);
b_right = -7.8024;
% Find a point on both planes
shared_point = [n_left; n_right]\[b_left; b_right];
To rotate around this shared_point instead of the origin, perform this operation:
% Transform points
after_rotation = R*(blue_points - shared_point) + shared_point;

Incorrect angle detected between two planes

I want to calculate the angle between 2 planes, Reference plane and Plane1. When I feed the X,Y,Z co-ordinates of pointCloud to the function plane_fit.m (by Kevin Mattheus Moerman), I get the coefficients:
reference_plane_coeff: [-0.13766204 -0.070385590 130.69409]
Plane1_coeff: [0.0044337390 -0.0013548643 95.890228]
Next, I find the intersection of both planes, separately on the XZ plane and get a line equation; ref_line_XZ and plane1_line_XZ respectively. For this, I make the second coefficient 0. (Is this right?)
Aref = reference_plane_coeff(1);
Cref = reference_plane_coeff(3);
ref_line_XZ = [Aref Cref];
Arun = Plane1_coeff(1);
Crun = Plane1_coeff(3);
plane1_line_XZ = [Arun Crun];
angle_XZ = acos( dot(ref_line_XZ,plane1_line_XZ ) / (norm(ref_line_XZ) * norm(plane1_line_XZ )) )
I get the angle_XZ value as 0.0012 rad. i.e. 0.0685 degrees
When I plot these planes on a graph and view it, the angle seems to be much more than 0.0012 degrees. I'm talking about the angle made by the two lines after intersection of both planes with the XZ plane.
What am I doing wrong?
Also, when I tried to find angle between its normals, using:
angle_beta_deg = acosd( dot(reference_plane_coeff,Plane1_coeff) / (norm(reference_plane_coeff) * norm(Plane1_coeff)) )
I got the angle as 0.0713.
On visual inspection of both planes' plots and manually calculating from the plot, angle_XZ should be around 9 degrees.
plane_fit.m (by Kevin Mattheus Moerman)

Dome rotation on arbitrary axis?

Imagine a dome with its centre in the +z direction. What I want to do is to move that dome's centre to a different axis (e.g. 20 degrees x axis, 20 degrees y axis, 20 degrees z axis). How can I do that ? Any hint/tip helps.
Add more info:
I've been dabbling with rotation matrices in wiki for a while. The problem is, it is not a commutative operation. RxRyRz is not same as RzRyRx. So based on the way I multiple it I get a different final results. For example, I want my final projection to have 20 degrees from the original X axis, 20 degrees from original Y axis and 20 degrees from original Z axis. Based on the matrix, giving alpha, beta, gamma values 20 (or its corresponding radian) does NOT result the intended rotation. Am I missing something? Is there a matrix that I can just put the intended angles and get it at the end ?
Using a rotation matrix is an easy way to rotate a collection of (x,y,z) points. You can calculate a rotation matrix for your case using the equations in the general rotation section. Note that figuring out the angle values to plug into those equations can be tricky. Think of it as rotating about one axis at a time and remember that the order of your rotations (order of multiplications) does matter.
An alternative to the general rotation equations is to calculate a rotation matrix from axis and angle. It may be easier for you to define correct parameters with this method.
Update: After perusing Wikipedia, I found a simple way to calculate rotation axis and angle between two vectors. Just fill in your starting and ending vectors for a and b here:
a = [0.0 0.0 1.0];
b = [0.5 0.5 0.0];
vectorMag = #(x) sqrt(sum(x.^2));
rotAngle = acos(dot(a,b) / (vectorMag(a) * vectorMag(b)))
rotAxis = cross(a,b)
rotAxis =
-0.5 0.5 0
rotAngle =
1.5708

Cant Understand Angle of Inclination Calculation using Accelerometer on iPhone

double = rollingZ = acceleration.x;
double = rollingX = acceleration.y;
if (rollingZ > 0.0) {
self.centerCoordinate.inclination = atan(rollingX / rollingZ) + M_PI / 2.0; //LINE 1
}
else if (rollingZ < 0.0) {
self.centerCoordinate.inclination = atan(rollingX / rollingZ) - M_PI / 2.0; // LINE 2
}
else if (rollingX < 0) {
self.centerCoordinate.inclination = M_PI/2.0; //atan returns a radian
}
else if (rollingX >= 0) {
self.centerCoordinate.inclination = 3 * M_PI/2.0;
Im just trying to fully understand this piece of code. I'm looking to build AR apps on the iphone and this code has the function of calculating the angle of inclination of the device using the accelerometer readings.
My understanding is this:
Assuming a portrait orientation if i roll the device forward the x axis of the accelerometer increases towards a negative number of -1.0 (i.e. the device is laid flat with the screen facing up). If i tilt the device towards me the x axis value increases towards a value of 1.0 (until the device is flat facing the ground).
The y axis changes up and down its axis between -1.0 and 0.0 (0 implies the device is horizontal).
If we take some example readings say x = 0.5 (a -45 degree angle, tilting the device towards me) and y = 0.8. If i plotted this on a cartesian coordinate graph with y (rollingX as the vertical axis) and x (rollingZ as the horizontal) and draw a line between them i understand that i can use the reverse tangent function (atan) to calculate the angle. My confusion comes on line 1. I dont understand why that line adds 90 degrees (in radians) to the calculated angle given by the atan function?
I just cant seem to visualise on a graph whats going on. If someone could shed some light on this - that would be much appreciated.
I suppose that these +90 degrees or -90 degrees (in case of negative rollingZ) are added to bring inclination value to widely used Polar coordinate system with angle between -180 and 180 degrees.
Assuming that you have Z line projecting upward when you look at the screen of the device and Z line looking at you from the screen, the result of calculations above vill give you an angle between screen plane and horizontal plane.
Let us assume that acceleration value is positive when it is goes "inside" the device:
1) Device is in vertical position, we have rollingZ = 1, rollingX = 0. The code returns 90 degrees.
2) Device is tilted towards user. Let rollingZ be 0.7 and rollingX be -0.7. This will give us 45 degree angle.
3) Device is in upside-down position, now we have rollingZ = -1 and rollingX = 0, and it is -90 degrees.

Draw Camera Range with Postgis

i am working on some camera data. I have some points which consist of azimuth, angle, distance, and of course coordinate field attributes. In postgresql postgis I want to draw shapes like this with functions.
how can i draw this pink range shape?
at first should i draw 360 degree circle then extracting out of my shape... i dont know how?
I would create a circle around the point(x,y) with your radius distance, then use the info below to create a triangle that has a larger height than the radius.
Then using those two polygons do an ST_Intersection between the two geometries.
NOTE: This method only works if the angle is less than 180 degrees.
Note, that if you extend the outer edges and meet it with a 90 degree angle from the midpoint of your arc, you have a an angle, and an adjacent side. Now you can SOH CAH TOA!
Get Points B and C
Let point A = (x,y)
To get the top point:
point B = (x + radius, y + (r * tan(angle)))
to get the bottom point:
point C = (x + radius, y - (r * tan(angle)))
Rotate your triangle to you azimouth
Now that you have the triangle, you need to rotate it to your azimuth, with a pivot point of A. This means you need point A at the origin when you do the rotation. The rotation is the trickiest part. Its used in computer graphics all the time. (Actually, if you know OpenGL you could get it to do the rotation for you.)
NOTE: This method rotates counter-clockwise through an angle (theta) around the origin. You might have to adjust your azimuth accordingly.
First step: translate your triangle so that A (your original x,y) is at 0,0. Whatever you added/subtracted to x and y, do the same for the other two points.
(You need to translate it because you need point A to be at the origin)
Second step: Then rotate points B and C using a rotation matrix. More info here, but I'll give you the formula:
Your new point is (x', y')
Do this for points B and C.
Third step: Translate them back to the original place by adding or subtracting. If you subtracted x last time, add it this time.
Finally, use points {A,B,C} to create a triangle.
And then do a ST_Intersection(geom_circle,geom_triangle);
Because this takes a lot of calculations, it would be best to write a program that does all these calculations and then populates a table.
PostGIS supports curves, so one way to achieve this that might require less math on your behalf would be to do something like:
SELECT ST_GeomFromText('COMPOUNDCURVE((0 0, 0 10), CIRCULARSTRING(0 10, 7.071 7.071, 10 0), (10 0, 0 0))')
This describes a sector with an origin at 0,0, a radius of 10 degrees (geographic coordinates), and an opening angle of 45°.
Wrapping that with additional functions to convert it from a true curve into a LINESTRING, reduce the coordinate precision, and to transform it into WKT:
SELECT ST_AsText(ST_SnapToGrid(ST_CurveToLine(ST_GeomFromText('COMPOUNDCURVE((0 0, 0 10), CIRCULARSTRING(0 10, 7.071 7.071, 10 0), (10 0, 0 0))')), 0.01))
Gives:
This requires a few pieces of pre-computed information (the position of the centre, and the two adjacent vertices, and one other point on the edge of the segment) but it has the distinct advantage of actually producing a truly curved geometry. It also works with segments with opening angles greater than 180°.
A tip: the 7.071 x and y positions used in the example can be computed like this:
x = {radius} cos {angle} = 10 cos 45 ≈ 7.0171
y = {radius} sin {angle} = 10 sin 45 ≈ 7.0171
Corner cases: at the antimeridian, and at the poles.