Microstation 中坐标变换

在进行矩阵转换时,谨记如下公式: \[ \begin{aligned} M_{world} \cdot P_{world} &= M_{local} \cdot P_{local} \\ \because M_{world} &= E \\ \therefore P_{world} &= M_{local} \cdot P_{local} \\ \end{aligned} \] \(M\) 可以叫做坐标系的度量矩阵,将某个坐标系统转到另一个坐标系,是在原坐标系的值上左乘新坐标系度量矩阵的逆。

在理解 MS 中各个对象返回的 DTransform 含义时,先弄明白谁是度量矩阵,另一个是它的逆,就很好理解了。

度量矩阵

度量矩阵_百度百科 (baidu.com) 是指欧氏空间的一组基之间的内积作为元素构成的矩阵。

在三维空间中,假设 3 组基向量分别为 \(\vec{X}=(xx,xy,xz)\)\(\vec{Y}=(yx,yy,yz)\)\(\vec{Z} = (zx,zy,zz)\);原点为 \(O=(wx,wy,wz)\)

则度量矩阵表示为: \[ M = \begin{bmatrix} xx & yx & zx & wx \\ xy & yy & zy & wy \\ xz & yz & zz & wz \\ 0 & 0 & 0 & 1 \end{bmatrix} \] \(M\) 为非奇异矩阵,添加最后一行是为了构成方阵,使得矩阵的秩为满秩。方便程序进行计算。

矩阵生成

在 Microstation 中,主要有两种方式表示矩阵,分别为 DMatrix 系列和 DTransform 系列。DMatrix 系列有 DMatrix2d/DMatrix3d/DMtrix4d,它是 Microstation 提供的最基础的矩阵操作结构体,其提供的功能有限,在实际的开发中一般使用 DTransform 系列。

DTransform 系列有 DTransform2d/DTransform3d。 三维开发中使用 DTransform3d

下面将介绍经常使用的矩阵创建方式。

直接构造法

通过 public DTransform3d(double axx, double axy, double axz, double axw, double ayx, double ayy, double ayz, double ayw, double azx, double azy, double azz, double azw) 这个构造函数直接生成 DTransform3d

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
/// <summary>
/// 向 xy 平面投影
/// 默认 z=0
/// </summary>
/// <param name="xPlane"></param>
/// <returns></returns>
public static DTransform3d ProjectToXY(double zValue = 0)
{
return new DTransform3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0, zValue);
}

构造函数与上述度量矩阵参数的对应关系为:\((axx,axy,axz) = (xx,xy,xz)\)\((ayx,ayy,ayz)=(yx,yy,yz)\)\((azx,azy,azz)=(zx,zy,zz)\)\((axw,ayw,azw)=(wx,wy,wz)\)

通过 DTransform3d 生成

DTransform3d 提供了一些静态方法来快速创建实例

比如下面这个方法:

1
2
// origin 代表的是平移值
public static DTransform3d FromOriginAndColumns(DPoint3d origin, DVector3d xVector, DVector3d yVector, DVector3d zVector)

上述静态方法通过局部坐标系(原点和三个方向)来生成一个矩阵,这个矩阵是该坐标系度量矩阵的逆,所以如果想要将模型变换到该坐标系下,直接左乘该矩阵即可。

通过 DPlane3d 生成

通过 DPlane3d 提供的 public DPlane3d(DPoint3d origin, DVector3d normal) 构造函数生成。

1
2
var plane = new DPlane3d(origin,normal);
plane.GetTransforms(out DTransform3d planeToWorld, out DTransform3d worldToPlane)

基中,planeToWorld 是 plane 坐标系的度量矩阵,worldToPlane 是 planeToWorld 的逆。

这种方式无法很好地控制 \(\vec {X}\)\(\vec {Y}\) 基向量的方向

常用转换示例

局部坐标转到世界坐标

\[ \begin{aligned} P_{world} = M_{local}*P_{local} \end{aligned} \]

  • \(P_{world}\) 为世界坐标系中的坐标
  • \(M_{local}\) 为局部坐标系的度量矩阵
  • \(P_{local}\) 为局部坐标系中的坐标

相当于将局部坐标转换成世界坐标

世界坐标系到局部坐标

\[ \begin{aligned} P_{local} = M_{local}^{-1}*P_{world} \end{aligned} \]

  • \(M_{local}^{-1}\) 为局部坐标系的度量矩阵的逆

相当于将世界坐标转换成局部坐标

局部坐标可以看成是原点位于 (0,0,0) 的世界坐标

世界坐标由坐标系 A 变换到坐标系 B

若已知坐标系 A 和 B 的度量矩阵,求由 A 变化到 B 的变换矩阵? \[ \begin{aligned} \because M_{A->B} \cdot M_{A} &= M_{B} \\ \therefore M_{A->B} &= M_{B} \cdot M_{A}^{-1} \end{aligned} \]

  • \(M_{A->B}\) 从坐标系 A 变换 B 的变换矩阵

所以最终公式为: \[ \begin{aligned} P'= M_{B} \cdot M_{A}^{-1} \cdot P \end{aligned} \]

测试用例

待补充......