我試圖計算位於平面上的多邊形面積(一個集合共麪點形成非相交封閉形狀),並且我知道一個方法那可以計算出area of an irregular (or any) polygon in two dimensions - 但不是三個。我的解決方案是旋轉平面,使其在z方向上正常爲0(因此我可以將它視爲2D),然後運行2D區域函數。計算平面上封閉多邊形的面積
問題是我不知道如何實際確定旋轉軸,並將其平面化爲Z軸。我通過我可以找到的三維旋轉最簡單的方法進行旋轉:Rotation Matrices。所以,鑑於我正在嘗試使用旋轉矩陣來進行旋轉,我如何計算角度來旋轉我的平面,使其與另一個矢量的方向相同?我實際上並不知道很多微積分或歐幾里德幾何,所以無論哪種解決方案都需要我至少教導我自己,這是理想的解決方案。有沒有更好的辦法?
下面是我的嘗試,它甚至沒有接近Z軸上的平面。這是我的「Surface」類的一個實例方法,它是我的「Plane」類的衍生物,並具有形成閉合多邊形的共麪點陣列(IntersectPoints)。
public virtual double GetArea()
{
Vector zUnit = new Vector(0, 0, 1); //vector perprendicualr to z
Vector nUnit = _normal.AsUnitVector();
Surface tempSurface = null;
double result = 0;
if (nUnit != zUnit && zUnit.Dot(nUnit) != 0) //0 = perprendicular to z
{
tempSurface = (Surface)Clone();
double xAxisAngle = Vector.GetAxisAngle(nUnit, zUnit, Physics.Formulae.Axes.X);
double yAxisAngle = Vector.GetAxisAngle(nUnit, zUnit, Physics.Formulae.Axes.Y);
double rotationAngle = Vector.GetAxisAngle(nUnit, zUnit, Physics.Formulae.Axes.Z);
tempSurface.Rotate(xAxisAngle, yAxisAngle, rotationAngle); //rotating plane so that it is flat on the Z axis
}
else
{
tempSurface = this;
}
for (int x = 0; x < tempSurface.IntersectPoints.Count; x++) //doing a cross sum of each point
{
Point curPoint = tempSurface.IntersectPoints[x];
Point nextPoint;
if (x == tempSurface.IntersectPoints.Count - 1)
{
nextPoint = tempSurface.IntersectPoints[0];
}
else
{
nextPoint = tempSurface.IntersectPoints[x + 1];
}
double cross1 = curPoint.X * nextPoint.Y;
double cross2 = curPoint.Y * nextPoint.X;
result += (cross1 - cross2); //add the cross sum of each set of points to the result
}
return Math.Abs(result/2); //divide cross sum by 2 and take its absolute value to get the area.
}
這裏是我的核心輪換和獲得軸角方法:
private Vector Rotate(double degrees, int axis)
{
if (degrees <= 0) return this;
if (axis < 0 || axis > 2) return this;
degrees = degrees * (Math.PI/180); //convert to radians
double sin = Math.Sin(degrees);
double cos = Math.Cos(degrees);
double[][] matrix = new double[3][];
//normalizing really small numbers to actually be zero
if (Math.Abs(sin) < 0.00000001)
{
sin = 0;
}
if (Math.Abs(cos) < 0.0000001)
{
cos = 0;
}
//getting our rotation matrix
switch (axis)
{
case 0: //x axis
matrix = new double[][]
{
new double[] {1, 0, 0},
new double[] {0, cos, sin * -1},
new double[] {0, sin, cos}
};
break;
case 1: //y axis
matrix = new double[][]
{
new double[] {cos, 0, sin},
new double[] {0, 1, 0},
new double[] {sin * -1, 0, cos}
};
break;
case 2: //z axis
matrix = new double[][]
{
new double[] {cos, sin * -1, 0},
new double[] {sin, cos, 0},
new double[] {0, 0, 1}
};
break;
default:
return this;
}
return Physics.Formulae.Matrix.MatrixByVector(this, matrix);
}
public static double GetAxisAngle(Point a, Point b, Axes axis, bool inDegrees = true)
{ //pretty sure this doesnt actually work
double distance = GetDistance(a, b);
double difference;
switch (axis)
{
case Axes.X:
difference = b.X - a.X;
break;
case Axes.Y:
difference = b.Y - a.Y;
break;
case Axes.Z :
difference = b.Z - a.Z;
break;
default:
difference = 0;
break;
}
double result = Math.Acos(difference/distance);
if (inDegrees == true)
{
return result * 57.2957; //57.2957 degrees = 1 radian
}
else
{
return result;
}
}
你需要對3個獨立的軸旋轉,以達到你所期望的狀態?另外,你可以用一個新的座標系來表示三維形狀嗎(即:改變爲正交基準)? – Warty
我相信我需要旋轉三個獨立的軸。至於你的第二個問題,我不確定。目前,我不能。我當然可以寫一個算法來表達另一種方式,如果這樣會更容易旋轉。 – Richard
如果你可以改變你的觀點以便選擇正確的基準,你可以使用由你的多邊形中的任何非共線3點p0,p1,p2形成的基礎。新的向量空間將包含由p0 + a * basisVec0 + b * basisVec1定義的點,並且您的座標將爲[a,b]。既然你的基礎是正交的,你可以用這些[a,b]作爲插入你的2D函數的點。另外,如果您選擇沿着這條路線走下去,我堅信您可以實現與xy平面共面的方向(從而與z軸垂直)兩次旋轉。 – Warty