Jim Andrews
Jim Andrews

Reputation: 55

Calculating the angle between the horizontal and a line through two points

A JavaScript question.

Below is a routine that seems to have some problems. What is the problem? The function, given two points, is supposed to return the angle (in radians) formed between the horizontal axis and the line containing the two points (X1,Y1) and (X2,Y2).

function GetAngle(X1, Y1, X2, Y2) {
    if (Y2 == Y1) {
        return (X1 > X2) ? Math.PI : 0; 
    }
    if (X2 == X1) {
        return (Y2 > Y1) ? Math.PI/2 : 1.5*Math.PI;
    }
    var tangent = (X2 - X1) / (Y2 - Y1);
    var ang = Math.atan(tangent);
    if (Y2-Y1 < 0) ang -= Math.PI;
    return ang;
}

Upvotes: 4

Views: 4975

Answers (3)

Jim Andrews
Jim Andrews

Reputation: 55

Thanks for the help! I did try atan2 but it didn't work right in some situations. I wrote my own function to handle this issue. Here it is. Works great.

function calcAngle(p1, p2) {
        // Returns the angle points p1 and p2 form with the horizontal.
        if (p2.x > p1.x) {
            // quad 1 or 2
            if (p2.y > p1.y) {
                // quad 2
                return arctan(p1, p2)}
                // should be 1-90
            else {
                if (p2.y==p1.y) {
                    return 0}
                else {
                    // quad 1
                    return 2*Math.PI+arctan(p1, p2)
                    // 270-360
                }
            }
        }
        else {    
            if (p2.x==p1.x) {
                // atan undefined
                if (p2.y == p1.y) {
                    return 0}
                else {
                    if (p2.y > p1.y) {
                        return Math.PI/2}
                    else {
                        return 1.5*Math.PI
                    }
                }
            }
            else {
                // else { p2.x < p1.x
                // quad 3 or 4
                if (p2.y == p1.y) {
                    return Math.PI}
                else {
                    if (p2.y > p1.y) {
                        // quad 3
                        return Math.PI + arctan(p1, p2)}
                        // 90-180
                    else {
                        // quad 4
                        return Math.PI+ arctan(p1, p2)
                        // 180-270
                    }
                }
            }
        }
    }


    function arctan(p1, p2) {
        // Returns the arcTan of points p1 and p2.
        rat=  (p2.y-p1.y)/(p2.x-p1.x)
        inradians=Math.atan(rat)
        //indegrees=180*inradians/Math.PI
        return inradians
    }

Upvotes: 0

pimvdb
pimvdb

Reputation: 154818

Why don't you use Math.atan2, which is more convenient. It automatically does it right when both numbers are negative (which information is lost with dividing), and returns the correct values for edge cases as well.

var angle = Math.atan2(Y2 - Y1, X2 - X1);


// these return differently, even though 0 / -1 === 0 / 1
Math.atan2( 0, -1); // Math.PI
Math.atan2( 0,  1); // 0

// same thing: 1 / 1 === -1 / -1
Math.atan2( 1,  1); // Math.PI / 4
Math.atan2(-1, -1); // -Math.PI * 3 / 4


// other values
Math.atan2( 1,  1); // Math.PI / 4
Math.atan2( 1,  0); // Math.PI / 2
Math.atan2(-1,  0); // -Math.PI / 2

Upvotes: 9

Mats
Mats

Reputation: 8628

The function is calculating the inverse of the tangent.

var tangent = (Y2 - Y1) / (X2 - X1);

But it is preferred to use Math.atan2(), as pimvdb has mentioned.

Upvotes: 1

Related Questions