两个向量之间的角度是否反射? (C#)

Is angle between 2 vectors reflex? (C#)

我需要能够检查构成形状的一部分的三点(A、B 和 C)之间的角度是否为反射角(> PI 弧度),如下图所示(抱歉画得不好技能!):

我的点应该总是逆时针的,我总是想测量形状内侧的角度

我目前正在使用以下代码执行此操作:

//triangle[] is an array of the three points I am testing, corresponding
// to [A, B, C] on the diagram above

//Vectors from B to A and C
PointF toA = PointFVectorTools.difference(triangle[0], triangle[1]);
PointF toC = PointFVectorTools.difference(triangle[2], triangle[1]);

double angle = Math.Atan2(toB.Y, toB.X) - Math.Atan2(toA.Y, toA.X);

//Put angle in range 0 to 2 PI
if (angle < 0) angle += 2 * Math.PI;
return angle > Math.PI;

到目前为止,这在我尝试过的所有情况下都有效,但是对于这些协调它不起作用:

(其中 B=(2,3) )

我得到的角度是 ~-0.5,而我期望是 ~+0.5。知道为什么这是错误的吗?

更新

我已经尝试实施 Nico 的解决方案,虽然我在理论上理解它,但在尝试实施它时却感到非常头疼。这是到目前为止的代码:

//Vector A -> B
float dx = triangle[1].X - triangle[0].X;
float dy = triangle[1].Y - triangle[0].Y;

//Left normal = (y, -x)
PointF leftDir = new PointF(dy, -dx);

//Vector B -> C
dx = triangle[2].X - triangle[1].X;
dy = triangle[2].Y - triangle[1].Y;

//Dot product of B->C and Left normal
float dot = dx * leftDir.X + dy * leftDir.Y;
return dot < 0;

我不确定你代码中的 toB 是如何定义的,而且我也不熟悉 PointF

无论如何你应该使用余弦规则 c^2 = a^2 + b^2 - 2ab cos(C)(其中 a,b,c 是三角形边的长度,C 是对着 c 的角度) :

public bool IsReflex(... triangle)
{
    var a = GetVectorLength(triangle[0].x, triangle[0].y, triangle[1].x, triangle[1].y);
    var b = GetVectorLength(triangle[1].x, triangle[1].y, triangle[2].x, triangle[2].y);
    var c = GetVectorLength(triangle[2].x, triangle[2].y, triangle[0].x, triangle[0].y);

    var cosC = (c*c - a*a - b*b) / (2*a*b);
    var C = Math.Acos(cosC); // this returns a value between 0 and pi

    return Math.Abs(C) > (Math.PI/2);
}

private double GetVectorLength(double x0, double y0, double x1, double y1)
{
    // using Pythagoras
    var sideX = x0 - x1;
    var sideY = y0 - y1;
    return Math.Sqrt(sideX*sideX + sideY*sideY);
}

下面我假设x轴指向右边,y轴指向上方。如果您的情况并非如此,您可能需要切换一些标志。

如果你有线段(x1, y1) - (x2, y2)并且点是逆时针排序的,你就知道形状在线段的左边。指向线段左侧的正交方向向量为:

leftDir = (y1 - y2, x2 - x1)

连同线段,这个方向定义了一半space。如果后面的角是凸角,则第三个点一定在这一半space内。如果不是这种情况,则角度是凹的(你显然称之为反射):

你可以判断点是否与点积在同一半space:

isConcave = dot(p3 - p2, leftDir) < 0

在代码中:

float dx = x3 - x2;
float dy = y3 - y2;
float dot = dx * leftDir.x + dy * leftDir.y
return dot < 0;