How to calculate (count) number of orbits from positional data? - algorithm

I have the x,y position of a body that makes roughly circular orbits around a known point. Is there an algorithm that will give me the number of orbits this body makes over time if I feed it a vector of x,y positions? I don't care about variations in the distance of the body from the "origin" of the orbit.
EDIT 1:
My solution so far:
shift the x,y coords of the body by the x,y position of the orbit origin (i.e. make origin of orbit [0,0])
compute atan2 of body xy to get radians, then convert to degrees
shift degrees so that 0 is start location of body
find all turn points in degree vector (find 359->0 transitions)
count orbits as number of turn points + remainder

The following algorithm assumes that there are more than 2 positions stored per orbit, with a spacing of less than 180 degrees.
Basically you define a "finishing line" for the orbit using the first position and increment a count when the body crosses it, which you can detect when the sign of the dot product of the position vector with the line normal changes:
Take the vector from the known point the body is orbiting around to the first position in your series and find a vector perpendicular to it. In 2D you can do this just by subtracting the center point from the first position, then swapping the x and y components and negating one of them. This vector defines the normal to the "finishing line" of each orbit.
Take the vector from the center to second position in the series, and find the dot product with the normal calculated above by multiplying component-wise.
Initialize an orbit count to zero
For each remaining position in the series:
Compute the vector from the center to the position, and the dot product of it with the finishing line normal. If the sign of the dot product the same as that of the second position, and different to the previous position in the series, increase the count by one.
You can work out the fractional part by calculating the angle between the last position and the first.

Related

Calculating the rotation vector of a sphere

I'm trying to calculate the axis of rotation of a ball which is moving and spinning at the same time, i.e. I want the vector along the axis that the ball is spinning on.
For every frame I know the x, y and z locations of 3 specific points on the surface of the sphere. I assume that by looking at how these 3 points have moved in successive frames, you can calculate the axis of rotation of the ball, however I have very little experience with this kind of maths, any help would be appreciated!
You could use the fact that the direction a position vector moves in will always be perpendicular to the axis of rotation. Therefore, if you have two position vectors v1 and v2 at successive times (for the same point), use
This gives you an equation with three unknowns (the components of w, the rotation axis). If you then plug in all three points you have knowledge of you should be able to solve these simultaneous equations and work out w.

Last Row of the perspective projection matrix

Could you explain to me what is the purpose of -1 in the last row of the gl_projection matrix? And how it affects the perspective division step ?
The essential property of a perspective projection is that you divide the x/y coordinates by the depth (distance from viewer). This makes objects closer to the viewer (which have smaller depth values) larger, and objects farther from the viewer (which have larger depth values) smaller.
The next piece of the puzzle is how homogenous coordinates work. The (x, y, z, w) coordinates in homogenous space produced by the vertex shader are converted to regular 3D coordinates by dividing them by w:
(x, y, z, w) --> (x/w, y/w, z/w, 1)
So we want a division by the depth to achieve a perspective, and we know that the coordinates produced by the vertex shader will be divided by w. To get the desired result, we can simply put the depth value in eye coordinate space into the w coordinate.
This is exactly what the last row of the projection matrix does. The dot product of the last row with the input vector (which are the eye space coordinates of the vertex) produces the w value of the output:
(0 0 -1 0) * (x y z 1) = -z
You might have expected the value of the matrix element to be 1, to simply copy the z value in eye space to the w value of the vertex shader output. The reason we use -1 to invert the sign is based on the common arrangement of eye space coordinates in OpenGL.
Eye coordinates in OpenGL typically have the "camera" at the origin, looking down the negative z-axis. So the visible range of z-coordinates has negative values. Since we want the distance from the viewer in the resulting w-coordinate, we flip the sign of the eye space z-coordinate, which turns the negative z-values into positive distance values from the origin.
Note that much of this is just common policy, partly rooted in the legacy fixed function pipeline. With the programmable pipeline used in current OpenGL versions, you have complete freedom in how you organize your coordinate spaces and transformations. For example, you could easily use an eye space coordinate system where the camera points in the positive z-direction, and then have a 1 in the last row of the projection matrix instead of a -1.
As stated here: http://www.songho.ca/opengl/gl_projectionmatrix.html
"Therefore, we can set the w-component of the clip coordinates as -ze. And, the 4th of GL_PROJECTION matrix becomes (0, 0, -1, 0)."

What is the fastest way to determine all cells in a regular 2d grid that are touched by a line segment

I want to find all grid tiles that touch or contain parts of a given finite line segment. The grid is a 2d regular grid, thus I can deduce any tile's center from a tile position (row,colum) and vice versa I can calculate a tile position from a given floating point coordinate with two fast integer divisions. The tiles are quadratic e.g. 0.25x0.25 with 0.25 defined as the tile width.
Now I need to determine all tiles that are touched by a given line segment
(two 2d points given in floats define a line segment).
My current approach is to split the segment into equidistant points with a distance half the tile-width (greetings to shannon). Than I collect all tiles that contain the given points and remove duplicate tiles.
Since this operation is the most performance critical part of my program I was wondering whether there is a faster approach to calculate the respective tiles.
Edit: As Patricia noted my current approach does not result in a complete tile set since a tile that is only touched to a very small fraction by the line would not be included. This is acceptable for me since in my case speed is more important than accuracy, but should be noted none the less.
To make it clearer: I want all red tiles in the image but I can spare e.g. the rose ones if I gain speed for that.
Your problem basically comes down to drawing a line segment on a raster image.
If you can spare the pink tiles, use the Bresenham's algorithm. Otherwise, use a similar technique as is used to draw antialiased lines:
You start at the tile which contains one end of the segment and put it to the queue. Then follow with a regular BFS algorithm, putting only tiles which intersect with the segment to the queue:
In one iteration take one tile from one end of the queue, this is your next found intersecting tile. Then find all its neighbors, and put those which intersect with the segment (it's enough to test intersection with a line in this case) to the other end of the queue. The neighbors must be chosen according to the direction of the line. If it goes down-right, use the down, right and down-right tiles as neighbors, if it goes up, use only up neighbors, and so on.
You end when you reach the tile which contains the other end of the segment.
Test the gradient of the line, against the tile diagonal with the same gradient sign. If it is steeper than a tile diagonal, exchange x and y coordinates in what follows.
If the gradient is shallower than the tile diagonal, the line touches or crosses a given tile, and the tile does not contain an end point, at least one of its intersections with the edges of the tile must be on an x boundary of the tile.
For each line end, collect the tile containing or tiles touching the end point.
For each x coordinate that is a tile edge between the two end point x coordinates, calculate the line's y coordinate. Collect the tiles touching that point.
I think this can all be done with at most a couple of divisions to do the gradient check. The main process is all multiplication, addition, and comparisons.
Given the line segment's end points, you can easily compute the equation of the line, y = mx + b. And given the length of the segment, you can compute the parametric form:
x = x0 + ft
y = y0 + gt
Given either of those equations, you can calculate the y coordinate for any given x coordinate on the line. So ...
Starting at the first end point of the line, you know that the cell containing that point is in the set. You know the x coordinates for each cell, so you can quickly determine the y coordinate at which your line segment crosses the cell boundary. If that y coordinate is above the cell's top y coordinate, then the line segment intersects the cell above the starting cell. (Substitute "below" if the line's slope is "down.)
If you repeat that test for each cell boundary along the x axis, you will get the list of all cells that the segment crosses.

Clockwise rotating line

I am given a pivot point (by the integer coordinates) and a line that goes through that point and makes an x degree with the horizontal. The line makes a 360 degrees clockwise rotation around the pivot point with speed s= 0.001 degree per second. I am now given N points (with integer coordinates) and I have to sort these points in the order in which the line touches these points. How can i compute this? Thank you in advance.
You need to do something equivalent to the following:
Translate everything so that the pivot point is at the origin
Convert each point to polar coordinates.
Subtract x from each point's angle component, modulo 360 degrees (2pi radians).
Sort the angle components in ascending order.
Write the comparison function that takes two points and compare the angles they make with horizontal line.

Help understanding 2D Inverse Kinematics

I found a Web Site which explains Inverse Kinematics in 2D:
Starting from the joint nearest the
end point:
1. Calculate a force vector from the end of the bone to the target.
2. Calculate the dot product of the force vector and the Right angle
vector.
3. Multiply it by a small value, like 0.01.
4. Add it to the angle of the joint.
http://freespace.virgin.net/hugo.elias/models/m_ik.htm
So the way the bones are designed in my application is in terms of a joint and an angle. Each 'bone' is a joint and an angle and a length. The bone's end point is then the unit vector of its starting point and angle, multiplied by its length.
So I think for step 1, I simply generate a unit vector whos direction points toward the target and multiply it by the distance between the end point and the target point.
Step 2 is where I'm unsure. I know how to produce a dot product, but I'm not sure how to get this right angle vector they speak of.
Thanks
The "right angle vector" is a vector that is at a right angle to the length of the bone.
If you are pushing the bone along its length, it shouldn't move. In this case, the angle between this "right angle vector" and your force vector is then 90 degrees, and so the dot product is zero. Hence, no change in angle of the bone.
The Right-Vector is the R-Vector in the pictures of the 2D-inv-kinematics-sections. It is a normalized vector orthogonal to the bone.
A small hint: the dot-product of vector A and a normalized vector B is just the projected length of vector A to the straight of vector B which is just the cos(angle). More details here: http://en.wikipedia.org/wiki/Dot_product#Geometric_interpretation
As a result if the target-vector is nearly the same as the right-vector then the cos will be near 1 and the algorithm will correct your bone-angle more than if the target-vector is nearly the same as your bone-vector (cos is near 0)

Resources