C# 计算三维网格的体积

C# 计算三维网格的体积,c#,algorithm,computational-geometry,C#,Algorithm,Computational Geometry,我厌倦了计算三维物体的体积(立方体,圆柱体…),有人能帮我吗 有这个问题吗?问题是,如何计算物体的体积 基于三角形的坐标。我的班做得不好,有人帮我吗 去上课吗 谢谢 public class Algorithm { private Mesh _mesh { get; set; } public Algorithm(Mesh mesh) { _mesh = mesh; } private double SignedVolumeOfTri

我厌倦了计算三维物体的体积(立方体,圆柱体…),有人能帮我吗

有这个问题吗?问题是,如何计算物体的体积

基于三角形的坐标。我的班做得不好,有人帮我吗

去上课吗

谢谢

public class Algorithm
{
    private  Mesh _mesh { get; set; }

    public Algorithm(Mesh mesh)
    {
        _mesh = mesh;
    }

    private double SignedVolumeOfTriangle(Vector3 p1, Vector3 p2, Vector3 p3)
    {
        var v321 = p3.X * p2.Y * p1.Z;
        var v231 = p2.X * p3.Y * p1.Z;
        var v312 = p3.X * p1.Y * p2.Z;
        var v132 = p1.X * p3.Y * p2.Z;
        var v213 = p2.X * p1.Y * p3.Z;
        var v123 = p1.X * p2.Y * p3.Z;
        return (1.0 / 6.0) * (-v321 + v231 + v312 - v132 - v213 + v123);
    }

    public double VolumeOfMesh()
    {
        double volume = 0.0;

        Vector3[] vertices = _mesh.Vertices;
        int[] triangles = _mesh.Triangles;

        for (int i = 0; i < _mesh.Triangles.Length; i += 3)
        {
            Vector3 p1 = vertices[triangles[i + 0]];
            Vector3 p2 = vertices[triangles[i + 1]];
            Vector3 p3 = vertices[triangles[i + 2]];

            volume += SignedVolumeOfTriangle(p1, p2, p3);
        }

        return Math.Abs(volume);
    }
}



public  class Mesh
{
    public Mesh(Vector3[] _vertices,int[] _triangles)
    {
        Vertices = _vertices;
        Triangles = _triangles;
    }

    public Vector3[] Vertices { get; set; }

    public int[] Triangles { get; set; }
}


public class Vector3
{
    public Vector3()
    {

    }

    public Vector3(double x,double y,double z)
    {
        X = x;
        Y = y;
        Z = z;
    }

    public double X { get; set; }

    public double Y { get; set; }

    public double Z { get; set; }
}



private void button1_Click(object sender, EventArgs e)
{
        Vector3[] vers = new Vector3[8] {
                                    new Vector3 {X = 5,Y = 5,Z =5},
                                    new Vector3 {X = 15,Y = 5,Z =5},
                                    new Vector3 {X = 15,Y = 15,Z =5},
                                    new Vector3 {X = 5,Y = 15,Z =5},
                                    new Vector3 {X = 5,Y = 5,Z =15},
                                    new Vector3 {X = 15,Y = 5,Z =15},
                                    new Vector3 {X = 15,Y = 15,Z =15},
                                    new Vector3 {X = 5,Y = 15,Z =15},
        };

        int[] trs = new int[36] { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 
                                  1, 6, 2, 1, 5, 6, 0, 4, 7, 0, 7, 3,
                                  0, 1, 5, 0, 5, 4, 3, 2, 6,3, 6, 7 };


        Mesh mesh = new Mesh(vers, trs);
        Algorithm algo = new Algorithm(mesh);
        var vol = algo.VolumeOfMesh();

        MessageBox.Show(vol.ToString());
}
公共类算法
{
私有网格_网格{get;set;}
公共算法(网格)
{
_网格=网格;
}
私有双签名卷三角(向量3 p1、向量3 p2、向量3 p3)
{
变量v321=p3.X*p2.Y*p1.Z;
变量v231=p2.X*p3.Y*p1.Z;
变量v312=p3.X*p1.Y*p2.Z;
var v132=p1.X*p3.Y*p2.Z;
变量v213=p2.X*p1.Y*p3.Z;
变量v123=p1.X*p2.Y*p3.Z;
返回(1.0/6.0)*(-v321+v231+v312-v132-v213+v123);
}
公共双卷FMESH()
{
双体积=0.0;
向量3[]顶点=_mesh.vertices;
int[]三角形=_mesh.triangles;
对于(int i=0;i<_mesh.Triangles.Length;i+=3)
{
向量3 p1=顶点[三角形[i+0]];
向量3 p2=顶点[三角形[i+1]];
向量3 p3=顶点[三角形[i+2]];
体积+=三角形的签名体积(p1、p2、p3);
}
返回Math.Abs(体积);
}
}
公共类网格
{
公共网格(矢量3[]_顶点,int[]_三角形)
{
顶点=_个顶点;
三角形=_三角形;
}
公共向量3[]顶点{get;set;}
公共int[]三角形{get;set;}
}
公共类向量3
{
公共向量3()
{
}
公共向量3(双x,双y,双z)
{
X=X;
Y=Y;
Z=Z;
}
公共双X{get;set;}
公共双Y{get;set;}
公共双Z{get;set;}
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
Vector3[]vers=新Vector3[8]{
新向量3{X=5,Y=5,Z=5},
新向量3{X=15,Y=5,Z=5},
新向量3{X=15,Y=15,Z=5},
新向量3{X=5,Y=15,Z=5},
新向量3{X=5,Y=5,Z=15},
新向量3{X=15,Y=5,Z=15},
新向量3{X=15,Y=15,Z=15},
新向量3{X=5,Y=15,Z=15},
};
int[]trs=新的int[36]{0,1,2,0,2,3,4,5,6,4,6,7,
1, 6, 2, 1, 5, 6, 0, 4, 7, 0, 7, 3,
0, 1, 5, 0, 5, 4, 3, 2, 6,3, 6, 7 };
网格=新网格(vers、trs);
算法algo=新算法(网格);
var vol=算法VolumeOfMesh();
Show(vol.ToString());
}
我的测试结果是vol=666666,但应该是1000。

double v132=(p3.X-基点.X)*(p3.Y-基点.Y)*(p2.Z-基点.Z)

根据它应该是不正确的(注意p1.X而不是p3.X):

var v132=p1.X*p3.Y*p2.Z

编辑

虽然您将此答案标记为正确,但我测试了代码并发现了更多错误

通过如下调整三角形索引,三角形并非全部朝外(或向内):

0, 1, 2,
0, 2, 3,
4, 6, 5,
4, 7, 6,// adjusted
1, 6, 2,
1, 5, 6,
0, 7, 4,// adjusted
0, 3, 7,// adjusted
0, 5, 1,// adjusted
0, 4, 5,// adjusted
3, 2, 6,
3, 6, 7

所有法线都朝外。然后计算返回-1000减去值,具体取决于基准偏移量。

可能的重复:@bobobo:它不是重复的。这一个实际上有一个问题,而这一个似乎使用了这里的答案。你的代码做了什么不正确的事情?它不能编译吗?它是否编译但运行时失败?它运行但产生不正确的结果吗?好的,它运行正确,但给出不正确的结果-(当然你需要减去基点。你链接到的答案是使用原点作为基点,这就是为什么减法不存在的原因。但是它提到了这个事实。嗨,我只是替换了返回值(1.0f/6.0f)*(-v321+v231+v312-v132-v213+v123);通过返回(-v321+v231+v312-v132-v213+v123)@Ali:你能解释一下你的评论吗?我不明白。我刚刚删除了(1.0f/6.0f)那么你为什么要删除1.0/6.0?你是否应用了我建议的更改?