欢迎光临
我们一直在努力

CAD程序设计——UCS(用户坐标系)体系设计分析

UCS(用户坐标系)体系设计分析

摘要:在 CAD 制图中,世界坐标系(WCS)难以直接支撑斜视图、局部斜坐标与任意方向制图。既有系统仅以 Plane {XY, YZ, XZ} 表示三投影面,且该枚举仅用于状态显示,完全不参与坐标换算,导致全代码库隐式假设坐标系恒为世界 XY。本文提出一套静态命名 UCS(用户坐标系)体系,将 UCS 形式化为二维刚性变换群 SE(2)SE(2)SE(2) 的子集,由原点 ooo 与绕 ZZZ 轴旋转角 θ\\thetaθ 唯一确定。设计遵循“插入层 = 输入/显示层,绝不碰存储层”的铁律,使 Element.pts 始终保存世界坐标,存档格式零改动。通过单一换算入口 SketchModel::toWorld()/toUcs() 收口所有坐标变换,并在 Snap、GraphicsView、命令解析、状态栏等模块按 UCS 轴对齐,同时保持约束求解器以世界系为唯一基准。新增 t_ucs 自测 24 条 CHECK,覆盖数学恒等、命令定义、极轴/正交/栅格、读数切换与不入档断言。全量自测零回归。本文进一步给出动态 UCS 的扩展路径、零回归设计模式与架构决策的形式化论证。

关键词:用户坐标系;UCS;二维刚性变换;世界坐标;坐标换算;零回归;CAD 制图;动态 UCS

0 引言

在计算机辅助设计(CAD)中,世界坐标系(World Coordinate System, WCS)为所有几何对象提供全局基准。然而,实际制图常需在斜视图、局部斜坐标或任意方向工作面上操作。若系统仅支持世界 XY 平面,用户不得不通过繁琐的坐标心算或辅助线完成斜向绘制,效率低且易错。

用户坐标系(User Coordinate System, UCS)允许用户定义局部原点与旋转方向,使输入、显示、捕捉、极轴、正交与读数均以局部系为基准,而底层存储仍保持世界坐标。这一“输入/显示变换、存储不变”的架构,既能满足斜向制图需求,又能保证存档兼容与既有算法无感。

本文对既有代码进行彻底勘察,发现三个关键问题:

  • Plane 是“空头机制”:enum class Plane { XY, YZ, XZ } 与 SketchModel::plane_ 只存、只显示,完全不参与任何坐标换算。全代码库隐式假设坐标系恒为世界 XY。
  • 无集中坐标换算入口:点解析 CommandContext::tryParsePoint 仅支持绝对 x,y[,z],不支持 @ 相对与 < 极坐标;DYN 动态输入 commitDynInput 直接对世界 X 轴计算 len*(cos,sin)。
  • Snap、GraphicsView、ConstraintSolver 硬编码世界轴:Snap.cpp 的 OTRACK/TK 对齐硬编码 (1,0,0) 与 (0,1,0),正交分解与极轴角基准以世界 X 为 0∘0^\\circ0∘;GraphicsView.cpp 的网格、坐标轴图标、极轴射线、正交引导线、HUD、坐标读数均以世界系为准;ConstraintSolver 的角度约束以世界 X 为 0∘0^\\circ0∘ 基准。
  • 本文的核心设计思想是:

    将 UCS 建模为二维刚性变换,插入到输入/显示边界,存储层始终为世界坐标。

    形式化地,设世界坐标为 pw∈R2p_w \\in \\mathbb{R}^2pw​∈R2,UCS 局部坐标为 pu∈R2p_u \\in \\mathbb{R}^2pu​∈R2,UCS 由原点 o∈R2o \\in \\mathbb{R}^2o∈R2 与旋转角 θ∈[0,2π)\\theta \\in [0, 2\\pi)θ∈[0,2π) 定义。则正变换 Tu→wT_{u \\to w}Tu→w​ 与逆变换 Tw→uT_{w \\to u}Tw→u​ 为:

    pw=Tu→w(pu)=o+R(θ)pu
    p_w = T_{u \\to w}(p_u) = o + R(\\theta) p_u
    pw​=Tu→w​(pu​)=o+R(θ)pu​

    pu=Tw→u(pw)=R(−θ)(pw−o)
    p_u = T_{w \\to u}(p_w) = R(-\\theta)(p_w – o)
    pu​=Tw→u​(pw​)=R(−θ)(pw​−o)

    其中旋转矩阵:

    R(θ)=(cos⁡θ−sin⁡θsin⁡θcos⁡θ)
    R(\\theta) =
    \\begin{pmatrix}
    \\cos\\theta & -\\sin\\theta \\\\
    \\sin\\theta & \\cos\\theta
    \\end{pmatrix}
    R(θ)=(cosθsinθ​−sinθcosθ​)

    满足正交性:

    R(θ)⊤R(θ)=I,R(θ)−1=R(θ)⊤=R(−θ)
    R(\\theta)^\\top R(\\theta) = I,\\qquad
    R(\\theta)^{-1} = R(\\theta)^\\top = R(-\\theta)
    R(θ)⊤R(θ)=I,R(θ)−1=R(θ)⊤=R(−θ)

    因此往返变换恒等:

    Tw→u(Tu→w(pu))=pu
    T_{w \\to u}(T_{u \\to w}(p_u)) = p_u
    Tw→u​(Tu→w​(pu​))=pu​

    误差仅来自浮点舍入,自测要求 ≤10−9\\le 10^{-9}≤10−9。

    本文贡献如下:

  • 形式化建模:将 UCS 定义为 SE(2)SE(2)SE(2) 的子集,给出正逆变换、轴向量、正交性与误差界。
  • 架构边界:提出“插入层 = 输入/显示层,绝不碰存储层”的铁律,保证存档零改动。
  • 单一换算入口:所有坐标变换收口到 SketchModel::toWorld()/toUcs(),杜绝方向不一致。
  • 零回归设计:默认 UCS = 世界系,所有新增参数带默认值,既有 963 条自测零回归。
  • 刻意不序列化:命名 UCS 表不入档,避免 JSON 兼容回归,并以自测断言防止误加。
  • 完整验证:新增 t_ucs 24 条 CHECK,覆盖数学、命令、捕捉、显示与不入档。

  • 1 现状勘察与问题定义

    1.1 Plane 空头机制

    既有代码中:

    enum class Plane { XY, YZ, XZ };

    SketchModel::plane_ 仅用于状态栏或 HUD 显示,不参与任何坐标换算。所有几何算法、渲染、捕捉、约束求解均隐式假设世界 XY 平面。因此,plane 命令虽可切换显示,但不会改变实际坐标语义。

    1.2 无集中坐标换算入口

    点解析 CommandContext::tryParsePoint 仅支持绝对 x,y[,z],不支持:

    • @dx,dy 相对笛卡尔坐标;
    • dist<angle 绝对极坐标;
    • @dist<angle 相对极坐标。

    DYN 动态输入 commitDynInput 直接对世界 X 轴计算:

    Δp=ℓ⋅(cos⁡α,sin⁡α)
    \\Delta p = \\ell \\cdot (\\cos\\alpha, \\sin\\alpha)
    Δp=ℓ⋅(cosα,sinα)

    未考虑 UCS 旋转。

    1.3 硬编码世界轴

    模块硬编码内容影响
    Snap.cpp OTRACK/TK 对齐硬编码 (1,0,0) / (0,1,0) 斜向追踪失效
    Snap.cpp 正交分解与极轴角基准以世界 X 为 0∘0^\\circ0∘ 极轴方向错误
    GraphicsView.cpp 网格、坐标轴图标、极轴射线、正交引导线、HUD、坐标读数 显示与 UCS 不一致
    ConstraintSolver 角度约束以世界 X 为 0∘0^\\circ0∘ 约束语义固定于世界系

    1.4 问题形式化

    设真实存储坐标为 pstorep_{\\text{store}}pstore​,用户输入坐标为 pinp_{\\text{in}}pin​,显示坐标为 pdispp_{\\text{disp}}pdisp​。理想 UCS 体系应满足:

    pstore=Tu→w(pin)
    p_{\\text{store}} = T_{u \\to w}(p_{\\text{in}})
    pstore​=Tu→w​(pin​)

    pdisp=Tw→u(pstore)
    p_{\\text{disp}} = T_{w \\to u}(p_{\\text{store}})
    pdisp​=Tw→u​(pstore​)

    且存档格式不变:

    JSONnew=JSONold
    \\mathrm{JSON}_{\\text{new}} = \\mathrm{JSON}_{\\text{old}}
    JSONnew​=JSONold​

    在顶层键集上完全一致。既有系统因缺少统一 TTT,导致输入、显示、捕捉各自为政,斜向制图无法正确工作。


    2 核心设计决策

    2.1 UCS = 二维刚性变换

    定义 UCS 结构:

    struct Ucs {
    QString name;
    Vec3 origin; // 原点(世界坐标)
    double angleRad; // 绕 Z 轴旋转角
    };

    派生轴向量:

    xaxis=(cos⁡θ,sin⁡θ,0)
    x_{\\text{axis}} = (\\cos\\theta, \\sin\\theta, 0)
    xaxis​=(cosθ,sinθ,0)

    yaxis=(−sin⁡θ,cos⁡θ,0)
    y_{\\text{axis}} = (-\\sin\\theta, \\cos\\theta, 0)
    yaxis​=(−sinθ,cosθ,0)

    二者单位正交,且 zzz 分量直通,不改变 Z 语义。正逆变换:

    pw=o+R(θ)pu
    p_w = o + R(\\theta) p_u
    pw​=o+R(θ)pu​

    pu=R(−θ)(pw−o)
    p_u = R(-\\theta)(p_w – o)
    pu​=R(−θ)(pw​−o)

    默认 UCS = 世界系:

    o=(0,0,0),θ=0
    o = (0,0,0),\\qquad \\theta = 0
    o=(0,0,0),θ=0

    此时:

    R(0)=I,Tu→w=Tw→u=id
    R(0) = I,\\qquad T_{u \\to w} = T_{w \\to u} = \\mathrm{id}
    R(0)=I,Tu→w​=Tw→u​=id

    既有 963 条自测零回归。
    旋转矩阵正交可逆,因此:

    Tw→u(Tu→w(p))=p
    T_{w \\to u}(T_{u \\to w}(p)) = p
    Tw→u​(Tu→w​(p))=p

    自测覆盖往返误差 ≤10−9\\le 10^{-9}≤10−9。

    2.2 插入层 = 输入/显示层,绝不碰存储层

    铁律:Element.pts 始终是世界坐标。

    UCS 只存在于两道转换边界上:

    用户输入(命令行/DYN/鼠标)──toWorld──▶ 世界坐标 ──▶ Element.pts(存储,不变)
    Element.pts(世界)──toUcs──▶ 显示(网格/极轴/读数/HUD)

    由此保证:

    • 存档格式零改动,旧档/新档完全兼容;
    • 既有渲染、导出、约束求解全部无感;
    • 几何算法不感知 UCS,避免大规模回归。

    2.3 世界 ↔ 用户换算收口到唯一入口

    SketchModel::toWorld() / toUcs() 是唯一换算入口,内联转发 currentUcs_。所有输入与显示路径均消费它,杜绝“同一处换算散落多处导致方向不一致”。

    形式化地,令所有输入路径集合为 Pin\\mathcal{P}_{\\text{in}}Pin​,显示路径集合为 Pdisp\\mathcal{P}_{\\text{disp}}Pdisp​,则:

    ∀p∈Pin,pw=SketchModel::toWorld(p)
    \\forall p \\in \\mathcal{P}_{\\text{in}},\\quad p_w = \\mathrm{SketchModel::toWorld}(p)
    ∀p∈Pin​,pw​=SketchModel::toWorld(p)

    ∀p∈Pdisp,pu=SketchModel::toUcs(p)
    \\forall p \\in \\mathcal{P}_{\\text{disp}},\\quad p_u = \\mathrm{SketchModel::toUcs}(p)
    ∀p∈Pdisp​,pu​=SketchModel::toUcs(p)

    不存在旁路。

    2.4 命名 UCS 表不序列化

    ucsTable_ 存内存(QMap),不入 toDrawingJson / Memento。理由:

  • 避免引入 JSON 兼容回归,顶层键集是旧档契约;
  • UCS 属“交互/视图态”,与会话态不入档的项目惯例一致;
  • 自测 t_ucs 明确断言 JSON 顶层无 ucs / ucsTable 键,防止将来误加。
  • 该决策可形式化为:

    Keys(JSONnew)=Keys(JSONold)
    \\mathrm{Keys}(\\mathrm{JSON}_{\\text{new}}) = \\mathrm{Keys}(\\mathrm{JSON}_{\\text{old}})
    Keys(JSONnew​)=Keys(JSONold​)

    且:

    "ucs"∉Keys(JSONnew)
    \\texttt{"ucs"} \\notin \\mathrm{Keys}(\\mathrm{JSON}_{\\text{new}})
    "ucs"∈/Keys(JSONnew​)

    "ucsTable"∉Keys(JSONnew)
    \\texttt{"ucsTable"} \\notin \\mathrm{Keys}(\\mathrm{JSON}_{\\text{new}})
    "ucsTable"∈/Keys(JSONnew​)

    2.5 plane 命令原样保留

    既有 plane xy|yz|xz 三态行为不变。UCS 与 Plane 是并行概念,状态栏同时呈现:

    平面:XY
    ⌖ WCS/UCS名 角度°


    3 数学原理与公式

    3.1 二维刚性变换群

    二维刚性变换群 SE(2)SE(2)SE(2) 元素可表示为:

    T(o,θ)=(R(θ)o0⊤1)
    T(o,\\theta) =
    \\begin{pmatrix}
    R(\\theta) & o \\\\
    0^\\top & 1
    \\end{pmatrix}
    T(o,θ)=(R(θ)0⊤​o1​)

    其中 o∈R2o \\in \\mathbb{R}^2o∈R2,R(θ)∈SO(2)R(\\theta) \\in SO(2)R(θ)∈SO(2)。本文 UCS 即为 SE(2)SE(2)SE(2) 的子集,但限制 zzz 分量直通,且仅绕 ZZZ 轴旋转。

    3.2 正逆变换

    正变换:

    pw=o+R(θ)pu
    p_w = o + R(\\theta) p_u
    pw​=o+R(θ)pu​

    逆变换:

    pu=R(−θ)(pw−o)
    p_u = R(-\\theta)(p_w – o)
    pu​=R(−θ)(pw​−o)

    展开为分量形式:

    $$
    \\begin{pmatrix} x_w \\ y_w \\end{pmatrix}

    \\begin{pmatrix} x_o \\ y_o \\end{pmatrix}
    +
    \\begin{pmatrix}
    \\cos\\theta & -\\sin\\theta \\
    \\sin\\theta & \\cos\\theta
    \\end{pmatrix}
    \\begin{pmatrix} x_u \\ y_u \\end{pmatrix}
    $$

    $$
    \\begin{pmatrix} x_u \\ y_u \\end{pmatrix}

    \\begin{pmatrix}
    \\cos\\theta & \\sin\\theta \\
    -\\sin\\theta & \\cos\\theta
    \\end{pmatrix}
    \\begin{pmatrix} x_w – x_o \\ y_w – y_o \\end{pmatrix}
    $$

    3.3 正交性与往返恒等

    旋转矩阵满足:

    R(θ)⊤R(θ)=I
    R(\\theta)^\\top R(\\theta) = I
    R(θ)⊤R(θ)=I

    det⁡R(θ)=1
    \\det R(\\theta) = 1
    detR(θ)=1

    因此:

    R(θ)−1=R(θ)⊤=R(−θ)
    R(\\theta)^{-1} = R(\\theta)^\\top = R(-\\theta)
    R(θ)−1=R(θ)⊤=R(−θ)

    往返恒等:

    Tw→u(Tu→w(pu))=R(−θ)(o+R(θ)pu−o)=pu
    T_{w \\to u}(T_{u \\to w}(p_u)) = R(-\\theta)(o + R(\\theta)p_u – o) = p_u
    Tw→u​(Tu→w​(pu​))=R(−θ)(o+R(θ)pu​−o)=pu​

    3.4 极坐标与相对坐标

    绝对极坐标:

    pu=o+d⋅(cos⁡(α+θ),sin⁡(α+θ))
    p_u = o + d \\cdot (\\cos(\\alpha + \\theta), \\sin(\\alpha + \\theta))
    pu​=o+d⋅(cos(α+θ),sin(α+θ))

    其中 ddd 为距离,α\\alphaα 为相对 UCS X 轴的角度。

    相对笛卡尔:

    pu=pbase,u+(Δx,Δy)
    p_u = p_{\\text{base},u} + (\\Delta x, \\Delta y)
    pu​=pbase,u​+(Δx,Δy)

    相对极坐标:

    pu=pbase,u+d⋅(cos⁡(α+θ),sin⁡(α+θ))
    p_u = p_{\\text{base},u} + d \\cdot (\\cos(\\alpha + \\theta), \\sin(\\alpha + \\theta))
    pu​=pbase,u​+d⋅(cos(α+θ),sin(α+θ))

    3.5 误差界

    浮点往返误差主要来自矩阵乘法与加减。设机器精度为 εm\\varepsilon_mεm​,则:

    ∥Tw→u(Tu→w(p))−p∥≤Cεm∥p∥
    \\left\\| T_{w \\to u}(T_{u \\to w}(p)) – p \\right\\| \\le C \\varepsilon_m \\|p\\|
    ∥Tw→u​(Tu→w​(p))−p∥≤Cεm​∥p∥

    自测要求:

    ∥Tw→u(Tu→w(p))−p∥≤10−9
    \\left\\| T_{w \\to u}(T_{u \\to w}(p)) – p \\right\\| \\le 10^{-9}
    ∥Tw→u​(Tu→w​(p))−p∥≤10−9

    45° 正向算例要求 ≤10−12\\le 10^{-12}≤10−12。

    3.6 零回归条件

    默认 UCS = 世界系时:

    o=0,θ=0
    o = 0,\\qquad \\theta = 0
    o=0,θ=0

    此时:

    Tu→w(p)=p,Tw→u(p)=p
    T_{u \\to w}(p) = p,\\qquad T_{w \\to u}(p) = p
    Tu→w​(p)=p,Tw→u​(p)=p

    所有新增带默认值的 UCS 参数取缺省值时,旧调用路径逐位等价。


    4 各模块改动清单

    4.1 新增 src/core/Ucs.h

    • struct Ucs:name/origin/angleRad + xAxis() / yAxis() / toWorld() / toUcs() / isWorld() / describe()。

    4.2 SketchModel (core)

    • 状态:
      • currentUcs_:默认世界;
      • ucsTable_:内存表;
      • coordDisplayUcs_:读数模式;
      • lastInputPointWorld_:相对坐标基准点。
    • API:
      • setCurrentUcs() / currentUcs();
      • toWorld() / toUcs();
      • parsePointToWorld(s, base, out);
      • displayCoord();
      • ucsSave/ucsDelete/ucsSetCurrent/ucsHas/ucsGet/ucsNames/ucsCount。
    • 信号:ucsChanged(),状态栏 / 视图联动;setCurrentUcs 另发 viewChanged 驱动重绘。

    4.3 点解析(UCS 感知)

    SketchModel::parsePointToWorld 支持四种语法,均经 toWorld 收口。

    语法语义基准
    x,y[,z] 绝对(UCS 局部) UCS 原点
    @dx,dy 相对笛卡尔 base(世界)转局部后偏移
    dist<angle 绝对极坐标 UCS 原点,UCS X = 0∘0^\\circ0∘
    @dist<angle 相对极坐标 base,UCS X = 0∘0^\\circ0∘

    接线点:

    • CommandLine::onReturn:键盘坐标输入改走 parsePointToWorld,基准 = lastInputPointWorld();UCS = 世界时与旧 tryParsePoint 行为逐位一致;
    • GraphicsView::injectPoint:提交后回写 lastInputPointWorld_,链式 @ 基准;
    • commitDynInput:偏移改沿 ucs.xAxis()/yAxis() 分解,updateDynBox 预填角减去 UCS 旋转角,显示口径 = 提交口径。

    4.4 ucs 命令(core/Commands)

    五种定义:

    命令含义
    ucs world 恢复世界系
    ucs view 按当前视图定义
    ucs 3p p1 p2 [p3] 三点定义
    ucs object <id> 按对象定义
    ucs z <x,y> <角°> 原点 + 角度

    便捷:

    ucs origin <x,y> [角°]

    CRUD:

    ucs save|set|restore|delete|list

    其中 set 与 restore 同义,WORLD 不可删。

    读数切换:

    ucs coords wcs|ucs

    便捷切换:

    ucs <已存在名>

    登记于 registerExact("ucs", …),紧邻 plane。

    4.5 Snap 按 UCS 轴对齐(零回归设计)

    三个函数追加带默认值的 UCS 参数,缺省 = 世界轴,既有调用零改动:

    • polarAngles(cfg, baseDir, ucsOffsetDeg=0):极轴角基准整体偏移;
    • track(…, ucsAngleRad=0):OTRACK/TK 的水平/垂直对齐线改为在 UCS 局部系内做轴对齐,落点转回世界系;ucsAngleRad=0 时两次变换恒等,逐位等价旧实现;
    • applyInputConstraints(…, ucsAngleRad=0):正交锁轴与栅格量化均转 UCS 局部系执行。

    4.6 GraphicsView 按 UCS 渲染

    • 网格:UCS ≠ 世界时转 UCS 局部系生成网格线,可见区四角转局部取包围盒保证覆盖,经 painter translate(UCS 原点) + rotate(UCS 角) 映射回世界;UCS = 世界走原快路。
    • 坐标轴图标:save/translate/rotate 后绘制,落在 UCS 原点、按 UCS 角旋转;UCS = 世界时变换恒等。
    • 极轴射线:与追踪吸附共用同一 polarAngles 入口,传 UCS 偏移,所见即所得。
    • 正交引导线:沿 ucs.xAxis()/yAxis() 绘制。
    • HUD:显示当前 UCS 名称/原点/旋转角,世界系显示 WCS。
    • 坐标读数:cursorMoved 改发 model_->displayCoord(w),WCS/UCS 随模式。
    • 视图矩阵不变式保持:applyTransform 的无旋转映射:

    screenx=wx⋅zoom+panX
    \\text{screen}_x = w_x \\cdot \\mathrm{zoom} + \\mathrm{panX}
    screenx​=wx​⋅zoom+panX

    screeny=−wy⋅zoom+panY
    \\text{screen}_y = -w_y \\cdot \\mathrm{zoom} + \\mathrm{panY}
    screeny​=−wy​⋅zoom+panY

    绝不旋转。UCS 旋转全部用几何层 UCS 基实现,避免破坏大量依赖该不变式的既有自测。

    • DYN:提交/预填角均以 UCS X 为 0∘0^\\circ0∘ 基准。

    4.7 状态栏 UCS 指示器

    • StatusBar::setUcsInfo() 新标签 ⌖ WCS / ⌖ 名称 角度°;
    • tooltip 提示 ucs 命令用法;
    • ModelMediator 订阅 ucsChanged + 启动回显一次;
    • 读数切到 UCS 时附加“(读数 UCS)”提示。

    4.8 ConstraintSolver 不动(刻意决策)

    t_horizontal/t_vertical/t_angle 等约束自测是世界 X 基准的回归用例。约束层若随 UCS 旋转将全面破坏“约束 = 几何恒等关系”的语义。约束继续以世界系为唯一基准,与“UCS 只是输入/显示变换”的定位一致。


    5 自测覆盖(t_ucs,共 24 条 CHECK)

  • 默认 = 世界系:isWorld / toWorld / toUcs 恒等,零回归基线;
  • Ucs 数学:xAxis/yAxis 单位正交、双向往返 ≤10−9\\le 10^{-9}≤10−9、45° 正向算例 ≤10−12\\le 10^{-12}≤10−12;
  • 验收断言:45° UCS 下 @100<0(基准原点)落点:
  • p=(100cos⁡45∘,100sin⁡45∘)
    p = (100\\cos 45^\\circ, 100\\sin 45^\\circ)
    p=(100cos45∘,100sin45∘)

    误差 ≤10−6\\le 10^{-6}≤10−6;另覆盖绝对笛卡尔、绝对极坐标、相对笛卡尔、世界系零回归 4 例;

  • ucs 命令:3p / z / object / view / world 五种定义逐项断言 origin + angle,save/restore/delete/set/list、非法子命令拒绝,共 13 条;
  • 极轴:polarAngles 偏移后含 30∘30^\\circ30∘ / 120∘120^\\circ120∘,不含 0∘0^\\circ0∘;track 在 UCS 30∘30^\\circ30∘ 命中极轴,世界系同光标不命中;
  • 正交/栅格:UCS 90∘90^\\circ90∘ 正交锁到世界 Y 轴;UCS 45∘45^\\circ45∘ 栅格沿 UCS 轴量化;UCS 0∘0^\\circ0∘ 与旧实现逐位一致;
  • 读数切换:WCS 原值 / UCS 局部值,且二者不同;
  • 网格方向:UCS 30∘30^\\circ30∘ 时主方向:
  • (cos⁡30∘,sin⁡30∘)
    (\\cos 30^\\circ, \\sin 30^\\circ)
    (cos30∘,sin30∘)

    世界系回到 (1,0)(1,0)(1,0);

  • 不入档:toDrawingJson 顶层无 ucs / ucsTable 键。

  • 6 创新点与讨论

    6.1 形式化 UCS 为 SE(2)SE(2)SE(2) 子集

    本文将 UCS 明确定义为二维刚性变换群 SE(2)SE(2)SE(2) 的子集,并给出正逆变换、正交性与误差界。该形式化使坐标换算从工程约定提升为可证明的数学对象。

    6.2 插入层 = 输入/显示层

    提出“UCS 只存在于输入/显示边界,存储层始终为世界坐标”的架构边界。该边界保证:

    • 存档格式零改动;
    • 几何算法无感;
    • 既有回归零破坏。

    可形式化为:

    Store=WCS,Input=Tu→w(UCS),Display=Tw→u(WCS)
    \\mathrm{Store} = \\mathrm{WCS},\\qquad
    \\mathrm{Input} = T_{u \\to w}(\\mathrm{UCS}),\\qquad
    \\mathrm{Display} = T_{w \\to u}(\\mathrm{WCS})
    Store=WCS,Input=Tu→w​(UCS),Display=Tw→u​(WCS)

    6.3 单一换算入口

    所有坐标变换收口到 SketchModel::toWorld() / toUcs(),杜绝方向不一致。该设计可视为“变换单例”模式,在架构上强制唯一性。

    6.4 零回归设计模式

    新增参数带默认值,默认 UCS = 世界系,旧调用路径逐位等价。该模式可概括为:

    默认参数+世界系恒等⇒零回归
    \\text{默认参数} + \\text{世界系恒等} \\Rightarrow \\text{零回归}
    默认参数+世界系恒等⇒零回归

    6.5 刻意不序列化

    命名 UCS 表不入档,避免 JSON 顶层键集变化。该决策以自测断言固化:

    "ucs"∉Keys(JSON)
    \\texttt{"ucs"} \\notin \\mathrm{Keys}(\\mathrm{JSON})
    "ucs"∈/Keys(JSON)

    "ucsTable"∉Keys(JSON)
    \\texttt{"ucsTable"} \\notin \\mathrm{Keys}(\\mathrm{JSON})
    "ucsTable"∈/Keys(JSON)

    6.6 动态 UCS 扩展路径

    动态 UCS 可在 snapWorld 入口前插入临时 Ucs,复用全部机制:

    Tdyn=T(odyn,θdyn)
    T_{\\text{dyn}} = T(o_{\\text{dyn}}, \\theta_{\\text{dyn}})
    Tdyn​=T(odyn​,θdyn​)

    无需改动存储层与约束层。


    7 已知边界与后续可选项

    • 动态 UCS:绘制时对临时工作平面自动吸附,列为可选子项,未实现;静态命名 UCS 全链路已正确,动态 UCS 可在 snapWorld 入口前插入临时 Ucs 而复用全部机制。
    • 约束求解不随 UCS 旋转;如未来需要“UCS 相对约束”应作为独立约束类型设计。
    • UCS 表不持久化是刻意取舍;若需随图保存应走“顶层键只追加”路径并同步黄金样本。
    • CommandContext::parsePoint(脚本/命令行整行命令的绝对点)保持世界系语义——键盘交互入口已 UCS 化,脚本参数保持确定性解析,避免既有脚本回归。

    8 结论

    本文以二维刚性变换为数学基础,构建了静态命名 UCS 体系。通过“插入层 = 输入/显示层”的架构边界、单一换算入口、零回归设计模式与刻意不序列化决策,系统在支持斜视图、局部斜坐标制图的同时,保证存档格式零改动、既有算法无感、全量自测零回归。新增 t_ucs 24 条 CHECK 覆盖数学恒等、命令定义、极轴/正交/栅格、读数切换与不入档断言。动态 UCS 可作为后续可选子项,在现有机制上无缝扩展。


    附录 A 符号表

    符号含义
    ooo UCS 原点,世界坐标
    θ\\thetaθ UCS 绕 Z 轴旋转角
    R(θ)R(\\theta)R(θ) 二维旋转矩阵
    Tu→wT_{u \\to w}Tu→w​ UCS 局部到世界的正变换
    Tw→uT_{w \\to u}Tw→u​ 世界到 UCS 局部的逆变换
    pwp_wpw​ 世界坐标
    pup_upu​ UCS 局部坐标
    SE(2)SE(2)SE(2) 二维刚性变换群
    SO(2)SO(2)SO(2) 二维旋转群
    xaxisx_{\\text{axis}}xaxis​ UCS 局部 X 轴单位向量
    yaxisy_{\\text{axis}}yaxis​ UCS 局部 Y 轴单位向量

    附录 B 公式汇总

    正变换:

    pw=o+R(θ)pu
    p_w = o + R(\\theta) p_u
    pw​=o+R(θ)pu​

    逆变换:

    pu=R(−θ)(pw−o)
    p_u = R(-\\theta)(p_w – o)
    pu​=R(−θ)(pw​−o)

    旋转矩阵:

    R(θ)=(cos⁡θ−sin⁡θsin⁡θcos⁡θ)
    R(\\theta) =
    \\begin{pmatrix}
    \\cos\\theta & -\\sin\\theta \\\\
    \\sin\\theta & \\cos\\theta
    \\end{pmatrix}
    R(θ)=(cosθsinθ​−sinθcosθ​)

    正交性:

    R(θ)⊤R(θ)=I,R(θ)−1=R(θ)⊤=R(−θ)
    R(\\theta)^\\top R(\\theta) = I,\\qquad
    R(\\theta)^{-1} = R(\\theta)^\\top = R(-\\theta)
    R(θ)⊤R(θ)=I,R(θ)−1=R(θ)⊤=R(−θ)

    轴向量:

    xaxis=(cos⁡θ,sin⁡θ,0)
    x_{\\text{axis}} = (\\cos\\theta, \\sin\\theta, 0)
    xaxis​=(cosθ,sinθ,0)

    yaxis=(−sin⁡θ,cos⁡θ,0)
    y_{\\text{axis}} = (-\\sin\\theta, \\cos\\theta, 0)
    yaxis​=(−sinθ,cosθ,0)

    绝对极坐标:

    pu=o+d⋅(cos⁡(α+θ),sin⁡(α+θ))
    p_u = o + d \\cdot (\\cos(\\alpha + \\theta), \\sin(\\alpha + \\theta))
    pu​=o+d⋅(cos(α+θ),sin(α+θ))

    零回归条件:

    o=0,θ=0⇒Tu→w=Tw→u=id
    o = 0,\\quad \\theta = 0 \\Rightarrow T_{u \\to w} = T_{w \\to u} = \\mathrm{id}
    o=0,θ=0⇒Tu→w​=Tw→u​=id

    不入档断言:

    "ucs"∉Keys(JSON)
    \\texttt{"ucs"} \\notin \\mathrm{Keys}(\\mathrm{JSON})
    "ucs"∈/Keys(JSON)

    "ucsTable"∉Keys(JSON)
    \\texttt{"ucsTable"} \\notin \\mathrm{Keys}(\\mathrm{JSON})
    "ucsTable"∈/Keys(JSON)


    附录 C 自测断言摘要

    编号断言期望
    C1 默认 UCS = 世界系 isWorld 为真,往返恒等
    C2 轴向量单位正交 ∣xaxis∣=∣yaxis∣=1|x_{\\text{axis}}| = |y_{\\text{axis}}| = 1∣xaxis​∣=∣yaxis​∣=1,点积为 0
    C3 双向往返误差 ≤10−9\\le 10^{-9}≤10−9
    C4 45° 正向算例 误差 ≤10−12\\le 10^{-12}≤10−12
    C5 @100<0 落点 (100cos⁡45∘,100sin⁡45∘)(100\\cos45^\\circ, 100\\sin45^\\circ)(100cos45∘,100sin45∘),误差 ≤10−6\\le 10^{-6}≤10−6
    C6 ucs 五种定义 origin + angle 正确
    C7 ucs CRUD save/restore/delete/set/list 正确
    C8 极轴偏移 含 30∘30^\\circ30∘ / 120∘120^\\circ120∘,不含 0∘0^\\circ0∘
    C9 正交锁轴 UCS 90∘90^\\circ90∘ 锁到世界 Y 轴
    C10 栅格量化 UCS 45∘45^\\circ45∘ 沿 UCS 轴量化
    C11 读数切换 WCS 与 UCS 值不同
    C12 网格方向 UCS 30∘30^\\circ30∘ 主方向为 (cos⁡30∘,sin⁡30∘)(\\cos30^\\circ, \\sin30^\\circ)(cos30∘,sin30∘)
    C13 不入档 JSON 顶层无 ucs / ucsTable

    总结:本文提出并实现了一套静态命名 UCS 体系,以二维刚性变换为数学核心,以“输入/显示边界插入”为架构原则,以“单一换算入口”为一致性保障,以“零回归设计”为工程约束,以“刻意不序列化”为兼容性决策。系统支持斜视图与局部斜坐标制图,同时保持存档格式零改动、既有算法无感、全量自测零回归。动态 UCS 可在现有机制上无缝扩展,为后续斜向制图与临时工作平面提供可复用路径。

    赞(0)
    未经允许不得转载:171主机测评 » CAD程序设计——UCS(用户坐标系)体系设计分析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址