Repository navigation
WSC3D v0.8.0
WSC3D v0.8.0 — 图谱 UI 修缮 · 资源独立 tab · 三维生成正射图 · 多资源画布切换 · 跨资源坐标变换 · .hpsml 解包 · 正射图 1:1 对齐与跨资源 SAM/YOLO(J 补丁)
发布日期:2026-05-04
对应计划:v0.7.0 验收反馈修缮 + v0.8.0 M4 多资源架构落地
上一发布:v0.7.0— 紧急修复 · 图谱完善 · 多解释 UI · AI 加深 · 多资源 · .hpsml 包
v0.7.0 浏览器端验收那轮的反馈集中在图谱 UI 挤、"资源"应该独立 tab、以及
没有原图 / 拓片时想用三维模型生成一张正射图当底图。把这波修掉后,顺势把
v0.8.0 规划的 M4 多资源架构三条线也落了地:多资源画布切换、跨资源
坐标变换(数据模型)、.hpsml 研究包解包导入。
这一版的核心是:这块画像石除了三维模型和 pic/ 下的原图之外,现在也能用
自己生成的正射图、手工注册的拓片 / 法线图 / RTI / 点云作为底图来标注,
还能把别人(别的研究者 / 别的机器)导出的 .hpsml 一键导进来。
工作日志:WORK_LOG_post_v0.7.0.md。
1. 图谱 UI 修缮(H1)
v0.7.0 的图谱 tab 被反馈:4 行 chip(布局 / 着色 / 中心性 / 类别)字太大挤换行;
PageRank 写英文没看懂;右侧 230px 排行榜侧栏把 canvas 挤窄。
这一版的调整:
- 中心性算法中文化:权威度(PageRank)/ 邻居数(Degree)/ 桥梁度(Betweenness)
/ 接近度(Closeness)。PageRank 不再露英文;hint 补 "Google PageRank 同款算法" - chip 行 4 → 2:第一行 "布局 + 着色 + 中心";第二行 "中心性 + 类别 + 来源"。
每段之间加.knowledge-graph-filter-divider细竖线视觉分组 - 排行榜从侧栏挪到下方:
.knowledge-graph-stage改flex-direction: column,
canvas 占整行min-height: 380px;排行榜改横向滚动卡片(每张 172px) - 群组规模 chip 并入排行榜 head:不再占独立区块;head 加
shortHintFor(kind)
简短提示(如 "被高权重邻居指向 → 综合权威") - 整体字号统一缩小:chip 从 11.5 → 10.5px,padding 缩;
.knowledge-graph-tab
min-height 360 → 520px 让 canvas 更舒展
2. 资源独立 tab + 三维模型生成正射图(H2 + H3)
2.1 "资源" tab
AnnotationPanel.TabKey 加 "resources"(Layers 图标 + 中文"资源")。
原本嵌在 ListTab 顶部的 ResourcesEditor 移到这个新 tab 下,可以占满面板高度。
2.2 ResourcesEditor 重写:3 个 section
- 从三维模型生成正射图:4 个方向 chip(正面 / 背面 / 顶面 / 底面)+
"生成正射图"按钮 - IIML 资源条目:列出
doc.resources[],每条支持预览图像(160px max-height
object-fit: contain)/ 删除 / 新标签页打开 - 后端已落盘:列出
data/stone-resources/{stoneId}/下实际文件;未关联
的一键"关联"到 IIML resources[]
2.3 正射图生成管线
前端 frontend/src/modules/annotation/orthophoto.ts(新建):
- 独立 offscreen Three.js 渲染器:
WebGLRenderer+document.createElement("canvas") - GLTFLoader 加载模型 → 算 AABB →
OrthographicCamerafrustum 正好裹住模型 + 5% 留白 - 4 种视图方向(front / back / top / bottom)
- 光照:AmbientLight 0.75 + DirectionalLight 1.0 斜上 45°(拓片摄影棚单灯效果)
- 背景 3 档:light(近拓片纸色 #efe7d8,默认)/ dark / transparent
- 输出 PNG blob + 像素尺寸 + 模型 AABB 尺寸 + frustumScale + view
- 所有 Three.js 资源在 finally 里 dispose +
forceContextLoss()防 WebGL context 泄漏
后端 backend/src/server.ts:
GET /api/stones/:id/resources:列出data/stone-resources/{stoneId}/下所有
落盘图像POST /api/stones/:id/resources:接收 PNG(Content-Type: image/png原始二进制
或 JSON{ type, imageBase64 }),落盘为{type}-{timestamp}.png- 静态托管
/assets/stone-resources/ - body size 25MB(3072px 长边 PNG 大约 5-10MB)
生成后自动:generateOrthoImage → uploadStoneResource → onAddResource 加进
IIML → refreshServerResources 刷新后端列表。
3. 多资源画布切换(I1)
SourceImageView 新增 imageUrl?: string props:默认走 /ai/source-image/{stoneId}
(pic/ 原图),传了就用它(任意 doc.resources 里的 image 类资源 URI)。
AnnotationWorkspace 新增"资源切换" segmented UI,高清图模式下显示在
source-switch 与 layer-switch 之间:
- 默认"原图"(pic/ 走
/ai/source-image/) doc.resources[]里 Orthophoto / Rubbing / NormalMap / LineDrawing /
OriginalImage / RTI / Other 类型的资源都会自动列成 chip- chip 文案按类型 + 方向生成("正射·正" / "拓片" / "法线" / ...)
- 切到非 pic/ 资源时强制禁用 Canny 线图叠加(后端 canny 管线只处理 pic/ 原图)
使用场景:生成正射图后切到"正射·正"底图,在上面继续标注;或手工注册
外部拓片 URI 后切到"拓片"底图做对照研究。
4. 跨资源坐标变换(I2)
数据模型层先行,为 v0.9.0 的画布跨资源投影做准备。
types.ts 新增 IimlResourceTransform 联合类型:
type IimlResourceTransform =
| {
kind: "orthographic-from-model";
view: "front" | "back" | "top" | "bottom";
modelAABB: { width: number; height: number; depth: number };
pixelSize: { width: number; height: number };
frustumScale: number;
generatedAt?: string;
}
| {
kind: "homography-4pt";
controlPoints: Array<{ model: [number, number]; image: [number, number] }>;
referenceResourceId?: string;
}
| {
kind: "affine-matrix";
matrix: number[];
referenceResourceId?: string;
};IimlResourceEntry.transform 字段可选保存变换。
正射图生成时自动填入 transform: { kind: "orthographic-from-model", view, modelAABB, pixelSize, frustumScale }。这样 modelBox UV ↔ 正射图 UV 就有了
精确可算的对应关系。
ResourcesEditor 卡片上新增 .resources-item-transform 金绿色提示条,显示
"正射投影 · 正面 · AABB W×H · frustum 1.05× · 像素 W×H"。
画布投影实装留 v0.9.0:v0.8.0 只把跨资源元数据铺好,画布渲染时暂仍按
原 frame 显示(不做跨资源投影),避免引入画布层 bug 影响主流程稳定性。
5. .hpsml 解包导入(I3)
backend/src/services/hpsml.ts 新建 importHpsmlPackage(root, config, getCatalog, payload, options):
- 校验:
format === "hpsml"+formatVersion(不同版本告警继续尝试) - 解 stoneId 优先级:
options.stoneId>context.stone.id>
iiml.documentId的前缀({stoneId}:iiml) - IIML 主体:直接走
saveIimlDoc(完整 ajv 校验,写入
data/iiml/{stoneId}.iiml.json) - 拼接方案:写入
data/assembly-plans/;冲突时生成新 id +
importedFromHpsml: true标记 - 冲突策略
options.conflictStrategy:"overwrite"(默认):直接覆盖本机已有"skip":若本机已存在则跳过 IIML 部分
后端端点:POST /api/hpsml/import?stoneId=...&conflict=overwrite|skip
(body = 完整 .hpsml JSON)
前端:
client.ts加importHpsmlPackage(payload, options)+HpsmlImportSummary类型AnnotationPanelListTab 下载区加"导入 .hpsml"按钮App.handleImportHpsml:用隐藏<input type="file" accept=".json,.hpsml">
触发文件选择,解析 JSON 后调 API;若导入的是当前stoneId,自动重新拉 IIML
让画布刷新
返回 summary:
{
"stoneId": "asset-29",
"imported": {
"iiml": true,
"annotations": 42,
"relations": 18,
"processingRuns": 6,
"resources": 3,
"assemblyPlans": 2
},
"skipped": { "iiml": false, "assemblyPlans": 0 },
"warnings": []
}6. commit 时间线
8cb7236 feat(annotation+backend): I1+I2+I3 多资源画布切换 + 跨资源坐标变换 + .hpsml 解包导入
8fb2583 feat(annotation+backend): H1+H2+H3 图谱 UI + 资源 tab 独立 + 三维模型生成正射图
ea995dc docs(v0.7.0): release notes + README + ROADMAP + 工作日志收尾
H 和 I 共 2 次 feat commit + 1 次 docs 收尾 commit(v0.7.0 → v0.8.0 共 3 次)。
7. 数据兼容
- 历史 IIML 文档没
resources[*].transform字段:按undefined处理,UI 容错显示 - 历史 IIML 文档没
resources[*].type === "Orthophoto":跨资源切换 UI 只显示
已存在的类型,不影响主流程 .hpsmlv0.1.0 formatVersion:导入时校验;未来 formatVersion 变化时先告警
再尝试兼容导入data/stone-resources/{stoneId}/目录不入库(.gitignore已有data/但
该子目录按需建立;多机协作时通过 .hpsml 包或单独 rsync)
8. 验收要点
进标注模式后依次试:
- 图谱 UI:图谱 tab → 布局 / 着色 / 中心 chip 一行完整显示不换行;
中心性下方是 "权威度 / 邻居数 / 桥梁度 / 接近度";canvas 占整行变大;
排行榜在 canvas 下方横向滚动 - 资源 tab:右侧 panel 应有 "资源" tab,点开看到 3 个 section
- 生成正射图:资源 tab → 选 "正面" → 点 "生成正射图" → 等 3-8 秒 →
IIML 资源条目区应新增一条 Orthophoto,缩略图显示生成的正射图;卡片下方
应有金绿色 "坐标变换 · 正射投影 · 正面 · AABB ... · frustum 1.05× · 像素 ..."
提示条 - 多资源画布切换:标注模式 → 切到高清图 → canvas 右上角 source-switch
下方应出现 "底图 原图 正射·正" 的资源切换条 → 点 "正射·正" → 画布显示
正射图;+线图 按钮自动置灰 - .hpsml 导入:先从 v0.7.0 导出的 .hpsml 文件 → 列表 tab 下载区点 "导入
.hpsml" → 选文件 → status 显示 "已导入 .hpsml(stoneId=xxx):IIML 写入、
标注 N / 关系 N / 拼接方案 N" → 若是当前画像石,画布自动刷新 - 后端已落盘刷新:资源 tab 第 3 个 section 应列出生成过的正射图文件;
点 "刷新" 应扫描data/stone-resources/{stoneId}/重新列出
9. J 补丁:正射图 1:1 对齐 + 跨资源 SAM / YOLO
收到用户反馈"生成的正射还有白边、SAM / YOLO 只能跑 pic/、正射和 3D 模型标注
不同步"之后在当天补的 J 补丁。核心思路是让正射图从生成开始就严格对齐 3D
模型 AABB,这样正射图 UV 数值上等于 modelBox UV,跨资源标注同步不需要再做
数学变换。
9.1 正射图 frustumScale 1.05 → 1.0
frontend/src/modules/annotation/orthophoto.ts:生成 frustum 从"AABB × 1.05
留白"改为"严格贴 AABB"。生成的 PNG 紧贴模型边缘,没有白边- 返回值增加
equivalentToModel: boolean;view=front + frustumScale=1.0 满足
时为 true,表示该正射图图像 UV 与 modelBox UV 完全 1:1 对应 IimlResourceTransform.orthographic-from-model也加equivalentToModel?: boolean
字段跟随持久化;老数据(没有该字段)通过 view=front + |frustumScale-1|<1e-3
的兜底判据也能识别为等价
9.2 SAM / YOLO 后端接 imageUri
ai-service/app/sam.py:新增sam_segment_by_uri(uri, prompts_uv)。URI 解析
支持/assets/stone-resources/...→<repo>/data/stone-resources/...本地
路径反解;不走 HTTP,不依赖 backend 在线ai-service/app/yolo.py:对应加yolo_detect_by_uri(uri, ...)ai-service/app/main.py:SamRequest/YoloRequestschema 加imageUri
字段;路由优先级 imageUri > stoneId > imageBase64- 这条新路径的坐标系是"图像 UV";当图像 UV 与 modelBox UV 等价时,前端直接
当 model frame 坐标用,不需要额外变换
9.3 前端 AI 调用随资源走
frontend/src/api/client.ts:runSamSegmentationBySource/runYoloDetection
参数加imageUri?: string;SAM 路径要求 imageUri 或 stoneId 至少给一个frontend/src/modules/annotation/sam.ts:refineBBoxWithSam和
requestSamCandidateWithSource加imageUri参数;传了就走 imageUri 分支frontend/src/modules/annotation/AnnotationCanvas.tsx:新增activeImageUri
prop;SAM 手动 prompt 提交时透传过去frontend/src/modules/annotation/AnnotationWorkspace.tsx:新增
onActiveImageResourceChange回调,把当前底图资源(id / uri / type /
equivalentToModel)告诉 App 层,让 YOLO 批量扫描 / SAM 精修都能拿到正确的
imageUrifrontend/src/App.tsx:handleSubmitYoloScan读activeImageResource.uri作为 YOLO 输入;候选
frame按 equivalentToModel 决定(等价时记 model,否则跟随 sourceMode)handleRefineWithSam从annotation.resourceId反查资源 URI,在原资源上
跑 SAM 精修,不错位到 pic/
9.4 跨资源标注自动同步(等价正射图)
AnnotationWorkspace新增派生状态activeResourceEquivalentToModel
(transform.equivalentToModel === true或 view=front + frustumScale≈1)effectiveSourceMode = sourceMode === "image" && activeResourceEquivalentToModel ? "model" : sourceMode:在等价正射图上,画布按 model 坐标系处理- 传给 AnnotationCanvas 的
sourceMode用 effectiveSourceMode → 在等价正射图
上新建的标注 frame="model",3D 模型视图自动能看到;反过来 model frame 的
历史标注也直接在等价正射图上显示 - UI 额外提示:等价正射图顶部有一枚绿色徽章"此图与 3D 模型坐标系已对齐 ·
标注自动双向同步"(.annotation-resource-aligned-hint样式) - 非等价资源(top/bottom/back 方向、或 frustumScale 不是 1.0 的老数据)仍按
image frame 处理,用户可走已有的 4 点单应性标定跨 frame 投影;这部分的
自动反投影留 v0.9.0(画布层按 resource.transform 投影任意资源坐标)
9.5 验收
- 生成正射图:图像紧贴模型 AABB,无白边
- 在等价正射图底图上 SAM 框选 → 候选直接出现在 3D 模型视图上(切回 3D 模型
模式可见) - 在 3D 模型上已有的标注 → 切到等价正射图底图自动出现在同样的位置
- YOLO 批量扫描:在正射图底图上点扫描,扫的是正射图而非 pic/ 原图;候选
resourceId 指向正射资源,SAM 精修时走该资源的 imageUri
10. 已知限制
- 本次发布所有功能已经过 typecheck,但 未做浏览器端到端测试
- 正射图生成依赖 WebGL 2.0 和 GLTFLoader;某些浏览器 / GPU 驱动对 offscreen
context 支持不佳时会失败(目前异常走 status 提示,不阻塞主流程) - J 补丁后:等价正射图(view=front + frustumScale=1.0)的跨 3D ↔ 正射
双向标注同步已实现;非等价资源(top/bottom 方向 / 拓片 / 法线图)的画布
跨资源投影仍留 v0.9.0(目前靠 annotation.frame + 4 点标定做跨 frame) - .hpsml 解包 只支持 overwrite / skip 两种冲突策略;三方合并 IIML(保留
双方的 annotation 差异)留 v0.9.0 - 多资源切换的 activeImageResourceId 不进 IIML 持久化,切了石头 / 刷新
浏览器会回到默认 pic/ 原图;这是设计(资源切换是临时视图状态) - Canny 线图后端管线只处理 pic/ 原图,切到非 pic/ 资源时前端强制禁用 +线图;
想要正射图的线图需要 v0.9.0 扩展 canny 管线支持任意 URI - 老正射图(v0.8.0 H3 生成、frustumScale=1.05)不会被自动识别为等价;重新
生成一次即可(生成按钮已默认 frustumScale=1.0)