0

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

角ABC

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

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

//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;
4

2 回答 2

1

在下文中,我假设 x 轴指向右侧,y 轴指向上方。如果您的场景不是这种情况,您可能需要切换一些标志。

如果您有线段(x1, y1) - (x2, y2)并且点按逆时针方向排序,则您知道形状位于线段的左侧。指向线段左侧的正交方向向量为:

leftDir = (y1 - y2, x2 - x1)

该方向与线段一起定义了一个半空间。如果跟随的角度是凸的,那么第三个点必须在这个半空间中。如果不是这种情况,则角度是凹的(您显然称之为反射):

您可以确定该点是否位于与点积相同的半空间中:

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;
于 2016-03-14T18:15:37.727 回答
1

我不确定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);
}
于 2016-03-13T15:30:29.613 回答