跳到主要内容
浏览器
导航
工程图纸浏览器

图层管理与坐标系变换

图纸实体按图层组织,坐标则在多个坐标系之间逐层映射。本文说明图层开关、冻结与锁定在语义上的差别,世界坐标与对象坐标、用户坐标的关系,仿射矩阵的复合顺序,嵌套块引用带来的变换叠加,以及屏幕坐标与图纸坐标的往返换算。

发布于 5 分钟阅读 1724 字

图纸内容通常按图层组织,每个图层带着一组控制显示与编辑的外观属性;与此同时,图纸坐标与屏幕坐标之间隔着若干层变换。解析器把实体的原始坐标还原到屏幕位置时,需要把这两条信息合起来看:图层决定「画不画、怎么画」,变换决定「画在哪」。

下面先说明图层属性的语义差别,再逐层展开坐标系的换算关系,接着讨论嵌套块与视口带来的变换叠加。

图层属性与状态

图层是实体的分类容器,一个实体通常只属于一个图层。图层上的属性可以分成几类:

属性取值影响范围
开关开 / 关是否绘制
冻结冻结 / 解冻是否参与重生成与相关计算
锁定锁定 / 解锁是否允许编辑
颜色、线型、线宽具体值或随层、随块未显式设置的实体所继承的外观
打印标志打印 / 不打印是否输出到打印结果

开关与冻结都会让图层不显示,但语义不同:关闭的图层不绘制,其上的实体仍可能参与图面范围统计等与可见性无关的处理;冻结的图层在重生成时被整体跳过,对处理开销的影响更明显。锁定只禁止编辑,不影响显示。外观属性方面,实体若显式设置了颜色、线型或线宽,则覆盖图层上的取值;未设置时按随层或随块的约定取值。这套结构决定了矢量路径与线宽映射中线宽与线型参数的来源。

坐标系的层次

图纸数据会在多个坐标系之间移动,常见的有:

  • 世界坐标系:几何数据的存储基准,文件中的坐标多数以此表示
  • 对象坐标系:部分二维实体的坐标在自身平面内给出,需结合拉伸方向换算到世界坐标系
  • 用户坐标系:由用户定义的局部坐标系,通常只影响输入与显示,不改变文件中保存的坐标
  • 模型空间与图纸空间:两套并存的布局,各自带独立的视图方向与比例
  • 设备或屏幕坐标系:以像素为单位、原点在窗口角点的坐标系

存储到文件中的一般是世界坐标系或对象坐标系下的值,其余换算在运行时完成。把哪些换算留在存储层、哪些放在运行时,会影响文件与显示之间能否保持一致。

仿射变换与矩阵复合顺序

二维仿射变换可以用 3×3 齐次矩阵表示。在列向量约定下,平移量位于矩阵的第三列,点按 p' = M · p 变换:

// 3x3 齐次矩阵乘法,列向量约定
function mul(a, b) {
  const r = new Array(9).fill(0);
  for (let i = 0; i < 3; i++)
    for (let j = 0; j < 3; j++)
      for (let k = 0; k < 3; k++)
        r[i * 3 + j] += a[i * 3 + k] * b[k * 3 + j];
  return r;
}

// 先绕原点旋转 R,再按世界偏移 T 平移:M = T · R
const M = mul(T, R);

缩放、旋转与平移的复合顺序会影响结果,因为矩阵乘法不满足交换律。上例中 T · R 表示先施加旋转再平移;若写成 R · T,效果变成在旋转后的坐标系里平移,结果通常不同。块引用、视口与打印布局各自引入变换,因此实现中一般维护一个矩阵栈:进入一层就压入并与当前矩阵相乘,退出时弹出,绘制前用栈顶矩阵把几何送到设备空间。

嵌套块与变换叠加

块定义内部的实体坐标相对块基点保存。插入时给出的插入点、比例与旋转角构成一次变换,展开时块内实体的坐标按缩放、旋转、平移的顺序映射到宿主坐标系,再与插入点所在层级的变换相乘。若块内部又含有块引用,变换逐层叠加。

这里要留意基点。坐标是相对块基点还是相对原点,会改变缩放与旋转的作用中心。多数实现把块内坐标保存为相对基点的偏移,展开时先减去基点、施加缩放与旋转、再加上插入点。若直接对已平移的坐标施加缩放,整体位置会偏离预期。逐层叠加还会放大数值误差,因此嵌套层数较深时,变换需要在足够精度的数值上完成。

视口与图框的坐标映射

图纸空间里的视口是一个矩形区域,它引用模型空间中的一块视图,并带有自己的视图中心与缩放比例。视口的映射可分解为:取模型坐标、减去视图中心、乘以比例、映射到视口矩形。多个视口可以引用同一模型空间的不同区域,彼此独立。

图框通常是图纸空间坐标下的边框,并与打印比例相关联。把视口比例与打印比例分开记录,是因为同一视图可能需要在不同图幅下以不同大小输出。两者的组合决定了从模型坐标到输出纸张的换算链。

屏幕坐标与图纸坐标的往返换算

从屏幕方向往回换算,需要依次经过设备像素、视口矩形归一化、平移与缩放,到达图纸坐标。往返互换要求变换可逆,因此缩放系数不能为零。Y 轴朝向是常见的易错点:屏幕坐标原点在窗口角点且 Y 轴向下,而图纸坐标通常 Y 轴向上,换算时需要对 Y 分量取反。

// 屏幕坐标(CSS 像素)换算为图纸坐标
function screenToWorld(pt, view) {
  const nx = (pt.x - view.rect.left) / view.rect.width;   // 归一化到 0..1
  const ny = (pt.y - view.rect.top) / view.rect.height;
  return {
    x: view.center.x + (nx - 0.5) * view.rect.width / view.scale,
    y: view.center.y - (ny - 0.5) * view.rect.height / view.scale, // Y 轴取反
  };
}

若视图带旋转角,上述近似不再成立,需要把屏幕偏移量先按负旋转角转回视图轴向,再按比例换算。涉及多视口时,还要先判断坐标落在哪个视口矩形内,再使用该视口自己的中心与比例。

小结

图层负责可见性、锁定与外观默认值,其语义差别集中在是否参与计算与是否允许编辑两处;坐标变换负责把存储坐标搬到屏幕,难点在矩阵复合顺序、Y 轴朝向与嵌套块的基点处理。两者交汇于渲染前的准备阶段:先按图层过滤实体、解析出各自的颜色与线型,再沿变换链把几何映射到设备空间。把过滤与变换分成两步,可以让图层状态变化只触发较轻的处理,而不必重建全部几何数据。

工程图纸浏览器 · 相关文章