diff --git a/EDGE_TREATMENT_CAPABILITY_REPORT.md b/EDGE_TREATMENT_CAPABILITY_REPORT.md new file mode 100644 index 0000000..8038dad --- /dev/null +++ b/EDGE_TREATMENT_CAPABILITY_REPORT.md @@ -0,0 +1,87 @@ +# M08/M09 F0:Manifold 内核能力探测报告 + +日期:2026-08-10 +范围:只读检查 `vendor/manifold/manifold.js`、`js/geometry.js` 与本地 Node/WASM 运行时;未修改生产源码,未启动浏览器、未下载依赖。 + +## 结论 + +**建议继续 F1(受限、纯网格的凸直棱倒角)进行原型验证;不建议直接进入 F2(实体圆角)的生产实现。** + +当前封装的 Manifold 能可靠执行网格构造、封闭性校验、布尔运算、切片和细分/平滑,但不提供可供 JavaScript 消费的 B-rep 拓扑面、拓扑棱边或原生 3D fillet/chamfer 算子。因此,真实倒角只能由 MiniSW 在 `MeshData` 层自行提取拓扑并重建网格;真实圆角还需要自行生成相切过渡面、处理边链与顶点角补片,风险显著更高。不得把 `smoothOut()` 当作实体圆角。 + +本地 vendor 文件不含可识别的 npm/package 版本元数据,因此本报告以实际导出和运行时行为为准,不猜测版本号。 + +## 基线与最小复现 + +- 执行:`node --loader ./tests/loader.mjs ./tests/test.mjs` +- 结果:64 通过、0 失败;几何内核初始化和既有实体布尔链路正常。 +- 运行时最小复现:`Manifold.cube([20,20,20], true)`,再调用 `getMesh()`、`decompose()`、`slice(0)`、`smoothOut()`、`refine(1)`,并在探测结束时手动释放全部创建的 WASM 对象。 +- 结果:立方体状态为 `NoError`,网格 8 顶点/12 三角形;`decompose()` 返回 1 个连通实体;`slice(0)` 返回 1 个二维多边形;`smoothOut()` 与 `refine(1)` 都返回 `NoError`。 + +## 已确认能力 + +| 能力 | 运行时接口/证据 | 对 M08/M09 的意义 | +|---|---|---| +| 网格读出 | `manifold.getMesh()` 返回 `vertProperties`、`triVerts`,并带可选 `faceID`、run/merge 数据 | 足以从 `MeshData` 合并共面三角形,自建拓扑面/边和稳定引用 | +| 网格构造与校验 | `new mod.Mesh({...})` + `new mod.Manifold(mesh)`;`status()` | 重建后的倒角/圆角网格可交由 Manifold 拒绝非流形结果 | +| 实体布尔 | `Manifold.union/difference/intersection`;现有 `geometry.js:booleanOp` 已统一封装 | 可用作工具体裁剪/并集的后备验证路线;不是原生边处理 | +| 组件分解 | `manifold.decompose()` | 仅按连通组件拆分,**不是**面/边分解,不能直接用于边选择 | +| 水平切片 | `manifold.slice(height)` 返回 `CrossSection`;`toPolygons()` 可读 | 可用于诊断或某些轴对齐特例;不能泛化为任意空间棱边圆角 | +| 细分/简化 | `refine`、`refineToLength`、`refineToTolerance`、`simplify` | 可改善离散网格质量,但不创建保持半径的圆角 | +| 平滑 | `smoothOut`、`smoothByNormals`、静态 `Manifold.smooth(mesh, sharpenedEdges)` | 是网格平滑/法线相关操作,非可控的几何圆角;不能用于 M09 验收 | +| 其他几何诊断 | `numVert/numEdge/numTri`、`volume`、`surfaceArea`、`genus`、`rayCast`、`boundingBox` | 可支持结果验证、性能统计及视口边拾取的射线辅助 | +| 二维偏移 | `CrossSection.offset(delta, joinType, ...)` | 只适用于 2D 截面;可服务某些专用工具体方案,不等于 3D 边偏移 | + +## 缺失能力与阻塞 + +1. **没有 B-rep 面/边枚举或邻接 API。** `numEdge()` 仅给数量;运行时没有 `faces()`、`edges()`、`faceID()` 等可遍历三维拓扑接口。`getMesh().faceID` 是可选来源/运行标识,不能作为完整稳定的几何边引用。 +2. **没有原生 3D chamfer/fillet/offset API。** 在 `manifold.js` 的导出和 Manifold 原型中未发现 `chamfer`、`fillet`、三维 `offset` 或曲面过渡算子。 +3. **`decompose()` 不是拓扑分面。** 它返回连通 Manifold 组件,无法定位“立方体的一条棱”。 +4. **`slice(height)` 仅限全局 Z 高度。** 它不能围绕任意选中边产生局部截面。 +5. **平滑不保特征语义。** `smoothOut()`/`smoothByNormals()` 无半径、目标边链、相切条件或顶点补片参数;用它冒充 R5 会改变不该处理的面且无法保证尺寸。 + +## 建议的 F1 可行路线:纯网格凸直棱倒角 + +前提:首版只接受封闭、方向一致、凸多面体上的直边;先做单条棱,再扩展相互不接触的多条平行棱。算法由 `js/features/edge-treatment.js` 独立实现,主代理随后负责注入 `geometry.js/doc.js/UI`。 + +1. 对 `MeshData` 以量化顶点坐标建立无向三角边表;合并共面的相邻三角形,得到逻辑平面与候选逻辑棱。 +2. 以相邻面法向、端点量化坐标、长度、二面角和凸性构造稳定边签名;重建时签名唯一匹配才解析,歧义或缺失必须明确报错。 +3. 对一条凸直棱,将其两侧面沿各自面内法向收缩,生成两条偏移边;以四边形(再三角化)替换原棱邻域,并处理端点局部拓扑。 +4. 严格检查倒角距离小于两侧可用面宽、未与其他待处理边冲突、输出无零面积三角形;构造后通过 `new mod.Manifold(new mod.Mesh(...)).status()` 做流形验收。 +5. 输出 `MeshData` 和边线段;WASM 对象只在主代理注入的上下文中创建和释放。 + +该路线可产生真实 STL 几何,但端点补片、多个相交选择边和凹边会迅速增加组合复杂度;首版不应承诺它们。 + +## F2 圆角评估 + +圆角在同一拓扑框架上还需:按半径生成圆弧截面、沿直棱扫出相切曲面、替换两侧面条带、在端点/边链转角处生成角补片,并保证共享顶点、面朝向和流形性。Manifold 可验证并布尔组合结果,却不替代这些构造步骤。 + +- **可验证的后备方案:** 仅对“贯穿整个实体、两端开放或端点可由明确平面封闭”的单条凸直棱,使用解析圆柱/四分之一圆柱工具体结合布尔差/并实现,并以截面、体积、流形状态验证。该方案仍需先可靠定位两相邻面与边局部坐标系。 +- **不可接受的方案:** 调用平滑 API、增加法线、仅在 Three.js 渲染高亮圆弧、或将草图圆角矩形改名。这些都不保证 STL 中存在真实 R 面。 +- **生产建议:** 在 F1 的拓扑提取、稳定引用、单边倒角、10 次重建稳定和独立网格流形测试完成前,暂停 F2。F2 首版范围应明确限制为立方体单条凸直棱 R 值,不承诺一般边链。 + +## 风险、复杂度与继续条件 + +| 项目 | 评估 | +|---|---| +| F1 单凸直棱倒角 | 中高复杂度;约 2–4 个实现/测试迭代,主要风险是端点补片和三角网格方向 | +| F1 多边选择 | 高复杂度;必须先检测相邻/相交选择边,否则偏移区域会重叠 | +| F2 单凸直棱圆角 | 高复杂度;需要圆柱曲面、两端补片、相切与半径上限校验 | +| F2 共线边链/一般边链 | 很高复杂度;需链识别、交界拼接和顶点角策略,当前不宜在同一轮承诺 | +| 性能 | 小型立方体可望低于 1 秒;必须设置三角数/分段数上限,避免无界细分 | + +继续 F1 的门槛:主代理认可“纯 MeshData 拓扑层”是 M08/M09 的正式基础,并允许先交付受限凸直棱功能。继续 F2 的门槛:F1 已通过闭合、体积、无退化三角形、稳定引用和 10 次重建测试;否则应以本报告记录技术阻塞,不做视觉伪实现。 + +## 对主代理的接入提示 + +F0 没有新增运行时代码或接口。若批准 F1,建议由子模块导出任务书中约定的 `extractTopology`、`makeStableEdgeRef`、`resolveEdgeRef`、`buildChamferMesh`;主代理再在 `geometry.js` 中以唯一已初始化的 `mod` 把 `MeshData` 转回 Manifold,并接入文档模型、拾取与序列化。 + +## 后续实施结果 + +本报告完成后,F1 的全部继续门槛已经通过,因此项目按报告建议继续了受限 F2: + +- M08 已实现凸多面体单条直棱的真实截切倒角、稳定引用和视口拾取。 +- M09 已实现凸多面体单条直棱的恒定半径多段圆柱过渡面;没有使用平滑 API。 +- 两者输出都使用共享索引的封闭 `MeshData`,并通过项目唯一 Manifold 内核的 `NoError`、正体积、无退化三角形和重复构建测试。 +- M08、M09 独立测试各 `5/5`,核心文档/AI/保存重建集成测试也已覆盖。 +- 安全范围仍严格限制为单条凸直棱;多边选择、边链、凹边和非凸实体按本报告风险结论明确拒绝。 diff --git a/PHASE1_M10_MANUAL_CHECKLIST.md b/PHASE1_M10_MANUAL_CHECKLIST.md new file mode 100644 index 0000000..833ab4f --- /dev/null +++ b/PHASE1_M10_MANUAL_CHECKLIST.md @@ -0,0 +1,77 @@ +# MiniSW 第一阶段 M10 手动验收清单 + +日期:2026-08-10 +状态:等待手动浏览器确认 +说明:M01~M09 的代码与自动化验收已完成;本文件只保留必须由人工观察的界面、交互和课程演练项目。全部勾选后,才在 `ROADMAP.md` 中把 M10 标为完成。 + +## 1. 启动与控制台 + +- [ ] 双击 `启动.bat`,浏览器能打开 `http://127.0.0.1:8898/index.html`。 +- [ ] 启动页正常消失,视口、Ribbon、特征树、属性面板和 AI 面板均可见。 +- [ ] 浏览器开发者工具控制台没有红色异常;允许出现浏览器自身的性能提示。 +- [ ] 前视、上视、右视和等轴测方向与界面名称一致。 + +## 2. AI 一句话轴承座 + +在 AI 面板输入: + +> 生成一个120×80×12的轴承座,主体凸台直径60高32,中心通孔直径30,两条厚4mm加强筋,实体倒角和R4实体圆角 + +验收: + +- [ ] AI 一次执行完成,不需要手工补特征。 +- [ ] 模型可见且没有错误提示,整体尺寸约为 `120×80×43 mm`。 +- [ ] 特征树依次包含:底板、实体倒角、实体圆角、主体凸台、左加强筋、右加强筋、中心通孔。 +- [ ] 参考几何中存在“筋定位基准面”。 +- [ ] 中心通孔使用“到下一面”而不是固定深度。 +- [ ] 模型上能观察到真实斜面倒角和多段圆弧过渡圆角。 + +## 3. 参数编辑与重建 + +- [ ] 右键左加强筋,进入特征参数编辑,把筋宽从 `4` 改为 `5`,确定后模型成功重建。 +- [ ] 编辑实体倒角距离,合法较小值能重建;过大值显示中文失败诊断而不是页面崩溃。 +- [ ] 编辑实体圆角半径或圆弧分段数,合法值能重建;过大半径显示中文失败诊断。 +- [ ] 编辑中心通孔,终止条件下拉框能看到固定深度、贯穿全部、对称、到下一面、到指定面和到实体。 +- [ ] 单击特征树中的新特征时,视口能显示对应高亮。 + +## 4. 实体棱边拾取 + +建议先新建一个简单长方体单独验证: + +- [ ] 点击“实体倒角”,再靠近长方体可见棱边单击,输入 `5` 后成功创建。 +- [ ] 点击“实体圆角”,选择另一条未处理凸直棱,输入 `5` 后成功创建。 +- [ ] 单击远离棱边的位置时,界面提示未拾取到棱边,不创建错误特征。 +- [ ] 对非凸复杂主体或不支持的多边选择,界面明确拒绝,不以光照平滑伪装成功。 + +## 5. 保存、撤销与导出 + +- [ ] 保存轴承座 JSON,刷新或关闭页面后重新打开,模型与特征树一致。 +- [ ] 修改一个新特征后执行撤销、重做,模型和参数能正确往返。 +- [ ] 导出 STL 成功,并能在外部查看器中打开;孔、筋、倒角和圆角均可见。 +- [ ] 打开一个第一阶段以前保存、没有 `references` 字段的旧工程,仍能正常重建。 + +## 6. 演练记录 + +- [ ] 完成一次从启动、AI 输入、参数编辑、保存到 STL 导出的连续课程作业演练。 +- [ ] 记录一段视频或至少四张截图:AI 输入、完整模型、特征树、STL 外部查看结果。 +- [ ] 在演练中没有持续卡顿、页面失去响应或连续重建后明显变慢。 + +## 7. 自动化证据(已完成) + +- 核心综合测试:`94/94` 通过。 +- 七个第一阶段独立模块测试:`93/93` 通过。 +- 总计:`187/187` 通过。 +- AI 轴承座 Node 环境完整重建:约 `20~25ms`,预算 `<1000ms`。 +- 轴承座连续重建 `10` 次体积一致。 +- 轴承座保存/打开体积一致,STL 三角数与网格一致。 +- 旧版无 `references` 字段工程可重建。 + +## 8. 最终签字 + +- [ ] 上述人工项目全部通过。 +- [ ] 将 `ROADMAP.md` 中 M10 改为 `[x]`。 +- [ ] 将路线图当前状态改为“第一阶段完成,下一步进入阶段二 M11”。 + +验收人:____________ +验收日期:____________ +备注:____________________________________________________________ diff --git a/PHASE1_SUBAGENT_TASKS.md b/PHASE1_SUBAGENT_TASKS.md new file mode 100644 index 0000000..4d21f6d --- /dev/null +++ b/PHASE1_SUBAGENT_TASKS.md @@ -0,0 +1,721 @@ +# MiniSW 第一阶段并行子代理任务书 + +版本:v1.0 +日期:2026-08-10 +适用范围:`ROADMAP.md` 的 M02~M10 +当前基线:M01 圆形截面基础扫描已完成,核心测试 51/51 通过 + +## 1. 目标 + +第一阶段的目标是补齐高级零件建模能力,使 MiniSW 能生成包含扫描、放样、筋、参考几何、复杂拉伸终止条件、实体倒角和实体圆角的机械零件,并最终通过“AI 一句话生成轴承座”的综合验收。 + +本任务书用于后续启动多个子代理并行开发。它只规定工作分工、接口、边界和验收方式,不代表现在已经启动子代理。 + +第一阶段包含: + +- M02:路径草图 + 任意封闭截面扫描 +- M03:两个平行等顶点截面的基础放样 +- M04:多截面、异顶点数放样 +- M05:筋特征 +- M06:参考几何 +- M07:`toNext`、`toFace`、`toBody` 终止条件 +- M08:实体棱边倒角 +- M09:实体棱边圆角 +- M10:阶段一综合验收 + +## 2. 协作模型 + +### 2.1 并发限制 + +当前包括主代理在内最多允许 4 个代理同时工作,因此每个批次最多同时运行 3 个子代理。 + +建议分三批执行: + +```text +批次 A(基础几何,可并行) + 子代理 A:扫描完整版 M02 + 子代理 B:放样 M03/M04 + 子代理 D:参考几何 M06 + ↓ 主代理集成与回归 + +批次 B(依赖基础能力,可并行) + 子代理 C:筋 M05 + 子代理 E:终止条件 M07 + 子代理 F:实体倒角/圆角 M08/M09 + ↓ 主代理集成与回归 + +批次 C(验收) + 子代理 G:第一阶段独立测试审查 + 主代理:M10 综合集成、浏览器验收、文档更新 +``` + +### 2.2 主代理是唯一集成者 + +主代理负责所有共享入口和最终决策。除非任务书后续被主代理显式修改,只有主代理可以修改下列共享文件: + +- `js/geometry.js` +- `js/doc.js` +- `js/agent.js` +- `js/main.js` +- `js/tree.js` +- `js/sketchui.js` +- `js/viewport.js` +- `js/math.js` +- `js/sketch.js` +- `index.html` +- `css/style.css` +- `tests/test.mjs` +- `tests/loader.mjs` +- `README.md` +- `ROADMAP.md` + +子代理负责在独立模块和独立测试文件中实现自己的能力,完成后把接口和交接说明提交给主代理,由主代理接入共享文件。 + +### 2.3 建议新增目录 + +为降低并行冲突,第一阶段的新实现优先放在: + +```text +js/features/ + sweep.js + loft.js + rib.js + reference.js + termination.js + edge-treatment.js + +tests/ + test.sweep.mjs + test.loft.mjs + test.rib.mjs + test.reference.mjs + test.termination.mjs + test.edge-treatment.mjs + test.phase1.mjs +``` + +目录和文件由对应子代理创建。其他子代理不得修改不属于自己的模块。 + +## 3. 全体子代理通用规则 + +### 3.1 开始工作前 + +每个子代理必须先完成以下只读检查: + +1. 阅读 `README.md`、`ROADMAP.md` 和本任务书。 +2. 查看 `git status --short`,识别用户和主代理已有改动。 +3. 阅读与自己任务直接相关的现有源码和测试。 +4. 运行当前核心测试,确认基线状态;如果基线已经失败,先报告主代理,不得擅自修复无关问题。 +5. 向主代理确认自己将创建或修改的文件列表,不得扩大范围。 + +### 3.2 文件边界 + +- 多个代理共享同一工作目录,文件修改会立即互相可见;严禁两个代理同时修改同一个文件。 +- 不得恢复或修改当前处于删除状态的 `SUBPROXY_TASKS.md`、`TASK_0_REPORT.md`、`TASK_A_REPORT.md`、`TASK_B_REPORT.md`、`TASK_C_REPORT.md`。 +- 不得修改 `E:\小灰\`、全局记忆或项目外部文件。 +- 不得使用 `git reset --hard`、`git checkout --`、清理工作区或其他会覆盖现有改动的命令。 +- 不得自行提交、推送或创建 PR,除非主人另行授权。 +- 不得重命名、移动或格式化与任务无关的文件。 +- 只使用 `apply_patch` 编辑文件,保留 UTF-8 中文内容。 + +### 3.3 架构约束 + +- 保持原生 JavaScript ESM,不引入打包器。 +- 不新增 CDN 或在线运行时依赖,应用必须继续彻底离线运行。 +- 优先复用仓库内 `vendor/three` 和 `vendor/manifold`。 +- 不得重新引入旧测试路径或外部源码副本;测试必须直接调用当前仓库源码。 +- 新模块使用命名导出,不使用隐式全局状态。 +- 所有长度单位统一为毫米,角度对外使用度数、内部可使用弧度但必须在接口说明中标明。 +- 世界坐标和草图坐标的转换只能走统一接口,不得在多个模块复制不同版本的坐标变换逻辑。 +- 错误必须提供可理解的中文信息,不能只返回 `undefined` 或底层 WASM 状态码。 + +### 3.4 几何内核生命周期 + +- 谁创建 manifold/CrossSection 等 WASM 对象,谁负责释放;所有权转移必须写在函数注释中。 +- 临时对象必须使用 `try/finally` 或等价结构释放。 +- 返回 manifold 的函数必须明确写明“返回值所有权交给调用方”。 +- 不得在失败路径遗留未释放对象。 +- 重复重建测试至少执行 10 次,并检查体积、包围盒和错误状态稳定。 + +### 3.5 测试要求 + +每个子代理必须提供独立测试文件,至少覆盖: + +- 正常路径 +- 参数边界 +- 退化输入 +- 非法引用 +- 保存/打开需要保留的纯数据 +- 重复执行稳定性 +- 中文错误信息 + +独立测试通过不等于任务完成。只有主代理完成共享入口接入并通过总回归后,里程碑才能在 `ROADMAP.md` 中勾选。 + +### 3.6 性能预算 + +- 普通拉伸、筋、参考几何解析:目标小于 200ms。 +- 扫描、放样、实体圆角/倒角:目标小于 1s。 +- 测试必须记录至少一个典型模型的运行时间。 +- 网格过密时应给出降采样建议,不得无上限增加路径和截面分段数。 + +### 3.7 子代理交付报告格式 + +每个子代理完成后必须向主代理报告: + +1. 完成的能力。 +2. 新增和修改的文件。 +3. 导出接口及参数语义。 +4. 对象所有权和释放规则。 +5. 测试命令、通过数和耗时。 +6. 已知限制。 +7. 需要主代理接入共享文件的具体位置。 +8. 是否存在与其他代理的接口冲突。 + +## 4. 公共数据与接口契约 + +子代理不得自行改变以下公共概念;如确需调整,先向主代理提交接口变更申请。 + +### 4.1 MeshData + +```js +{ + verts: Float32Array, // xyz 连续排列 + tris: Uint32Array, // 三角形顶点索引 +} +``` + +要求:三角面朝外、无退化三角形、封闭实体满足二维流形条件。 + +### 4.2 PathData + +```js +{ + points: [[x, y, z], ...], + closed: false, + sourceSketchId: number | null, +} +``` + +路径至少包含两个不同点。采样点去重容差统一为 `1e-6 mm`。 + +### 4.3 ProfileData + +```js +{ + points: [[u, v], ...], + closed: true, + plane: { + origin: [x, y, z], + xAxis: [x, y, z], + yAxis: [x, y, z], + normal: [x, y, z], + }, + sourceSketchId: number | null, +} +``` + +轮廓不得包含重复末点;闭合由 `closed` 表达。外环和孔环需要明确分组,禁止依赖不稳定的顺逆时针猜测。 + +### 4.4 ReferenceData + +参考几何使用稳定 ID,不直接保存运行时对象: + +```js +{ id, type: 'plane', name, origin, normal, xAxis, sourceRefs, params } +{ id, type: 'axis', name, origin, direction, sourceRefs, params } +{ id, type: 'point', name, position, sourceRefs, params } +{ id, type: 'csys', name, origin, xAxis, yAxis, zAxis, sourceRefs, params } +``` + +### 4.5 特征构建结果 + +纯网格算法优先返回 `MeshData`。需要 manifold 布尔运算的模块通过主代理提供的内核上下文工作,不得自行初始化第二套 WASM 模块。 + +接口成功时返回结果,失败时抛出 `Error`。不得混用“返回 null”和“抛异常”两种失败协议。 + +## 5. 子代理 A:扫描完整版(M02) + +### 5.1 目标 + +把当前“世界坐标离散路径 + 圆形截面”扫描扩展为“路径草图 + 任意封闭截面草图”,并支持可控的截面方向和扭转。 + +### 5.2 允许修改 + +- 新建并修改 `js/features/sweep.js` +- 新建并修改 `tests/test.sweep.mjs` +- 如需测试夹具,可新建 `tests/fixtures/sweep/` 下的 JSON 文件 + +### 5.3 禁止修改 + +- 所有第 2.2 节列出的共享文件 +- `js/features/loft.js` 及其他子代理文件 + +### 5.4 具体任务 + +1. 从路径草图的直线、圆弧和连续多段线生成有序三维采样点。 +2. 从封闭截面草图提取一个或多个轮廓环。 +3. 支持圆形、矩形和一般多边形截面。 +4. 使用平行传递标架,避免低曲率处的 Frenet 标架翻转。 +5. 支持 `frameMode: 'parallelTransport' | 'fixed'`。 +6. 支持 `twistDegrees`,沿路径累计旋转截面。 +7. 支持起点/终点封端。 +8. 检测零长度路径、路径断裂、开放截面、截面退化、急弯自交和截面尺寸过大。 +9. 保持当前 M01 圆形截面扫描结果兼容。 + +### 5.5 建议导出接口 + +```js +export function samplePathSketch(sketch, options = {}) +export function profileFromSketch(sketch, options = {}) +export function buildSweepMesh({ path, profile, frameMode, twistDegrees, capStart, capEnd, segments }) +``` + +### 5.6 最低测试集 + +- 圆形截面沿直线扫描 +- 矩形截面沿直线扫描 +- 圆形截面沿四分之一圆弧扫描 +- 矩形截面沿多段线路径扫描 +- 固定方向与平行传递结果不同但均有效 +- 90° 扭转后的终点截面方向正确 +- 开放截面被拒绝 +- 路径只有一个点被拒绝 +- 急弯导致自交时给出明确错误或降采样提示 +- 生成网格满足流形要求 + +### 5.7 验收标准 + +- 独立测试全部通过。 +- 直线、圆弧、多段线三类路径均可工作。 +- 圆形、矩形、一般封闭多边形三类截面均可工作。 +- 典型模型构建小于 1s。 +- 向主代理提供从现有 `Doc` 草图引用转换到公共 `PathData/ProfileData` 的接入说明。 + +## 6. 子代理 B:放样(M03/M04) + +### 6.1 目标 + +实现两个及多个封闭截面间的实体放样,解决顶点配对、异顶点数重采样和截面起点对齐问题。 + +### 6.2 允许修改 + +- 新建并修改 `js/features/loft.js` +- 新建并修改 `tests/test.loft.mjs` +- 如需测试夹具,可新建 `tests/fixtures/loft/` + +### 6.3 禁止修改 + +- 所有共享文件 +- 扫描、筋、参考几何等其他代理模块 + +### 6.4 具体任务 + +1. M03:两个平行、等顶点数封闭截面的侧壁连接和端面封闭。 +2. 自动统一截面环方向。 +3. 自动选择截面起始点,使相邻截面连线总长度尽量小。 +4. M04:支持三个及以上截面。 +5. 支持异顶点数截面的均匀弧长重采样。 +6. 支持矩形到圆形、圆形到多边形的过渡。 +7. 检测截面顺序错误、共面重复截面、面积趋近于零、自交和生成体翻转。 +8. 为后续切除放样保留同一网格接口,不在本任务中改文档布尔语义。 + +### 6.5 建议导出接口 + +```js +export function resampleClosedProfile(points, count) +export function alignProfileStart(reference, candidate) +export function buildLoftMesh({ profiles, resampleCount, capStart, capEnd, alignment }) +``` + +### 6.6 最低测试集 + +- 等顶点矩形到矩形 +- 等顶点圆到圆 +- 异顶点矩形到圆形 +- 三截面方—圆—方过渡 +- 截面输入顺序反向时自动修正 +- 两个截面重合时报错 +- 退化截面时报错 +- 网格封闭且体积大于零 +- 保存所需的截面引用参数可以 JSON 序列化 + +### 6.7 验收标准 + +- M03 与 M04 测试分别报告,不得用“基础版完成”代替完整版。 +- 至少通过矩形到圆形的异顶点放样。 +- 输出为稳定、封闭的 `MeshData`。 +- 典型三截面放样小于 1s。 + +## 7. 子代理 C:筋特征(M05) + +### 7.1 依赖 + +在批次 A 集成完成后启动。依赖稳定的草图平面转换、拉伸工具和布尔并集接口。 + +### 7.2 允许修改 + +- 新建并修改 `js/features/rib.js` +- 新建并修改 `tests/test.rib.mjs` + +### 7.3 禁止修改 + +- 所有共享文件 +- 扫描、放样和参考几何模块 + +### 7.4 具体任务 + +1. 接受一条或多条连续开放轮廓作为筋中心线。 +2. 支持厚度、单侧/双侧、翻转方向和拔模角参数。 +3. 将中心线扩展为薄壁封闭轮廓。 +4. 沿草图平面法向拉伸到目标实体范围。 +5. 与已有实体求交/并集,确保筋只保留与主体相连的部分。 +6. 检测筋不接触主体、厚度过大、轮廓自交、路径不连续和零长度线段。 + +### 7.5 建议导出接口 + +```js +export function offsetOpenPath(points, thickness, side) +export function buildRibProfile({ path, thickness, side, draftDegrees }) +export function buildRibTool(ctx, { sketch, thickness, side, flip, extent, body }) +``` + +其中 `ctx` 由主代理注入几何内核能力,子代理不得创建第二个 manifold 实例。 + +### 7.6 最低测试集 + +- 底板与侧板之间单条直筋 +- 双侧对称筋 +- 翻转方向 +- 折线筋 +- 筋不接触主体时报错 +- 厚度过大时报错 +- 重复重建体积稳定 + +### 7.7 验收标准 + +- “底板 + 侧板 + 厚 3mm 筋板”端到端几何有效。 +- 筋与主体形成一个连通实体。 +- 普通筋特征构建小于 200ms。 + +## 8. 子代理 D:参考几何(M06) + +### 8.1 目标 + +提供稳定、可序列化、可重建的基准面、基准轴、基准点和坐标系计算模块。 + +### 8.2 允许修改 + +- 新建并修改 `js/features/reference.js` +- 新建并修改 `tests/test.reference.mjs` + +### 8.3 禁止修改 + +- `doc.js`、`math.js`、UI 和其他共享文件;数据接入由主代理完成 + +### 8.4 具体任务 + +1. 偏移基准面:相对已有平面沿法向偏移指定距离。 +2. 角度基准面:绕指定轴旋转指定角度。 +3. 平行于指定面并经过指定点的基准面。 +4. 两点基准轴。 +5. 两平面交线基准轴。 +6. 显式坐标基准点和引用实体中心点。 +7. 用户坐标系:原点和正交三轴。 +8. 验证法向、方向向量归一化和右手坐标系。 +9. 检测平行平面无交线、重合点、零方向向量、循环引用和丢失引用。 + +### 8.5 建议导出接口 + +```js +export function makeOffsetPlane(basePlane, distance) +export function makeAngledPlane(basePlane, axis, degrees) +export function makePlaneThroughPoint(basePlane, point) +export function makeAxisFromPoints(a, b) +export function makeAxisFromPlanes(a, b) +export function makeCoordinateSystem(origin, xHint, yHint) +export function resolveReference(reference, lookup) +``` + +### 8.6 最低测试集 + +- 前视面偏移 10mm +- 绕基准轴旋转 30° +- 两垂直平面求交轴 +- 平行平面求交被拒绝 +- 两个相同点不能建立轴 +- 坐标系满足单位长度、互相垂直和右手性 +- JSON 往返后计算结果一致 +- 循环引用被检测 + +### 8.7 验收标准 + +- 所有参考几何均为纯数据,可 JSON 序列化。 +- 计算结果具有稳定 ID 引用,不依赖数组下标。 +- 主代理可据此在偏移基准面上创建草图并拉伸。 + +## 9. 子代理 E:拉伸终止条件(M07) + +### 9.1 依赖 + +在参考几何和稳定拓扑引用完成初步集成后启动。 + +### 9.2 允许修改 + +- 新建并修改 `js/features/termination.js` +- 新建并修改 `tests/test.termination.mjs` + +### 9.3 禁止修改 + +- 现有 `buildExtrude`、文档模型和 UI;接入由主代理完成 + +### 9.4 具体任务 + +1. 统一终止模式:`blind`、`throughAll`、`symmetric`、`toNext`、`toFace`、`toBody`。 +2. `toNext`:沿拉伸方向找到第一个有效实体交点。 +3. `toFace`:根据稳定面引用解析目标面,并计算有效深度。 +4. `toBody`:生成足够长工具体后与目标实体裁剪。 +5. 支持正向、反向和偏置距离。 +6. 检测目标位于反方向、目标不存在、没有交点、深度趋近于零和引用失效。 +7. 不允许用固定超大深度冒充 `toFace` 的最终结果;近似方案必须明确标注并有误差测试。 + +### 9.5 建议导出接口 + +```js +export function normalizeTermination(params) +export function resolveToNext({ origin, direction, body, tolerance }) +export function resolveToFace({ origin, direction, targetFace, offset, tolerance }) +export function buildToBodyTool(ctx, { profileTool, targetBody, direction }) +``` + +### 9.6 最低测试集 + +- 两层实体间 `toNext` +- 到平面 `toFace` +- 到倾斜面 `toFace` +- 到独立实体 `toBody` +- 翻转方向 +- 目标在反方向时报错 +- 丢失引用时报错 +- 重复重建结果稳定 + +### 9.7 验收标准 + +- 三种新增模式均有独立测试和文档参数示例。 +- 结果不能越过目标面或目标实体。 +- 普通终止条件解析小于 200ms。 + +## 10. 子代理 F:实体倒角与圆角(M08/M09) + +### 10.1 目标 + +建立实体拓扑边识别和稳定引用,在此基础上实现真正作用于三维棱边的倒角与圆角。草图圆角矩形不能作为本任务的替代品。 + +### 10.2 允许修改 + +- 新建并修改 `js/features/edge-treatment.js` +- 新建并修改 `tests/test.edge-treatment.mjs` +- 可新建 `tests/fixtures/edge-treatment/` + +### 10.3 禁止修改 + +- `geometry.js`、`doc.js`、`viewport.js`、`tree.js` 和 AI 文件 +- 不得把已有 `chamfer_rect`、`fillet_rect` 政名后宣称实体功能完成 + +### 10.4 执行顺序 + +该任务必须按三个检查点推进: + +1. **F0 内核能力探测**:确认当前 manifold 版本能提供哪些面、边、切片、分解、平滑或网格操作;形成能力报告。 +2. **F1 实体倒角**:先完成凸多面体的一条直棱边倒角,再扩展到多边选择。 +3. **F2 实体圆角**:先完成立方体一条直棱边的恒定半径圆角,再扩展到共线边链。 + +如果 F0 证明内核无法安全提供精确圆角所需能力,必须报告技术阻塞和可验证替代方案,不能提交会产生非流形网格的视觉伪实现。 + +### 10.5 具体任务 + +1. 从三角网格合并共面三角形,提取拓扑面和拓扑边。 +2. 为边生成稳定引用:相邻面特征、端点量化坐标和几何签名组合,禁止只保存三角形索引。 +3. 倒角支持距离参数和单边/多边选择。 +4. 圆角支持半径参数、圆弧分段数和相切边链。 +5. 检测距离/半径过大、边不存在、凹凸方向不支持、拓扑引用失效和处理后非流形。 +6. 输出选中边、高亮所需的线段数据,供主代理接入视口拾取。 + +### 10.6 建议导出接口 + +```js +export function extractTopology(mesh, tolerance) +export function makeStableEdgeRef(edge, topology) +export function resolveEdgeRef(ref, topology) +export function buildChamferMesh({ mesh, edgeRefs, distance, tolerance }) +export function buildFilletMesh({ mesh, edgeRefs, radius, segments, tolerance }) +``` + +### 10.7 最低测试集 + +- 立方体单边倒角 5mm +- 立方体四条平行边倒角 +- 倒角距离过大被拒绝 +- 立方体单边圆角 R5 +- 共线边链圆角 +- 圆角半径过大被拒绝 +- 保存/打开后稳定边引用仍能解析 +- 上游尺寸改变后引用能重定位或明确报失效 +- 输出网格封闭、体积合理、无退化三角形 +- 连续 10 次重建稳定 + +### 10.8 验收标准 + +- 放大观察可见真实三维斜面或圆弧过渡。 +- STL 输出包含处理后的真实几何,而非仅渲染效果。 +- 单边处理小于 1s。 +- M08 和 M09 分开报告测试结果。 + +## 11. 子代理 G:第一阶段独立测试审查 + +### 11.1 启动时机 + +仅在 A~F 的成果全部由主代理接入后启动。该代理不得参与功能实现,以保持审查独立性。 + +### 11.2 允许修改 + +- 新建并修改 `tests/test.phase1.mjs` +- 新建 `PHASE1_QA_REPORT.md` + +### 11.3 禁止修改 + +- 所有生产源码 +- 其他代理测试文件 +- README 和 ROADMAP + +### 11.4 审查内容 + +1. 检查 M01~M09 每项是否有正常、边界和错误测试。 +2. 检查 DSL、文档模型、几何构建和 UI 参数是否语义一致。 +3. 检查保存/打开后的全部新特征能否重建。 +4. 检查撤销/重做是否保留新参数。 +5. 连续重建组合模型,观察体积、包围盒和错误状态。 +6. 检查 WASM 临时对象释放路径。 +7. 测量扫描、放样、筋、终止条件、倒角、圆角耗时。 +8. 测试旧 51 条基线断言无回归。 +9. 为“轴承座”综合模型准备确定性数据夹具。 + +### 11.5 验收输出 + +QA 报告必须把问题分成: + +- 阻断 M10 +- 可在第一阶段收尾修复 +- 可延期到第二阶段 + +不得只写“全部正常”,每项结论必须附测试证据。 + +## 12. 主代理集成职责 + +主代理不把共享入口交给子代理并行修改。每一批完成后,主代理按以下顺序集成: + +1. 审查子代理文件边界和测试结果。 +2. 统一公共数据格式和错误协议。 +3. 接入 `geometry.js` 的内核包装和对象生命周期。 +4. 接入 `doc.js` 的特征类型、重建分支、稳定引用和序列化。 +5. 接入 `agent.js` 的 DSL、规则解析、校验与执行。 +6. 接入 `tree.js`、`main.js`、`viewport.js` 的名称、属性表单、拾取和高亮。 +7. 更新统一测试入口。 +8. 跑全部测试并修复集成问题。 +9. 只有总回归通过后才更新 README 和 ROADMAP 勾选状态。 + +主代理必须特别检查: + +- 子代理是否越界修改共享文件。 +- 是否出现同一概念的多个不兼容数据结构。 +- 是否初始化了多个 manifold WASM 实例。 +- 是否在失败路径泄漏对象。 +- 是否把近似功能错误描述为精确功能。 +- 是否破坏旧工程文件兼容性。 + +## 13. M10 综合验收 + +### 13.1 轴承座模型 + +最低包含: + +- 底板 +- 主体凸台 +- 中心通孔 +- 至少两条筋 +- 至少一个参考基准面 +- 至少一个非固定深度终止条件 +- 实体倒角 +- 实体圆角 +- 可选扫描或放样结构 + +### 13.2 AI 验收句 + +最终应能用一条中文描述生成完整模型。AI 输出允许分解为多个底层操作,但不得依赖手工补特征。 + +### 13.3 功能验收 + +- 特征树顺序正确,所有特征无错误。 +- 每个新特征可编辑参数并重建。 +- 撤销/重做有效。 +- 保存、关闭、重新打开后结果一致。 +- STL 导出有效。 +- 旧工程文件仍能打开。 + +### 13.4 质量验收 + +- 第一阶段模块测试全部通过。 +- 原有 51 条测试无回归。 +- 不存在已知 WASM 对象泄漏路径。 +- 单个普通特征满足性能预算。 +- 浏览器控制台无新增错误。 +- 完成一次浏览器课程作业演练并记录结果。 + +### 13.5 路线图完成条件 + +只有以上条件全部满足,才能在 `ROADMAP.md` 中将 M10 标记为完成,并宣布第一阶段结束。 + +## 14. 冲突与异常处理 + +### 14.1 文件冲突 + +发现其他代理正在修改自己的目标文件时: + +1. 立即停止写入。 +2. 保留当前分析结果,不覆盖对方改动。 +3. 向主代理报告冲突文件和双方任务。 +4. 由主代理重新划分边界后再继续。 + +### 14.2 接口冲突 + +需要改变公共数据结构或共享函数签名时,子代理只提交一份接口申请,包含: + +- 现有接口为什么不足 +- 建议的新签名 +- 调用方影响 +- 向后兼容方案 +- 所需测试 + +未经主代理批准,不得自行修改共享接口。 + +### 14.3 技术阻塞 + +同一阻塞连续验证三次仍无法解决时,提交最小复现、底层错误、尝试过的方案和建议替代路径。不得用空实现、静默跳过或仅视觉效果掩盖阻塞。 + +### 14.4 资源异常 + +发现测试、浏览器自动化或几何构建出现异常 token、内存或时间消耗时立即暂停,向主人说明规模、原因和更省资源的方案;未经确认不继续高消耗流程。 + +## 15. 第一阶段完成后的交付物 + +第一阶段结束时应具备: + +- M02~M09 的生产实现 +- 模块化测试文件和统一回归入口 +- 更新后的 DSL 说明 +- 更新后的文件格式版本和兼容逻辑 +- 第一阶段 QA 报告 +- 轴承座课程作业演练记录 +- README 功能说明 +- ROADMAP 完成标记和遗留问题清单 + +本任务书是第一阶段并行开发的边界依据。实际启动子代理时,主代理应从对应章节复制任务,并额外告知当时的最新 Git 状态和已完成依赖。 diff --git a/README.md b/README.md index 308a74c..751333b 100644 --- a/README.md +++ b/README.md @@ -6,24 +6,33 @@ ## 功能特性 -- **参数化建模**:草图(直线 / 矩形 / 圆 / 圆弧 / 中心线)→ 特征(拉伸 / 切除 / 旋转 / 圆柱 / 圆柱切除)→ 重建,特征树可回看编辑 -- **AI 智能体**:中文自然语言描述零件,自动解析为建模操作并执行;离线可用(内置规则解析器),也可配置 LLM 走深度推理 +- **参数化建模**:草图(直线 / 矩形 / 圆 / 圆弧 / 椭圆 / 长圆槽 / 样条 / 中心线)→ 特征(拉伸 / 切除 / 旋转 / 圆柱 / 扫描 / 放样 / 筋 / 实体倒角 / 实体圆角)→ 重建,特征树可回看编辑 +- **参数化草图**:水平、垂直、重合、相等、平行、垂直、相切、角度、半径等约束;命名尺寸/参数表达式;草图线性和圆周阵列 +- **装配体工作区**:组件树、零件插入、同心/重合/距离等基础配合、包围盒与实体布尔干涉检查、爆炸视图 +- **工程图工作区**:A3/A4 图框、第一角三视图、尺寸与基础公差、关联剖视图、标题栏,以及 SVG/PNG 导出 +- **AI 智能体**:中文自然语言描述零件,自动解析为建模操作并执行;支持手动切换“内置解析器 / LLM 智能体”,并支持新建、追加、查询、修改、删除;它还能读取实体尺寸、体积、网格统计、特征增量和错误状态进行几何自观察;遇到依赖顺序错误会按“建模→装配→工程图”自动重排,重建失败时会诊断并自动移除不可用操作后重试 +- **严格模式路由**:选择 LLM 后,查询、新建、追加、修改、删除、装配和工程图全部先由 LLM 理解;本地只校验并执行带稳定特征 ID 的 `query_document`、`update_feature`、`delete_feature` 等操作,不再提前用本地 CRUD 截获,也不静默降级 +- **LLM 质量优先流程**:设置中可选“快速模式/专家完整模式”;快速模式保留为用户手动选择的低延迟方案,专家模式不再为节省 token 跳过阶段,查询、新建、追加、修改、删除和建模都会依次经过顶级机械工程师预审、完整意图规范化与 DSL 规划。第一阶段机械工程师只输出完整的 Markdown 工程架构说明(工程目标、对象与场景、坐标基准、几何组成与特征顺序、尺寸与默认假设、几何约束、装配意图、工程图意图、风险项),不被 JSON 格式束缚;第二阶段再把这份 Markdown 转为规范化意图 JSON,第三阶段才生成 `{"ops":[...]}` DSL。每一层都允许模型充分内部推理,不向请求注入 `max_tokens` 输出上限;执行纠错与视觉复核仍分别严格限定为 JSON。生成并重建成功后,MiniSW 本地几何观察器会把模型位置、尺寸、网格、特征树和实体完整性反馈给机械制图专家,再进行一次生成后视觉复核;格式、计划或执行失败时会把真实错误回传模型继续纠错。界面会显示 API 调用次数、总耗时、当前阶段和视觉复核结论 +- **Agent 调试窗口**:AI 面板顶部可打开调试窗口,以 OpenAI/DeepSeek 兼容 SSE 流式方式实时查看模型增量输出,并查看每次请求的阶段、请求消息、原始响应、DSL 校验、文档预检、执行错误、视觉复核和纠错记录;支持日志内标准 `Ctrl+C`,以及 `Ctrl+Shift+C` 复制全部调试文本 - **高级宏指令**:倒角矩形、圆角矩形、多边形、抽壳、镜像、线性阵列、圆周阵列、凸台等一键生成 - **文档能力**:保存 / 打开(JSON)、导出 STL、撤销 / 重做 -- **SolidWorks 风格界面**:可拖拽调整的 Ribbon / 特征树 / 属性面板,可移动的 AI 浮动面板,四向视图切换 +- **参考几何**:偏移/角度/过点基准面、基准轴、基准点和用户坐标系,草图可挂载到自定义参考面 +- **拉伸终止条件**:固定深度、贯穿全部、对称、到下一面、到指定面和到实体;目标面引用随文档保存 +- **实体边处理**:视口直接拾取凸直棱;倒角用真实网格截切,圆角用多段圆柱过渡面,均通过 manifold 内核闭合验证 +- **SolidWorks 风格界面**:可拖拽调整的 Ribbon / 特征树 / 属性面板,可移动的 AI 浮动面板,四向视图切换;首次生成或打开实体时按包围盒自动取景,保持真实 mm 工程尺寸,不用“缩放模型”冒充适配视口 ## 快速开始 ### 方式一:双击启动脚本(推荐) -双击 `启动.bat`,脚本会自动启动本地服务器并打开浏览器,访问 `http://127.0.0.1:8898/index.html`。关闭黑色命令行窗口即停止服务器。 +双击当前项目目录中的 `启动.bat`,脚本会从脚本所在目录启动本地服务器并打开浏览器。默认端口为 `8898`;如果该端口已被旧服务器占用,会自动选择下一个空闲端口。关闭黑色命令行窗口即停止服务器。 > 注意:不要直接双击 `index.html` 用 `file://` 协议打开——ES Module 和 WASM 会被浏览器安全策略拦截,页面会卡在加载页。 ### 方式二:手动启动 ```bash -cd F:\Program Files\MiniSW +cd E:\MiniSW python -m http.server 8898 ``` @@ -45,6 +54,11 @@ python -m http.server 8898 | 输入 | 生成结果 | |---|---| | 做一个 100×100×20 的方块,中心开一个半径15的圆孔 | 底板 + 中心通孔 | +| 查询当前模型有哪些特征和尺寸 | 返回实体尺寸、草图和特征清单 | +| 把加强筋厚度改为6mm | 定位加强筋并全树重建 | +| 删除最后一个特征 | 删除末尾特征,并清理未使用草图 | +| 在当前零件上添加一个直径20mm的通孔 | 仅追加孔草图与切除,不重建底板 | +| 你能看到什么?请描述当前模型 | 返回实体状态、尺寸、体积、网格和特征观察结果 | | 空心圆柱,外径60,内径40,高50 | 空心圆柱 | | 做一个 200×120×10 的板,中间开一个 60×40 的矩形槽,四角打 4 个直径6的孔 | 槽板 + 四角孔 | | 做一个 100×80×20 的矩形板,四边倒角 5mm | 倒角板 | @@ -53,6 +67,13 @@ python -m http.server 8898 | 做一个直径120厚10的圆盘,打一个直径10的孔距离中心40,圆周阵列6个 | 圆周阵列孔 | | 做一个 100×80×10 的底板,顶面中心加一个直径30高20的圆柱凸台 | 底板 + 凸台 | | 做一个 100×60×10 的板,左侧凸台镜像到右侧 | 镜像特征 | +| 沿半径50的四分之一圆弧扫描直径8的圆形截面 | 90° 弯管实体 | +| 从40×30的矩形放样到直径20的圆形,高度50 | 矩形—圆形过渡体 | +| 创建距离前视面10mm的偏移基准面 | 偏移参考面 | +| 做一个100×60×10的底板,加一条厚3mm、筋高30mm的加强筋 | 底板 + 加强筋 | +| 做一个40×30×20的方块,给一条实体棱边倒角5mm | 单棱实体倒角 | +| 做一个40×30×20的方块,给一条实体棱边做R5圆角 | 多段实体圆角 | +| 生成一个120×80×12的轴承座,主体凸台直径60高32,中心通孔直径30,两条厚4mm加强筋,实体倒角和R4实体圆角 | 第一阶段综合轴承座 | ## 项目结构 @@ -63,6 +84,8 @@ MiniSW/ ├── css/ │ └── style.css # 全部样式(含可拖拽面板的 resizer) ├── js/ +│ ├── features/ # 扫描、放样、筋、参考几何、终止条件、倒角/圆角、装配、工程图 +│ ├── constraints.js # 轻量 2D 约束求解与参数表达式 │ ├── main.js # 应用主控:Ribbon、面板交互、事件绑定 │ ├── doc.js # 零件文档模型:草图/特征/重建/序列化/撤销 │ ├── geometry.js # manifold 几何内核封装:布尔/拉伸/旋转/圆柱 @@ -88,13 +111,13 @@ MiniSW/ node --loader ./tests/loader.mjs ./tests/test.mjs ``` -测试覆盖:WASM 加载、底板 + 四角孔手动建模、包围盒校验、STL 导出、旋转特征、AI 自然语言解析等。 +测试覆盖:WASM 加载、底板 + 四角孔手动建模、包围盒校验、STL 导出、旋转、扫描、放样、筋、参考几何、六种拉伸终止条件、实体倒角/圆角与 AI 一句话轴承座等。 ### 架构说明 - **几何内核**:manifold-3d WASM。`geometry.js` 统一封装实体构造(`buildExtrude` / `buildRevolve` / `buildCylinder`)与布尔运算(`booleanOp`),并负责 WASM 对象生命周期管理(`delete()`) - **文档模型**:`doc.js` 的 `Doc` 类持有草图与特征的有序列表,`rebuild()` 按顺序重建实体,支持增量网格(`deltaMeshes`,用于特征高亮) -- **AI 链路**:`agent.js` 先做中文规则匹配生成操作序列(ops),再经宏展开层(`expandOps`)扩展为底层操作,最终由 `executeOps` 写入文档并重建;LLM 模式则把 ops 交给模型规划 +- **AI 链路**:`agent.js` 先判断自然语言意图(新建 / 追加 / 查询 / 修改 / 删除),再生成操作序列或文档 CRUD 请求;`inspectDocument` 汇总实体状态、尺寸、体积、网格和特征增量作为自观察;几何请求经宏展开层(`expandOps`)交给 `executeOps`,重建出现特征错误时会回滚并自动修正一次;LLM 模式则把几何 ops 与观察上下文交给模型规划 - **坐标系统**:草图平面(前视 / 上视 / 右视)通过 `math.js` 的 `toWorld` 映射到世界系,拉伸方向由平面法向决定 ### 依赖本地化 @@ -104,14 +127,21 @@ node --loader ./tests/loader.mjs ./tests/test.mjs ## 已知限制 - 圆形分段数固定为 96(`js/sketch.js`),已满足绝大多数教学场景;极端大半径圆弧如需更光滑可调高该值(会相应增加面数) -- 目前仅支持单一实体(多体、装配、工程图在规划中,见 `ROADMAP.md`) -- 约束系统为数据结构层面,尚无数值求解器(尺寸标注暂不驱动几何) +- 装配体当前以当前文档实体作为组件来源,配合求解以轻量平移约束为主;跨文件零件库、完整旋转自由度和高级动画仍在后续路线图中 +- 扫描支持路径草图、单环任意封闭截面、固定/平行传递标架与扭转;带孔多环截面目前不支持自动封端 +- 放样支持平行单环多截面和异顶点数重采样;带孔截面及非平行截面尚未支持 +- `toBody` 的独立几何模块支持显式目标实体;当前单实体文档中的稳定目标名为 `current`,跨独立实体引用将在多实体文档阶段开放 +- 实体倒角/圆角当前只接受方向一致、封闭凸实体上的一条凸直棱;多边选择、边链、凹边和非凸体会明确报错。圆角是可导出 STL 的多段圆柱面近似,不是精确 NURBS/B-rep 圆角 +- 约束求解器为可解释的轻量 2D 迭代实现,支持常用教学约束与欠/过约束报告;尚不等同于工业级全局求解器 +- 工程图轮廓来自网格棱边投影,剖视采用三角形裁剪与剖面线;复杂曲面隐藏线和精确 B-rep 标注仍可继续增强 - LLM 模式需自行配置 API 地址与密钥(AI 面板 ⚙ 设置) ## 路线图 进阶规划(扫描 / 放样 / 筋 / 实体圆角、约束求解器与尺寸驱动、装配体、工程图)详见 [ROADMAP.md](ROADMAP.md)。 +第一阶段的最终浏览器与课程演练步骤见 [PHASE1_M10_MANUAL_CHECKLIST.md](PHASE1_M10_MANUAL_CHECKLIST.md)。 + ## 许可与声明 本项目为教学演示性质,仅用于学习与实验用途。SolidWorks 为 Dassault Systèmes 的注册商标,本项目与其无任何关联。 diff --git a/ROADMAP.md b/ROADMAP.md index 5e966be..428f78e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,6 +2,65 @@ 版本:v1.0 · 日期:2026-08-10 · 编写:总工程师(审阅视角) +## 当前实施进度(2026-08-10) + +- **M01~M09 已完成生产接入。** 扫描、放样、参考几何、筋、六种拉伸终止模式、真实网格实体倒角和多段圆柱面实体圆角均已接入文档、AI DSL、保存/打开和界面参数编辑;倒角/圆角支持视口拾取与稳定边引用。 +- 测试直接调用当前仓库的 `js/` 与 `vendor/`,不依赖旧外部源码副本;当前核心综合测试为 **94/94 通过**,七个第一阶段独立模块测试为 **93/93 通过**,合计 **187/187**。 +- M10 自动化部分已通过,最终浏览器演练由用户按 [`PHASE1_M10_MANUAL_CHECKLIST.md`](PHASE1_M10_MANUAL_CHECKLIST.md) 手动确认。实体倒角/圆角当前采用经过内核验证的保守范围:封闭凸实体的一条直棱;多边链、凹边和非凸体会明确拒绝,不以平滑伪装成功。 +- **阶段二至阶段四核心闭环已完成(2026-08-10)**:参数化草图、装配体、工程图均已接入文档模型、AI DSL、保存/打开和界面工作区;工程图支持 SVG/PNG 导出,装配体支持组件树、基础配合、干涉检查和爆炸视图。 +- 阶段二至四自动化验收:`test.phase2.mjs` 8/8、`test.assembly.mjs` 5/5、`test.drawing.mjs` 4/4、`test.phase34.mjs` 16/16;Agent 质量优先多轮编排(第一阶段 Markdown 工程架构 → 意图 JSON → DSL)、结构化 JSON、兼容接口降级、参数化直齿轮编译、模糊对象默认工程假设、视觉反馈复核、DeepSeek/OpenAI 兼容 SSE 流式调试、DSL 容错与增删改查回归 `test.agent-crud.mjs` 42/42、核心 `test.mjs` 94/94,合计 **169/169**(不含阶段一独立报告中的历史计数)。 + +### 阶段二至四交付边界 + +- 约束求解器是可解释的轻量 2D 迭代求解器,支持欠约束/完全约束/过约束报告;当前不承诺工业级全局最优求解。 +- 装配体支持当前文档实体插入、稳定组件引用、基础平移配合、包围盒预筛与可用时的实体布尔复核;高级旋转自由度和跨文件引用仍属于后续增强项。 +- 工程图使用网格棱边投影生成矢量视图,剖视使用三角形裁剪与剖面线;已满足课程作业交付所需的三视图、标注、标题栏和 SVG/PNG 输出,复杂曲面隐藏线算法仍可继续增强。 + +## 可执行里程碑拆分 + +执行规则:一次只推进一个里程碑。每个里程碑必须完成核心实现、文档模型接入、AI DSL/规则解析、保存/打开兼容、错误提示、自动化测试和本文档进度更新,才可以勾选完成。浏览器录像集中在每个阶段的综合验收任务中进行,避免重复消耗资源。 + +### 阶段一:高级零件建模 + +- [x] **M01 圆形截面基础扫描**:圆形截面沿直线、离散三维路径和四分之一圆弧扫描;支持封端、AI 指令和保存/打开。当前核心测试 51/51 通过。 +- [x] **M02 扫描完整版**:支持路径草图、任意封闭截面草图、截面与路径引用、方向控制和扭转控制。 +- [x] **M03 放样基础版**:支持两个平行、等顶点数的封闭截面放样,完成基本顶点配对和端面封闭。 +- [x] **M04 放样完整版**:支持三个及以上截面、异顶点数均匀重采样、截面起点对齐和自交诊断。 +- [x] **M05 筋特征**:支持开放轮廓、厚度、双侧/单侧方向、延伸到相邻实体并自动合并。 +- [x] **M06 参考几何**:增加偏移/角度基准面、两点/两平面基准轴、基准点与坐标系,并允许草图引用。 +- [x] **M07 拉伸终止条件**:为拉伸和切除增加 `toNext`、`toFace`、`toBody`,保留现有 `blind`、`throughAll` 和 `symmetric`。 +- [x] **M08 实体棱边倒角**:建立拓扑边引用与拾取,支持距离参数、特征重建、AI 指令和失败诊断;当前安全范围为凸实体单条直棱。 +- [x] **M09 实体棱边圆角**:支持半径参数、多段真实圆弧过渡、拓扑边引用、特征重建、AI 指令和失败诊断;当前安全范围为凸实体单条直棱。 +- [ ] **M10 阶段一综合验收**:用 AI 一句话生成轴承座(底板、凸台、通孔、筋、圆角),检查几何内存生命周期和性能预算,并录制课程作业演练。 + +### 阶段二:参数化草图 + +- [x] **M11 基础约束求解器**:实现固定、水平、垂直、重合和距离约束,建立残差方程、迭代求解与收敛报告。 +- [x] **M12 完整几何约束**:增加平行、垂直、相等、同心、相切、角度和半径约束,并检测欠约束、完全约束和过约束状态。 +- [x] **M13 新草图图元**:增加椭圆、长圆槽和样条曲线,支持绘制、编辑、离散化和轮廓检测。 +- [x] **M14 命名尺寸与参数表**:增加命名尺寸、表达式解析、单位校验和特征参数引用,修改参数后可全模型联动重建。 +- [x] **M15 草图阵列及阶段二验收**:实现草图线性/圆周阵列;完成“修改矩形尺寸驱动全部关联特征”的参数化闭环与自动化验收。 + +### 阶段三:装配体 + +- [x] **M16 多实体与零件引用基础**:扩展文档模型以安全表达多个实体、独立零件文档和稳定的面/边/轴引用。 +- [x] **M17 装配数据模型与装配树**:新增组件、变换和配合数据结构,支持零件插入、固定、隐藏、选择和装配树显示。 +- [x] **M18 配合约束求解**:实现重合、同心、距离、平行、垂直和角度配合,并保留合理自由度。 +- [x] **M19 干涉检查**:使用包围盒预筛与实体布尔交集检测干涉,显示干涉体积并高亮冲突区域。 +- [x] **M20 爆炸视图及阶段三验收**:实现组件爆炸方向、距离和动画;完成组件插入、配合、干涉与爆炸视图演练。 + +### 阶段四:工程图 + +- [x] **M21 图纸文档与图框**:建立工程图文档、视图和标注模型,提供 A3/A4 横竖图框、标题栏、比例与单位设置。 +- [x] **M22 第一角投影三视图**:从零件生成主视、俯视和左视轮廓,按第一角投影规则自动布局并支持比例调整。 +- [x] **M23 尺寸、公差与参数引用**:将模型命名尺寸映射到工程图,支持线性、角度、直径、半径尺寸及基础 ± 公差。 +- [x] **M24 剖视图**:实现裁剪平面、全剖视图、剖面轮廓和剖面线,保持与三维模型关联更新。 +- [x] **M25 工程图导出及阶段四验收**:支持 SVG/PNG 导出;完成任意零件一键生成 A4 三视图、尺寸和标题栏的课程交付演练。 + +### 最终收尾 + +- [ ] **M26 全项目交付验收**:按几何、约束、装配、工程图拆分测试套件;检查性能、WASM 内存、文件兼容、离线运行、错误恢复和文档完整性,完成代表性课程作业总演练。 + ## 1. 定位与目标 MiniSW 目前的定位是"能跑通基础草图和特征链路的原型",与 SolidWorks 的差距不在渲染层(Three.js 已足够),而在**建模能力覆盖**和**工程语义完整度**。 diff --git a/SUBPROXY_TASKS.md b/SUBPROXY_TASKS.md deleted file mode 100644 index e3447ae..0000000 --- a/SUBPROXY_TASKS.md +++ /dev/null @@ -1,152 +0,0 @@ -# MiniSW 并行子代理任务书 - -版本:v1.0 · 日期:2026-08-09 · 适用范围:MiniSW 项目全部子代理 - -## 1. 项目背景 - -MiniSW 是一款 AI 原生的 Web 参数化建模软件,参照 SolidWorks 的工作流(草图 → 特征 → 特征树 → 参数化重建)从零实现。核心差异点是"AI Agent 全自动建模":用户输入中文描述,系统解析为建模指令并自动完成建模。 - -技术栈:原生 JavaScript ESM,无打包器。Three.js r160(渲染)、manifold-3d 3.5.1(WebAssembly 布尔内核)、CSS2DRenderer(标注)、自定义中文规则解析器 + 可选 OpenAI 兼容 LLM 智能体。 - -运行方式:本地 HTTP 服务器打开 `index.html`(`python -m http.server 8899`,目录 `f:\Program Files\MiniSW`)。 - -## 2. 当前进度 - -已完成并通过 Node 冒烟测试(16/16 断言通过)的链路: - -- 几何内核:`math.js`(坐标系/平面映射)、`sketch.js`(图元/封闭环检测)、`geometry.js`(拉伸/旋转/圆柱/布尔/STL)、`doc.js`(文档模型/顺序重建) -- AI 解析器:`agent.js` 的中文规则解析路径(12 个 op 序列端到端建模成功) - -已编写但**未在真实浏览器验证**的模块:`main.js`(UI 主入口,约 1000+ 行)、`sketchui.js`(草图交互)、`viewport.js`(3D 视口)、`tree.js`(特征树)、`css/style.css`、`index.html`。 - -最高风险:`main.js` 从未在浏览器中实际运行,存在运行时错误、事件绑定失效、模块集成问题等未知风险。因此**浏览器联调(任务 0)是全部并行分支的前置依赖**。 - -## 3. 文件地图与归属 - -| 文件 | 归属 | 说明 | -|---|---|---| -| `js/math.js` | 任务 A | 坐标系、平面映射、几何工具(已稳定,可加固) | -| `js/sketch.js` | 任务 A | 图元、封闭环检测、轮廓校验(已稳定,可加固) | -| `js/geometry.js` | 任务 A | 特征构造、布尔运算、STL(已稳定,可加固) | -| `js/doc.js` | 任务 A | 文档模型、重建、序列化(已稳定,可加固) | -| `js/main.js` | 任务 B | UI 主入口,Ribbon/面板/状态机/AI 面板(最大风险文件) | -| `js/sketchui.js` | 任务 B | 草图交互工具(画线/矩形/圆/圆弧/标注/约束) | -| `js/viewport.js` | 任务 B | 3D 视口、导航、拾取、网格、高亮 | -| `js/tree.js` | 任务 B | 特征树 UI | -| `css/style.css` | 任务 B | SolidWorks 风格样式 | -| `index.html` | 任务 C | 页面骨架、AI 面板容器、依赖加载(import map) | -| `js/agent.js` | 任务 C | AI 解析器、DSL、LLM 接入 | -| `js/geometry.js` | 任务 0 | 联调发现的核心缺陷可修(需与 A 协调) | -| `js/main.js` | 任务 0 | 联调主战场(需与 B 协调) | -| 测试目录 `c:\Users\32919\.trae-cn\work\6a78857c0515f1e48ec3076f\` | 任务 0/A | Node 冒烟测试 `test.mjs`、`loader.mjs`、`swjs/`(工作区源码副本) | - -## 4. 通用协作规则 - -1. **文件互斥**:每个任务只能修改归属自己的文件。跨文件修改必须明确写入交接说明,交给主代理协调,禁止自行修改他人文件。 -2. **接口契约**:模块间通过命名导出通信(如 `geometry.js` 的 `buildExtrude/booleanOp/meshFromManifold`,`doc.js` 的 `Doc` 类)。改动签名必须同步更新所有调用方,并在报告中标明。 -3. **测试优先**:任何修改先跑测试(Node 冒烟测试或浏览器自动化),确认回归后再提交。 -4. **报告格式**:任务结束时报告必须包含:改动文件清单、新增/修复的功能点、测试结果(命令 + 断言数)、遗留问题、对下游任务的交接说明。 -5. **禁止事项**:不得重命名或移动他人文件;不得改变 `index.html` 的 import map 结构(任务 C 专属);不得删除 `swjs/` 副本的同步机制(改完工作区文件后同步 `Copy-Item` 到 `swjs/`)。 - -## 5. 任务 0:浏览器联调(前置,串行) - -**目标**:让 `main.js` 在真实浏览器中跑通,消除最高风险。 - -**职责**: - -1. 启动本地服务器,用浏览器自动化(或人工引导)加载 `index.html`,收集控制台错误。 -2. 逐项修复运行时错误:模块导入失败、事件绑定失效、初始化顺序错误、DOM 引用缺失。 -3. 验证最小闭环:新建草图 → 画矩形 → 拉伸 → 3D 显示 → 保存 → 加载 → STL 导出。 -4. 验证 AI 面板最小闭环:输入中文描述 → 生成建模指令 → 重建 → 视口刷新。 -5. 修复过程中发现的几何内核缺陷(`geometry.js`/`doc.js`)可以直接修,但需在报告中单独列出,供任务 A 复核。 - -**文件边界**:`js/main.js` 为主;`js/geometry.js`、`js/doc.js` 仅限修 bug;`index.html` 仅限修加载问题(不改 AI 面板结构);不得改动 `js/sketchui.js`、`js/viewport.js`、`js/tree.js` 的 API 签名。 - -**验收标准**: - -- 页面加载无控制台报错。 -- 上述两条最小闭环全部可手动操作完成。 -- 修复清单与交接说明写入报告。 - -## 6. 任务 A:特征引擎加固 - -**目标**:扩充特征引擎的健壮性与能力边界,把 Node 冒烟测试扩展到 25+ 断言。 - -**职责**: - -1. 扩充 `test.mjs`:拉伸"贯穿所有/对称"、旋转轴显式指定、多环轮廓(含嵌套孔)、圆柱原语、撤销重做栈(`Doc` 层)、STL 导出的二进制头与三角数校验。 -2. 修复测试暴露的缺陷:环方向、退化轮廓、极端尺寸、浮点边界。 -3. 加固 `buildRevolve` 的旋转轴校验与截面跨越检测。 -4. 为 `doc.js` 增加重建缓存的正确释放逻辑验证(manifold 对象的 delete 生命周期)。 -5. 保持 `geometry.js` 的导出签名不变。 - -**文件边界**:`js/math.js`、`js/sketch.js`、`js/geometry.js`、`js/doc.js`、测试目录(`test.mjs` 等)。不得改动 `js/main.js` 及任何 UI 文件。 - -**验收标准**: - -- Node 冒烟测试 25+ 断言全绿(`node --experimental-loader ./loader.mjs test.mjs`)。 -- 现有 16 条断言无回归。 -- 报告列出每个新增用例覆盖的场景与修复的缺陷。 - -## 7. 任务 B:UI 交互完善 - -**目标**:把 UI 从"能加载"提升到"可完整操作",对标 SolidWorks 的交互心智。 - -**职责**: - -1. 草图工具全流程:画线/矩形/圆/圆弧、标注编辑(双击)、裁剪、捕捉、约束的交互逻辑走查与修复。 -2. 特征工作流:属性面板(拉伸/切除/旋转表单)、特征树右键菜单(编辑草图/删除/编辑特征)、视图切换(前视/上视/右视/等轴测)。 -3. 3D 交互:拾取高亮、特征增量网格显示、相机操作(OrbitControls)的默认行为修正。 -4. 状态栏、Ribbon 分区、撤销/重做按钮的可用性打磨。 -5. 在浏览器自动化中走通 3 条完整用户路径并截图留证。 - -**文件边界**:`js/main.js`、`js/sketchui.js`、`js/viewport.js`、`js/tree.js`、`css/style.css`。不得改动 `js/geometry.js`、`js/doc.js` 的导出签名(如需新接口,向主代理申请,由任务 A 实现)。`index.html` 的 AI 面板区域不归本任务。 - -**验收标准**: - -- 3 条完整用户路径(草图→拉伸→保存;草图→切除→撤销→重做;视图切换+拾取高亮)在浏览器自动化中全部通过。 -- 无新增控制台错误。 -- 报告包含操作路径清单与截图。 - -## 8. 任务 C:AI 智能体扩展 - -**目标**:把 AI 从"基础指令解析"扩展到"覆盖常见建模意图的智能体"。 - -**职责**: - -1. 扩展 `agent.js` 的 DSL 与中文规则解析:倒角/圆角、阵列(线性/圆周)、镜像、抽壳、多草图组合等指令。 -2. 扩展 `executeOps` 到新指令的执行支持(与 `geometry.js` 对接的接口若缺,向主代理申请由任务 A 实现)。 -3. LLM 路径完善:OpenAI 兼容 API 接入、JSON 输出校验、失败重试与错误提示、多轮对话(基于当前模型状态的上下文)。 -4. AI 面板体验:指令历史、一键执行、执行结果反馈(成功/失败原因)。 -5. 离线可用性保障:无 LLM 时规则解析器仍能处理常见句式。 - -**文件边界**:`js/agent.js`、`index.html`(仅 AI 面板区域)、`js/main.js` 中 AI 面板相关的事件处理函数(如需)。不得改动 `js/sketch.js`、`js/geometry.js`、`js/doc.js`、`js/sketchui.js`、`js/viewport.js`、`js/tree.js`。 - -**验收标准**: - -- 10 条覆盖新指令的中文描述端到端建模成功(Node 或浏览器验证)。 -- 无效指令给出明确的中文错误信息,不崩溃。 -- 报告列出新增 DSL 指令、句式规则与测试用例。 - -## 9. 依赖关系与执行顺序 - -``` -任务 0(浏览器联调,串行前置) - │ - ├──→ 任务 A(特征引擎加固,可并行启动) - ├──→ 任务 B(UI 交互完善,依赖 0 的联调结果) - └──→ 任务 C(AI 智能体扩展,依赖 0 的最小闭环) -``` - -启动顺序建议:先完成任务 0,再并行启动 A、B、C。若任务 0 无法完整完成(环境限制),则 A 可立即并行(不依赖浏览器),B、C 的验收改为"代码走查 + 局部验证"。 - -任务间的接口申请统一走主代理:B 或 C 需要新几何接口时,提交接口规格(名称、参数、返回值、语义),主代理转交 A 实现后,B/C 再集成。 - -## 10. 验收总表 - -| 任务 | 核心验收 | 完成标志 | -|---|---|---| -| 0 浏览器联调 | 页面无报错,两条最小闭环可操作 | 修复清单 + 交接说明 | -| A 特征引擎 | Node 测试 25+ 断言全绿,16 条无回归 | 测试报告 + 缺陷清单 | -| B UI 交互 | 3 条完整用户路径浏览器自动化通过 | 操作路径 + 截图 | -| C AI 智能体 | 10 条新指令端到端建模成功 | DSL 指令表 + 测试用例 | diff --git a/TASK_0_REPORT.md b/TASK_0_REPORT.md deleted file mode 100644 index 8eccc4b..0000000 --- a/TASK_0_REPORT.md +++ /dev/null @@ -1,88 +0,0 @@ -# MiniSW 任务 0 报告:浏览器联调 - -版本:v1.0 · 日期:2026-08-09 · 执行者:主代理(任务 0) - -## 1. 目标 - -把任务 A/B/C 的成果在真实浏览器环境中跑通,验证两条完整闭环并修复联调中发现的问题: - -- 最小建模闭环:新建草图 → 画矩形 → 拉伸 → 3D 显示 → 保存 → 加载 → STL 导出 -- AI 面板闭环:自然语言 → 解析 → 特征生成 → 建模 → 导出 - -## 2. 测试环境 - -| 项 | 值 | -|---|---| -| 服务器 | `python -m http.server 8899`(目录 `f:\Program Files\MiniSW`) | -| 浏览器 | agent-browser(Chromium headless,CDP 驱动) | -| 页面 | http://localhost:8899 | -| 依赖加载 | three.js、OrbitControls、manifold.wasm 均从 CDN 正常加载(仅 favicon 404,无害) | - -## 3. 闭环验证结果 - -### 3.1 最小建模闭环 ✅ - -| 步骤 | 操作 | 结果 | -|---|---|---| -| 1 | 进入"前视草图",选矩形工具 | 草图模式激活,HUD 显示"草图1 · 前视" | -| 2 | 视口绘制矩形(pointerdown × 2) | HUD 更新"1 实体" | -| 3 | 拉伸凸台,深度 20,确定 | 特征树新增"拉伸",状态栏"1 草图 · 1 特征 · 尺寸 225.989×135.594×20 mm" | -| 4 | 3D 显示验证 | WebGL 持续绘制(1.5s 内 3318 次 drawElements),视口区域实测含实体着色像素 | -| 5 | 保存 | 捕获 JSON 完整:1 草图、1 特征(extrude depth=20)、矩形 226×135.6 | -| 6 | 加载 | 文件上传后重建正确,尺寸精确还原(100×60×25 mm) | -| 7 | STL 导出 | 12 三角形(长方体 6 面×2),文件长度 = 84+50×12 精确匹配 | - -### 3.2 AI 面板闭环 ✅ - -| 示例输入 | 结果 | -|---|---| -| 120×80×15 底板 + 四角直径8孔 + 中心半径12孔 | 3 草图 3 特征,尺寸 120×80×15 正确 | -| 空心圆柱,外径60,内径40,高50 | 圆柱 + 内孔,外径 60 → 半径 30 正确 | -| 200×120×10 板 + 60×40 矩形槽 + 四角直径6孔 | 3 草图 3 特征(主体/矩形槽/四角孔),尺寸正确 | -| 自定义输入"60×40×12 板 + 中心直径10圆孔" | 特征树正确新增板 + 孔 | -| 复合模型 STL 导出 | 1072 三角形,文件长度精确匹配 | - -### 3.3 视口交互 ✅ - -鼠标拖拽旋转验证:视口区域 30.3% 像素变化,OrbitControls 正常工作。 - -## 4. 联调发现并修复的问题 - -| # | 文件 | 问题 | 修复 | -|---|---|---|---| -| 1 | `js/main.js` | 隐藏的 file input 未挂载 DOM,自动化/外部代码无法触发"打开" | 挂载到 body 并保持 `display:none` | -| 2 | `js/agent.js` | 槽尺寸正则 `[槽坑凹][^\d]*(\d+)...` 只在"槽"字后找数字,"60×40 的矩形槽"解析失败,槽未生成 | 支持数字在槽字前或后(双分支正则) | -| 3 | `js/agent.js` | "中间开一个矩形槽"被中心孔正则 `/中心\|中间\|.../` 误触发,生成假中心孔 | 位置词后 12 字符内必须出现"孔"才触发 | -| 4 | `js/agent.js` | 四角孔正则 `四角各?一个?[^\d]*?(?:直径\|半径)?(\d+)` 匹配到数量"4 个"而非直径"6" | 优先匹配"直径N / 半径N"字样,数量词兜底 | -| 5 | `js/agent.js` | "外径60 / 内径40"未识别,空心圆柱半径回退默认 20(实际应为 30) | 新增 `outerDia` / `innerDia` 解析,圆柱分支优先使用 | -| 6 | `js/geometry.js` | STL 80 字节 header 全为 0 | 写入 "MiniSW binary STL" + ISO 时间戳标识 | - -## 5. 测试结果 - -Node 回归测试从 38 条扩充到 **43 条全部通过**,新增 5 条针对联调修复的断言: - -| 新增断言 | 覆盖 | -|---|---| -| 矩形槽尺寸 60×40 解析正确 | 槽正则修复 | -| 中间开槽不误判为中心孔 | 中心孔误触发修复 | -| 四角孔直径6 → 半径3 × 4 | 四角孔正则修复 | -| 外径60 → 半径30 | 外径解析 | -| 内径40 → 内孔半径20 | 内径解析 | - -## 6. 遗留问题 - -| 问题 | 严重性 | 说明 | -|---|---|---| -| 多次 AI 生成叠加建模,无"新文档"入口 | 低 | 连续 AI 指令在同一文档累积特征,尺寸显示为整体包围盒(联调中曾误判为解析错误,实际是叠加结果) | -| LLM 路径未联调 | 中 | LLM 配置(`runLLM`)依赖外部 API Key,本次联调仅验证内置解析器路径 | -| 视口拾取精度 | 低 | Raycaster 拾取在 headless 下未做像素级验证,依赖任务 B 的 DOM 断言结果 | - -## 7. 验收对照 - -| 验收标准 | 状态 | -|---|---| -| 最小闭环:草图 → 拉伸 → 3D → 保存 → 加载 → STL | ✅ 全链路通过 | -| AI 面板闭环:自然语言 → 建模 | ✅ 4 组输入通过 | -| 控制台无错误 | ✅ 仅 favicon 404(无害) | -| 修复问题回归 | ✅ 43 条断言全部通过 | -| 报告 | ✅ 本文档 + TASK_A_REPORT.md | diff --git a/TASK_A_REPORT.md b/TASK_A_REPORT.md deleted file mode 100644 index 7f1f690..0000000 --- a/TASK_A_REPORT.md +++ /dev/null @@ -1,92 +0,0 @@ -# MiniSW 任务 A 报告:特征引擎加固 - -版本:v1.0 · 日期:2026-08-09 · 执行者:子代理 A - -## 1. 目标 - -在任务 B 的 UI 基础上加固底层特征引擎,补齐旋转、切除、布尔运算的边界情况,建立文档层撤销/恢复能力,并把 Node 冒烟测试从 16 条断言扩充到 38 条,为核心几何链路提供回归保障。 - -## 2. 改动文件清单 - -| 文件 | 改动类型 | 说明 | -|---|---|---| -| `js/doc.js` | 增强 | 新增 `snapshot()` / `restore()` 文档层快照;`deleteSketch()` 增加"被特征引用则拒绝删除"保护 | -| `js/geometry.js` | 加固 | `buildRevolve` 新增旋转轴退化/跨轴/轴不存在三类校验;`buildExtrude` 新增非流形状态检查 | -| `tests/test.mjs` | 大幅扩充 | 断言从 16 条扩充到 38 条,覆盖旋转、切除、嵌套轮廓、布尔叠加、快照、错误路径、delete 生命周期 | - -## 3. 特征引擎加固点 - -### 3.1 旋转特征(buildRevolve) - -| 加固项 | 说明 | 失败表现 | -|---|---|---| -| 旋转轴退化 | 轴线实体长度 `< 1e-6` 时报错,避免 `atan2` 除零 | `旋转轴退化` | -| 截面跨轴校验 | 截面点集同时分布在 u>0 与 u<0 两侧时报错(manifold revolve 对跨轴截面行为未定义) | `旋转截面跨越了旋转轴,请把截面放在轴的一侧` | -| 显式轴存在性 | `axisEntityId` 指定的实体不存在时报错,而不是静默回退 | `指定的旋转轴实体不存在` | -| 轴类型约束 | 仅 `line` / `centerline` 可作为轴,其他类型忽略并回退默认轴 | — | - -### 3.2 拉伸特征(buildExtrude) - -在 `CrossSection.extrude()` 后检查 `tool.status()`,非 `NoError` 时释放资源并抛错,避免把非流形实体带入后续布尔运算。 - -### 3.3 文档层快照(Doc.snapshot / restore) - -- `snapshot()` 复用 `toJSON()`,几何缓存(`bodyManifold` / `bodyMesh` / `deltaMeshes` / `bbox`)不参与序列化 -- `restore(snap)` 从 JSON 重建文档结构并清空几何缓存,调用方随后执行 `rebuild()` 刷新几何 -- 该机制被任务 B 的撤销/重做栈复用,也供未来编辑特征参数后回滚使用 - -### 3.4 草图删除保护 - -`deleteSketch(id)` 增加引用检查:若有特征仍引用该草图,返回 `false` 拒绝删除,防止重建时出现"草图不存在"级联错误。 - -## 4. 测试结果 - -### 4.1 测试命令 - -```bash -cd c:\Users\32919\.trae-cn\work\6a78857c0515f1e48ec3076f -node --experimental-loader ./loader.mjs test.mjs -``` - -### 4.2 结果 - -**通过: 38,失败: 0 — 全部通过** - -### 4.3 测试覆盖清单 - -| # | 场景 | 断言要点 | -|---|---|---| -| 1 | 几何内核初始化 | manifold wasm 加载成功 | -| 2 | 手动建模:底板 + 四角孔 | 重建无错误、实体网格、包围盒 120×80×15、特征增量网格存在、STL 导出 | -| 3 | 旋转特征(中心线作轴) | 旋转重建无错误、生成实体、外径 80 | -| 4 | AI 解析器 → op 序列 → 执行 | 解析识别、校验通过、重建无错误、特征数 ≥3 | -| 5 | 空心圆柱 | 圆柱 + 内孔两个特征、重建无错误 | -| 6 | 对称拉伸 | z∈[-5,5] 对称 | -| 7 | 贯穿所有切除 | 体积 60000-π·25·10 误差 <1% | -| 8 | 显式旋转轴 | 外径 50 正确 | -| 9 | 嵌套矩形孔(多环轮廓) | 体积 72000(100×80×10 - 40×20×10) | -| 10 | 圆柱原语 | 包围盒 40×40×50 | -| 11 | 圆柱凸台叠加(顺序布尔) | 凸台顶部 z=15、合并体积 = 60000+π·225·5 | -| 12 | 文档层快照/撤销恢复 | 快照1 → 1 特征;快照2 → 2 特征,均重建无错误 | -| 13 | 旋转截面跨越旋转轴 | 报错信息包含"旋转轴" | -| 14 | 退化轮廓 | 单线段拉伸被拦截报错 | -| 15 | STL 二进制头部 | 三角数一致、文件长度 = 84+50×N | -| 16 | 重复重建稳定性(delete 生命周期) | 连续 3 次重建体积一致 | -| 17 | 显式旋转轴不存在 | 报错信息包含"轴" | - -## 5. 关键修复记录 - -| 问题 | 原因 | 修复 | -|---|---|---| -| revolve 跨轴截面产生垃圾几何 | manifold `revolve` 对跨轴截面行为未定义 | 重建前遍历截面点,u 轴两侧均有分布时抛错 | -| `axisEntityId` 指向不存在的实体时静默回退 | 未校验轴实体存在性 | 增加显式存在性检查并抛错 | -| 旋转轴退化为点导致 `atan2` 异常 | 轴实体两端点重合 | 长度 `< 1e-6` 时报"旋转轴退化" | -| `deleteSketch` 删除被引用的草图导致重建崩溃 | 无引用检查 | 返回 `false` 拒绝删除 | -| 拉伸非流形实体进入布尔运算 | 未检查 `tool.status()` | 非 `NoError` 时抛错并释放 | - -## 6. 对下游任务的交接说明 - -- **doc.js / geometry.js 接口未变**:新增方法均为增量(`snapshot` / `restore`),原有导出签名不变 -- **`deltaMeshes` 契约**:`rebuild()` 始终填充每个特征的增量网格,供任务 B 的高亮/拾取消费 -- **错误特征标记**:单个特征失败时仅标记 `f.error`,不中断整体重建,后续特征继续执行 -- **任务 0 依赖**:快照/恢复、delete 生命周期、错误路径等已在 Node 层验证,需在浏览器联调中复核实际 UI 触发路径(撤销/重做按钮、特征删除右键菜单) diff --git a/TASK_B_REPORT.md b/TASK_B_REPORT.md deleted file mode 100644 index 865dc4d..0000000 --- a/TASK_B_REPORT.md +++ /dev/null @@ -1,125 +0,0 @@ -# MiniSW 任务 B 报告:UI 交互完善 - -版本:v1.0 · 日期:2026-08-09 · 执行者:子代理 B - -## 1. 目标 - -把 UI 从"能加载"提升到"可完整操作",对标 SolidWorks 的交互心智。完善草图工具、特征工作流、3D 交互、状态栏/Ribbon 打磨,并在浏览器自动化中走通 3 条完整用户路径。 - -## 2. 改动文件清单 - -| 文件 | 改动类型 | 说明 | -|---|---|---| -| `js/main.js` | 修复+增强 | 运行时缺陷修复、撤销/重做按钮状态管理、特征工作流完善、草图预检查、AI 操作入栈 | -| `js/sketchui.js` | 修复 | 实体选择交互修复、约束应用逻辑修正 | -| `js/viewport.js` | 修复+增强 | toNDC 坐标转换修复(getBoundingClientRect 后备)、几何/材质内存释放、高亮渲染 | -| `js/tree.js` | 增强 | 特征右键菜单新增"编辑草图"、单击草图节点进入编辑 | -| `css/style.css` | 修复+增强 | CSS 选择器修正(.rib-tabs → .ribbon-tabs)、HUD 样式、工具按钮激活态 | -| `index.html` | 无改动 | — | - -## 3. 新增/修复的功能点 - -### 3.1 运行时缺陷修复 -- **main.js `rebuildAndRefresh()` 空指针**:`ui.sk` 可能为 null,增加 `ui.sk && doc.sketchById(ui.sk.id)` 双重检查 -- **main.js `updateStatus()` 未调用**:在 `rebuildAndRefresh()` 中补充调用 -- **CSS 选择器错误**:`.rib-tabs` 修正为 `.ribbon-tabs` -- **工具按钮激活态**:为 `tool:` 类型按钮补充 `data-tool` 属性,确保 `updateToolButtons()` 正确高亮当前工具 -- **特征按钮草图模式禁用**:草图模式下拉伸/切除/旋转按钮标记 `bad` 类 - -### 3.2 草图工具交互 -- **实体列表选择**:属性面板中实体列表项点击可选中对应实体,同步 `ui.sel.ents` 并刷新视口 -- **矩形/圆/圆弧绘制**:验证 PointerEvent 事件链(pointerdown → pointermove → pointerdown)正确触发绘制 -- **工具提示**:每个草图工具切换时显示操作提示(如"矩形:单击一角→拖到对角") - -### 3.3 特征工作流 -- **拉伸/切除/旋转表单**:属性面板显示参数表单(深度、双向、反向等),确定/取消按钮 -- **特征树右键菜单**:特征节点右键弹出"编辑草图/编辑特征参数/删除特征" -- **草图节点单击编辑**:特征树中单击草图节点直接进入草图编辑模式 -- **特征预检查**:创建特征前检查是否在草图模式、草图是否有实体 - -### 3.4 撤销/重做 -- **按钮状态管理**:`updateUndoRedo()` 根据栈深度启用/禁用按钮 -- **AI 操作入栈**:`sendAI()` 在执行 AI 指令前 `pushUndo()`,失败时从栈中弹出并恢复 -- **特征创建入栈**:新建草图、创建特征、裁剪、约束等操作前均 `pushUndo()` - -### 3.5 3D 视口 -- **toNDC 坐标转换修复**:`getBoundingClientRect()` 在部分浏览器环境下返回 0 宽高,增加 `clientWidth/clientHeight` + offset 链遍历后备 -- **内存释放**:`updateBody()` 和 `highlightFeature()` 中正确 dispose 旧 geometry/material,防止内存泄漏 -- **拾取高亮**:`pickFeature()` 使用 Raycaster 对 pickMeshes 求交,命中后 `highlightFeature()` 渲染半透明橙色高亮 - -### 3.6 状态栏与 HUD -- **HUD 显示**:草图模式显示草图名/平面/实体数/约束数/标注数;模型模式显示"3D 模型模式" -- **状态栏**:显示草图数/特征数/错误数/包围盒尺寸 -- **重建反馈**:重建后显示"重建完成"或错误信息 - -## 4. 测试结果 - -### 4.1 测试环境 -- 浏览器:集成浏览器自动化(Chromium 内核) -- 服务器:`python -m http.server 8899`(目录 `f:\Program Files\MiniSW`) -- 页面加载:无控制台错误 - -### 4.2 三条用户路径验证 - -#### 路径 1:草图 → 拉伸 → 保存 ✅ -| 步骤 | 操作 | 结果 | -|---|---|---| -| 1 | 点击"前视草图" | 草图1 创建,进入草图模式,HUD 显示"草图1 · 前视 0 实体" | -| 2 | 选择"矩形"工具,绘制矩形 | HUD 更新为"1 实体",属性面板显示矩形 #2 | -| 3 | 点击"拉伸凸台",深度 10mm,确定 | 特征树新增"拉伸",状态栏"1 草图 · 1 特征 · 尺寸 129.775×162.219×10 mm" | -| 4 | 点击"保存" | 无错误(JSON 序列化 + Blob 下载触发) | - -#### 路径 2:草图 → 切除 → 撤销 → 重做 ✅ -| 步骤 | 操作 | 结果 | -|---|---|---| -| 1 | 新建前视草图2,画圆 | HUD 显示"草图2 · 前视 1 实体" | -| 2 | 点击"拉伸切除",确定 | 特征树新增"切除",状态"2 草图 · 2 特征" | -| 3 | 点击"撤销" | 切除消失,状态"2 草图 · 1 特征",重做按钮启用 | -| 4 | 点击"重做" | 切除恢复,状态"2 草图 · 2 特征",重做按钮禁用 | - -#### 路径 3:视图切换 + 拾取高亮 ✅ -| 步骤 | 操作 | 结果 | -|---|---|---| -| 1 | 切换到"视图"选项卡 | 显示前视/上视/右视/等轴测按钮 | -| 2 | 依次点击 4 个视图按钮 | 全部无错误,相机视角切换 | -| 3 | 特征树点击"拉伸"节点 | 节点选中(sel 类),属性面板显示特征参数表单 | -| 4 | 3D 视口拾取 | 见遗留问题 | - -### 4.3 控制台状态 -全部测试过程中**无控制台错误**。 - -## 5. 遗留问题 - -### 5.1 3D 视口拾取(环境限制) -在集成浏览器自动化环境中,`getBoundingClientRect()` 偶发返回 0 宽高,已通过 offset 链后备修复坐标转换。但 WebGL 渲染缓冲在不可见标签页中可能不完整渲染,导致 Raycaster 求交结果不稳定。特征树拾取高亮路径已验证可用,3D 视口直接拾取需在可见浏览器窗口中进一步验证。 - -### 5.2 截图限制 -集成浏览器自动化在当前环境中无法截图(标签页不可见),3 条路径的验证结果以 DOM 状态断言替代截图。 - -### 5.3 草图工具交互细节 -- 矩形工具为"两次点击"模式(click-move-click),非拖拽模式,与 SolidWorks 的拖拽矩形有差异 -- 圆弧工具需要三次点击确定,无预览圆心标记 - -## 6. 对下游任务的交接说明 - -### 6.1 对任务 A(特征引擎) -- `doc.deltaMeshes` 在 `rebuildAndRefresh()` 中被 `vp.setDeltas()` 和 `vp.buildPickTargets()` 消费,请确保 `doc.rebuild()` 正确填充 `deltaMeshes`(每个特征的增量网格) -- `doc.toJSON()` / `doc.fromJSON()` 已被保存/加载功能调用,请确保序列化格式稳定 - -### 6.2 对任务 C(AI 智能体) -- AI 操作已接入撤销栈:`sendAI()` 中 `pushUndo()` → `executeOps()` → 失败时 `restore(snap)` -- `executeOps()` 异常时会从 undoStack 弹出快照并恢复,确保 AI 指令失败不影响模型状态 -- AI 面板的示例按钮(chip)data-ex 属性包含中文描述,可直接被 `parseNaturalLanguage()` 消费 - -### 6.3 对任务 0(浏览器联调) -- 页面加载无控制台错误 -- `toNDC()` 的 `getBoundingClientRect()` 后备逻辑需在真实浏览器中验证(当前环境的间歇性 0 值问题可能不存在于真实浏览器) -- 所有 Ribbon 按钮、草图工具、特征表单、特征树交互均已验证无运行时错误 - -## 7. 验收对照 - -| 验收标准 | 状态 | 说明 | -|---|---|---| -| 3 条完整用户路径浏览器自动化通过 | ✅ | 路径 1/2 全通过,路径 3 视图切换+特征树拾取通过 | -| 无新增控制台错误 | ✅ | 全程 0 控制台错误 | -| 报告包含操作路径清单与截图 | ⚠️ | 操作路径清单完整;截图因环境限制以 DOM 断言替代 | diff --git a/TASK_C_REPORT.md b/TASK_C_REPORT.md deleted file mode 100644 index ee85ca5..0000000 --- a/TASK_C_REPORT.md +++ /dev/null @@ -1,155 +0,0 @@ -# 任务 C 完成报告:AI 智能体扩展 - -版本:v1.0 · 日期:2026-08-10 · 任务:C(AI 智能体扩展) - -## 1. 改动文件清单 - -| 文件 | 改动类型 | 说明 | -|---|---|---| -| `js/agent.js` | 重大扩展 | 新增 7 种高级 DSL 指令、宏展开引擎、解析器增强、LLM 多轮上下文 | -| `index.html` | 修改 | AI 面板新增 10 个示例按钮、清空对话按钮 | -| `js/main.js` | 修改 | AI 面板事件处理增强:历史记录、执行反馈、LLM 上下文传递 | - -## 2. 新增 DSL 指令 - -### 2.1 高级 op(宏展开层) - -| 指令 | 参数 | 展开为 | 说明 | -|---|---|---|---| -| `chamfer_rect` | cx, cy, w, h, chamfer | 8 段直线轮廓 | 倒角矩形(四角 45° 斜角) | -| `fillet_rect` | cx, cy, w, h, fillet | 直线+圆弧点列轮廓 | 圆角矩形(四角圆弧) | -| `polygon` | points[[u,v],...] | 顺序连线 | 自定义多边形 | -| `shell` | w, h, d, wall, plane | 外凸台+内腔切除 | 抽壳盒体 | -| `mirror` | axis(x\|y) | 复制上一特征并镜像 | 镜像复制 | -| `pattern_linear` | count, dx, dy | 复制上一特征并平移 | 线性阵列 | -| `pattern_circular` | count, cx, cy | 复制上一特征并旋转 | 圆周阵列 | - -### 2.2 宏展开引擎(expandOps) - -- 位于 `validateOps` / `executeOps` 之前,将高级 op 展开为已有原语序列 -- **无需修改 geometry.js / doc.js 的接口契约** -- 幂等设计:已经是原语的 op 原样通过 -- 特征组查找(lastFeatureGroup):自动识别上一个特征及其所属草图和实体 - -### 2.3 解析器增强(parseNaturalLanguage) - -新增关键词识别: -- 倒角:`/倒角/` + 支持 "Nmm倒角" 和 "倒角N" 两种句式 -- 圆角:`/圆角|过渡圆/` + 支持 "半径N" 作为回退 -- 抽壳:`/抽壳|空心盒|中空盒/` -- 线性阵列:`/线性阵列|直线阵列|排成一行|排成一列/` -- 圆周阵列:`/圆周阵列|环形阵列|圆周均布|环形均布/` -- 镜像:`/镜像|对称复制/` -- 凸台:`/凸台|凸起|加.*圆柱|顶.*圆柱|加.*凸/` - -特征冲突防护: -- 四角孔仅在 `!hasFillet && !hasChamfer` 时生成(避免与圆角/倒角冲突) -- 中心孔仅在 `!hasBoss` 时生成(避免凸台直径被误用为孔径) -- 纯抽壳路径仅在无附加特征时触发(`!hasHole && !hasChamfer && !hasFillet && !hasMirror && !hasBoss`) - -### 2.4 LLM 智能体完善 - -- OpenAI 兼容 API 接入(`callLLMAPI`) -- JSON 输出校验(`extractOps` + `validateOps`) -- 失败重试机制(maxRetries=1,带修正提示) -- 多轮对话上下文(`modelStateSummary` + `aiHistory`,最近 6 条) -- 离线保障:无 LLM 配置时自动回退到内置解析器 - -## 3. 测试结果 - -### 3.1 测试命令 - -```bash -cd c:\Users\32919\.trae-cn\work\6a788fba0515f1e48ec30a23 -node test_agent.mjs -``` - -### 3.2 测试结果 - -**通过: 103,失败: 0 — 全部通过** - -### 3.3 测试覆盖 - -#### 10 条新指令端到端测试 - -| # | 测试名称 | 输入描述 | 原始指令 | 展开后 op | 特征数 | -|---|---|---|---|---|---| -| 1 | 倒角矩形拉伸 | 100×80×20 矩形板,四边倒角5mm | 3 | 10 | 1 | -| 2 | 圆角矩形拉伸 | 100×80×20 矩形,四角圆角半径8 | 3 | 27 | 1 | -| 3 | 抽壳盒体 | 100×80×40 抽壳盒子,壁厚3mm | 1 | 6 | 2 | -| 4 | 线性阵列孔 | 200×100×10 板,直径10通孔,线性阵列4个间距40 | 7 | 15 | 5 | -| 5 | 圆周阵列孔 | 直径120厚10圆盘,直径10孔距中心40,圆周阵列6个 | 5 | 19 | 7 | -| 6 | 圆柱凸台 | 100×80×10 底板,直径30高20圆柱凸台 | 4 | 4 | 2 | -| 7 | 倒角+中心孔 | 80×80×20 带5mm倒角方块,中心直径20通孔 | 6 | 13 | 2 | -| 8 | 圆角+抽壳 | 100×80×30 圆角盒子,半径10,抽壳壁厚2 | 6 | 30 | 2 | -| 9 | 线性阵列+镜像 | 150×100×10 板,直径8孔,线性阵列3个间距50,镜像 | 8 | 15 | 5 | -| 10 | 凸台+镜像 | 100×60×10 板,凸台直径20高15在x-30,镜像到右侧 | 5 | 5 | 3 | - -#### 回归测试(3 条原有指令) - -| 输入 | 特征数 | 结果 | -|---|---|---| -| 120×80×15 底板,四角直径8孔,中心半径12孔 | 3 | 通过 | -| 空心圆柱,外径60,内径40,高50 | 2 | 通过 | -| 200×120×10 板,60×40 矩形槽,四角4个直径6孔 | 3 | 通过 | - -#### 无效指令容错测试(4 条) - -| 输入 | 结果 | -|---|---| -| "asdfghjkl" | 正确返回 null | -| "" | 正确返回 null | -| "你好" | 正确返回 null | -| "做一个不知道什么东西的模型" | 正确返回 null | - -#### 高级 op 直接构造测试 - -| 测试 | 结果 | -|---|---| -| polygon 五边形展开为 5 段直线 | 通过 | -| mirror 无前置特征 → 校验拦截 | 通过 | -| pattern_circular 无前置特征 → 校验拦截 | 通过 | - -## 4. 关键修复记录 - -| 问题 | 原因 | 修复 | -|---|---|---| -| mirrorEntityOp 崩溃 | rect/circle op 使用 `cx`/`cy` 属性,但镜像函数错误访问 `op.c[neg]`(c 数组是 executeOps 后的内部格式) | 改为 `if (axis === 'x') op.cx = -op.cx; else op.cy = -op.cy;` | -| validateOps 对无前置特征的 mirror/pattern 抛异常 | `expandOps` 内部 throw 未被捕获 | 用 try-catch 包裹,返回错误字符串 | -| 圆角盒子 "半径10" 未被提取 | "半径10" 与 "圆角" 分离,正则无法匹配 | 添加 `?? radius` 作为回退 | -| 四角圆角误触发四角孔 | 四角孔条件未排除圆角/倒角场景 | 添加 `!hasFillet && !hasChamfer` 条件 | -| 抽壳盒子走了板路径 | 纯抽壳条件未排除附加特征 | 添加 `!hasMirror && !hasBoss` 等条件 | -| 凸台直径被误用于中心孔 | 中心孔条件未排除凸台场景 | 添加 `!hasBoss` 条件 | -| 倒角 "5mm倒角" 句式未匹配 | 正则只匹配 "倒角N",不匹配 "Nmm倒角" | 添加反向匹配 `(\\d+)\\s*(?:mm)?\\s*倒角` | - -## 5. index.html AI 面板更新 - -新增 10 个示例按钮(chip),覆盖所有新指令: -- 底板+孔、空心圆柱、槽+孔(原有) -- 倒角、圆角、抽壳、线性阵列、圆周阵列、凸台、镜像(新增) - -新增清空对话按钮(↻),重置 AI 历史记录。 - -## 6. main.js AI 面板更新 - -- `aiHistory` 数组:维护最近 12 条对话(6 轮),用于 LLM 多轮上下文 -- `modelStateSummary()`:生成当前模型状态摘要,传递给 LLM -- `expandOps` 集成:执行前展开高级 op,反馈中显示原始/展开后 op 数量 -- 执行结果反馈:成功/失败原因、特征列表、错误特征数 - -## 7. 遗留问题 - -| 问题 | 严重性 | 说明 | -|---|---|---| -| 矩形槽尺寸提取正则有 `[^\\d]` bug | 低 | 在 regex literal 中 `\\d` 匹配字面 "\d" 而非数字,但中文场景下不影响功能 | -| "外径"/"内径" 未作为直径/半径别名 | 低 | "空心圆柱,外径60,内径40" 中外径/内径未提取,使用默认值;特征数正确但尺寸不准 | -| 镜像只复制最后一个特征 | 设计限制 | 用户期望镜像整个特征组时需手动指定;当前设计为镜像最后单个特征 | -| LLM 路径未经浏览器实测 | 中 | LLM 集成代码已完成但未在真实浏览器环境中验证(依赖任务 0 联调) | - -## 8. 对下游任务的交接说明 - -- **agent.js 导出接口未变**:`parseNaturalLanguage`、`expandOps`、`validateOps`、`executeOps`、`runLLM`、`getLLMSettings`、`setLLMSettings`、`DSL_SPEC` 均保持原有签名 -- **新增导出**:`expandOps` 为新增导出函数,main.js 已集成调用 -- **doc.js / geometry.js 未修改**:所有新指令通过宏展开为已有原语,不涉及底层接口变更 -- **index.html import map 未改动**:仅修改 AI 面板 DOM 结构 -- **任务 0 依赖**:main.js 的 AI 面板事件处理需在浏览器联调中验证 diff --git a/assets/solidworks/appearance-textures/ash_bump.jpg b/assets/solidworks/appearance-textures/ash_bump.jpg new file mode 100644 index 0000000..2be4d53 Binary files /dev/null and b/assets/solidworks/appearance-textures/ash_bump.jpg differ diff --git a/assets/solidworks/appearance-textures/birch_bump.jpg b/assets/solidworks/appearance-textures/birch_bump.jpg new file mode 100644 index 0000000..2f3b483 Binary files /dev/null and b/assets/solidworks/appearance-textures/birch_bump.jpg differ diff --git a/assets/solidworks/materials/en-US/SolidWorks DIN Materials.sldmat b/assets/solidworks/materials/en-US/SolidWorks DIN Materials.sldmat new file mode 100644 index 0000000..1728b31 Binary files /dev/null and b/assets/solidworks/materials/en-US/SolidWorks DIN Materials.sldmat differ diff --git a/assets/solidworks/materials/en-US/shader_mapping.dat b/assets/solidworks/materials/en-US/shader_mapping.dat new file mode 100644 index 0000000..31b6b99 --- /dev/null +++ b/assets/solidworks/materials/en-US/shader_mapping.dat @@ -0,0 +1,399 @@ +leather, Leather (PW) +sponge, Sponge (PW) +grass, Grass (PW) +sand, Sand (PW) +skin, Skin (PW) +heavyclouds, Heavy Clouds (PW) +lightclouds, Light Clouds (PW) +clearsky, Clear Sky (PW) +waterstill, Water Still (PW) +orientedstrandboard, Oriented Strand Board (OSB) (PW) +hardwoodfloor, Hardwood Floor (PW) +hardwoodfloor2, Hardwood Floor 2 (PW) +hardwoodfloor3, Hardwood Floor 3 (PW) +laminatefloor, Laminate Floor (PW) +laminatefloor2, Laminate Floor 2 (PW) +laminatefloor3, Laminate Floor 3 (PW) +polishedash, Polished Ash (PW) +satinfinishash, Satin Finish Ash (PW) +unfinishedash, Unfinished Ash (PW) +polishedbeech, Polished Beech (PW) +satinfinishbeech, Satin Finish Beech (PW) +unfinishedbeech, Unfinished Beech (PW) +polishedbirch, Polished Birch (PW) +satinfinishbirch, Satin Finish Birch (PW) +unfinishedbirch, Unfinished Birch (PW) +polishedcherry, Polished Cherry (PW) +satinfinishcherry, Satin Finish Cherry (PW) +unfinishedcherry, Unfinished Cherry (PW) +polishedmahogany, Polished Mahongany (PW) +satinfinishmahogany, Satin Finish Mahogany (PW) +unfinishedmahogany, Unfinished Mahogany (PW) +polishedmaple, Polished Maple (PW) +satinfinishmaple, Satin Finish Maple (PW) +unfinishedmaple, Unfinished Maple (PW) +polishedoak, Polished Oak (PW) +satinfinishoak, Satin Finish Oak (PW) +unfinishedoak, Unfinished Oak (PW) +polishedpine, Polished Pine (PW) +satinfinishpine, Satin Finish Pine (PW) +unfinishedpine, Unfinished Pine (PW) +polishedrosewood, Polished Rosewood (PW) +satinfinishrosewood, Satin Finish Rosewood (PW) +unfinishedrosewood, Unfinished Rosewood (PW) +polishedsatinwood, Polished Satinwood (PW) +satinfinishsatinwood, Satin Finish Satinwood (PW) +unfinishedsatinwood, Unfinished Satinwood (PW) +polishedspruce, Polished Spruce (PW) +satinfinishspruce, Satin Finish Spruce (PW) +unfinishedspruce, Unfinished Spruce (PW) +polishedteak, Polished Teak (PW) +satinfinishteak, Satin Finish Teak (PW) +unfinishedteak, Unfinished Teak (PW) +polishedwalnut, Polished Walnut (PW) +satinfinishwalnut, Satin Finish Walnut (PW) +unfinishedwalnut, Unfinished Walnut (PW) +redceramictile, Red Ceramic Tile (PW) +floortile7, Floor Tile 7 (PW) +floortile6, Floor Tile 6 (PW) +floortile5, Floor Tile 5 (PW) +floortile4, Floor Tile 4 (PW) +floortile3, Floor Tile 3 (PW) +floortile2, Floor Tile 2 (PW) +floortile1, Floor Tile 1 (PW) +cobblestone4, Cobblestone 4 (PW) +cobblestone3, Cobblestone 3 (PW) +cobblestone2, Cobblestone 2 (PW) +cobblestone1, Cobblestone 1 (PW) +cobblestone, Cobblestone (PW) +limestone, Limestone (PW) +sandstone, Sandstone (PW) +slate, Slate (PW) +granite, Granite (PW) +polishedpinkmarble, Polished Pink Marble (PW) +pinkmarble, Pink Marble (PW) +polishedgreenmarble, Polished Green Marble (PW) +greenmarble, Green Marble (PW) +polisheddarkmarble, Polished Dark Marble (PW) +darkmarble, Dark Marble (PW) +polishedbeigemarble, Polished Beige Marble (PW) +beigemarble, Beige Marble (PW) +polishedbluemarble, Polished Blue Marble (PW) +bluemarble, Blue Marble (PW) +flemishbrick, Flemish Brick (PW) +firebrick, Fire Brick (PW) +weatheredbrick, Weathered Brick (PW) +oldenglishbrick2, Old English Brick 2 (PW) +oldenglishbrick, Old English Brick (PW) +bonechina, Bone China (PW) +ceramic, Cermaic (PW) +stoneware, Stoneware (PW) +earthenware, Earthenware (PW) +porcelain, Porcelain (PW) +pavingasphalt, Paving Asphalt (PW) +pavingwetconcrete, Paving Wet Concrete (PW) +pavingdarkconcrete, Paving Dark Concrete (PW) +pavinglightconcrete, Paving Light Concrete (PW) +pavingredconcrete, Paving Red Concrete (PW) +pavingstone, Paving Stone (PW) +clothwhitecotton, Cloth White Cotton (PW) +clothbeigecotton, Cloth Beige Cotton (PW) +clothbluecotton, Cloth Blue Cotton (PW) +clothburgundycotton, Cloth Burgundy Cotton (PW) +clothgreycotton, Cloth Grey Cotton (PW) +clothcanvas, Cloth Canvas (PW) +clothburlap, Cloth Burplap (PW) +carpetcolor5, Carpet Color 5 (PW) +carpetcolor4, Carpet Color 4 (PW) +carpetcolor3, Carpet Color 3 (PW) +carpetcolor2, Carpet Color 2 (PW) +carpetcolor1, Carpet Color 1 (PW) +sandblastedglass, Sandblasted Glass (PW) +frostedglass, Frosted Glass (PW) +reflectivegreenglass, Reflective Green Glass (PW) +reflectiveblueglas, Reflective Blue Glass (PW) +reflectiveclearglass, Reflective Clear Glass (PW) +mirror, Mirror (PW) +brownglass, Brown Glass (PW) +greenglass, Green Glass (PW) +blueglass, Blue Glass (PW) +clearglass, Clear Glass (PW) +texturedrubber, Textured Rubber (PW) +perforatedrubber, Perforated Rubber (PW) +tiretreadrubber, Tire Tread Rubber (PW) +glossyrubber, Glossy Rubber (PW) +matterubber, Matte Rubber (PW) +darkpowdercoat, Dark Powdercoat (PW) +aluminumpowdercoat, Aluminum Powdercoat (PW) +blackspraypaint, Black Spray Paint (PW) +redspraypaint, Red Spray Paint (PW) +candyappleredcarpainthq, Candy Apple Red Car Paint HQ (PW) +steelgreycarpainthq, Steel Grey Car Paint HQ (PW) +sienacarpainthq, Siena Car Paint HQ (PW) +glossredcarpainthq, Gloss Red Car Paint HQ (PW) +glossbluecarpainthq, Gloss Blue Car Paint HQ (PW) +metallicgoldcarpainthq, Metallic Gold Car Paint HQ (PW) +metallicwarmgreycarpainthq, Metallic Warm Grey Car Paint HQ (PW) +metalliccoolgreycarpainthq, Metallic Cool Grey Car Paint HQ (PW) +whitecarpaint, White Car Paint (PW) +blackcarpaint, Black Car Paint (PW) +beigesatinfinishplastic, beige Satin Finish Plastic (PW) +yellowsatinfinishplastic, Yellow Satin Finish Plastic (PW) +greensatinfinishplastic, Green Satin Finish Plastic (PW) +redsatinfinishplastic, Red Satin Finish Plastic (PW) +bluesatinfinishplastic, Blue Satin Finish Plastic (PW) +blacksatinfinishplastic, Black Satin Finish Plastic (PW) +darkgreysatinfinishplastic, Dark Grey Satin Finish Plastic (PW) +lightgreysatinfinishplastic, Light Grey Satin Finish Plastic (PW) +creamsatinfinishplastic, Cream Satin Finish Plastic (PW) +whitesatinfinishplastic, White Satin Finish Plastic (PW) +beigelowglossplastic, beige Low Gloss Plastic (PW) +yellowlowglossplastic, Yellow Low Gloss Plastic (PW) +greenlowglossplastic, Green Low Gloss Plastic (PW) +redlowglossplastic, Red Low Gloss Plastic (PW) +bluelowglossplastic, Blue Low Gloss Plastic (PW) +blacklowglossplastic, Black Low Gloss Plastic (PW) +darkgreylowglossplastic, Dark Grey Low Gloss Plastic (PW) +lightgreylowglossplastic, Light Grey Low Gloss Plastic (PW) +creamlowglossplastic, Cream Low Gloss Plastic (PW) +whitelowglossplastic, White Low Gloss Plastic (PW) +beigemediumglossplastic, Beige Medium Gloss Plastic (PW) +yellowmediumglossplastic, Yellow Medium Gloss Plastic (PW) +greenmediumglossplastic, Green Medium Gloss Plastic (PW) +redmediumglossplastic, Red Medium Gloss Plastic (PW) +bluemediumglossplastic, Blue Medium Gloss Plastic (PW) +blackmediumglossplastic, Black Medium Gloss Plastic (PW) +darkgreymediumglossplastic, Dark Grey Medium Gloss Plastic (PW) +lightgreymediumglossplastic, Light Grey Medium Gloss Plastic (PW) +creammediumglossplastic, Cream Medium Gloss Plastic (PW) +whitehighglossplastic, White High Gloss Plastic (PW) +beigehighglossplastic, beige High Gloss Plastic (PW) +yellowhighglossplastic, Yellow High Gloss Plastic (PW) +greenhighglossplastic, Green High Gloss Plastic (PW) +redhighglossplastic, Red High Gloss Plastic (PW) +bluehighglossplastic, Blue High Gloss Plastic (PW) +blackhighglossplastic, Black High Gloss Plastic (PW) +darkgreyhighglossplastic, Dark Grey High Gloss Plastic (PW) +lightgreyhighglossplastic, Light Grey High Gloss Plastic (PW) +creamhighglossplastic, Cream High Gloss Plastic (PW) +whitehighglossplastic, White High Gloss Plastic (PW) +translucentplastic, Translucent Plastic (PW) +frostedplastic, Frosted Plastic (PW) +polypropyleneplastic, Polypropylene Plastic (PW) +polycarbonateplastic, Polycarbonate Plastic (PW) +largesparkerosionplasticblue, Large Spark Erosion Plasitc Blue (PW) +sparkerosionplasticblue, Spark Erosion Plasitc Blue (PW) +blueknurledplastic, Blue Knurled Plastic (PW) +bluedimpledplastic, Blue Dimpled Plastic (PW) +bluetreadplateplastic, Blue Treadplate Plastic (PW) +carbonfiberaramidfabric, Carbon Fiber Aramid Fabric (PW) +carbonfiberdesignfabric, Carbon Fiber Design Fabric (PW) +carbonfiberdyneemaplain, Carbon Fiber Dyneema Plain (PW) +carbonfiberinlayunidirectional, Carbon Fiber Inlay Unidirectional (PW) +carbonfiberepoxy, Carbon Fiber Epoxy (PW) +circularmeshplastic, Circular Mesh Plastic (PW) +diamondmeshplastic, Diamond Mesh Plastic (PW) +polishedsteel, Polished Steel (PW) +brushedsteel, Brushed Steel (PW) +satinfinishstainlesssteel, Satin Finish Stainless Steel (PW) +mattesteel, Matte Steel (PW) +sandblastedsteel, Sandblasted Steel (PW) +burnishedsteel, Burnished Steel (PW) +caststainlesssteel, Cast Stainless Steel (PW) +castcarbonsteel, Cast Carbon Steel (PW) +plaingalvanized, Plain Galvanized (PW) +chainlinksteel, Chain Link Steel (PW) +machinedsteel, Machined Steel (PW) +stainlesssteeltreadplate, Stainless Steel Treadplate (PW) +stainlesssteelknurled, Stainless Steel Knurled (PW) +wroughtstainlesssteel, Wrought Stainless Steel (PW) +chromiumplate, Chromium Plate (PW) +brushedchromium, Brushed Chromium (PW) +satinfinishchrome, Satin Finish Chrome (PW) +mattechrome, Matte Chrome (PW) +sandblastedchrome, Sandblasted Chrome (PW) +burnishedchrome, Burnished Chrome (PW) +chromiumplatecast, Chromium Plate Cast (PW) +polishedaluminum, Polished Aluminum (PW) +brushedaluminum, Brushed Aluminum (PW) +satinfinishaluminum, Satin Finish Aluminum (PW) +mattealuminum, Matte Aluminum (PW) +sandblastedaluminum, Sandblasted Aluminum (PW) +burnishedaluminum, Burnished Aluminum (PW) +castaluminum, Cast Aluminum (PW) +blueanodizedaluminum, Blue Anodized Aluminum (PW) +aluminumtreadplate, Aluminum Treadplate (PW) +polishedbronze, Polished Bronze (PW) +brushedbronze, Brushed Bronze (PW) +satinfinishbronze, Satin Finish Bronze (PW) +mattebronze, Matte Bronze (PW) +sandblastedbronze, Sandblasted Bronze (PW) +burnishedbronze, Burnished Bronze (PW) +castbronze, Cast Bronze (PW) +manganesebronze, Manganese Bronze (PW) +polishedbrass, Polished Brass (PW) +brushedbrass, Brushed Brass (PW) +satinfinishbrass, Satin Finish Brass (PW) +mattebrass, Matte Brass (PW) +sandblastedbrass, Sandblasted Brass (PW) +burnishedbrass, Burnished Brass (PW) +castbrass, Cast Brass (PW) +polishedcopper, Polished Copper (PW) +brushedcopper, Brushed Copper (PW) +satinfinishcopper, Satin Finish Copper (PW) +mattecopper, Matte Copper (PW) +sandblastedcopper, Sandblasted Copper (PW) +burnishedcopper, Burnished Copper (PW) +castcopper, Cast Copper (PW) +wroughtcopper, Wrought Copper (PW) +polishednickel, Polished Nickel (PW) +brushednickel, Brushed Nickel (PW) +satinfinishnickel, Satin Finish Nickel (PW) +mattenickel, Matte Nickel (PW) +sandblastednickel, Sandblasted Nickel (PW) +burnishednickel, Burnished Nickel (PW) +castnickel, Cast Nickel (PW) +polishedzinc, Polished Zinc (PW) +brushedzinc, Brushed Zinc (PW) +satinfinishzinc, Satin Finish Zinc (PW) +sandblastedzinc, Sandblasted Zinc (PW) +burnishedzinc, Burnished Zinc (PW) +castzinc, Cast Zinc (PW) +brushedmagnesium, Brushed Magnesium (PW) +mattemagnesium, Matte Magnesium (PW) +satinfinishmagnesium, Satin Finish Magnesium (PW) +sandblastedmagnesium, Sandblasted Magnesium (PW) +burnishedmagnesium, Burnished Magnesium (PW) +castmagnesium, Cast Magnesium (PW) +matteiron, Matte Iron (PW) +sandblastediron, Sandblasted Iron (PW) +castiron, Cast Iron (PW) +wroughtiron, Wrought Iron (PW) +brushedtitanium, Brushed Titanium (PW) +mattetitanium, Matte Titanium (PW) +satinfinishtitanium, Satin Finish Titanium (PW) +sandblastedtitanium, Sandblasted Titanium (PW) +burnishedtitanium, Burnished Titanium (PW) +casttitanium, Cast Titanium (PW) +brushedtungsten, Brushed Tungsten (PW) +matttetungsten, Mattte Tungsten (PW) +satinfinishtungsten, Satin Finish Tungsten (PW) +sandblastedtungsten, Sandblasted Tungsten (PW) +burnishedtungsten, Burnished Tungsten (PW) +casttungsten, Cast Tungsten (PW) +polishedgold, Polished Gold (PW) +mattegold, Matte Gold (PW) +satinfinishgold, Satin Finish Gold (PW) +polishedsilver, Polished Silver (PW) +mattesilver, Matte Silver (PW) +satinfinishsilver, Satin Finish Silver (PW) +polishedplatinum, Polished Platinum (PW) +matteplatinum, Matte Platinum (PW) +satinfinishplatinum, Satin Finish Platinum (PW) +mattelead, Matte Lead (PW) +sandblastedlead, Sandblasted Lead (PW) +burnishedlead, Burnished Lead (PW) +castlead, Cast Lead (PW) +brushedgalvanized, Brushed Galvanized (PW) +mattegalvanized, Matte Galvanized (PW) +coarsegalvanized, Coarse Galvanized (PW) +castgalvanized, Cast Galvanized (PW) +roughgalvanized, Rough Galvanized (PW) +shinygalvanized, Shiny Galvanized (PW) +SpecCobblestone, Cobble Stone Specular (BGE) +SpecFloorTile, Floor Tile Specular (BGE) +TransFloorTile, Floor Tile Transparent (BGE) +Aluminum1345Alloy, Aluminum 1345 Alloy +Aluminum1350Alloy, Aluminum 1350 Alloy +Aluminum2014Alloy, Aluminum 2014 Alloy +Aluminum2018Alloy, Aluminum 2018 Alloy +Aluminum2024Alloy, Aluminum 2024 Alloy +Aluminum3003Alloy, Aluminum 3003 Alloy +Aluminum6061Alloy, Aluminum 6061 Alloy +Aluminum7079Alloy, Aluminum 7079 Alloy +AluminumBrushed, Aluminum Brushed +AluminumCircularBrushed, Aluminum Circular Brushed +AluminumSatin, Aluminum Satin +BrassPolished, Brass Polished +BronzeAluminum, Bronze Aluminum +BronzeCommercial, Bronze Commercial +BronzeManganese, Bronze Manganese +BronzeTinBearing, Bronze Tin Bearing +CarbonFibre, Carbon Fiber +ceramicporcelain, Ceramic Porcelain +ceramicporcelain2, Ceramic Porcelain2 +ChromePolished, Chrome Polished +Cobalt, Cobalt +CopperPolished, Copper Polished +CopperWrought, Copper Wrought +Glass, Glass +GlassFibre, Glass Fiber +GoldDull, Gold +IronCast, Iron Cast +IronDuctile, Iron Ductile +IronMalleableCast, Iron Malleable Cast +LeadPure, Lead Pure +Molybdenum, Molybdenum +AlloyMagnesium, Magnesium Alloy +AlloyMonel400, Monel 400 +NickelBrushed, Nickel Brushed +NickelPolished, Nickel Polished +PlasticAcrylic, Plastic Acrylic +PlasticDimpled, Plastic Dimpled +PlasticMT11010, Plastic MT11010 +PlasticMT11020, Plastic MT11020 +PlasticMT11030, Plastic MT11030 +PlasticMT11040, Plastic MT11040 +PlasticMT11050, Plastic MT11050 +PlasticMT11060, Plastic MT11060 +PlasticMT11070, Plastic MT11070 +PlasticMT11080, Plastic MT11080 +PlasticMT11090, Plastic MT11090 +PlasticMT11100, Plastic MT11100 +PlasticMT11110, Plastic MT11110 +PlasticMT11120, Plastic MT11120 +PlasticMT11130, Plastic MT11130 +PlasticMT11140, Plastic MT11140 +PlasticMT11150, Plastic MT11150 +PlasticMT11155, Plastic MT11155 +PlasticMT11200, Plastic MT11200 +PlasticMT11205, Plastic MT11205 +PlasticMT11215, Plastic MT11215 +PlasticMT11230, Plastic MT11230 +PlasticMT11235, Plastic MT11235 +PlasticMT11240, Plastic MT11240 +PlasticMT11245, Plastic MT11245 +PlasticMT11250, Plastic MT11250 +PlasticNylon, Plastic Nylon +PlasticShiny, Plastic Shiny +PlasticPerspex, Plastic Perspex +PlasticPTFE, Plastic PTFE +PlasticPolycarbonate, Plastic Polycarbonate +PlasticPolypropylene, Plastic Polypropylene +PlasticPolystyrene, Plastic Polystyrene +PlasticPVC, Plastic PVC +RubberSoft, Rubber Soft +Silicon, Silicon +SiliconDioxide, Silicon Dioxide +silverpure, Silver Pure +StainlessSteel, Steel Stainless +SteelAISI304, Steel AISI 304 +SteelAISI1020, Steel AISI 1020 +SteelCastCarbon, Steel Cast Carbon +SteelCastStainless, Steel Cast Stainless +SteelGalvanised, Steel Galvanised +SteelPlainCarbon, Steel Plain Carbon +SteelSatin, Steel Satin +SteelWroughtStainless, Steel Wrought Stainless +Titanium, Titanium +Tungsten, Tungsten +Vanadium, Vanadium +water, Water +WoodBeech, Wood Beech +WoodMahogany, Wood Mahogany +WoodMaple, Wood Maple +WoodOak, Wood Oak +WoodPine, Wood Pine +WoodRedCedar, Wood Red Cedar +WoodTeak, Wood Teak +Zirconium, Zirconium \ No newline at end of file diff --git a/assets/solidworks/materials/en-US/solidworks materials.sldmat b/assets/solidworks/materials/en-US/solidworks materials.sldmat new file mode 100644 index 0000000..e492c7b Binary files /dev/null and b/assets/solidworks/materials/en-US/solidworks materials.sldmat differ diff --git a/assets/solidworks/materials/en-US/sustainability extras.sldmat b/assets/solidworks/materials/en-US/sustainability extras.sldmat new file mode 100644 index 0000000..45a3ad0 Binary files /dev/null and b/assets/solidworks/materials/en-US/sustainability extras.sldmat differ diff --git a/assets/solidworks/materials/zh-CN/SolidWorks DIN Materials.sldmat b/assets/solidworks/materials/zh-CN/SolidWorks DIN Materials.sldmat new file mode 100644 index 0000000..d222ec6 Binary files /dev/null and b/assets/solidworks/materials/zh-CN/SolidWorks DIN Materials.sldmat differ diff --git a/assets/solidworks/materials/zh-CN/shader_mapping.dat b/assets/solidworks/materials/zh-CN/shader_mapping.dat new file mode 100644 index 0000000..93cad00 --- /dev/null +++ b/assets/solidworks/materials/zh-CN/shader_mapping.dat @@ -0,0 +1,399 @@ +leather, Ƥ(PW) +sponge, (PW) +grass, (PW) +sand, ɳ (PW) +skin, Ƥ (PW) +heavyclouds, (PW) +lightclouds, (PW) +clearsky, (PW) +waterstill, ˮ (PW) +orientedstrandboard, Ť (OSB) (PW) +hardwoodfloor, Ӳľذ (PW) +hardwoodfloor2, Ӳľذ 2 (PW) +hardwoodfloor3, Ӳľذ 3 (PW) +laminatefloor, ״ذ (PW) +laminatefloor2, ״ذ 2 (PW) +laminatefloor3, ״ذ 3 (PW) +polishedash, ľ (PW) +satinfinishash, ľ (PW) +unfinishedash, ľ (PW) +polishedbeech, ɽë (PW) +satinfinishbeech, ɽë (PW) +unfinishedbeech, ɽë (PW) +polishedbirch, ľ (PW) +satinfinishbirch, ľ (PW) +unfinishedbirch, ľ (PW) +polishedcherry, ӣľ (PW) +satinfinishcherry, ӣľ (PW) +unfinishedcherry, ӣľ (PW) +polishedmahogany, ľ (PW) +satinfinishmahogany, ľ (PW) +unfinishedmahogany, ƺľ (PW) +polishedmaple, ľ (PW) +satinfinishmaple, ľ (PW) +unfinishedmaple, ľ (PW) +polishedoak, ľ (PW) +satinfinishoak, ľ (PW) +unfinishedoak, ľ (PW) +polishedpine, ľ (PW) +satinfinishpine, ľ (PW) +unfinishedpine, ľ (PW) +polishedrosewood, ľ (PW) +satinfinishrosewood, ľ (PW) +unfinishedrosewood, ľ (PW) +polishedsatinwood, ľ (PW) +satinfinishsatinwood, ľ (PW) +unfinishedsatinwood, ľ (PW) +polishedspruce, ɼ (PW) +satinfinishspruce, ɼ (PW) +unfinishedspruce, ɼ (PW) +polishedteak, ľ (PW) +satinfinishteak, ľ (PW) +unfinishedteak, ľ (PW) +polishedwalnut, ľ (PW) +satinfinishwalnut, ľ (PW) +unfinishedwalnut, ƺľ (PW) +redceramictile, ש (PW) +floortile7, ذש 7 (PW) +floortile6, ذש 6 (PW) +floortile5, ذש 5 (PW) +floortile4, ذש 4 (PW) +floortile3, ذש 3 (PW) +floortile2, ذש 2 (PW) +floortile1, ذש 1 (PW) +cobblestone4, ʯ 4 (PW) +cobblestone3, ʯ 3 (PW) +cobblestone2, ʯ 2 (PW) +cobblestone1, ʯ 1 (PW) +cobblestone, ʯ (PW) +limestone, ʯʯ (PW) +sandstone, ɰ (PW) +slate, ʯ (PW) +granite, (PW) +polishedpinkmarble, ۺʯ (PW) +pinkmarble, ۺʯ (PW) +polishedgreenmarble, ɫʯ (PW) +greenmarble, ɫʯ (PW) +polisheddarkmarble, ɫʯ (PW) +darkmarble, ɫʯ (PW) +polishedbeigemarble, ɫʯ (PW) +beigemarble, ɫʯ (PW) +polishedbluemarble, ɫʯ (PW) +bluemarble, ɫʯ (PW) +flemishbrick, äӲש (PW) +firebrick, ͻש (PW) +weatheredbrick, 绯ʯ (PW) +oldenglishbrick2, ʽӢӲש 2 (PW) +oldenglishbrick, ʽӢӲש (PW) +bonechina, ʴ (PW) +ceramic, մ (PW) +stoneware, մ (PW) +earthenware, (PW) +porcelain, (PW) +pavingasphalt, · (PW) +pavingwetconcrete, ·ʪ (PW) +pavingdarkconcrete, ·ڻ (PW) +pavinglightconcrete, · (PW) +pavingredconcrete, · (PW) +pavingstone, ·ʯ (PW) +clothwhitecotton, (PW) +clothbeigecotton, ɫ (PW) +clothbluecotton, ɫ (PW) +clothburgundycotton, Ѿɫ (PW) +clothgreycotton, ɫ (PW) +clothcanvas, (PW) +clothburlap, 鲼 (PW) +carpetcolor5, ̺ɫ 5 (PW) +carpetcolor4, ̺ɫ 4 (PW) +carpetcolor3, ̺ɫ 3 (PW) +carpetcolor2, ̺ɫ 2 (PW) +carpetcolor1, ̺ɫ 1 (PW) +sandblastedglass, ɳ (PW) +frostedglass, ë (PW) +reflectivegreenglass, ̲ (PW) +reflectiveblueglas, (PW) +reflectiveclearglass, (PW) +mirror, (PW) +brownglass, ز (PW) +greenglass, ̲ (PW) +blueglass, (PW) +clearglass, (PW) +texturedrubber, ṹ (PW) +perforatedrubber, (PW) +tiretreadrubber, ̥ (PW) +glossyrubber, (PW) +matterubber, (PW) +darkpowdercoat, ɫ۲(PW) +aluminumpowdercoat, ۲ (PW) +blackspraypaint, ɫ (PW) +redspraypaint, ɫ (PW) +candyappleredcarpainthq, ʺƻɫ (PW) +steelgreycarpainthq, ʸֻɫ (PW) +sienacarpainthq, ɫ (PW) +glossredcarpainthq, ʹɫ (PW) +glossbluecarpainthq, ʹɫ (PW) +metallicgoldcarpainthq, ʽɫ (PW) +metallicwarmgreycarpainthq, ʽȻɫ (PW) +metalliccoolgreycarpainthq, ʽɫ (PW) +whitecarpaint, ɫ (PW) +blackcarpaint, ɫ (PW) +beigesatinfinishplastic, ɫ (PW) +yellowsatinfinishplastic, ɫ (PW) +greensatinfinishplastic, ɫ (PW) +redsatinfinishplastic, ɫ (PW) +bluesatinfinishplastic, ɫ (PW) +blacksatinfinishplastic, ɫ (PW) +darkgreysatinfinishplastic, ɫ (PW) +lightgreysatinfinishplastic, ɫ (PW) +creamsatinfinishplastic, ɫ (PW) +whitesatinfinishplastic, ɫ (PW) +beigelowglossplastic, ɫ (PW) +yellowlowglossplastic, ɫ (PW) +greenlowglossplastic, ɫ (PW) +redlowglossplastic, ɫ (PW) +bluelowglossplastic, ɫ (PW) +blacklowglossplastic, ɫ (PW) +darkgreylowglossplastic, ɫ (PW) +lightgreylowglossplastic, ɫ (PW) +creamlowglossplastic, ɫ (PW) +whitelowglossplastic, ɫ (PW) +beigemediumglossplastic, ɫй (PW) +yellowmediumglossplastic, ɫй (PW) +greenmediumglossplastic, ɫй (PW) +redmediumglossplastic, ɫй (PW) +bluemediumglossplastic, ɫй (PW) +blackmediumglossplastic, ɫй (PW) +darkgreymediumglossplastic, ɫй (PW) +lightgreymediumglossplastic, ɫй (PW) +creammediumglossplastic, ɫй (PW) +whitemediumglossplastic, ɫй (PW) +beigehighglossplastic, ɫ߹ (PW) +yellowhighglossplastic, ɫ߹ (PW) +greenhighglossplastic, ɫ߹ (PW) +redhighglossplastic, ɫ߹ (PW) +bluehighglossplastic, ɫ߹ (PW) +blackhighglossplastic, ɫ߹ (PW) +darkgreyhighglossplastic, ɫ߹ (PW) +lightgreyhighglossplastic, ɫ߹ (PW) +creamhighglossplastic, ɫ߹ (PW) +whitehighglossplastic, ɫ߹ (PW) +translucentplastic, (PW) +frostedplastic, ë (PW) +polypropyleneplastic, ۱ϩ (PW) +polycarbonateplastic, ̼ (PW) +largesparkerosionplasticblue, ɫʴ (PW) +sparkerosionplasticblue, ɫʴ (PW) +blueknurledplastic, (PW) +bluedimpledplastic, (PW) +bluetreadplateplastic, ̤ (PW) +carbonfiberaramidfabric, ̼ά᰷֯ (PW) +carbonfiberdesignfabric, ̼άװ֯ (PW) +carbonfiberdyneemaplain, ̼άͨ (PW) +carbonfiberinlayunidirectional, ̼ά (PW) +carbonfiberepoxy, ̼ά˹ (PW) +circularmeshplastic, Բ (PW) +diamondmeshplastic, (PW) +polishedsteel, (PW) +brushedsteel, Ϳˢ (PW) +satinfinishstainlesssteel, ⲻ (PW) +mattesteel, (PW) +sandblastedsteel, ɳ (PW) +burnishedsteel, ĥ (PW) +caststainlesssteel, 첻 (PW) +castcarbonsteel, ̼ (PW) +plaingalvanized, ͨƸ (PW) +chainlinksteel, (PW) +machinedsteel, ӹ (PW) +stainlesssteeltreadplate, ̤ (PW) +stainlesssteelknurled, ֹ (PW) +wroughtstainlesssteel, Ʋ (PW) +chromiumplate, Ƹ (PW) +brushedchromium, Ϳˢ (PW) +satinfinishchrome, (PW) +mattechrome, (PW) +sandblastedchrome, ɳ (PW) +burnishedchrome, ĥ (PW) +chromiumplatecast, Ƹģ (PW) +polishedaluminum, (PW) +brushedaluminum, Ϳˢ (PW) +satinfinishaluminum, (PW) +mattealuminum, (PW) +sandblastedaluminum, ɳ (PW) +burnishedaluminum, ĥ (PW) +castaluminum, (PW) +blueanodizedaluminum, ɫ (PW) +aluminumtreadplate, ̤ (PW) +polishedbronze, ͭ (PW) +brushedbronze, Ϳˢͭ (PW) +satinfinishbronze, ͭ (PW) +mattebronze, ͭ (PW) +sandblastedbronze, ɳͭ (PW) +burnishedbronze, ĥͭ (PW) +castbronze, ͭ (PW) +manganesebronze, ͭ (PW) +polishedbrass, ͭ (PW) +brushedbrass, Ϳˢͭ (PW) +satinfinishbrass, ͭ (PW) +mattebrass, ͭ (PW) +sandblastedbrass, ɳͭ (PW) +burnishedbrass, ĥͭ (PW) +castbrass, ͭ (PW) +polishedcopper, ͭ (PW) +brushedcopper, Ϳˢͭ (PW) +satinfinishcopper, ͭ (PW) +mattecopper, ͭ (PW) +sandblastedcopper, ɳͭ (PW) +burnishedcopper, ĥͭ (PW) +castcopper, ͭ (PW) +wroughtcopper, ƺͭ (PW) +polishednickel, (PW) +brushednickel, Ϳˢ (PW) +satinfinishnickel, (PW) +mattenickel, (PW) +sandblastednickel, ɳ (PW) +burnishednickel, ĥ (PW) +castnickel, (PW) +polishedzinc, п (PW) +brushedzinc, Ϳˢп (PW) +satinfinishzinc, п (PW) +sandblastedzinc, ɳп (PW) +burnishedzinc, ĥп (PW) +castzinc, п (PW) +brushedmagnesium, Ϳˢþ (PW) +mattemagnesium, þ (PW) +satinfinishmagnesium, þ (PW) +sandblastedmagnesium, ɳþ (PW) +burnishedmagnesium, ĥþ (PW) +castmagnesium, þ (PW) +matteiron, (PW) +sandblastediron, ɳ (PW) +castiron, (PW) +wroughtiron, (PW) +brushedtitanium, Ϳˢ (PW) +mattetitanium, (PW) +satinfinishtitanium, (PW) +sandblastedtitanium, ɳ (PW) +burnishedtitanium, ĥ (PW) +casttitanium, (PW) +brushedtungsten, Ϳˢ (PW) +matttetungsten, (PW) +satinfinishtungsten, (PW) +sandblastedtungsten, ɳ (PW) +burnishedtungsten, ĥ (PW) +casttungsten, (PW) +polishedgold, (PW) +mattegold, (PW) +satinfinishgold, (PW) +polishedsilver, (PW) +mattesilver, (PW) +satinfinishsilver, (PW) +polishedplatinum, (PW) +matteplatinum, (PW) +satinfinishplatinum, (PW) +mattelead, Ǧ (PW) +sandblastedlead, ɳǦ (PW) +burnishedlead, ĥǦ (PW) +castlead, Ǧ (PW) +brushedgalvanized, Ϳˢ (PW) +mattegalvanized, (PW) +coarsegalvanized, (PW) +castgalvanized, (PW) +roughgalvanized, ֲڵ (PW) +shinygalvanized, (PW) +SpecCobblestone, ʯ (BGE) +SpecFloorTile, ذש (BGE) +TransFloorTile, ذש (BGE) +Aluminum1345Alloy, 1345 Ͻ +Aluminum1350Alloy, 1350 Ͻ +Aluminum2014Alloy, 2014 Ͻ +Aluminum2018Alloy, 2018 Ͻ +Aluminum2024Alloy, 2024 Ͻ +Aluminum3003Alloy, 3003 Ͻ +Aluminum6061Alloy, 6061 Ͻ +Aluminum7079Alloy, 7079 Ͻ +AluminumBrushed, Ϳˢ +AluminumCircularBrushed, ԲͿˢ +AluminumSatin, +BrassPolished, ͭ +BronzeAluminum, ͭ +BronzeCommercial, ҵͭ +BronzeManganese, ͭ +BronzeTinBearing, ͭ +CarbonFibre, ̼ά +ceramicporcelain, մɴ +ceramicporcelain2, մɴ2 +ChromePolished, +Cobalt, +CopperPolished, ͭ +CopperWrought, ƺͭ +Glass, +GlassFibre, ά +GoldDull, +IronCast, +IronDuctile, +IronMalleableCast, ɶ +LeadPure, Ǧ +Molybdenum, +AlloyMagnesium, þϽ +AlloyMonel400, Monel 400 +NickelBrushed, Ϳˢ +NickelPolished, +PlasticAcrylic, ϩ +PlasticDimpled, +PlasticMT11010, MT11010 +PlasticMT11020, MT11020 +PlasticMT11030, MT11030 +PlasticMT11040, MT11040 +PlasticMT11050, MT11050 +PlasticMT11060, MT11060 +PlasticMT11070, MT11070 +PlasticMT11080, MT11080 +PlasticMT11090, MT11090 +PlasticMT11100, MT11100 +PlasticMT11110, MT11110 +PlasticMT11120, MT11120 +PlasticMT11130, MT11130 +PlasticMT11140, MT11140 +PlasticMT11150, MT11150 +PlasticMT11155, MT11155 +PlasticMT11200, MT11200 +PlasticMT11205, MT11205 +PlasticMT11215, MT11215 +PlasticMT11230, MT11230 +PlasticMT11235, MT11235 +PlasticMT11240, MT11240 +PlasticMT11245, MT11245 +PlasticMT11250, MT11250 +PlasticNylon, +PlasticShiny, +PlasticPerspex, л +PlasticPTFE, PTFE +PlasticPolycarbonate, ̼֬ +PlasticPolypropylene, ۱ϩ +PlasticPolystyrene, ۱ϩ +PlasticPVC, ϩ +RubberSoft, +Silicon, +SiliconDioxide, +silverpure, +StainlessSteel, +SteelAISI304, AISI 304 +SteelAISI1020, AISI 1020 +SteelCastCarbon, ̼ +SteelCastStainless, 첻 +SteelGalvanised, Ƹ +SteelPlainCarbon, ̼ͨ +SteelSatin, и +SteelWroughtStainless, 첻 +Titanium, +Tungsten, +Vanadium, +water, ˮ +WoodBeech, ɽëľ +WoodMahogany, ľ +WoodMaple, ľ +WoodOak, ľ +WoodPine, ľ +WoodRedCedar, ѩľ +WoodTeak, ľ +Zirconium, \ No newline at end of file diff --git a/assets/solidworks/materials/zh-CN/solidworks materials.sldmat b/assets/solidworks/materials/zh-CN/solidworks materials.sldmat new file mode 100644 index 0000000..300d263 Binary files /dev/null and b/assets/solidworks/materials/zh-CN/solidworks materials.sldmat differ diff --git a/assets/solidworks/materials/zh-CN/sustainability extras.sldmat b/assets/solidworks/materials/zh-CN/sustainability extras.sldmat new file mode 100644 index 0000000..75bc471 Binary files /dev/null and b/assets/solidworks/materials/zh-CN/sustainability extras.sldmat differ diff --git a/bearing_bracket.stl b/bearing_bracket.stl new file mode 100644 index 0000000..ad71fc1 Binary files /dev/null and b/bearing_bracket.stl differ diff --git a/build-bearing-bracket.mjs b/build-bearing-bracket.mjs new file mode 100644 index 0000000..394b5d7 --- /dev/null +++ b/build-bearing-bracket.mjs @@ -0,0 +1,99 @@ +import fs from 'node:fs/promises'; +import { initGeometry } from './js/geometry.js'; +import { Doc } from './js/doc.js'; + +await initGeometry(); + +const doc = new Doc(); +doc.name = '轴承支座_160x70_φ68_φ40H7'; +doc.units = 'mm'; + +// Named dimensions are kept in the document for editing and inspection. +for (const [name, expression] of [ + ['BaseLength', '160'], ['BaseWidth', '70'], ['BaseHeight', '14'], ['BaseCornerR', '12'], + ['MountHoleDia', '13'], ['MountHoleX', '60'], ['MountHoleY', '15'], + ['StandThicknessX', '26'], ['StandWidthY', '46'], ['StandHeight', '22'], + ['BossOuterDia', '68'], ['BossBoreDia', '40'], ['BossLengthX', '60'], ['BossCenterZ', '70'], + ['BoreChamfer', '2'], ['RibThickness', '8'], +]) doc.setDimension(name, expression); + +function sketch(plane, offset, name) { + return doc.addSketch({ plane, offset, name }); +} +function line(sk, p1, p2) { + doc.addEntity(sk.id, { type: 'line', p1, p2 }); +} +function arc(sk, c, r, a0, a1) { + doc.addEntity(sk.id, { type: 'arc', c, r, a0, a1 }); +} +function circle(sk, c, r) { + doc.addEntity(sk.id, { type: 'circle', c, r }); +} +function feature(type, name, params, sketchId = null) { + return doc.addFeature({ type, name, params, sketchId }); +} + +// 1. 160 x 70 x 14 base plate, true R12 corner arcs. +const base = sketch('front', 0, '底板外轮廓_R12'); +line(base, [-68, -35], [68, -35]); +arc(base, [68, -23], 12, -Math.PI / 2, 0); +line(base, [80, -23], [80, 23]); +arc(base, [68, 23], 12, 0, Math.PI / 2); +line(base, [68, 35], [-68, 35]); +arc(base, [-68, 23], 12, Math.PI / 2, Math.PI); +line(base, [-80, 23], [-80, -23]); +arc(base, [-68, -23], 12, Math.PI, 3 * Math.PI / 2); +feature('extrude', '底板_160x70x14', { depth: 14 }, base.id); + +// 2. Four Ø13 through holes at ±60, ±15. +const holes = sketch('front', 0, '四个安装孔_孔距120x30'); +for (const x of [-60, 60]) for (const y of [-15, 15]) circle(holes, [x, y], 6.5); +feature('cut', '四个φ13安装通孔_边距20', { throughAll: true, mode: 'throughAll' }, holes.id); + +// 3. Central upright plate, z=14 to z=36. +const stand = sketch('front', 14, '立板_26x46'); +doc.addEntity(stand.id, { type: 'rect', c: [0, 0], w: 26, h: 46 }); +feature('extrude', '立板_厚26_宽46_高22', { depth: 22 }, stand.id); + +// 4. Hollow boss along X: x=-30..30, center (y,z)=(0,70). +const boss = sketch('right', -30, '圆筒座_φ68_φ40'); +circle(boss, [70, 0], 34); +circle(boss, [70, 0], 20); +feature('extrude', '圆筒座_外φ68_内φ40_长60', { depth: 60 }, boss.id); + +// 5. C2 inner-bore chamfers. The extended cylinder primitive is used as a +// conical cutting tool, with the large radius at each outside end. +feature('cylcut', '内孔左端_C2', { r: 22, r2: 20, h: 2, axis: 'x', tx: -29, tz: 70 }); +feature('cylcut', '内孔右端_C2', { r: 20, r2: 22, h: 2, axis: 'x', tx: 29, tz: 70 }); + +// 6. Two triangular gussets, front and rear of the upright plate. +// The 8 mm extrusion is along Y; the apex intentionally penetrates the boss +// slightly so the Boolean union is robust while remaining tangent in design. +const ribFront = sketch('top', -27, '前加强筋_三角截面'); +line(ribFront, [-13, 14], [0, 14]); +line(ribFront, [0, 14], [13, 14]); +line(ribFront, [13, 14], [0, 66]); +line(ribFront, [0, 66], [-13, 14]); +feature('extrude', '前加强筋_厚8', { depth: 8 }, ribFront.id); + +const ribRear = sketch('top', 19, '后加强筋_三角截面'); +line(ribRear, [-13, 14], [0, 14]); +line(ribRear, [0, 14], [13, 14]); +line(ribRear, [13, 14], [0, 66]); +line(ribRear, [0, 66], [-13, 14]); +feature('extrude', '后加强筋_厚8', { depth: 8 }, ribRear.id); + +doc.rebuild(); +const errors = doc.features.filter(f => f.error).map(f => ({ name: f.name, error: f.error })); +if (errors.length) throw new Error(JSON.stringify(errors)); + +const bbox = doc.bbox; +const summary = { + bbox: { min: bbox.min, max: bbox.max }, + volume: doc.bodyManifold.volume(), + sketches: doc.sketches.length, + features: doc.features.length, + featureNames: doc.features.map(f => f.name), +}; +console.log(JSON.stringify(summary, null, 2)); +await fs.writeFile('./轴承支座_160x70_φ68_φ40H7.json', JSON.stringify(doc.toJSON(), null, 2), 'utf8'); diff --git a/css/style.css b/css/style.css index 1f68b95..20c72d4 100644 --- a/css/style.css +++ b/css/style.css @@ -4,16 +4,30 @@ --fg:#d7dce3; --fg-dim:#8b94a1; --fg-bright:#fff; --accent:#3d8bff; --accent2:#5ea3ff; --warn:#ffb454; --err:#ff6b6b; --ok:#5fd08a; --sketch:#ffd54a; --sel:#7fb8ff; - --ribbon-h:86px; --status-h:26px; + --chrome-h:30px; --ribbon-h:86px; --status-h:28px; } *{box-sizing:border-box; margin:0; padding:0} html,body{height:100%; overflow:hidden} body{background:var(--bg); color:var(--fg); font:13px/1.45 "Microsoft YaHei", "Segoe UI", sans-serif; user-select:none} #app{display:flex; flex-direction:column; height:100%} +/* ---------- application chrome ---------- */ +#app-chrome{height:var(--chrome-h); display:flex; align-items:center; gap:14px; padding:0 10px; background:#1a1e23; border-bottom:1px solid #11151a; color:var(--fg-dim); flex-shrink:0; font-size:11px} +.chrome-brand{display:flex; align-items:center; gap:6px; color:var(--fg); font-weight:700; letter-spacing:.6px; min-width:84px} +.chrome-mark{display:inline-grid; place-items:center; width:18px; height:18px; border-radius:4px; background:linear-gradient(135deg,#5ea3ff,#2f6fd6); color:#fff; font-size:11px; box-shadow:0 1px 4px rgba(0,0,0,.35)} +.chrome-context{display:flex; align-items:center; gap:8px; min-width:0} +.chrome-doc{color:var(--fg); max-width:260px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap} +.chrome-sep{color:var(--line2)} +.chrome-mode{color:var(--accent2)} +.chrome-state{padding:2px 7px; border:1px solid #2e5c40; border-radius:9px; color:#a5e8c0; background:#213a2c} +.chrome-state.err{border-color:#7a3a34; color:#ffb4ae; background:#3a2424} +.chrome-actions{display:flex; align-items:center; gap:6px; margin-left:auto; white-space:nowrap} +.chrome-status-dot{width:7px; height:7px; border-radius:50%; background:var(--ok); box-shadow:0 0 0 3px rgba(95,208,138,.12)} +.chrome-status-label{color:var(--fg-dim)} button{font-family:inherit; color:var(--fg); background:var(--panel2); border:1px solid var(--line); border-radius:5px; cursor:pointer} button:hover{background:var(--panel3); border-color:var(--line2)} button.active{background:#27456e; border-color:var(--accent)} button:disabled{opacity:.4; cursor:default} +button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline:2px solid var(--accent2); outline-offset:1px} input,textarea,select{font-family:inherit; color:var(--fg); background:#1a1e24; border:1px solid var(--line); border-radius:4px; padding:4px 6px; outline:none} input:focus,textarea:focus,select:focus{border-color:var(--accent)} input[type=number]{width:90px} @@ -47,8 +61,8 @@ input[type=number]{width:90px} /* ---------- workspace ---------- */ #workspace{flex:1; display:flex; min-height:0} -#tree-panel{width:210px; background:var(--panel); border-right:1px solid var(--line); display:flex; flex-direction:column; flex-shrink:0} -#props-panel{width:280px; background:var(--panel); border-left:1px solid var(--line); display:flex; flex-direction:column; flex-shrink:0; overflow-y:auto} +#tree-panel{width:230px; background:var(--panel); border-right:1px solid var(--line); display:flex; flex-direction:column; flex-shrink:0} +#props-panel{width:300px; background:var(--panel); border-left:1px solid var(--line); display:flex; flex-direction:column; flex-shrink:0; overflow-y:auto} /* ---------- resizer ---------- */ .resizer{position:relative; flex-shrink:0; z-index:15} @@ -56,8 +70,9 @@ input[type=number]{width:90px} .resizer-h:hover, .resizer-h.dragging{background:var(--accent)} .resizer-v{height:4px; cursor:row-resize; background:var(--line); transition:background .15s} .resizer-v:hover, .resizer-v.dragging{background:var(--accent)} -.panel-title{padding:8px 10px; font-size:12px; color:var(--fg-dim); border-bottom:1px solid var(--line); background:var(--panel2); flex-shrink:0} +.panel-title{display:flex; align-items:center; gap:0; min-height:36px; padding:8px 12px; font-size:12px; color:var(--fg); border-bottom:1px solid var(--line); background:linear-gradient(180deg,#303640,#2b3038); flex-shrink:0; font-weight:600} .panel-sub{color:var(--line2); margin-left:6px} +.panel-meta{margin-left:auto; color:var(--fg-dim); font-size:10px; font-weight:400; border:1px solid var(--line); border-radius:9px; padding:1px 6px; background:rgba(0,0,0,.14)} #tree{flex:1; overflow-y:auto; padding:6px 4px} #props{flex:1; padding:10px} @@ -76,8 +91,11 @@ input[type=number]{width:90px} .prop-sec{font-size:11px; color:var(--fg-dim); margin:12px 0 6px; text-transform:uppercase; letter-spacing:.5px} .prop-row{display:flex; align-items:center; gap:8px; margin:6px 0} .prop-row label{width:64px; color:var(--fg-dim); font-size:12px; flex-shrink:0} -.prop-row .val{flex:1} +.prop-row .val{flex:1; min-width:0; overflow-wrap:anywhere; word-break:break-word} .prop-note{font-size:11px; color:var(--fg-dim); line-height:1.5; margin:6px 0} +.prop-note{max-width:100%; overflow-wrap:anywhere; word-break:break-word; white-space:pre-wrap} +.prop-note.prop-error{color:#ffb4ae;border-left:2px solid var(--err);padding-left:8px} +.prop-note.prop-ok{color:#a5e8c0;border-left:2px solid var(--ok);padding-left:8px} .prop-btns{display:flex; gap:8px; margin-top:12px} .prop-btns button{flex:1; padding:6px} .btn-ok{background:linear-gradient(180deg,#3d8bff,#2f6fd6); border-color:#2459a8; color:#fff} @@ -95,8 +113,17 @@ input[type=number]{width:90px} /* ---------- viewport ---------- */ #viewport-wrap{flex:1; position:relative; min-width:0; background:#15181d} #viewport{position:absolute; inset:0} +#drawing-preview{position:absolute; inset:18px; z-index:8; display:flex; align-items:center; justify-content:center; background:#20252b; border:1px solid var(--line); border-radius:8px; overflow:auto; box-shadow:0 10px 28px rgba(0,0,0,.25)} +#drawing-preview svg{width:min(92%,900px); height:auto; max-height:94%; background:#fff; box-shadow:0 4px 18px rgba(0,0,0,.35)} +#viewport-wrap:after{content:""; position:absolute; inset:0; pointer-events:none; border:1px solid rgba(255,255,255,.025)} +#empty-state{position:absolute; z-index:5; left:50%; top:50%; transform:translate(-50%,-46%); width:min(390px,calc(100% - 44px)); padding:24px 26px 22px; text-align:center; border:1px solid var(--line); border-radius:12px; background:rgba(29,34,41,.9); box-shadow:0 16px 40px rgba(0,0,0,.28); backdrop-filter:blur(7px)} +.empty-glyph{width:44px; height:44px; margin:0 auto 10px; display:grid; place-items:center; color:var(--accent2); border:1px solid #3f6594; border-radius:12px; background:#1d2c47; font-size:27px; line-height:1} +.empty-title{font-size:16px; color:var(--fg-bright); font-weight:700} +.empty-copy{margin:7px auto 16px; max-width:300px; color:var(--fg-dim); font-size:12px; line-height:1.6} +.empty-actions{display:flex; justify-content:center; gap:8px} +.empty-actions button{padding:6px 12px; font-size:12px} #viewport-hud{position:absolute; left:10px; top:10px; pointer-events:none; color:var(--fg-dim); font-size:12px; display:flex; flex-direction:column; gap:4px} -#viewport-hud .hud-line{background:rgba(20,24,30,.7); padding:2px 8px; border-radius:4px; backdrop-filter:blur(4px)} +#viewport-hud .hud-line{background:rgba(20,24,30,.78); padding:4px 9px; border:1px solid rgba(69,78,91,.7); border-radius:5px; backdrop-filter:blur(4px)} #viewport-hud .hud-sub{font-size:11px; color:var(--fg-dim)} #viewport-hud .hud-snaptip{color:var(--warn)} @@ -112,20 +139,23 @@ input[type=number]{width:90px} .minisw-label.snapmark{pointer-events:none; color:#7fb8ff; font-size:13px; background:transparent; border:none} /* ---------- status bar ---------- */ -#statusbar{height:var(--status-h); background:var(--panel); border-top:1px solid var(--line); display:flex; align-items:center; gap:16px; padding:0 10px; font-size:12px; color:var(--fg-dim); flex-shrink:0} +#statusbar{height:var(--status-h); background:#20252b; border-top:1px solid var(--line); display:flex; align-items:center; gap:16px; padding:0 10px; font-size:11px; color:var(--fg-dim); flex-shrink:0} #statusbar .sb-item{white-space:nowrap} #statusbar .sb-tip{flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap} #statusbar .sb-snap{color:var(--warn)} +.sb-item strong{font-weight:600} /* ---------- AI panel ---------- */ -#ai-panel{position:absolute; right:12px; bottom:12px; width:400px; max-height:70%; background:var(--panel); border:1px solid var(--line2); border-radius:10px; box-shadow:0 8px 30px rgba(0,0,0,.5); display:flex; flex-direction:column; z-index:30; overflow:hidden} +#ai-panel{position:absolute; right:14px; bottom:14px; width:min(430px,calc(100% - 28px)); max-height:72%; background:var(--panel); border:1px solid var(--line2); border-radius:10px; box-shadow:0 8px 30px rgba(0,0,0,.5); display:flex; flex-direction:column; z-index:30; overflow:hidden} #ai-panel.hidden{display:none} .ai-header{display:flex; align-items:center; gap:8px; padding:8px 12px; background:var(--panel2); border-bottom:1px solid var(--line); cursor:move; user-select:none} .ai-title{font-weight:700; color:var(--accent2)} -.ai-mode-badge{font-size:11px; background:#1d2c47; color:#9ecbff; border:1px solid #23466e; padding:1px 8px; border-radius:10px} +.ai-mode-badge{font-size:11px; background:#1d2c47; color:#9ecbff; border:1px solid #23466e; padding:1px 8px; border-radius:10px; cursor:pointer} .ai-mode-badge.llm{background:#3a2c1d; color:#ffd9a0; border-color:#6e5523} +.ai-mode-badge:focus-visible{outline:2px solid var(--accent2); outline-offset:2px} .ai-close{margin-left:auto; background:none; border:none; font-size:16px; color:var(--fg-dim); padding:0 4px} .ai-close:hover{color:var(--fg)} +.ai-guide{padding:6px 12px; font-size:11px; color:var(--fg-dim); background:#20252c; border-bottom:1px solid var(--line); line-height:1.4} .ai-chat{flex:1; overflow-y:auto; padding:10px; display:flex; flex-direction:column; gap:8px; min-height:120px; max-height:280px} .ai-msg{max-width:88%; padding:7px 10px; border-radius:8px; font-size:12.5px; line-height:1.55; white-space:pre-wrap; word-break:break-word} .ai-msg.user{align-self:flex-end; background:#27456e; color:#eaf2ff} @@ -139,9 +169,11 @@ input[type=number]{width:90px} .chip:hover{color:var(--fg); border-color:var(--accent)} .ai-input-row{display:flex; gap:8px; padding:10px; border-top:1px solid var(--line)} .ai-input-row textarea{flex:1; resize:none; user-select:text} +#ai-input{min-height:48px; line-height:1.5} #ai-send{width:64px; background:linear-gradient(180deg,#3d8bff,#2f6fd6); border-color:#2459a8; color:#fff; font-weight:600} #ai-send:disabled{filter:grayscale(.7)} #ai-send .spin{display:inline-block; animation:spin 1s linear infinite} +.ai-input-hint{padding:0 12px 8px; color:var(--fg-dim); font-size:10px; text-align:right; border-top:0} @keyframes spin{to{transform:rotate(360deg)}} /* ---------- misc ---------- */ @@ -164,6 +196,21 @@ input[type=number]{width:90px} .splash-bar-fill{height:100%; width:0%; background:var(--accent); transition:width .3s} .hidden{display:none !important} +@media (max-width:900px){ + #app-chrome{gap:8px} + .chrome-actions{display:none} + #tree-panel{width:190px} + #props-panel{width:250px} + #ai-panel{width:min(390px,calc(100% - 20px)); right:10px; bottom:10px} +} +@media (max-width:680px){ + #app-chrome{padding:0 7px} + .chrome-context{font-size:10px} + .chrome-doc{max-width:150px} + #tree-panel{width:170px} + #props-panel{display:none} + #ai-panel{width:calc(100% - 16px); right:8px; bottom:8px; max-height:76%} +} ::-webkit-scrollbar{width:9px; height:9px} ::-webkit-scrollbar-thumb{background:var(--line2); border-radius:5px} ::-webkit-scrollbar-track{background:transparent} diff --git a/index.html b/index.html index 7f44a10..fa7b210 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@