S02E17：任意点在三角形上的重心坐标

·  阅读 1738

说明

• 代表每个顶点的权重，即受到每个顶点影响的大小；
• 将三顶点看成是局部坐标系统的 x、y、z 轴，重心坐标就是局部坐标系内的坐标；

• 重心坐标的每个分量，代表了该点分割三角形后，形成的小三角形的面积比。

代码

``````///点在三角形上的重心坐标
static func computeBarycenricCoordinate(of point:simd_float3, in triangle:Triangle) -> simd_float3? {
let e1 = triangle.point3 - triangle.point2
let e2 = triangle.point1 - triangle.point3
let e3 = triangle.point2 - triangle.point1
let d1 = point - triangle.point1
let d2 = point - triangle.point2
let d3 = point - triangle.point3

let n = cross(e1, e2)
if !n.isPerpendicular(to: d1) {
// 点与三角形不共面
return nil
}
let an = dot(cross(e1, e2), n)
if an < Float.leastNormalMagnitude {
// 退化三角形:面积为零的三角形
return nil
}
let b1 = dot(cross(e1, d3), n) / an
let b2 = dot(cross(e2, d1), n) / an
let b3 = dot(cross(e3, d2), n) / an
return simd_float3(b1, b2, b3)
}
///点在三角形上的重心坐标
static func computeBarycenricCoordinate2(of point:simd_float3, in triangle:Triangle) -> simd_float3? {
let d1 = triangle.point2 - triangle.point1
let d2 = triangle.point3 - triangle.point2
let n = cross(d1, d2)

let t = point - triangle.point1
if !n.isPerpendicular(to: t) {
// 点与三角形不共面
return nil
}
var u1,u2,u3,u4:Float
var v1,v2,v3,v4:Float
if (fabsf(n.x) >= fabsf(n.y)) && (fabsf(n.x) >= fabsf(n.z)) {
// 抛弃 x，向 yz 平面投影
u1 = triangle.point1.y - triangle.point3.y
u2 = triangle.point2.y - triangle.point3.y
u3 = point.y - triangle.point1.y
u4 = point.y - triangle.point3.y

v1 = triangle.point1.z - triangle.point3.z
v2 = triangle.point2.z - triangle.point3.z
v3 = point.z - triangle.point1.z
v4 = point.z - triangle.point3.z
} else if fabsf(n.y) >= fabsf(n.z){
// 抛弃 y，向 xz 平面投影
u1 = triangle.point1.z - triangle.point3.z
u2 = triangle.point2.z - triangle.point3.z
u3 = point.z - triangle.point1.z
u4 = point.z - triangle.point3.z

v1 = triangle.point1.x - triangle.point3.x
v2 = triangle.point2.x - triangle.point3.x
v3 = point.x - triangle.point1.x
v4 = point.x - triangle.point3.x
} else {
u1 = triangle.point1.x - triangle.point3.x
u2 = triangle.point2.x - triangle.point3.x
u3 = point.x - triangle.point1.x
u4 = point.x - triangle.point3.x

v1 = triangle.point1.y - triangle.point3.y
v2 = triangle.point2.y - triangle.point3.y
v3 = point.y - triangle.point1.y
v4 = point.y - triangle.point3.y
}
let denom = v1 * u2 - v2 * u1
if abs(denom) < Float.leastNormalMagnitude {
// 退化三角形:面积为零的三角形
return nil
}
// 计算重心坐标
let oneOverDenom = 1.0 / denom
let b0 = (v4*u2 - v2*u4) * oneOverDenom
let b1 = (v1*u3 - v3*u1) * oneOverDenom
let b2 = 1 - b0 - b1
return simd_float3(b0, b1, b2)
}

iOS