python math.acos inverse cosine issues
Question: I need to find an angle of a triangle with only three coordinate points on a
plane. In regular trigonometry at the end of the equation i would use:

    
    
    cos = (a ** 2) - (b ** 2) - (c ** 2) / -2 * b * c
    

I used the `**` operator for to the power of, and `sideA`, `sideB` and `sideC`
are the lengths of the sides of the triangle.

I am currently using `math.acos()` to find the angle, but I'm getting a math
domain error. Is `math.acos()` the right function to use for what I understand
as the inverse cosine?

Here is a excerpt of code from my program:

    
    
    x = 100
    y = 100
    centerX = x + 50
    centerY = y + 50
    
    if event.type == MOUSEMOTION:
                mousex, mousey = event.pos
                sideA = math.sqrt((x - mousex)**2)+((y - mousey)**2)
                sideB = math.sqrt((centerX - mousex)**2)+((centerY - mousey)**2)
                sideC = math.sqrt((centerX - x)**2)+((centerY - y)**2)
                cos = float(sideA**2)-(sideB**2)-(sideC**2)/(-2*(sideB*sideC))
                angle = math.acos(cos)
                print angle
    

What am i doing wrong? When I enter the numbers from my program into my
calculator I get the right angle.


Answer: Your problem here is that your code is formatted so badly, you can't see the
errors with parentheses that you're making.

## Error 1

For instance, this line:

    
    
    sideA = math.sqrt((x - mousex)**2)+((y - mousey)**2)
    

when formatted properly, looks like this:

    
    
    sideA = math.sqrt((x - mousex) ** 2) + ((y - mousey) ** 2)
    

and when you remove the redundant parentheses, you can see what's happening
even more clearly:

    
    
    sideA = math.sqrt((x - mousex) ** 2) + (y - mousey) ** 2
    

You're only passing the square of _one_ of your sides to `math.sqrt()`, and
just adding the square of the second side to it. It should be:

    
    
    sideA = math.sqrt((x - mousex) ** 2 + (y - mousey) ** 2)
    

or even better:

    
    
    sideA = math.hypot(x - mousex, y - mousey)
    

## Error 2

Then this line:

    
    
    cos = float(sideA**2)-(sideB**2)-(sideC**2)/(-2*(sideB*sideC))
    

has a similar problem - you're missing parentheses around those first three
terms, and you're only dividing the square of side C by 2bc. It should be:

    
    
    cos = (sideA ** 2 - sideB ** 2 - sideC ** 2) / ( -2 * sideB * sideC)
    

## Solution

As a result of the above, you're not calculating the cosine correctly, so what
you're passing to `math.acos()` is way out of an allowable range for a cosine
(a cosine will always be in the range `-1 <= cos A <= 1`), so it's giving you
that domain error. Printing out your values would have helped see you were
getting something really strange, here.

Here's a fixed and working version of your program, modified to just set
values directly for `mousex` and `mousey`:

    
    
    #!/usr/bin/env python
    
    import math
    
    x, y = 100, 100
    centerX, centerY = x + 50, y + 50
    mousex, mousey = 100,150 
    
    sideA = math.hypot(x - mousex, y - mousey);
    sideB = math.hypot(centerX - mousex, centerY - mousey)
    sideC = math.hypot(centerX - x, centerY - y)
    cosA = (sideB ** 2 + sideC ** 2 - sideA ** 2) / (2 * sideB * sideC)
    angle = math.acos(cosA)
    
    print "sideA: %.2f, sideB: %.2f, sideC: %.2f" % (sideA, sideB, sideC)
    print "cosA: %.6f" % (cosA)
    print "angle: %.2f radians, %.2f degrees" % (angle, math.degrees(angle))
    

which outputs:

    
    
    paul@horus:~/src/sandbox$ ./angle.py
    sideA: 50.00, sideB: 50.00, sideC: 70.71
    cosA: 0.707107
    angle: 0.79 radians, 45.00 degrees
    paul@horus:~/src/sandbox$ 
    

I've taken the liberty of rearranging your cosine rule calculation slightly to
eliminate the need to negate the denominator.

