我希望我能正确理解您的问题,因为想要锐角而不是两条线相交的钝角。我对么?
相交的锐角和钝角是 180 度的互补角。IE
acute + obtuse = PI.
http://www.mathworks.com/access/helpdesk/help/techdoc/ref/atan.html
表明 atan 在 +/- pi/2 处是渐近的。
因此,atan 的两个结果之间的最大差异是 pi 或 180 度,无论您使用梯度的+/-
符号还是正0 to pi
符号。
考虑以下伪代码:
acuteAngle(m1, m2){
a = atan(m1) - atan(m2);
// if obtuse get the complementary acute angle:
if (a>PI/2)
a = PI - a;
return a;
}
该函数acuteAngle
以数学方式说明了您需要做什么。
但是,它不能用于 PI/2 邻域中的角度值,因为角度与该邻域中的结果的二进制比较是否表示钝角或锐角是有问题的。
因此,我们必须比较两条线的点的坐标。我们找出由 形成的第三条线是否[(x2,y2)(x3,y3)]
比假设的斜边更短、相等或更长。
根据毕达哥拉斯定理,如果角度正好是 PI/2 或 90 度,则形成斜边。我们称他的假设斜边线为 L3Hypo。
通过你脑海中的几何形象化,
- 如果第 3 条线比 L3Hypo 长,则角度为钝角。
- 如果较短,则角度为锐角。
- 否则,完美90。
所以,
L1.lengthSquared = sq(x2-x1) + sq(y2-y1)
L2.lengthSquared = sq(x3-x1) + sq(y3-y1)
L3Hypo.lengthSquared = L1.lengthSquared + L2.lengthSquared
L3.lengthSquared = sq(x3-x2) + sq(y3-y2)
因此,下面的伪代码,
struct Point{
double x, y;
}
// no need to struct, for clarity only
struct Line{
double lengthSquared;
}
#define sq(n) (n*n)
int isObtuse(Point P1, P2, P3){
Line L1, L2, L3, L3Hypo;
L1.lengthSquared = sq(P2.x-P1.x) + sq(P2.y-P1.y);
L2.lengthSquared = sq(P3.x-P1.x) + sq(P3.y-P1.y);
L3Hypo.lengthSquared = L1.lengthSquared + L2.lengthSquared;
L3.lengthSquared = sq(P3.x-P2.x) + sq(P3.y-P2.y);
if (L3>L3Hypo) return 1; //obtuse
else if (L3<L3Hypo) return -1; //acute
else return 0;
}
假设您已经拥有函数 getGradient(Point P, Q):
double m1m2 = getGradient(P1,P2);
double m1m3 = getGradient(P1,P3);
double a = Abs(atan(m1m2) - atan(m1m3));
if (isObtuse(P1, P2, P3)>0)
a = PI - a;
我可能在伪代码中犯了一些拼写错误(希望不会),但我展示了这个概念的要点。如果是这样,有人可能会很好地编辑掉错别字。
进一步
然而,在仔细考虑之后,我发现由于指令,精确度的斗争在其最薄弱的环节上
#define PI 3.14159blah..blah..blah.
所以,我们不妨省去所有的麻烦,干脆这样做:
double m1m2 = getGradient(P1,P2);
double m1m3 = getGradient(P1,P3);
double a = Abs(atan(m1m2) - atan(m1m3));
double b = PI - a;
return min(a, b);//the smaller of the two is the acute