Skip to content

v0.6.0:图层分级与锁定、测绘坐标与深度放大的显示精度(修复 #29)、文字与天正显示 - #30

Merged
CHMOSE023 merged 17 commits into
mainfrom
dev
Oct 29, 2026
Merged

CHMOSE023 merged 17 commits into
mainfrom
dev

Conversation

@CHMOSE023

Copy link
Copy Markdown
Owner

发布 v0.6.0(发布说明:docs/release-notes/v0.6.0.md,合并后在 main 上打 v0.6.0 标签)。

主要内容

  • 图层:名字里用 $ 分级显示成树(同 Rhino 的子图层),上级的开关、锁定、删除、改名连同下级一起改;锁定图层淡显、不能选中,打开与另存保留锁定标志;锁定图标改得一眼能分清;修复在位改名按 Enter 提交时崩溃
  • 显示精度
    • 测绘坐标(几十万、几百万)的图纸:顶点相对渲染原点存 float,放大后线不再画偏,夹点、捕捉标记不再"不在线上",画线预览不再一格一格地跳
    • 修复 捕捉功能完全无效 #29:放到最大时进局部显示(原点移到视图附近,圆、圆弧、椭圆、多段线圆弧段在视图附近按弦高 ≤ 1/4 像素加密),圆仍是圆、线交得上;对象捕捉优先于正交 / 极轴
  • 文字:\U+XXXX 转义还原,下划线 / 上划线 / 删除线,TrueType 缺字用自带 GB2312.ttf 补上,镜像块参照里的文字跟着翻转
  • 天正:墙柱按图纸设置填充、幕墙交接、门洞封口、门槛线、材料分界线、尺寸文字位置与颜色、轴号文字图层、角度去零、文字宽度与上标、矩形对角线;天正自带的填充图案编进程序

提交(v0.5.1 以来)

  • 8e87075 显示:测绘坐标的图纸顶点相对渲染原点存 float
  • 2447b41 修复 捕捉功能完全无效 #29:局部显示与曲线加密;对象捕捉优先于正交 / 极轴
  • b3e8a70 v0.6.0 发布说明与版本号
  • 以及此前已在 dev 上的 14 个提交(图层分级与锁定、文字、天正显示、内置天正填充图案、改名崩溃修复)

验证

  • 本机:MiniCADTests 1874 项、MiniCADTianzhengTests、MiniCADTchOpeningTests、MiniCADTchGeometryTests、SolidViewTests、NodeGraphTests、MiniGUITests 全部通过;桌面版自测 412 项全过;网页版本机编译通过
  • 第一个提交单独编译、测试过(MiniCADTests 1868 项通过)
  • 大图纸 CK-05 的 --bench:局部显示判断打开 / 关闭时平移每帧 24.9 / 24.9 ms、滚轮每格 87.9 / 88.5 ms(调试版)

🤖 Generated with Claude Code

CHMOSE023 and others added 17 commits October 29, 2026 00:06
管综.dwg 的 1290 个多行文字把中文存成 \U+8D1F\U+4E00…(代码页外字符的写法),
读入时保留原文、显示时还原的设计里,显示这一侧没做:去格式码时把 \U 当未知转义丢掉,
画成 +8D1F+4E00…。现在多行文字在 MTextEntity::StripInlineCodes、单行文字在
TextLayoutEngine::DecodeLine 还原(src/Core/TextCodes.h)。

下划线 \L、上划线 \O、删除线 \K(按 {} 分组恢复)与单行文字的 %%u、%%o 换成排版流里的
开关字符,TextLayoutEngine::Layout 输出 DecorationLine,DrawContext 画成直线。位置按
AutoCAD 2020 用 TXTEXP 分解量得:基线下 0.2、上 1.2、上 0.5 倍字高。纯文本与度量不含开关;
MeasureWidth 改用 DecodeLine,与 Layout 量画一致。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
管综.dwg 的 Arial_5 等样式(arial.ttf)写中文,Arial 里没有汉字,以前画成 .notdef 方块;
AutoCAD 经 Windows 的字体链接照样显示。现在 TTFFont 缺的字改用 FontEngine 设好的替代字体
(自带 GB2312.ttf,各 TrueType 字体共用一份)的字形与步进;两者都按大写字母高归一化,字形
直接复用。HasGlyph 改按字体里是否真有该字符判断(以前 .notdef 方块也算有),MINICAD_GLYPHS
因此能报出 TrueType 的缺字。%%d 等控制码在 TrueType 里按 Unicode 码点查,不再画成方块。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
块里的文字以前只按插入变换的缩放与转角近似,镜像(负比例、法向朝 -Z)不管:管综.dwg
右侧车位的 "A""2600X6000""电动车" 在 AutoCAD 里倒着,MiniCAD 画成正的。现在
TransformDrawSink 按变换求文字基线的真实方向(镜像时 30° 画成 -30°),行列式为负时转发文字
前后各调一次 IDrawSink::ToggleTextMirror,DrawContext 把字形、下划线沿基线上下翻转;两层镜像
相互抵消,ClipDrawSink 照样转发。块定义级缓存的键已含镜像,不受影响。

多行文字按附着点求首行基线时,偏移没有跟着文字旋转(MTextEntity::DrawOrigin):
转 180° 的左上附着文字差出两个字高,车位里的 "A" 压在 "电动车" 上。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8#楼-A平面图与天正 2014 的显示对照:中西文混排的天正文字拆成西文、汉字段,起点按天正步进排,
画出的宽度却是 MiniCAD 替代字体的——原图大字体 GBCBIG 程序不带,替代的 TSSDCHN 汉字宽约 37%,
汉字段压到下一段上,平面小说明的长句冲出表格。现在 Detail::AddRuns 按天正步进排时,按 MiniCAD
实际显示的字体(simplex / TSSDCHN)反算每段的宽度因子,画出的宽度等于天正步进;天正单行文字
(含纯西文、纯汉字)、多行文字的符号字体分段同样处理。

引出标注以前用写死的注释符号字宽,没乘样式宽度(_TCH_DIM 宽 0.7):汉字按 1.0 留位置、按 0.7
画,"预留 DN100钢套管" 中间空出一截。现在字宽乘样式宽度、按天正步进排;宽度为 1 的样式结果不变。

天正上标 ^U…^U(m^U2^U 为 m²)以前原样显示,现在字高为本段一半、抬高 0.5 × 名义字高,
每字步进 0.35 × 西文步进("公卫(4.56m²)"等的天正 2014 分解结果核对)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MiniCADDwgInspect:
- MINICAD_GREPTEXT=子串:原文含该子串的 TEXT / ATTRIB / ATTDEF / MTEXT(插入点、字高、样式字体、
  未处理的原始内容,格式码与 \U+XXXX 原样打印)
- MINICAD_H:实体另打印透明度与图层扩展数据里的透明度;块记录打印块名与引用它的 INSERT;
  多行文字打印附着点、方向、框宽;填充打印各边界路径的边数与范围
- MINICAD_HATCH 列出读入时会跳过的填充(HATCHSKIP);MINICAD_GLYPHS 按多行文字的纯文本查缺字

--bench 加 MINICAD_BENCH_VIEWS=x0,y0,x1,y1;...:模型页再按这些世界坐标窗口各截一张,并打印
画面左上、右下角的世界坐标(适配时扣掉了功能区、面板挡住的留边,画面不以窗口为中心)。
截图脚本 shot.ps1 加 -Views。drawing-debug skill 补上与 AutoCAD 截图对照的做法
(样板启动、-INSERT 或 OPEN 图纸、脚本结束前 FILEDIA 1)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tianzheng.dwg 与天正 2014 的显示对照:
- 墙柱填充:图纸设置 TCH_DBCONFIG 里的"填充"开关打开时才填(Tch::DecodeConfig),按墙、柱的
  材料码(TchWall::Material、TchColumn::Material)取设置里的标准或详图图案(出图比例小于详图
  比例时用详图),放在 PUB_HATCH 图层、颜色随层。图案库里没有时普通砖、钢筋混凝土用近似图案
  (Tch::MaterialHatchFallback),其余不画。规则按天正内核 TDbWall / TDbConfig::dwgInFields 的
  反编译,并用清掉填充开关的变体在天正里核对;柱有填充时显示为块(填充在轮廓下面)。
- 门窗断口两侧的墙端各画一条横穿墙厚的封口线,以前只是断开。
- 门槛线以前每扇门都画;现在只在门窗标志(TchOpening::Flags)含 0x200 / 0x400 时画,分别在
  门扇一侧 / 门扇对面的墙面上(内核 TDbOpening::DrawDoorLine,改标志与镜像的变体在天正里核对)。

MiniCADDwgInspect 的 MINICAD_WALLRAW 另打印墙的材料码等字段、门窗标志与图纸的填充设置;
MiniCADTchPatch 也能替换非图形对象(如 TCH_DBCONFIG)的位流。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8#楼-A平面图 外窗所在的竖墙是两个幕墙:玻璃幕墙(外窗)与转角处的一段普通幕墙。以前幕墙只按
轴线画侧边线,不用连接量、不填充:转角处的墙段没有斜接和填充,玻璃幕墙伸进下面的横墙 100。

- 内核 TDbCurtainWall::dwgInFields 先读墙的全部字段,其后是幕墙自己的 RC 版本、RC、6 个 BD、
  2 个 RC:Tch::DecodeCurtainWall 读出连接量、材料码与标志(与 DecodeWall 共用
  Detail::DecodeWallFields),读不出时仍按 DecodeWallPrefix 只取轴线与墙厚
- 非玻璃幕墙与墙画法相同:按连接量斜接、按材料填充、门窗处封口
- 玻璃幕墙的 4 条线按连接量缩进或伸出,各线在左右两侧的连接量之间按偏移插值(端点落在斜接
  线上);方头的一端封口,与相邻幕墙斜接的一端不封口
- 断口与墙线端点比较用 1e-6 的容差:通风井百叶宽 1999.9999999963,以前多出横穿墙厚的线和
  零长的墙线

与天正 2014 的显示核对了左右两侧外窗的上下转角、通风井与两段玻璃幕墙的转角。天正分解块内
对象时先分解的邻墙会断开连接,这些交接处以显示截图为准。

MiniCADDwgInspect 的 MINICAD_WALLRAW 也列出幕墙,另打印解码后的轴线、连接量、材料码与标志;
门窗的宽度与位置按全精度打印。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8#楼-A平面图 暖通套管规格表里的套管图例是天正矩形,天正画成矩形加"×",MiniCAD 只画了矩形。
以前当作"基点类型"跳过的 BS 是矩形标志(内核 TDbRect::GetRectFlag):TDbRect::ExplodeOrDraw2d
在矩形之外,1 画左下—右上的对角线,2 画左上—右下的,3 两条都画(TchRect::Flag)。版本 2
末尾的 RC 才是基点位置(GetBaseFlag)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 墙:句柄流里内核 TDbWall::dwgInFields 先读的 6 个软指针中,后 4 个是两端相接的墙
  (TchWall::Connections,起点、终点各两个)。接着的墙材料不同时这一端画端线——天正在两种
  材料之间画分界线,同材料的墙在节点处连成一体,不画。tianzheng.dwg 钢筋混凝土墙与砖墙的
  夹角以前是开口的;8#楼 横墙接玻璃幕墙处也补上了天正有的这条线
- 尺寸标注:标志 0x02 的各段文字位置(天正里拖动过的文字)以前读了不用,现在作为该段文字的
  中心(TchDimension::TextPositions)。8#楼 电梯井上方挤不下的 30、20 移到上一行与尺寸线下方,
  两端的 50 移到界线外侧,与天正一致
- 文字方向竖直带浮点误差时(8#楼 一组竖向尺寸比 π/2 大 2e-9)以前翻成自上而下、画到尺寸线
  另一侧,与旁边的文字叠在一起;现在按自下而上(Detail::Upright 容差 1e-6)

MiniCADDwgInspect:MINICAD_WALLRAW 按顺序打印全部句柄(含空句柄);新增 MINICAD_DIM,列出
另行指定了文字位置的尺寸标注(=all 时全部)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 打开 DWG / DXF 时读入图层的锁定标志(标志位 4),另存时写回。以前没有读,图纸里锁定的图层在
  MiniCAD 里与普通图层一样,不淡显、能选中
- 淡显:锁定图层上的对象顶点不透明度减半(DrawContext::kLockedFade,同 AutoCAD 的 LAYLOCKFADECTL
  默认 50,画到背景上前景、背景各半)。块参照在锁定图层上时整块淡显,块里锁定图层上的子实体也淡显;
  块定义级细分缓存的键加上是否整块淡显(BlockTessKey::faded),同一块定义淡显与否分开记
- 不能选中:Picking::IsPickable 排除锁定图层,点选、框选、悬停高亮、工具点取都选不中,捕捉不受影响;
  图层锁定后,已选中的该层对象移出选择集(Picking::DropUnpickable)。程序直接设进选择集的锁定对象,
  修改操作仍照旧跳过

测试:各版本 DXF / DWG 往返保留锁定标志;锁定的块参照整块淡显、块内锁定图层上的子实体淡显、淡显与否
分开缓存;桌面版自测改为锁定对象点不中、交叉框选不中、选中后锁定图层即移出选择集。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
图层面板的改名回调会同步刷新面板,ListView::SetItems 在回调里就取消了编辑;回调返回后
InlineEditor::Commit 又结束一次,输入框指针已是空的,按 Enter 提交改名时崩溃(点到别处提交的路径有判空,
不崩)。先输入重名被拒绝、改好后按 Enter 就会碰到。

- InlineEditor:提交、失焦提交时记下自己的输入框,回调里已经结束(或已开始新的一次)就不再结束、不再抢焦点
- ListView:SetItems 时行版本号加一,回调里行被换掉时不再把文字写回同一行号(那一行可能已是别的项)
- MiniGUITests 加回调里重建行后按 Enter、失焦提交的用例

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
锁定 / 解锁图标原来形状相同、只差颜色:现在锁定为琥珀色实心闭合的锁(带锁孔),解锁为灰色空心、锁梁抬起
打开的锁。

图层层级写在图层名里,各级之间用 $ 分隔(src/Scene/LayerPath.h):DWG 图层表是平的、AutoCAD 图层名不能含
“:”(Rhino 自己的 A::B 写不进去),Rhino 导出 DWG 时子图层就写成“父$子$孙”。文件格式不变,与 AutoCAD、
Rhino 往返都不丢层级。有空的一级时不分级(“$0$xx”这类绑定外部参照留下的名字)。

- 图层面板名称列是树(ListView 新增树形列 SetTreeColumn:按层级缩进、展开箭头,→ / ← 展开折叠):
  只有 A$B 没有 A 时补分组行,开 / 锁定显示下级的总体状态;可折叠、全部展开 / 折叠,搜索时全部展开
- 上级的开关、锁定、删除、改名连同下级一起改,一步撤销(LayerOps::ChangeTree / DeleteTree、
  RenameLayerTreeCommand)。下级不继承上级的状态,文件里存的就是每个图层实际的开关,AutoCAD 里看到的相同
- 改名只改这一级,名字里带 $ 即再往下分级;工具行与右键菜单“子图层”新建“上级$图层N”并进入改名;
  改名被拒绝(重名)时不再把文档标成已修改
- 名称列默认宽度 110 → 160(下级逐级缩进)
- 工具栏与特性面板的图层下拉框:下拉列表里接在最近的、确有其层的上级下面缩进、只写这一段,收起时写全名
- 图层排序改为逐级比较(上级在下级前面)
- 测试:LayerCommandTests 加路径拆分与上下级命令;自测加第 9.2 节(分组行、折叠、点分组行的锁、重名改名、
  Enter 改名、下拉框缩进);截图对比的 4 张图层表基准图换成新图标

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8#楼-A平面图 的尺寸数字、轴号编号在 MiniCAD 里是白色,天正 + AutoCAD 里与尺寸线、轴号圆同色。

- 尺寸、半径标注的数字取对象引用的标注样式的 DIMCLRT(TchDimStyle::TextColor):8#楼 各图的 _TCH_ARCH
  为随层;电气 CK、1#楼 的多为 7 号色,个别随块,按样式取色后它们不变
- 轴号读出句柄流里文字样式之后的文字图层(内核 TDbAxisLabelSet::GetTextLayerId,天正默认 AXIS_TEXT,
  版本 > 1 才有),编号放在该图层上、随层
- 角度标注按 DIMAZIN 去零(TchDimStyle::AngularZeros):8#楼 为 2,“90.00°”显示为“90°”,“100.55°”不变
- 其余天正文字逐类与天正 2014 的显示对照:把 PUB_TEXT 改红、对象图层改蓝后截图,索引符号、引出标注、
  箭头引注、剖切符号、指北针、楼梯的文字仍是白色,图名按对象里存的颜色(7),MiniCAD 原来的画法正确,不改
- MiniCADDwgInspect 的 DIMSTYLE 行打印 azin、clrt / clrd / clre

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
地形测试.dwg 的坐标约 (538845, 3686327):世界坐标直接转 float 在 y≈368 万处只剩 0.25 的分辨率,
视图投影矩阵里几百万的平移转成 float 后与顶点相减又丢一截。放大后线画偏几十个像素,画线的预览线
一格一格地跳;夹点、捕捉标记是按双精度换算的屏幕坐标,于是看起来落在线外。

- 各顶点流都存"世界坐标 − 渲染原点"(ToRenderFloat3):场景静态 / 动态流、点流、字形实例的平移、
  纹理文字、图像、选中流、悬停高亮、Overlay(内部改存双精度)、着色面与轮廓线、节点图预览;区域覆盖、
  视口合成、块裁剪的裁剪多边形同样减去原点。DrawContext::SetRenderOrigin,延迟长虚线铺的时候减
- ViewState::RenderOrigin 交给 Viewport::Render,原点平移在双精度里乘进视图投影矩阵;三维视图的
  网格与坐标轴按世界坐标生成,用合进原点之前的矩阵
- 原点在所有实体重新细分时选(Editor::ChooseRenderOrigin):可见实体中心的中位数,取 4096 的整数倍,
  图纸在原点附近时就是 0、显示与以前完全相同;改动的实体离原点太远(空图纸里画到测绘坐标上)时
  换原点、整图重新细分(Editor::NeedsRenderRebase)
- Editor::GetRenderOrigin;Editor::ForEachCachedVertex 给出世界坐标
- --bench 打印的画面角点改为 4 位小数(按它把原图坐标换成像素核对)

核对:地形测试.dwg 放大到约 4.7 个单位宽,折线到最近亮像素的距离平均 20.5 → 0.22 像素(最多 43 → 1)。
新增 RenderOriginTests:按 GPU 的 float 运算把顶点换到屏幕,场景线、选中流、夹点、画线预览与双精度
位置的差都在 0.08 像素以内(对照:直接转 float 差 63.8 像素)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
issue #29(捕捉功能完全无效:画的图没有闭合,线条长一点或短一点;在圆上取点,点落在圆内或圆外)。
几何数据本身是双精度的捕捉结果,问题在显示与约束:
- 放到最大(可视高度 0.01)时,原点附近的图纸坐标几百就差几个像素、上千差十几像素(float);
  圆固定 64 段,R21 的圆折线离真圆 0.025,即 2500 像素,捕捉到真圆上的点看起来不在圆上
- 极轴 / 正交在对象捕捉之后套用,开着时会把捕捉到的端点挪到角度线上

曲线加密(src/Core/Draw/CurveSampling.hpp):
- 圆、圆弧、椭圆、多段线的圆弧段(含带宽度的:BuildNodes、虚线粗线)先按原来的段数均分
  (SampleCurveSpans,不加密时画出的点与以前逐位相同),再逐段问 IDrawSink::RefineCurveSegment 要不要二分
- TransformDrawSink 把弦端点经插入变换、弦高与伸出量按最大轴向缩放放大后转发,ClipDrawSink 原样转发;
  DrawContext::SetCurveRefinement、悬停高亮按 CurveRefinement 判断(靠近范围、弦高超过容差的段加密)

局部显示(Editor::UpdateLocalDisplay):
- 视图附近(向四周各扩一个视图)的实体不多(块参照按块内子实体计,≤ 5000),且全图显示在这个缩放下
  float 误差超过 1/4 像素、或那里按默认段数细分的曲线棱角超过半个像素时,只细分那个范围里的实体:
  原点取在范围中心,圆弧在范围里按弦高 ≤ 1/4 像素加密,不用块定义级缓存。视图出了范围或缩放出了
  一半到两倍就换范围;已在局部显示时门槛放宽,免得来回切换。范围的 z 取全范围(测点块参照的 z 是高程)
- 全图的逐实体缓存进局部显示时收起来,缩小回来(LeaveLocalDisplay)拿回来重新拼接、不重新细分;
  局部显示期间改动过的、按当时缩放烘焙的实体重新细分,全图的显示设置变了则整个作废
- 查视图附近的结果缓存在 LocalEval(视图还在范围里时不再查拾取索引),包围盒取拾取索引里记的
  (Picking::GetIndexedBox,SpatialIndex::Query 加数量上限)。不缓存时 CK-05 平移每帧 25 → 245 ms
  (调试版);缓存后平移 24.9 / 24.9 ms、滚轮每格 87.9 / 88.5 ms(开 / 关判断),与不判断时相同

对象捕捉优先(InputResolver):捕捉到对象上的点时不再套正交 / 极轴(同 AutoCAD),并清掉上一次的
辅助线(ConstraintEngine::Clear);网格捕捉不是对象捕捉,照常约束。

核对:原点附近、带标高的 R21 圆与直线放到最大,圆离真圆 0.12 像素、直线 0.000 像素,顶点 146 个(全图 130);
地形测试.dwg 测点圆盘(带宽度的多段线)放到最大,边缘离真圆平均 0.24、最多 0.60 像素(改前 5° 一段的折线,
折角处约 15 像素)。RenderOriginTests 加:开着极轴画到端点(终点正好是端点)、放到最大、局部显示期间画的线
缩小回来仍在。桌面版自测 412 项全过。

天正对象、填充、样条、SHX 文字里的圆弧仍按各自的段数;三维视图不进局部显示。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MINICAD_VERSION 0.5.1 → 0.6.0;docs/release-notes/v0.6.0.md 汇总 v0.5.1 以来的改动:图层分级与锁定、
测绘坐标与深度放大的显示精度(#29)、对象捕捉优先于正交 / 极轴(#29)、文字转义与装饰线、天正对象显示、
天正填充图案编进程序、图层改名崩溃。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CHMOSE023
CHMOSE023 merged commit c088855 into main Oct 29, 2026
0 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant