给定空间三角形的三个顶点(a, b, c),把这三个顶点的x, y, z分量组成一个3X3的矩阵(行矩阵与列矩阵都行,因为它们的det相等),然后计算出这个矩阵的det值。
如果 det > 0, 表示这三点是逆时针方向;
如果 det = 0, 表示这三点共线;
如果 det < 0, 表示这三点呈顺时针方向。
代码如下:
//判断三角形顶点的方向。返回1表示顺时针,0表示三点共线,-1表示逆时针。
int ccw(Point3f a, Point3f b, Point3f c){
float m00 = a.x;
float m01 = a.y;
float m02 = a.z;
float m10 = b.x;
float m11 = b.y;
float m12 = b.z;
float m20 = c.x;
float m21 = c.y;
float m22 = c.z;
// 计算det.
float f =
m00 * (m11 * m22 - m12 * m21)
+ m01 * (m12 * m20 - m10 * m22)
+ m02 * (m10 * m21 - m11 * m20);
return f > 0 ? 1 : f < 0 ? -1 : 0;
}
对于2维平面的三角形,可以简单的把z值设为0来计算。除此之外,还有一种更为简单的算法,算法描述如下:
1,用三角形顶点b减去顶点a,得到一个向量A;用顶点c减去顶点a,得到向量B,
也就是 A = b - a,B = c - a。
2,用向量A叉乘以向量B得要一个值t,也就是t = A × B,然后像判断det那样判断t值就能确定三个顶点的方向。
除此之外,t的值刚好等于这个平面三角形面积的2倍,因为t值有正负之分,所以用这种方法计算三角形面积
会有可能得到负值。
需要注意的是,2d向量原本是没有叉乘的。
代码如下:
// 2d向量的叉乘
float crossProduct(Vector2f a, Vector2f b){
float x1 = a.x, y1 = a.y;
float x2 = b.x, y2 = b.y;
return x1 * y2 - x2 * y1;
}
// 计算三角形的面积,可能为负
float triangleArea(Point2f a, Point2f b, Point2f c) {
float x1 = a.x, y1 = a.y;
float x2 = b.x, y2 = b.y;
float x3 = c.x, y3 = c.y;
return ((x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2)) * 0.5f;
}
//判断三角形顶点的方向。返回1表示顺时针,0表示三点共线,-1表示逆时针。
int ccw(Point2f a, Point2f b, Point2f c) {
float ax = a.x, ay = a.y;
float bx = b.x, by = b.y;
float cx = c.x, cy = c.y;
float v = (bx - ax) * (cy - ay) - (cx - ax) * (by - ay);
return v < 0 ? -1 : v > 0 ? 1 : 0;
}