Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取多面体(3D对象)的表面积_C#_Math_Geometry_Computational Geometry_Area - Fatal编程技术网

C# 获取多面体(3D对象)的表面积

C# 获取多面体(3D对象)的表面积,c#,math,geometry,computational-geometry,area,C#,Math,Geometry,Computational Geometry,Area,我有一个3D曲面(想想xy平面)。飞机可以倾斜。(想想一条斜坡路) 给定定义曲面的三维坐标列表(Point3D1X,Point3D1Y,Point3D1Z,Point3D12X,Point3D2Y,Point3D2Z,Point3D3Y,point3dz,等等),如何计算曲面的面积 注意,我这里的问题类似于在二维平面上求面积。在二维平面中,我们有一个定义多边形的点列表,使用这个点列表我们可以找到多边形的区域。现在假设所有这些点都有z值,它们在3D中升高以形成曲面。我的问题是如何找到该三维曲面的面

我有一个3D曲面(想想xy平面)。飞机可以倾斜。(想想一条斜坡路)

给定定义曲面的三维坐标列表(
Point3D1X
Point3D1Y
Point3D1Z
Point3D12X
Point3D2Y
Point3D2Z
Point3D3Y
point3dz
,等等),如何计算曲面的面积


注意,我这里的问题类似于在二维平面上求面积。在二维平面中,我们有一个定义多边形的点列表,使用这个点列表我们可以找到多边形的区域。现在假设所有这些点都有
z
值,它们在3D中升高以形成曲面。我的问题是如何找到该三维曲面的面积?

您可以根据二维解导出解

考虑由一堆较小三角形组成的多边形

将每个三角形投影回XY平面。可以显示原始三角形的面积是投影三角形面积的1/(n.k)倍。(这里n是垂直于包含多边形的平面的单位,k是z方向上的单位向量)

因此,原始图形的总面积是投影到XY平面的多边形面积的1/(n.k)倍。可以使用现有的二维公式计算出

可以通过(e1 x e2)/| | e1 x e2 | |计算n,其中e1和e2是多边形的任意两条非平行边


当然,通过投影到XZ或YZ平面,可以获得更好(更精确)的结果。。你应该选择法线最接近你的平面的那一个。

我不知道如何优化这个方法(我以前没有在代码中这样做过),但数学上接近它的方法是将你的形状分割成三角形,然后很容易计算和求和三角形的面积。(请记住:三角形的面积是宽度*高度*0.5-您需要计算非直角三角形的高度。)

在3D中执行这些操作通常意味着每个阶段都需要进行一次计算。例如,在2D中,两点之间的距离(形状一侧的长度)是这样计算的(PSEDOOCODE,因为我在这台机器上没有VS):

在三个维度中,即:

double DistanceBetween(Point3d a, Point3d b)
{
   double dx = a.x - b.x;
   double dy = a.y - b.y;
   double dz = a.z - b.z;
   return SquareRoot(dx*dx + dy*dy + dz*dz);
}

将形状拆分为任意三角形只需一次拾取任意三个相邻顶点,直到最后三个顶点为止

既然你说它是一个多面体,stacker的链接()是适用的

以下是我针对您的情况对C代码的近似C#翻译:

// NOTE: The original code contained the following notice:
// ---------------------------------------
// Copyright 2000 softSurfer, 2012 Dan Sunday
// This code may be freely used and modified for any purpose
// providing that this copyright notice is included with it.
// iSurfer.org makes no warranty for this code, and cannot be held
// liable for any real or imagined damage resulting from its use.
// Users of this code must verify correctness for their application.
// ---------------------------------------
// area3D_Polygon(): computes the area of a 3D planar polygon
//    Input:  int n = the number of vertices in the polygon
//            Point[] V = an array of n+2 vertices in a plane
//                       with V[n]=V[0] and V[n+1]=V[1]
//            Point N = unit normal vector of the polygon's plane
//    Return: the (float) area of the polygon
static float
area3D_Polygon( int n, Point3D[] V, Point3D N )
{
    float area = 0;
    float an, ax, ay, az;  // abs value of normal and its coords
    int   coord;           // coord to ignore: 1=x, 2=y, 3=z
    int   i, j, k;         // loop indices

    // select largest abs coordinate to ignore for projection
    ax = (N.x>0 ? N.x : -N.x);     // abs x-coord
    ay = (N.y>0 ? N.y : -N.y);     // abs y-coord
    az = (N.z>0 ? N.z : -N.z);     // abs z-coord

    coord = 3;                     // ignore z-coord
    if (ax > ay) {
        if (ax > az) coord = 1;    // ignore x-coord
    }
    else if (ay > az) coord = 2;   // ignore y-coord

    // compute area of the 2D projection
    for (i=1, j=2, k=0; i<=n; i++, j++, k++)
        switch (coord) {
        case 1:
            area += (V[i].y * (V[j].z - V[k].z));
            continue;
        case 2:
            area += (V[i].x * (V[j].z - V[k].z));
            continue;
        case 3:
            area += (V[i].x * (V[j].y - V[k].y));
            continue;
        }

    // scale to get area before projection
    an = Math.Sqrt( ax*ax + ay*ay + az*az);  // length of normal vector
    switch (coord) {
    case 1:
        area *= (an / (2*ax));
        break;
    case 2:
        area *= (an / (2*ay));
        break;
    case 3:
        area *= (an / (2*az));
        break;
    }
    return area;
}
//注意:原始代码包含以下通知:
// ---------------------------------------
//版权所有2000 softSurfer,2012 Dan Sunday
//本规范可出于任何目的自由使用和修改
//前提是本版权声明包含在其中。
//iSurfer.org对此代码不作任何保证,并且不能保留
//对因其使用而造成的任何实际或想象的损害负责。
//此代码的用户必须验证其应用程序的正确性。
// ---------------------------------------
//area3D_Polygon():计算3D平面多边形的面积
//输入:int n=多边形中的顶点数
//点[]V=平面中n+2个顶点的数组
//V[n]=V[0]和V[n+1]=V[1]
//点N=多边形平面的单位法向量
//返回:多边形的(浮动)区域
静态浮动
area3D_多边形(int n,Point3D[]V,Point3D n)
{
浮动面积=0;
float an,ax,ay,az;//法线及其坐标的abs值
int-coord;//要忽略的坐标:1=x,2=y,3=z
int i,j,k;//循环索引
//选择要忽略投影的最大abs坐标
ax=(N.x>0?N.x:-N.x);//abs x-coord
ay=(N.y>0?N.y:-N.y);//abs y-coord
az=(N.z>0?N.z:-N.z);//abs z-coord
coord=3;//忽略z-coord
如果(ax>ay){
如果(ax>az)坐标=1;//忽略x坐标
}
如果(ay>az)坐标=2;//忽略y坐标
//计算二维投影的面积

对于(i=1,j=2,k=0;i你是指三维平面多边形的面积吗

  • 我认为这是正确的,但我认为最简单的方法是——不管是2D还是3D,使用以下公式:

    area = sum(V(i+1) × V(i))/2;
    
    其中,
    ×

    执行此操作的代码是:

        public double Area(List<Point3D> PtList)
        {
    
            int nPts = PtList.Count;
            Point3D a;
            int j = 0;
    
            for (int i = 0; i < nPts; ++i)
            {
                j = (i + 1) % nPts;
                a += Point3D.Cross(PtList[i], PtList[j]);
            }
            a /= 2;
            return Point3D.Distance(a,default(Point3D));
        }
    
        public static Point3D Cross(Point3D v0, Point3D v1)
        {
            return new Point3D(v0.Y * v1.Z - v0.Z * v1.Y,
                v0.Z * v1.X - v0.X * v1.Z,
                v0.X * v1.Y - v0.Y * v1.X);
        }
    
    公共双区(列表列表)
    {
    int nPts=PtList.Count;
    点3D a;
    int j=0;
    对于(int i=0;i
    请注意,该解决方案不依赖于到x平面的投影,我认为这很笨拙


    你认为呢?

    另一个不需要创建多边形网格的解决方案是围绕周长进行轮廓积分。你可以使用将面积积分转换为轮廓积分,然后使用一些简单的方法来积分和求和每个贡献。你必须有周长的定义


    这个过程也适用于有孔的2D形状。你只需定义一个从外周长到孔的切口,围绕孔进行积分,然后返回到周长。

    @Graviton我无法对上述答案发表评论,因此我将提交一个新的答案

    这可能是我不熟悉c#语法,但我相信你的答案缺少单位法向量的点积
        public double Area(List<Point3D> PtList)
        {
    
            int nPts = PtList.Count;
            Point3D a;
            int j = 0;
    
            for (int i = 0; i < nPts; ++i)
            {
                j = (i + 1) % nPts;
                a += Point3D.Cross(PtList[i], PtList[j]);
            }
            a /= 2;
            return Point3D.Distance(a,default(Point3D));
        }
    
        public static Point3D Cross(Point3D v0, Point3D v1)
        {
            return new Point3D(v0.Y * v1.Z - v0.Z * v1.Y,
                v0.Z * v1.X - v0.X * v1.Z,
                v0.X * v1.Y - v0.Y * v1.X);
        }
    
    area = n.sum( V(i+1) x V(i) )/2;
    
    n = (V1-V0)x(V2-V0)/magnitude((V1-V0)x(V2-V0))
    
      function getArea (vecs) {
        var area = 0;
        var vecs = [];
        var j = 0;
        var a = new Vector(0,0,0);
    
        for (var i = 0; i < vecs.length; i++) {
          j = (i + 1) % vecs.length;
          a = a.add( vecs[i].cross(vecs[j]) );
        }
        a = a.divide(2);
        var v1 = vecs[1].subtract(vecs[0]);
        var v2 = vecs[2].subtract(vecs[0]);
        var normal = v1.cross(v2);
        normal = normal.unit();
        // area = a.length()/10000; // convert to m2
        area = (normal.dot(a))/10000;
        return area;
      };