DTranform3d和DMatrix理解

DTransform3d 是 Bentley 中几何变换的类,通过它可以快速生成变换矩阵。

程序集 命名空间
Bentley.GeometryNET.Structs.dll Bentley.GeometryNET

DPoint3d

代表点,点也可以看成是从原点开始的向量

DVector3d

代表向量

DMatrix

它的类型的是 Struct,代表方阵,有 DMatrix2d、DMatrix3d、DMatrix4d,是基本的数学几何表达。

DTransform3d

DTransform3d 是齐次表达式型矩阵的一种封装,有 DTransform2d 和 DTransform3d,分别代表 2x3 和 3x4 阶矩阵。

它内部的一些变换使用到了 DMatrix,因为 DMatrix 是结构体,运行在栈上,执行效率高。

Bentley 中使用 DTransform3d 来实现三维变换,它使用三维矩阵加上一个平移矩阵的方式来表达齐次矩阵。

Bentley 在进行三维仿射时,其原理是先将 DTransform3d 中的数据转成一个三维齐次矩阵,然后再对图形左乘变换矩阵进行变换。

左乘

要对图形进行仿射变换,需要左乘矩阵,同时,变换的顺序是从右向左的。

Bentley 中很多对象重载了运算符,可以方便进行仿射变换,在使用的过程中,直接使用 * 号即可。

例如: 对 DVector3d 进行变换,可以使用:

1
2
3
DVector3d vector = DVector3d.UnitZ;
DTransform3d trans = DTransform3d.Identity;
DVector3d result = trans * vector;

关于矩阵的理解

矩阵的通用表达式为: \[ M_{local} \cdot P_{local} = M_{world} \cdot P_{world} = I \cdot P \] 从上面的表达式中,我们可以理解为:

  1. 对象的真实坐标为 \(P\)
  2. P 在世界坐标系中是 \(P_{world}\)
  3. P 在局部坐标系中是 \(P_{local}\)

所以,如果要将一个坐标系转换到另一个坐标系,可以先将该坐标系中的点转换到真实坐标,然后再通过真实坐标转换到另一个坐标系中。

假设有坐标系: \[ \begin{align} M_1 \cdot P_1 = M \cdot P \\ M_2 \cdot P_2 = M \cdot P \end{align} \] 如果要将 \(P_1\) 变成 \(P_2\),则可以: \[ M_1 \cdot P_1 = M_2 \cdot P_2 => P_2 = M_2^{-1} \cdot M_1 \cdot P_1 \] 要转换到某个坐标系,就要左乘该坐标系的逆矩阵。

混淆概念解析

在使用 DTranform3 时,经常会有 worldToLocallocalToWorld,它们的关系如下: \[ \begin{align} P_{world} = M_{localToWorld} \cdot P_{local} \\ M_{worldToLocal} = M_{localToWorld}^{-1} \end{align} \]

  • worldToLocal

    将世界坐标系转换到局部坐标系,从而获取局部坐标,即是局部坐标系矩阵的逆矩阵

    对于元素来说,就是将世界坐标系中的元素旋转到自己定义的坐标系下

  • localToWorld

    worldToLocal的逆矩阵

求逆变换

逆矩阵

DTransform3d 的实例上,有一个 TryInvert,调用该方法可以获取一个变换的逆变换。因为一个矩阵,不一定是可逆的,所以 TryInvert 不一定会获取到逆变换,需要根据返回值来确定。

1
2
3
// 使用代码片段
DTransform3d trans = new DTransform3d(cursorLocation.ViewRotation);
trans.TryInvert(out DTransform3d invertTras);

伪逆

一个矩阵不一定有逆矩阵,但是一定有伪逆。所以可以通过下列方法求得:

1
2
3
4
5
6
7
8
9
10
// DTransform 中包含静态 FromPseudoInverse,直接调用即可
public static DTransform3d FromPseudoInverse(DTransform3d transform)
{
// 先转置
DMatrix3d matrix = new DMatrix3d(transform).Transpose();
DVector3d vector = DMatrix3d.Multiply(matrix,-transform.coffxw,-transform.coffyw,-transform.coffzw);
// 对转置进行平移
return FromMatrixAndTranslation(matrix, vector);
}

参考

  1. 几何变换/坐标变换/矩阵变换 等基础概念和代码应用

  2. 计算机中 堆 、栈、