说明
多边形重心需要对多边形分割,分成小三角形来进行计算,因为计算时面积是有符号的,所以对于凹多边形也是适用的。
几何
我们依次取多边形的两个顶点,再加上坐标原点(0, 0, 0),就构成了一个小三角形。这个小三角形的重心很好求,就是两个顶点的平均值,而面积也可以用向量叉乘来计算。
需要注意的是,我们要计算的面积是带有符号的,也就是可能是负的。所以不能直接用叉乘后得到向量的长度来计算,需要先计算出一个法线,再将代表小三角形面积的叉乘向量与法线比较,判断正负。
我们这里,直接用第一个小三角形的法线,代表了整个多边形的法线,并将其归一化,也就令其长度为一。再将各个小三角形的叉乘向量与该法线点乘,就得到了带有符号的小三角形面积。
代码
///重心
static func barycenter(polygon:Polygon) -> simd_float3 {
var center = simd_float3.zero
if polygon.count <= 3 {
for point in polygon.points {
center += point
}
return center / Float(polygon.count)
}
var area:Float = 0
var first = polygon.points[polygon.count - 1]
var second = polygon.points[0]
//归一化的法线
let n = normalize(cross(first, second))
for point in polygon.points {
second = point
//计算以 first、second 和 原点(0,0,0) 组成的三角形,重心及有向面积
let triangleCenter = (first + second)/2
let triangleArea = dot(cross(first, second), n)
center += triangleCenter * triangleArea
first = second
area += triangleArea
}
return center / area / 3
}