/* 
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)

This software is licensed under the "BSD" License as described in the "LICENSE" file, 
which should be included with this package. The terms are also available at 
http://www.hardcoded.net/licenses/bsd_license
*/

#import "HSGeometry.h"

CGFloat deg2rad(CGFloat deg)
{
    return deg * M_PI / 180;
}

CGFloat distance(NSPoint p1, NSPoint p2)
{
    CGFloat dX = p1.x - p2.x;
    CGFloat dY = p1.y - p2.y;
    return sqrt(dX * dX + dY * dY);
}

NSPoint pointInCircle(NSPoint center, CGFloat radius, CGFloat angle)
{
    // a/sin(A) = b/sin(B) = c/sin(C) = 2R
    // the start point it (center.x + radius, center.y) and goes counterclockwise
    angle = fmod(angle, M_PI*2);
    CGFloat C = M_PI/2;
    CGFloat A = fmod(angle, M_PI/2);
    CGFloat B = C - A;
    CGFloat c = radius;
    CGFloat ratio = c / sin(C);
    CGFloat b = ratio * sin(B);
    CGFloat a = ratio * sin(A);
    if (angle >= M_PI * 1.5)
        return NSMakePoint(center.x + a, center.y - b);
    else if (angle >= M_PI)
        return NSMakePoint(center.x - b, center.y - a);
    else if (angle >= M_PI/2)
        return NSMakePoint(center.x - a, center.y + b);
    else
        return NSMakePoint(center.x + b, center.y + a);
}

CGFloat angleFromPoints(NSPoint pt1, NSPoint pt2)
{
    // Returns the angle (radian) formed by the line pt1-pt2. The angle follows the same logic
    // as in pointInCircle.
    // What we do here is that we take the line and reduce it to fit a "unit circle" (circle with
    // a radius of 1). Then, either asin(adjusted_dy) or acos(adjusted_dx) will give us our angle.
    // We'll use asin(adjusted_dy).
    CGFloat length = distance(pt1, pt2);
    CGFloat dx = pt2.x - pt1.x;
    CGFloat dy = pt2.y - pt1.y;
    CGFloat ajdusted_dy = ABS(dy) / length;
    CGFloat angle = asin(ajdusted_dy);
    
    if ((dx < 0) && (dy >= 0)) {
        // top-left quadrant
        angle = M_PI - angle;
    }
    else if ((dx < 0) && (dy < 0)) {
        // bottom-left quadrant
        angle = M_PI + angle;
    }
    else if ((dx >= 0) && (dy < 0)) {
        // bottom-right quadrant
        angle = (2 * M_PI) - angle;
    }
    return angle;
}