gpt4 book ai didi

c# - 计算三角形 3D 网格的质心

转载 作者:行者123 更新时间:2023-12-03 16:09:32 26 4
gpt4 key购买 nike

我正在尝试计算 3D 三角形网格的质心。
编辑:事实证明我不是,我试图计算重心,这是不一样的
我的代码由点点滴滴组成,主要是:

  • This nice paper by Cha Zhang and Tsuhan Chen
  • SO : How to calculate the volume of a 3D mesh object the surface of which is made up triangles
  • SO : How to compute the centroid of a mesh with triangular faces?

  • 我将我的结果与 Rhino 提供的结果进行了比较。我计算质心和体积:
  • 引用 NURBS 体积与 Rhino 7
  • 使用 Rhino 7 的 27k 三角形网格
  • 使用 Rhino 7 的简化 1k 三角形网格
  • 与我的代码相同的 1k 三角形网格。

  • enter image description here
    如您所见,计算体积效果很好,但不适用于质心,我似乎不知道为什么。我需要误差小于 0.01。我检查了好几次,但肯定有一些明显的东西。
    我不太擅长数值不稳定:
  • 我应该以毫米而不是米为单位工作吗?
  • 我应该像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;
    }
    }

    最佳答案

    原来是commonly accepted answer在堆栈溢出和整个互联网都是错误的:
    几何质心并不总是与质心重合,尽管它非常接近 .
    仅适用于某些卷,如 n-dimensional simplexesplatonic solids .
    我通过计算船舶平衡时的船体位置,将我的结果与 Rhino 的结果和现实进行了比较。
    想了很多,现在看来还是很明显的,但是非常欢迎大家来检查和批评我的方法。
    方法
    我使用了Zhang & Chen's paper中描述的方法的原理,质心。
    四面体的质心确实与其质心重合(即其顶点的等重心)。
    由四面体的有符号体积加权的质心的重心是网格的质心。
    Unit tetrahedron, from 3
    代码

    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/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com