有时候需要计算点点之间的相对角度,使用arctan等需要考虑符号问题,而且比较慢,如果只需要用来比较或排序,可以完全不用计算精确大小。
下面是两个函数,可以完美解决,返回值是单调的~~
pseudoangle
// Returns the pseudoangle between the line p1 to (infinity, p1.y)
// and the line from p1 to p2. The pseudoangle has the property
// that the ordering of points by true angle anround p1 and
// ordering of points by pseudoangle are the same The result is
// in the range [0, 4) (or error -1).
float pseudoangle(const WPoint& p1, const WPoint& p2) {
WVector delta = p2 - p1;
float result;
if ((delta.x == 0) && (delta.y == 0)) {
return -1;
} else {
result =(float) (delta.y / (abs(delta.x) + abs(delta.y)));
if (delta.x < 0.0) {
result = 2.0f - result;
} else {
result = 4.0f + result;
}
}
return result;
}
Fowler Angles
from: http://paulbourke.net/geometry/fowler//*
This function is due to Rob Fowler. Given dy and dx between 2 points
A and B, we calculate a number in [0.0, 8.0) which is a monotonic
function of the direction from A to B.
(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0) correspond to
( 0, 45, 90, 135, 180, 225, 270, 315, 360) degrees, measured
counter-clockwise from the positive x axis.
*/
double FowlerAngle(dy,dx)
double dy,dx;
{
double adx, ady; /* Absolute Values of Dx and Dy */
int code; /* Angular Region Classification Code */
adx = (dx < 0) ? -dx : dx; /* Compute the absolute values. */
ady = (dy < 0) ? -dy : dy;
code = (adx < ady) ? 1 : 0;
if (dx < 0) code += 2;
if (dy < 0) code += 4;
switch (code)
{
case 0: return (dx==0) ? 0 : ady/adx; /* [ 0, 45] */
case 1: return (2.0 - (adx/ady)); /* ( 45, 90] */
case 3: return (2.0 + (adx/ady)); /* ( 90,135) */
case 2: return (4.0 - (ady/adx)); /* [135,180] */
case 6: return (4.0 + (ady/adx)); /* (180,225] */
case 7: return (6.0 - (adx/ady)); /* (225,270) */
case 5: return (6.0 + (adx/ady)); /* [270,315) */
case 4: return (8.0 - (ady/adx)); /* [315,360) */
}
}