[英]How can I rotate a 3D array in c#?
我在原点(0,0,0)的3d数组中有一个二进制对象。 我需要在z轴上旋转该对象。 如何以任意角度旋转没有固定大小的多维数组?
我创建了一个3d点类:
public class Point3
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}
我正在考虑在每个点上做foreach并旋转它:
foreach (Point3 p in listPoint3)
{
RotatePoint(p, angle);
}
有什么建议吗?
您可以创建一个例程,使用参数方程式旋转每个点,以旋转3d对象。
x'= x * cos(o)-y * sin(o)
y'= y * sin(o)-y * cos(o)
则z
private Point3 RotatePoint(Point3 p0, int angle)
{
Point3 p = new Point3()
{
X = p0.X * Math.Cos(angle) - p0.Y * Math.Sin(angle),
Y = p0.X * Math.Sin(angle) + p0.Y * Math.Cos(angle),
Z = p0.Z,
};
return p;
}
您需要知道要在哪个轴上旋转。 但这只是一个问题,在哪里看。 (命名空间为System.Windows.Media.Media3D)
您可以尝试以下方法:
double angle = 45;
RotateTransform3D zrotation = new RotateTransform3D(new AxisAngleRotation3D(
new Vector3D(0, 0, 1), angle));
foreach (Point3D p in listPoint3)
{
Point3D rotatedPoint = zrotation.Transform(p);
}
您应该使用内置的Point3D
另外,如果您想堆叠这些:( 多次转换)
double zAngle = 45;
double xAngle = 10;
Transform3DGroup group = new Transform3DGroup();
group.Children.Add( new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(1, 0, 0), xAngle)));
group.Children.Add( new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), zAngle)));
foreach (Point3D p in listPoint3)
{
Point3D rotatedPoint = group.Transform(p);
}
因此,您有一个“单色对象”,该对象存储为想要绕Z轴旋转的3D位图。 您必须首先了解,经过多次旋转后,由于使用array index
这是代表对象组件坐标的自然数)导致的光学像差,最终会导致光学像差。
旋转时,任何整数值很可能会成为无理数。 传统上(不是在讨论特殊程序和框架)人们将无理数的近似值存储在double
float
或float
或decimal
变量中(只能存储有理数集的一小部分),与无理数的逼近相比没有任何意义 。通过将其存储在整数( array index
)中。
此外,即使质量损失对您的应用而言并不重要,您也必须确保您了解,从数学上讲,经过多次旋转后,您的3D形状将被原件上刻有圆柱体进行修剪平行六面体,沿Z轴。
就像这样 您说您已经制作了一个名为Point3
的类:
public class Point3 {
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}
如果已经存在此类,也许您应该遵循@Jeroen van Langen的建议并使用标准类。 好处是,如果有人在那里已经建立或将要建立一个使用该类的库,则可以立即开始使用该库。 但这现在还不那么重要。
@Alpert已经给出了很棒的C#代码,用于绕oZ轴旋转点。 这是该代码的n个“扩展方法”的改编:
public static class RotationHelpers {
public static Point3 RotatePoint(this Point3 point, int angle) {
var result = new Point3() {
X = point.X * Math.Cos(angle) - point.Y * Math.Sin(angle),
Y = point.X * Math.Sin(angle) + point.Y * Math.Cos(angle),
Z = point.Z,
};
return result;
}
...
}
您甚至可以更进一步,制作一个扩展方法,该方法绕oZ轴旋转一系列点:
public static class RotationHelpers {
...
public static IEnumerable<Point3> RotatePoints(this IEnumerable<Point3> points, int angle) {
foreach (var point in points)
yield return point.RotatePoint(angle);
}
...
}
现在您说您有一个3d基本矩阵,其中包含1和0:
int[,,] matrix;
您需要以某种方式将矩阵中的内部定义的点转换为Point3
实例的序列,旋转它们,然后将所得序列转换回int[,,]
矩阵。
可以像这样实现(记住我之前所说的质量下降):
public static class RotationHelpers {
...
public static IEnumerable<Point3> ToPoints(this int[,,] matrix) {
int lx = matrix.GetLength(0);
int ly = matrix.GetLength(1);
int lz = matrix.GetLength(2);
for (int x = 0; x < lx; x++)
for (int y = 0; y < ly; y++)
for (int z = 0; z < lz; z++) {
bool is1 = matrix[x, y, z] != 0;
if (is1)
yield return new Point3 {
X = x - lx / 2,
Y = y - ly / 2,
Z = z - lz / 2
};
}
}
...
}
这将占用WIDTH x HEIGHT x DEPTH矩阵中的所有像元,并且对于每个不等于0的像元,它将产生一个具有该特定位置坐标的新Point3
实例。
然后可以使用前面描述的RotatePoints
方法将该序列旋转一个角度,然后可以使用以下方法将Point3
实例的结果序列“渲染”回数组:
public static class RotationHelpers {
...
public static void AssignPoints(this int[,,] matrix, IEnumerable<Point3> points) {
int lx = matrix.GetLength(0);
int ly = matrix.GetLength(1);
int lz = matrix.GetLength(2);
for (int x = 0; x < lx; x++)
for (int y = 0; y < ly; y++)
for (int z = 0; z < lz; z++)
matrix[x, y, z] = 0;
foreach (var point in points) {
// this is when quality is lost, because things like 1.7 and 1.71
// will both become =2
var x = (int)Math.Round(point.X) + lx / 2;
var y = (int)Math.Round(point.Y) + ly / 2;
var z = (int)Math.Round(point.Z) + lz / 2;
// this is where you loose parts of the object because
// it doesn't fit anymore inside the parallelepiped
if ((x >= 0) && (y >= 0) && (z >= 0) &&
(x < lx) && (y < ly) && (z < lz))
matrix[x, y, z] = 1;
}
}
...
}
要打包,可以使用所有这些方法,如下所示:
int[,,] matrix = ...
int angle = ...
IEnumerable<Point3> points = matrix.ToPoints();
IEnumerable<Point3> rotatedPoints = points.RotatePoints(angle);
matrix.AssignPoints(rotatedPoints);
// now you have the original matrix, rotated by angle
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.