我正在尝试计算由三角形组成的3D网格的质心。
编辑:事实证明我并没有这样做,我是在尝试计算重心,这不是一回事
我的代码由各种部分组成,主要包括:
我将我的结果与Rhino提供的结果进行了比较。我计算出了质心和体积:
- 使用Rhino 7对参考NURBS体进行优化。
- 使用Rhino 7对包含27k三角形的网格进行优化。
- 使用Rhino 7对包含1k三角形的简化网格进行优化。
- 使用我的代码对相同的1k三角形网格进行优化。
我不太擅长数值不稳定性:
- 我应该使用毫米而不是米吗? - 我应该使用比起原点更好的点来计算四面体有符号的体积,正如第二个参考中galinette所建议的那样?我尝试了一下,但并没有改善多少。
我的代码
在计算任何内容之前,我检查了我的网格是否正确(未提供代码):
- 封闭网格,没有裸边或任何孔; - 所有三角形的顶点都按一致的顺序排序,即正确定向朝向网格的外部。
using HelixToolkit.Wpf;
using System.Collections.Generic;
using System.Windows.Media.Media3D;
internal static class CentroidHelper
{
public static Point3D Centroid(this List<MeshGeometry3D> meshes, out double volume)
{
Vector3D centroid = new Vector3D();
volume = 0;
foreach (var mesh in meshes)
{
var c = mesh.Centroid(out double v);
volume += v;
centroid += v *c ;
}
return (centroid / volume).ToPoint3D();
}
public static Vector3D Centroid(this MeshGeometry3D mesh, out double volume)
{
Vector3D centroid = new Vector3D();
double totalArea = 0;
volume = 0;
for (int i = 0; i < mesh.TriangleIndices.Count; i += 3)
{
var a = mesh.Positions[mesh.TriangleIndices[i + 0]].ToVector3D();
var b = mesh.Positions[mesh.TriangleIndices[i + 1]].ToVector3D();
var c = mesh.Positions[mesh.TriangleIndices[i + 2]].ToVector3D();
var triangleArea = AreaOfTriangle(a, b, c);
totalArea += triangleArea;
centroid += triangleArea * (a + b + c) / 3;
volume += SignedVolumeOfTetrahedron(a, b, c);
}
return centroid / totalArea;
}
private static double SignedVolumeOfTetrahedron(Vector3D a, Vector3D b, Vector3D c)
{
return Vector3D.DotProduct(a, Vector3D.CrossProduct(b, c)) / 6.0d;
}
private static double AreaOfTriangle(Vector3D a, Vector3D b, Vector3D c)
{
return 0.5d * Vector3D.CrossProduct(b - a, c - a).Length;
}
}