Calculate the coordinate on a sphere - python

How do you calculate the coordinate on a sphere if you know the xy angle and the z angle?
To elaborate:
I have a sphere with a radius, let's say 50cm.
The centre of the sphere is xyz 0,0,0
Lets put the origin point on the surface of the sphere at 0,50,0
If we move x 90 degrees the coordinate would be -50, 0, 0
If we move z 90 then the coordinate would be 0, 0, 50
If we return to the surface origin 0,50,0 and move x: 4 degrees y: 72 degrees and z: 64.6 degrees what is the coordinate?
Rather than just answering the question, how would python calculate it? What is the equation and how would it be coded in python?
EDIT:
Having followed the suggested solution, I've still not getting what I expect.
r is the Radius
alpha is the horizontal angle from the X axis
polar is the vertical angle from the Z axis
from math import cos, sin
def location_on_sphere(radius, alpha, polar):
x = radius * sin(polar) * cos(alpha)
y = radius * sin(polar) * sin(alpha)
z = radius * cos(polar)
print(str(x) + ' ' + str(y) + ' ' + str(z))
location_on_sphere(radius=0.5, alpha=0, polar=0)
When I enter location_on_sphere(radius=0.5, alpha=0, polar=0) I get x=0, y=0, z=0.5 ok, that seems correct.
So the point is at the top of the sphere, not ideal but ok.
If I bring the point down the sphere so z=-90 it gives me -0.4469983318002789 -0.0 -0.22403680806458506 I was expecting something like x:0, y:90, z:0 or x:90, y:0, z:0 since the z angle should now be at the xy plane. Do I have the correct equation or have I misunderstood something?

Related

how to draw a line knowing the starting coordinate, line length x angle and y, angle

I am trying to draw a line knowing the starting coordinate, line length x angle and y, angle. I am trying to visualize the eye gaze direction of a human in a video.
For an example, I want to draw the blue lines here:
I already have the center point of the eye (start of the blue line), and I already have the x and y angle of the eye. How do I draw this line?
I've found a lot of tutorials on how to draw such lines (https://learnopencv.com/head-pose-estimation-using-opencv-and-dlib/), but they involve translation and rotation vectors. Is there a clean way to do this just using the known x/y angles?
Given a length r and an angle φ between the x-axis and your line to draw, you can calculate a coordinate for a point P(x, y) like this:
x = r * cos(φ)
y = r * sin(φ)
For example, a vertical line with r = 1; φ = 90° = π / 2 would return y = 1 * sin(π / 2) = 1
Then you can import your image in opencv and draw a line using cv2.line.
It’s basically just math:
As far as I know, the height of the triangle is height = math.sinus(h) * l and its width is width = math.cos(h) * l.
I hope this help.

Undo the rotation by keeping the rotated object in position

I am rotating an object about an arbitrary axis with a given angle using (Link) following rotation matrix:
def rotate_object(self, direction_vector, origin_point, point_to_rotate, angle):
angle = np.radians(angle)
a, b, c = origin_point
x, y, z = point_to_rotate
if direction_vector == 0:
u, v, w = [1.0, 0.0, 0.0] # Rotate in +x direction
elif direction_vector == 1:
u, v, w = [0.0, 1.0, 0.0] # Rotate in +y direction
elif direction_vector == 2:
u, v, w = [-0.1027, -0.1525, 0.9829] # Rotate in +z direction
cos = np.cos(angle)
sin = np.sin(angle)
qx = (a*(v**2 + w**2) -u*(b*v + c*w - u*x - v*y - w*z)) * (1-cos) + x*cos + (-c*v + b*w - w*y + v*z) * sin
qy = (b*(u**2 + w**2) -v*(a*u + c*w - u*x - v*y - w*z)) * (1-cos) + y*cos + (c*u - a*w + w*x - u*z) * sin
qz = (c*(u**2 + v**2) -w*(a*u + b*v - u*x - v*y - w*z)) * (1-cos) + z*cos + (-b*u + a*v - v*x + u*y) * sin
return qx, qy, qz
The rotation of the object about a desired axis with a given angle works as expected. But I want to undo the coordinate system after every rotation to the original state by keeping the object on its rotated position. How could I do that?
Thank you!
Suppose you have two rotation axis: axis1 and axis2 which are 3D lines connected at a point (they intersect at a point).
Suppose the axis form a hierarchy, like the turret of a tank which can rotate around axis1 and the cannon mounted on the turret which can rotate around axis2.
The goal is to compute rotation of the cannon given the rotation of the turret or... compute rotation around axis2 given rotation around axis1.
Let's define your transform function as F(axis, angle, p)
Rotation around axis1 can be computed as F(axis1, angle1, p). Take into account that axis1 is "parent" of axis2. In our example that means that when turret rotates also the cannon rotates. So all points from turret AND cannon are rotated like F(axis1, angle1, p).
Rotation around axis2 can be defined as:
F(axis1, angle1, F(axis2, angle2, p))
That is a conposition of transforms in which we first apply rotation around axis2 and then around axis1. Which means that all points of the cannon are transformed first and then they transform according to turret transform.
If you follow this receipt, composition of F(a1,F(a2,F(a3, ...))), you will be able to animate hierarchical models using F.

calculating an intercept point between a straight line and an ellipse - python

Iv'e been trying lately to calculate a point an ellipse
The desired point is the green point , knowing the red dots
and the ellipse equation.
I've used numpy linspace to create an array on points
and iterate them using zip(x axis , y axis)
between the red points , and using the ellipse
equation figure which of the points is the closest to 1.
(which is the outcome of the ellipse equation ).
this concept works most of the time , but in some location
of the red outer dot , this method doesn't seem to give good outcome
long story short, any idea how to calculate the green dot in python?
p.s - ellipse might have angle, both of hes axis are known.
I end up using the ellipse equation from this answer:
and created an in_ellipse function
then Iv'e used the Intermediate value theorem , to get a good estimation
of the point
def in_ellipse(point, ellipse):
return true if point in ellipse
return false
dot_a = ellipse_center
dot_b = dot
for i in range(20):
center_point = ((dot_b.y - dot_a.y)/2, (dot_b.x - dot_a.x)/2)
if in_ellipse(center_point):
dot_a = center_point
else:
dot_b = center_point
return center_point
this system gives the point in 7 (2^20) digits resolution after decimal point
you can increase the range for better resolution.
Let ellipse center is (0,0) (otherwise just subtract center coordinates), semi-axes are a, b and rotation angle is theta. We can build affine tranformation to transform ellipse into circle and apply the same transform to point P.
1) Rotate by -theta
px1 = px * Cos(theta) + py * Sin(theta)
py1 = -px * Sin(theta) + py * Cos(theta)
2) Extend (or shrink) along OY axis by a/b times
px2 = px1
py2 = py1 * a / b
3) Find intersection point
plen = hypot(px2, py2) (length of p2 vector)
if (a > plen), then segment doesn't intersect ellipse - it fully lies inside
ix = a * px2 / plen
iy = a * py2 / plen
4) Make backward shrinking
ix2 = ix
iy2 = iy * b / a
5) Make backward rotation
ixfinal = ix2 * Cos(theta) - iy2 * Sin(theta)
iyfinal = ix2 * Sin(theta) + iy2 * Cos(theta)

Converting Polar to Cartesian coordinates (0-360 degrees)

I am currently using the following code to convert from Cartesian (x, y) coordinates to an angle (0-360 degrees):
def anti_clockwise(x,y):
alpha = degrees(atan2(y,x))
return (alpha + 360) % 360
I am now trying to go back by specifying a distance (eg, 100) and angle (result from above code) to return to some x, y coordinates.
I have been able to get this to work using a simple trigonometry function, but this is limited to 0-90 degrees. Is there any way of getting the x, y coordinates for the full 0-360 degrees range?
Following is what I'm using but realized I didn't convert back to radians!
def get_coord(magnitude, degrees):
angle = radians(degrees)
x = magnitude * cos(angle)
y = magnitude * sin(angle)
return x, y
The following has been tested ans is working:
def get_coord(magnitude, degrees):
angle = radians(degrees)
x = magnitude * cos(angle)
y = magnitude * sin(angle)
return x, y
The problem was not converting to radians during the angle calculation.

Create a square polygon (random oriented) from midpoints in Python

I have a midpoint (x,y) and i need to create a square polygon with random orientation using a 2D (random) planar rotation.
def get_square_plot(x, y, side):
return [(x-(side/2), y+(side/2)), (x+(side/2), y+(side/2)), (x+(side/2), y-(side/2)), (x-(side/2), y-(side/2))]
This function creates the vertices of a square polygon without a specific orientation. I wish to improve this function adding the possibility to rotation randomly these vertices (and with a specific angle if is possible)
If I've understood you correctly, this should be able to do what you want:
from math import sin, cos, radians
def rotated_square(cx, cy, size, degrees=0):
""" Calculate coordinates of a rotated square centered at 'cx, cy'
given its 'size' and rotation by 'degrees' about its center.
"""
h = size/2
l, r, b, t = cx-h, cx+h, cy-h, cy+h
a = radians(degrees)
cosa, sina = cos(a), sin(a)
pts = [(l, b), (l, t), (r, t), (r, b)]
return [(( (x-cx)*cosa + (y-cy)*sina) + cx,
(-(x-cx)*sina + (y-cy)*cosa) + cy) for x, y in pts]
print rotated_square(50, 50, 100)
Output:
[(0.0, 0.0), (0.0, 100.0), (100.0, 100.0), (100.0, 0.0)]
Note that in the general case, the resulting coordinates won't be integers.
What this does effectively is first translate each coordinate to the origin by subtracting cx,cy from it, rotates that by the angle, and then un-translates it back by the same amount. This is necessary to compensate for the fact that rotation formulas usually are relative to origin of a coordinate system.
having determined the four corner coordinates, you can rotate them relative to the origin (or midpoint) using a simple 2D Matrix Rotation:
http://en.wikipedia.org/wiki/Rotation_%28mathematics%29 (search for 2D rotation equation)
x' = x cos(theta) - y sin(theta)
y' = x sin(theta) + y cos(theta)
You can use the built-in Python Math library for the cos/sin functions: http://docs.python.org/2/library/math.html section 9.2.3
Math.cos(theta)
Math.sin(theta)
I hope this is of some use!

Categories

Resources