我试图计算位于平面上的多边形面积(一个集合共面点形成非相交封闭形状),并且我知道一个方法那可以计算出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