12

3D サーフェスがあります (xy 平面について考えてください)。平面は傾けることができます。(坂道を考えてみてください)。

表面を定義する 3D 座標のリスト ( Point3D1XPoint3D1YPoint3D1ZPoint3D12XPoint3D2YPoint3D2ZPoint3D3XなどPoint3D3Y)が与えられた場合Point3D3Z、表面の面積を計算する方法は?

ここでの私の質問は、2D 平面で面積を見つけることに類似していることに注意してください。2D 平面では、多角形を定義する点のリストがあり、この点のリストを使用して多角形の面積を見つけることができます。zここで、これらすべてのポイントが3D で隆起してサーフェスを形成するような値を持っていると仮定します。私の質問は、その 3D サーフェスの面積を見つける方法です。

4

7 に答える 7

11

多面体って言うから、スタッカーズリンク(http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm ) が適用されます。

あなたの状況での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;
}
于 2010-02-28T09:46:17.513 に答える
1

この方法の最適化については知りません (以前にコードで実行したことはありません) が、数学的にアプローチする方法は、形状を三角形に分割することです。三角形の面積は簡単に計算され、合計されます。(覚えておいてください: 三角形の面積は幅 * 高さ * 0.5 です。直角でない三角形の高さを計算する必要があります。)

これらのことを 3D で行うということは、通常、各段階でもう 1 つの計算が必要になることを意味します。たとえば、2D では、2 点間の距離 (形状の辺の長さ) は次のように計算されます (このマシンには VS がないため、疑似コードです)。

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

3 次元では次のようになります。

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);
}

形状を任意の三角形に分割するには、最後の 3 つになるまで、隣接する 3 つの頂点を一度に選択するだけです。

于 2010-02-28T09:35:23.680 に答える
1

@Graviton上記の回答にはコメントできないため、新しい回答を送信します。

これは私の c# 構文の不慣れかもしれませんが、あなたの答えには単位法線ベクトルとの内積が欠けていると思います。式は次のようになります。

area = n.sum( V(i+1) x V(i) )/2;

ここでn、 は平面に対する単位法線ベクトル、.内積および外積を指しxます。

法線は、ポリゴンの任意の 3 つのベクトルを使用して計算できます。

n = (V1-V0)x(V2-V0)/magnitude((V1-V0)x(V2-V0))

以下は、Vector.js ライブラリを使用した JavaScript の実装です。

  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;
  };
于 2013-05-23T09:40:32.567 に答える
1

ポリゴンのメッシュを作成する必要のない別の解決策は、周囲の輪郭積分を行うことです。グリーンの定理を使用して面積積分を等高線積分に変換し、ガウス求積法のような単純なものを使用して各寄与を積分および合計します。境界の定義が必要です。

このプロセスは、穴のある 2D 形状でも機能します。外周から穴までのカットを定義し、穴の周りを統合して、外周に戻るだけです。

于 2010-02-28T12:03:27.093 に答える
1

2D ソリューションの観点からソリューションを導き出すことができます。

小さな三角形のヒープから構成される多角形を考えてみましょう。

各三角形を XY 平面に投影します。元の三角形の面積が投影された三角形の面積の 1/(nk) 倍であることを示すことができます。(ここで、n はポリゴンを含む平面に垂直な単位であり、k は z 方向の単位ベクトルです)

したがって、オリジナルの総面積は、XY 平面に投影されたポリゴンの面積の 1/(nk) 倍になります。これは、既存の 2D 式を使用して計算できます。

n は (e1 x e2 ) / || で計算できます。e1 x e2 || e1 と e2 は、ポリゴンの平行でない 2 つのエッジです。

もちろん、XZ 平面または YZ 平面に投影すると、より良い (より正確な) 結果が得られる場合があります。平面の法線に最も近い法線を持つものを選択する必要があります。

于 2010-02-28T09:27:48.097 に答える