Simple circular gesture detection - c

I'm looking at a simple, programmatic way of detecting whether or not the user has drawn a circular shape. I'm working in C, but am happy to work from pseudo-code. A bit of Googling brings up a number of (hopefully) overly-complex methods.
I'm tracking the mouse coordinates as floats, and have created an array of vectors to track the mouse movement over time. Essentially I'm looking to detect when a circle has been drawn and then disgard all movement data not associated with that circle.
I have a basic idea of how this might be accomplished:
Track all movements using a polling function. Each time the function is polled the current mouse position is stored. Here, we loop through the historic position data and do a rough 'snap to position' to compare the two locations. If the new location is within a close enough distance to an old position, we remove all historic data before the old location.
While this works in theory, it's a mess in practice. Does anyone have any suggestions? Bonus points if the method suggested can detect whether it's been drawn clockwise or counter-clockwise.

Based on your tracking/polling function, which pushes float pairs on a stack. This must be done on a regular timing interval.
Do a threshold-based search for two equal entries in the list. Now you have two indexes in your stack; the first and the second equal entries. Consider this as a line.
Get the absolute difference in indices. Then divide by two and get the coordinates of this point. (Center of the line.)
You've got two points: thus you can get the radius of the circle, by getting the distance between the two points divided by two.
Divide the number of step 2 by 2, now you've got the quarters.
If the line at step 1 is vertical and the first point of the line is at the top: If the first quarter is left of the center-point, the circle was drawn counter-clockwise. If the first quarter is right of the center-point, the circle was drawn clockwise. If the first point of the line is at the bottom, reverse (i.e. ccw => cw and cw => ccw)
If the line at step 1 is horizontal and the first point of the list is at the left: If the first quarter is above the center-point, the circle was drawn counter-clockwise. If the first quarter is below of the center-point, the circle was drawn clockwise. If the first point of the line is at the right, reverse.
Check if it was a circle: iterate over all pairs of coordinates and calculate the distance to the center-point. Tweak the threshold of allowed distances from the calculated distance and the actual distance to the center-point.
In step 2 and 4 you can tweak this algorithm further by taking the average of several indices if the timing interval is very low (fast polling). For instance: there are 30 pairs in the array, then you average pairs at 0, 1 and 28, 29 to get the upper point. Do the same for all other points.
I hope this is easy enough.

You are definitely on the right track IMHO. Basically you need to compare each mouse point with the previous mouse point and calculate the angle between them (as envisioned on a unit circle where the first point is at the origin). For this you can use the formula:
double angle = atan2(y2 - y1, x2 - x1) * 180 / PI;
if (angle < 0)
angle += 360;
What you end up with is that for clockwise movement, the angle will cycle in a positive direction, whereas for counterclockwise movement the angle will cycle in a negative direction. You can figure out if the current angle is greater or less than the previous one with the following logic:
if (angle2 > 270 && angle1 < 90)
{
angle1 += 360
}
else if (angle1 > 270 && angle2 < 90)
{
angle2 += 360
}
bool isPositive = (angle2-angle1 > 0);
If you get a certain number of vectors all with angles that are increasing (isPositive is true, let's say, 10 times), you can assume a clockwise circle is being drawn; if the tendency is negative (isPositive is false 10 times) it's a counterclockwise circle. :)

Here's an algorithm to see if an array of points fits a circle:
calculate the centroid of the points (average of all the x and y coordinates)
calculate the distance of all points to the centroid
find the maximum and minimum distances
if maximum - minimum < tolerance, circular section detected
NB This will detect a section of a circle as well so you will need to determine that enough of an angle is swept through for it to be a full circle.
To do this:
calculate centroid as above
calculate angle between centroid and each point (use atan2 function)
map angles to segments (I find 12 30 degree segments works for me; just divide angle by 30 and round down to integer - assuming you are working in degrees here)
if all segments contain at least 1 point, then it is a circle (i.e. your mapped segments array contains all values between 0 and 11)
bonus: increasing angle is anti-clockwise; decreasing is clockwise

Haven't tried this, but the idea came to mind reading your question, so might as well share it with you:
I'm assuming the circle has to be drawn within a reasonable amount of time, given a steady "sample-rate" of the mouse that would leave a known-size array of 2D vectors (points). Add them all and divide by the count of 2D vectors to get an estimate of the "center" point in the array. Then form vectors from this center-point to the points in the array and do dot-products (normalizing by vector length), making sure the sign of the dot-products remain identical for a range of points means those points all move in the same direction, a positive sign will indicate counter-clockwise movement, negative is just the opposite. If the accumulated angle exceeds 2 PI, a circular movement was drawn..
Good luck.

1 - Pick any 3 of the points
2 - If the points are collinear +/- 'some buffer' then it isn't a circle.
3 - Use the method described on Wikipedia for finding the circumscribed circle for a triangle to find the midpoint and radius of your candidate circle
The circumcenter of a triangle can be constructed by drawing any two
of the three perpendicular bisectors. For three non-collinear points,
these two lines cannot be parallel, and the circumcenter is the point
where they cross. Any point on the bisector is equidistant from the
two points that it bisects, from which it follows that this point, on
both bisectors, is equidistant from all three triangle vertices. The
circumradius is the distance from it to any of the three vertices.
4 - Check the distance to the remaining points. If those points are within the 'candidate circle radius' +/- 'some buffer allowance' then it is a circle.
5 - To determine direction, simply calculate the angle between the first and 2nd points from the midpoint. A negative angle is right. A positive angle is left. (Could be reversed depending on the coordinate system you are using)

Related

Positioning the AC servo from 0 to 360 degrees to return to the shortest path

I am doing absolute positioning using AC servo.I calculated how many steps of pulse are needed for a full rotation of the servo and converted it to degrees between 0-360.
For the current situation.
For example, if the motor is in the zero position, if I give a position in the CW direction. It goes to that degree in the CW direction. There is no problem here.
If the motor is in the 0 position, if I give a negative position, it moves in the CCW direction.
If the motor has moved in the CCW (negative position) direction, if I give a positive position, it will return to the position where it went in the negative direction and switch to the positive position.The method I want to create here is to go to the position given between 0 and 360 from the nearest path, regardless of the negative or positive direction of the motor.
It is completely similar to the logic of a compass, but it has to take the closest path to the given location.I'm trying a few ways, but I can't calculate the shortest path.
I tried to explain a little in the picture below.
Can anyone help with this?
If X and Y are numbers of degrees from 0 to 360 (measuring clockwise from an origin), then Y−X is the number of degrees to go clockwise from X to get to Y. That may be a positive number or a negative number (or zero), indicating clockwise or counterclockwise. If −180 ≤ Y−X ≤ +180, then it is making a turn of less than half a circle, so use it. Otherwise, if Y−X < −180, use Y−X+360, or, if +180 < Y−X, use Y−X−360.

Question about performance for raytracing algorithm intersection test

I'm currently building a basic raytracing algorithm and need to figure out which system of handling the intersections would be best performance-wise.
In the method I'm checking for a intersection of the ray and the object I'm returning a struct with the distance of the ray traveled to the hit, the position vector of the hit and the normal vector or -1 for the distance if there is no intersection.
For the next step I have to find the shortest distance of all intersections and exclude the ones with a negative distance.
I even thought about having 2 structs, one with only negative distances and one full struct to reduce the amount of space needed, but thought this wouldn't really make a difference.
My options so far:
first go over the array of the intersections and exclude the ones with negative distances, then find the shortest distance from the remainings via a sorting algorithm (probably insertion sort due to quick implementation).
Or put them together in one algorithm and test in each sort step if the distance is negative.
typedef Point3f float[3];
typedef struct {
float distance;
Point3f point;
Point3f normal;
} Intersection;
Intersection intersectObject (Ray-params, object) {
Intersection intersection;
//...
if (hit) {
intersection.distance = distance;
intersection.point = point;
intersection.normal = normal;
} else {
intersection.distance = -1.0f;
}
return intersection;
}
//loop over screen pixel
Intersection* intersections;
int amountIntersections;
//loop over all objects
//here I would handle the intersections
if (amountIntersections) {
//cast additional rays
}
I can't really figure out what would be the best way to handle this, since this would be called a lot of times. The intersection array will probably be a dynamic array with the amountIntersections as the length variable or an array with the most expected amount of intersections which then have intersections in it with negative distances.
Here is the approach I've succesfully used for a huge number of objects. (Especially for ball-and-stick atomic models; see my Wikipedia user page for the equations I used for those.)
First, transform the objects to a coordinate system where the eye is at origin, and the projected plane is parallel to the xy plane, with center on the positive z axis. This simplifies the equations needed a lot, as you can see from the above linked page.
As an example, if you have a unit ray n (so n·n = 1) and a sphere of radius r centered at c, the ray intersects the sphere if and only if h ≥ 0,
h = (n·c)2 + r2 - (c·c)
and if so, at distance d,
d = n·c ± sqrt(h)
If you work out the necessary code, and use sensible temprary variables, you'll see that you can reject non-intersecting spheres using eight multiplications and six additions or subtractions, and that this vectorizes across objects easily using SSE2/AVX intrinsics (#include <x86intrin.h>). (That is, do not try to use an XMM/YMM vector register for n or c, and instead use each register component for a different object, calculating h for 2/4/8 objects at a time.)
For each ray, sort/choose the objects to be tested according to their known minimum z coordinate (say, cz - r for spheres). This way, when you find an intersection at distance d, you can ignore all objects with minimum z coordinate larger than d, because the intersection point would necessarily be further out, behind the already known intersection.
Similarly, you should ignore all intersections where the distance is smaller than the distance to the projection plane (which is zd / nz, if the plane is at z = zd, and only needs to be computed once per ray), because those intersections are between the eye and the projection plane. (Technically, you've "crashed into" something then, if you think of the projection plane as a camera.)

Sprite Rotation Math Formula for Screen Width and Height

I am programming an asteroids type game in C, and I have a sprite sheet of 36 sprites that is the ship rotating. I would like to know a math formula for figuring out how to move the ship in the direction of the sprite I have chosen from the sprite sheet. Note that I am incrementing by 10 degrees (hence 36 sprites for 360 degrees).
For example, my screen is 320 pixels wide by 256 pixels high.
If I select sprite image 10 (which is 90 degrees (the ship is facing right)), how can I calculate (using some sort of formula) the X and Y coordinates to move the ship in? I know 90 degrees is an easy one, by imagine if it were 30 degrees. There is a certain value for X and a certain value for Y. Since the screen in wider in width that height, the X speed would be higher than the Y speed.
Hope that makes sense.
Many thanks.
There are two easy approaches: you can build a table of [x,y] distances for each of the 36 angles, or you can do the math "on the fly".
The advantage of calculating the distances immediately is that you can easily increase the accuracy later on, if you decide you want more than 36 angles (and don't mind the sprite is off by a couple of degrees). Also, since you will be working with floats anyway, you can do all of your calculations with a far greater accuracy. Your speed could be as low as 0.01 pixel per second, and if you store your position as floats as well, you'd see your sprite move a tiny bit every few minutes.
Pre-calculating a table is easy and fast, though. Run this program to create the arrays xmove and ymove. Then, for an angle a, you can set xpos += ((speed*xmove[a])>>8) and ypos += ((speed*ymove[a])>>8).
The table stores sin and cos times 256, as integers. The values need to be multiplied by some large factor because they always fall inside the floating point range -1..1; storing them as their original floating point value is possible but unnecessary (it would only re-introduce floating point calculations in what can be reasonably approximated with pure integers, in your case). Now since the values are "premultiplied" by 256, you need to divide the speed*move calculation again by that number -- shifting right by 8 bits is all it takes. (There is a small rounding issue here; if it bothers you, add 128 before the right-shift.)
You can use a larger accuracy by using a multiplier of 1024 or higher, but again, more accuracy is probably entirely invisible for your purposes. ('1024' instead of '1000' because you can still efficiently use bit-shifting with that number.)
I believe that nowadays any modern screen has nigh-on square pixels, so unless you want it as some sort of special effect, speed in the y direction should be the same as x-speed. However, it's simple to add. Instead of dividing by 256, you'd use something like ypos += ((speed*ymove[angle])/341); -- this is (4*256/3), so the vertical speed is 75% of the horizontal speed.
A final possible refinement: you can also store your xpos,ypos as pre-multiplied by 256! Then you would not shift right the new coordinates, but immediately add the correct value. Only when displaying the actual sprite, you'd divide the coordinates by 256. That way your ship will not move by "entire pixels" only, but way more smooth. If your speed is variable, you can store it with higher accuracy the same way (remember to scale down correctly, because it'd make your 'virtual' speed is 256*256 higher than your 'screen' speed).
The table created below assumes #0 is "straight up", #9 (not 10!) is "right", #18 is down and #27 is "left", where positive y points downwards.
By the way: the size of your ship doesn't really matter ... You probably don't want it to "jump" distances equal to its own size.
#include <stdio.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
int main (void)
{
int i, angle;
printf ("int xmove[36] = {\n");
for (i=0; i<36; i++)
{
angle = 10*i;
// x distance: sin
printf ("\t%d,", (int)(round(256*sin(angle * M_PI/180))));
printf ("\t\tangle: %d\n", angle);
}
printf ("};\n");
printf ("\n");
printf ("int ymove[36] = {\n");
for (i=0; i<36; i++)
{
angle = 10*i;
// y distance: cos
printf ("\t%d,", (int)(round(-256*cos(angle * M_PI/180))));
printf ("\t\tangle: %d\n", angle);
}
printf ("};\n");
return 0;
}

How would you convert X,Y points to Rho,Theta for hough transform in C?

So I am trying to code Hough Transform on C. I have a binary image and have extracted the binary values from the image. Now to do hough transform I have to convert the [X,Y] values from the image into [rho,theta] to do a parametric transform of the form
rho=xcos(theta)+ysin(theta)
I don't quite understand how it's actually transformed, looking at other online codes. Any help explaining the algorithm and how the accumulator for [rho,theta] values should be done based on [X,Y] would be appreciated.Thanks in advance. :)
Your question hints at the fact that you think that you need to map each (X,Y) point of interest in the image to ONE (rho, theta) vector in the Hough space.
The fact of the matter is that each point in the image is mapped to a curve, i.e. SEVERAL vectors in the Hough space. The number of vectors for each input point depends on some "arbitrary" resolution that you decide upon. For example, for 1 degree resolution, you'd get 360 vectors in Hough space.
There are two possible conventions, for the (rho, theta) vectors: either you use [0, 359] degrees range for theta, and in that case rho is always positive, or you use [0,179] degrees for theta and allow rho to be either positive or negative. The latter is typically used in many implementation.
Once you understand this, the Accumulator is little more than a two dimension array, which covers the range of the (rho, theta) space, and where each cell is initialized with 0. It is used to count the number of vectors that are common to various curves for different points in the input.
The algorithm therefore compute all 360 vectors (assuming 1 degree resolution for theta) for each point of interest in the input image. For each of the these vectors, after rounding rho to the nearest integral value (depends on precision in the rho dimension, e.g. 0.5 if we have 2 points per unit) it finds the corresponding cell in the accumulator, and increment the value in this cell.
when this has been done for all points of interest, the algorithm searches for all cells in the accumulator which have a value above a chosen threshold. The (rho, theta) "address" of these cells are the polar coordinates values for the lines (in the input image) that the Hough algorithm has identified.
Now, note that this gives you line equations, one is typically left with figure out the segment of these lines that effectively belong in the input image.
A very rough pseudo-code "implementation" of the above
Accumulator_rho_size = Sqrt(2) * max(width_of_image, height_of_image)
* precision_factor // e.g. 2 if we want 0.5 precision
Accumulator_theta_size = 180 // going with rho positive or negative convention
Accumulator = newly allocated array of integers
with dimension [Accumulator_rho_size, Accumulator_theta_size]
Fill all cells of Accumulator with 0 value.
For each (x,y) point of interest in the input image
For theta = 0 to 179
rho = round(x * cos(theta) + y * sin(theta),
value_based_on_precision_factor)
Accumulator[rho, theta]++
Search in Accumulator the cells with the biggest counter value
(or with a value above a given threshold) // picking threshold can be tricky
The corresponding (rho, theta) "address" of these cells with a high values are
the polar coordinates of the lines discovered in the the original image, defined
by their angle relative to the x axis, and their distance to the origin.
Simple math can be used to compute various points on this line, in particular
the axis intercepts to produce a y = ax + b equation if so desired.
Overall this is a rather simple algorithm. The complexity lies mostly in being consistent with the units, for e.g. for the conversion between degrees and radians (most math libraries' trig functions are radian-based), and also regarding the coordinates system used for the input image.

7 Point computational stencil cache access in C (or..map a 3D array into a 1D array)

I have a problem I am trying to tackle that involves a 7 point computational stencil. For those who may not know, this would be a 3D grid, and the 7 points are the n'th point, and the neighbors one point away in the x, y and z directions, both positive and negative (or neighbors to the east/west/north/south and up/down).
So these 6 points plus the 1 additional point i am working on are used in a calculation, and are all stored in a 1 dimensional array.
Assume nx is the width of the cube, and ny is the height. In memory, then, when I am accessing a point in the array All_Points, such as All_points[n], then to get it's neighbors in each direction, I also want to access All_points[n-1], All_points[n+1], All_points[n-nx], All_points[n+nx], All_points[n-nxny], and All_points[n+nxny].
So my problem with this is that I am getting a ton of cache misses. I can't seem to find any code example that demonstrate how to avoid This problem. Ideally I'd like to split this array back up into it's x, y and z coordinates, such as All_x_points[] but then I run into a problem trying to keep that updated, since All_points[n] changes, and when it does, that means for some other All_points[n'] my x, y or z value will need to be updated with it.
Anyone seen this kind of thing done before?
What kind of access pattern is using your 7-point stencil? If you're having cache coherence problems, this is the first question to ask -- if the access pattern of your central (x,y,z) coordinate is completely random, you may be out of luck.
If you have some control over the access pattern, you can try to adjust it to be more cache-friendly. If not, then you should consider what kind of access pattern to expect; you may be able to arrange the data so that this access pattern is more benign. A combination of these two can sometimes be very effective.
There is a particular data arrangement that is frequently useful for this kind of thing: bit-interleaved array layout. Assume (for simplicity) that the size of each coordinate is a power of two. Then, a "normal" layout will build the index by concatenating the bits for each coordinate. However, a bit-interleaved layout will allocate bits to each dimension in a round-robin fashion:
3D index coords: (xxxx, yyyy, zzzz)
normal index: data[zzzzyyyyxxxx] (x-coord has least-significant bits, then y)
bit-interleaved: data[zyxzyxzyxzyx] (lsb are now relatively local)
Practically speaking, there is a minor cost: instead of multiplying the the coordinates by their step values, you will need to use a lookup table to find your offsets. But since you will probably only need very short lookup tables (especially for a 3D array!), they should all fit nicely into cache.
3D coords: (x,y,z)
normal index: data[x + y*ystep + z*zstep] where:
ystep= xsize (possibly aligned-up, if not a power of 2?)
zsetp= ysize * ystep
bit-interleaved: data[xtab[x] + ytab[y] + ztab[z]] where:
xtab={ 0, 1, 8, 9, 64, 65, 72, 73,512...} (x has bits 0,3,6,9...)
ytab={ 0, 2, 16, 18,128,130,144,146,1024...} (y has bits 1,4,7,10...)
ztab={ 0, 4, 32, 36,256,260,288,292,2048...} (y has bits 2,5,8,11...)
Ultimately, whether this is any use depends entirely on the requirements of your algorithm. But, again, please note that if your algorithm is too demanding of your cache, you may want to look into adjusting the algorithm, instead of just the layout.
7 points? Six defining a spatial coordinate, one defining a length? Are these... Stargate coordinates?
Why not turn your Array of Structures (AOS) into a Structure of Arrays (SOA)?
int point = points_all[i]; // the point you want
Vec2 points_x[point]; // x and y are the neighbours left and right
Vec2 points_y[point]; // x and y are the neighbours up and down
Vec2 points_z[point]; // x and y are the neighbours front and back

Resources