# Finding Closest of 8 Possible Angles to Theta Value

I'm working on creating a gesture recognition system, and I saw one simple implementation that isn't as accurate, but is really easy to implement. The idea is that you have a unit circle with the 8 significant angles (0, 45, 90, 135, 180, etc) and you map those angles to a value of 1-8. So 45 would be 2, 180 would be 5, etc. Then you just use the Levenshtein distance algorithm to find the closest matching gesture.

I have a prototype that is "almost" working, but I'm having some trouble getting the math functions to play nicely with my algorithm. Right now, I have a list of points representing segments of a defined size that make up the gesture. I iterate over these points and get the theta value of the segment like so:

start = points[i]
end = points[i + 1]
theta = math.atan2((p2[1] - p1[1]), (p2[0] - p1[0]))
theta = ((theta + (math.pi * 2)) % (math.pi * 2))


The math.pi correction is so that I'll have all positive radian values. Makes it a lot easier to compare them. I also have a list containing the radian equivalent values of [0, 45, 90, 135, 180, 225, 270, 315, 360]. I iterate over the segments and compare the theta value to each of those 8 directions (360 is a redundancy so that I can compare values greater than 315 to 0). I use the index of the direction + 1 to get my mapped value.

So if I have a drawing of a box like so:

Then according to the algorithm, I should get the values "1357" to indicate the directions being 0, 90, 180, and 270 degrees in change.

However, something seems to be off about the way I calculate my theta values, or the way I compare them, because for that drawing, I get "1753" indicating that it's flipping the theta values for the second and third lines (the vertical ones). Here is how I'm comparing the points:

for i in range(len(points) - 1):
p1 = points[i]
p2 = points[i + 1]
theta = math.atan2((p2[1] - p1[1]), (p2[0] - p1[0]))
theta = ((theta + TWO_PI) % TWO_PI)
closest = 0
cDiff = TWO_PI
for i in range(len(DIRECTIONS)):
direction = DIRECTIONS[i]
diff = abs(direction - theta)
if diff < cDiff:
cDiff = diff
closest = I
if closest == (len(DIRECTIONS) - 1):
dir.append(1)
else:
dir.append(closest + 1)


So my theta values seem to be increasing clockwise, rather than counter-clockwise, so for the following angle:

...I would expect the theta value to be (pi / 4), but instead, it seems to be (7pi / 4).

Can anyone spot a flaw in my logic? This same math works in my game written in Java. Are Python's math functions different somehow?

Edit: Added a diagram to explain the encoded gesture movement values.

Uh...

for i in...
for i in...


You have two loop variables with the same name. This is probably playing havoc with your execution.

Then this:

closest = I


That I isn't declared anywhere. It isn't either of the two loop iterators.

• Wow, I must have been more tired this morning than I thought... the capital I was because the StackExchange editor kept auto-correcting my lower-case i's. Commented Jan 14, 2019 at 19:13
• Unfortunately still doesn't explained the flipped vertical indexes (it's saying 7 when I draw up and 3 when I draw down, for example, when it should be the opposite. Commented Jan 14, 2019 at 19:16
• That might be due to the cartesian origin being in a different place than you expect. That is, for you "up" (increasing y values) means that the origin is in the lower left, while typically computer graphics have an origin in the top left...For better support of different screen resolutions. Commented Jan 14, 2019 at 19:33
• I'm well acquainted working with computer graphics origins. I just don't know all of the intricacies of trig. I'm not sure why you feel that matters, though, because the center-right of the unit circle should still be 0 and increase going counter-clockwise, so my selected angle indices should still correspond to my algorithm unless I missed something. Commented Jan 14, 2019 at 19:38
• I added a diagram to my post to explain how the angle nearest the angle of the line segment should be encoded. Hopefully it will help to understand what the end result should be. Commented Jan 14, 2019 at 19:43