我正在尝试计算 3D 三角形网格的质心。
编辑:事实证明我不是,我试图计算重心,这是不一样的
我的代码由点点滴滴组成,主要是:
我将我的结果与 Rhino 提供的结果进行了比较。我计算质心和体积:
如您所见,计算体积效果很好,但不适用于质心,我似乎不知道为什么。我需要误差小于 0.01。我检查了好几次,但肯定有一些明显的东西。
我不太擅长数值不稳定:
我的代码
在计算任何东西之前,我检查我的网格是否正确(未提供代码):
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;
}
}
最佳答案
原来是commonly accepted answer在堆栈溢出和整个互联网都是错误的:
几何质心并不总是与质心重合,尽管它非常接近 .
仅适用于某些卷,如 n-dimensional simplexes和 platonic solids .
我通过计算船舶平衡时的船体位置,将我的结果与 Rhino 的结果和现实进行了比较。
想了很多,现在看来还是很明显的,但是非常欢迎大家来检查和批评我的方法。
方法
我使用了Zhang & Chen's paper中描述的方法的原理,质心。
四面体的质心确实与其质心重合(即其顶点的等重心)。
由四面体的有符号体积加权的质心的重心是网格的质心。
代码
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();
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 tetrahedronVolume = SignedVolumeOfTetrahedron(a, b, c);
centroid += tetrahedronVolume * (a + b + c) / 4.0d;
volume += tetrahedronVolume;
}
return centroid / volume;
}
private static double SignedVolumeOfTetrahedron(Vector3D a, Vector3D b, Vector3D c)
{
return Vector3D.DotProduct(a, Vector3D.CrossProduct(b, c)) / 6.0d;
}
}
关于c# - 计算三角形 3D 网格的质心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66891594/