前段时间有写过一个计算多边形角度的代码,这里给它整理整理,留给自己也送给萌新。
看左下图,这是一个多环的多边形,一个外环(内部为多边形内部区域),一个内环(外部为多边形内部区域),同时多边形中任意一个角不等于零角(等于 0° 的角)或周角(等于 360° 的角)。注意:本文下文所讨论的多边形求角度不包含零角和周角。
现在我们要求 ∠ABC 和∠DEF 的大小。那咋算唻?
1. 内积计算夹角
给它加上坐标系(坐标是自己配的,计算出的角度值不一定准确,但不影响角度大小的关系), 如右上图。角度采用向量的内积来求。
以上面的 ∠ABC 为例,数学计算公式如下。
于是乎,有:
角度计算代码如下:
public struct CxPoint
{
public CxPoint(double x, double y)
{
X = x;
Y = y;
}
public double X;
public double Y;
}
///
/// 计算三点角度,p1-p2-p3为沿环方向的三个连续顶点,其中p2为角点。计算结果范围 0° - 180°,-1为无效值
///
private static double CalculationAngle(CxPoint p1, CxPoint p2, CxPoint p3)
{
//Cos(Angle) = a•b/(|a|*|b|)
double x1 = p1.X - p2.X, y1 = p1.Y - p2.Y; //向量 a
double x2 = p3.X - p2.X, y2 = p3.Y - p2.Y; //向量 b
//零向量,存在共点
if (x1 == 0 && y1 == 0) return -1;
if (x2 == 0 && y2 == 0) return -1;
double v = x1 * x2 + y1 * y2; //向量内积 a•b
double val = Math.Sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2)); //a,b模长乘积 |a|*|b|
double CosAngle = v / val; //求出来的值可能略小于 -1 或者略大于 1,此时 Angle 等于 NaN
double Angle = Math.Acos(CosAngle) * 180.0 / 3.14159265358979; //两向量夹角,0-180
if (System.Double.IsNaN(Angle))
{