我需要能够检查构成形状一部分的三个点(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;
答案 0 :(得分:1)
我不确定代码中的toB
是如何定义的,而且我也不熟悉PointF
。
无论如何,你应该使用余弦规则c^2 = a^2 + b^2 - 2ab cos(C)
(其中a,b,c
是三角形边长,C
是对向c
的角度:< / p>
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);
}
答案 1 :(得分: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;