2013-06-23 01:32:48 +00:00
|
|
|
/*
|
2014-02-01 22:54:30 +00:00
|
|
|
Copyright 2014 Hardcoded Software (http://www.hardcoded.net)
|
2013-06-23 01:32:48 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|