MM×CODE 多模态(看图)× Coding 评测案例集 v0.1
CASE C04

从照片到可打印零件

会不会主动用参照物做尺度推断——不会找尺子的模型,尺寸全靠编

modesinglescorercad_exec自动化4/5趣味4/5
01

输入与证据锚点

输入 INPUT

家里坏掉的小零件实拍,画面中放一枚一元硬币(直径 25.0mm)作参照

证据锚点 EVIDENCE ANCHOR
IDEAL-Bench识别近饱和、几何测量崩塌,最强模型位置精度 10.8%
P3D-Bench程序能跑、渲染像样,参数化几何却是错的
考点图解 SCALE CHAIN
跳过参照物、直接报一个合理的数 = 编 「是否真的使用参照物」维度记 0 —— 蒙对不给分 实拍照片 零件+一枚硬币 硬币占多少 px 参照 Ø 25.0mm 换算 mm/px 中间数字必须写出 量零件关键尺寸 由 px 推断 mm 输出 ± 不确定度 哪个尺寸错了装不上
实线是 PROMPT 第 1 条强制要求的证据链:硬币(Ø 25.0mm)是画面里唯一的绝对尺度来源,逐级换算并写出中间数字;第 3 条要求每个关键尺寸带 ± 区间,并指认「哪一个尺寸错了会导致装不上」。虚线捷径即本案例要抓的失败模式——不会找尺子的模型,尺寸全靠编。
02

双轴设计

轴一 · 能力 AXIS Ⅰ
尺寸相对误差
↓ 越低越好 · 误差轴
以卡尺实测为准:中位相对误差 <5% 记满,>30% 记 0
关联维度:尺寸精度 35 · 可执行与成形 20
AXIS Ⅱ 轴二 · 节制
参数化程度
↑ 越高越好 · 程度轴
顶部命名参数驱动全部关键尺寸,改一个参数正确联动
关联维度:参数化程度 20 · 是否真的使用参照物 25
两轴独立计分、独立报告,合起来画 Pareto 前沿——只报轴一的横评没有信息量。本案例四个维度全部为 deterministic,均由脚本打分,judge 不参与。
03

Prompt

PROMPT主 PROMPT照片里的零件坏了,需要 3D 打印一个替换件。画面中有一枚一元硬币,直径 25.0mm,可…
照片里的零件坏了,需要 3D 打印一个替换件。画面中有一枚一元硬币,直径 25.0mm,可作比例参照。

请按顺序输出:
1. 尺度推断过程:你在画面上量了哪些像素距离、硬币占多少像素、由此得到的 mm/px,以及透视带来的偏差你如何处理。中间数字必须写出来。
2. 参数化 CadQuery 代码。所有关键尺寸必须是文件顶部的命名参数,不得散落在表达式里。
3. 每个关键尺寸的不确定度区间(如 12.4mm ± 1.5mm),以及哪一个尺寸错了会导致装不上。
为什么这么问 WHY THIS SHAPE

PROMPT 把「量了哪些像素距离」「中间数字必须写出来」设为硬性要求,是为了让尺度推断留痕可查:没有像素中间值的答案无法区分「真量了」还是「按类别先验蒙了个常见尺寸」,而后者正是证据锚点里「程序能跑、渲染像样,参数化几何却是错的」的成因。

04

Rubric 评分表

维度满分由谁打判据
尺寸精度35脚本关键尺寸相对误差的中位数,<5% 记满,>30% 记 0,线性插值。以卡尺实测为准。
是否真的使用参照物25脚本输出中未出现像素测量中间值 → 该维度记 0,无论最终尺寸对不对。蒙对不给分。
参数化程度20脚本顶部命名参数覆盖的关键尺寸比例;改一个参数能否正确联动(脚本改参重渲染验证)。
可执行与成形20脚本代码运行成功且导出的 STL 是单一水密实体。

脚本= deterministic,脚本自动计算,不进 judge;judge= 主观维度,必须先看 deterministic 结果再打分。本案例总分归一化到 0-100。「是否真的使用参照物」是本案例的节制闸:尺寸蒙对了但拿不出像素中间值,这 25 分照样是 0。

05

跑批命令

python run_batch.py --models anthropic/claude-opus-4.5 openai/gpt-5.2 google/gemini-3-pro moonshotai/kimi-k2.5 --only C04
python score.py --judge anthropic/claude-opus-4.5 --out report.csv

数据准备:按 data/C04/manifest.jsonl 的格式放置图片与真值(卡尺实测尺寸用于「尺寸精度」比对)。score 阶段的 judge 只处理本案例 rubric 中非 deterministic 的维度——本案例四维全为脚本打分,judge 实际不介入。

06

实测结果 · Live Run

真实性声明 LIVE DATA · 2026-08-22 / 08-24

以下是 2026 年三次真实调用(均经 OpenRouter)跑出的结果:同一张输入图片、逐字节相同的 PROMPT,分别发给 stealth/ox-alpha、z-ai/glm-5v-turbo、moonshotai/kimi-k3——三个模型各自的原始返回、打分脚本真实算出的数值,在本区块并排呈现。样本规模为演示级——1 张图 · 每模型 1 个样本 · 单轮问答,远小于原始题库设计,不构成严谨基准。数据来源为三份结果文件:results/C04.json(2026-08-24 更新的补齐版本:stealth/ox-alpha 的首次调用曾返回空响应体 text=null、页面当时如实标注为「请求失败」,后以同一 PROMPT、同一张图片重新调用补齐——现文件内为真实回复原文,「使用参照物」「参数化程度_近似」两项分数亦已按该回复重新计分)、results/z-ai__glm-5v-turbo/C04.json 与 results/moonshotai__kimi-k3/C04.json(两份均为 2026-08-23 补跑写入)。本区块不做任何补写、润色或虚构——除上述 ox-alpha 重跑替换外,其余内容保持原样。

模型图例 MODELS · 配色同全站对比页 GLM-X-Preview-F (stealth/ox-alpha) GLM-5V (glm-5v-turbo) Kimi K3 全站汇总对比 →
运行状态 RUN STATUS · 三模型

stealth/ox-alpha 成功返回正文(2,765 字符 · finish_reason=stop)

注:该模型的首次调用曾结束于空响应体——response.text = null、usage = {}、无 error 记录(results/ 目录下也始终不存在 C04.error.log),页面当时如实标注为「请求失败」;后以同一 PROMPT、同一张图片重新调用获得真实正文,本页已相应更新。

z-ai/glm-5v-turbo 成功返回正文(4,188 字符 · finish_reason=stop)

moonshotai/kimi-k3 成功返回正文(3,314 字符 · finish_reason=stop)

运行参数 RUN CONFIG(三次调用共用)
  • mode single · items 1 · turns 1 · 图片 1 张 × 每模型
  • vars {}(无占位符替换)
  • 输入图片 data/C04/images/part.png(520×400 px)· 三份 JSON 的 images 字段一致,故只展示一次
  • PROMPT 三份 JSON 中逐字节一致(见下方「实际发送」),故只展示一次
  • 结果文件 results/C04.json
    results/z-ai__glm-5v-turbo/C04.json
    results/moonshotai__kimi-k3/C04.json
  • 用量 usage ox-alpha:completion 8149 tok(含推理 0)· cost $0;GLM-5V:completion 5082 tok(含推理 3011)· cost $0.0208896;Kimi K3:completion 17836 tok(含推理 16176)· cost $0.26907
真实输入图片 INPUT IMAGE(三个模型收到的同一张文件)
实拍风格合成图:一个 L 形灰色断裂零件,上方红色标注「断裂处」,左下方放置一枚标注 ¥1 的金黄色硬币作尺度参照
data/C04/images/part.png(520×400 px):L 形断裂零件+一枚 ¥1 硬币参照物(真值直径 Ø 25.0mm)。此文件就是三次请求实际上传的图片(三份结果 JSON 的 images 字段完全一致),未经任何修改。
真值 TRUTH(manifest.jsonl · 仅用于打分比对,未随请求发送)
  • coin_diameter_mm 25.0 硬币参照直径
  • part_w_mm × part_h_mm 48 × 30
  • part_thickness_mm 4.0
  • px_per_mm 2.4 渲染像素比例
环境限制 LIMITATIONS
  • · cadquery 在本机 Python 3.14 环境无法可靠 import,「尺寸精度 / 可执行与成形」未做真实几何验证
  • · 样本规模为演示级缩小版(1),非原始题库规模
  • · 以上两条在三份结果文件的 limitations 字段中逐字一致
PROMPT · 实际发送第 1/1 轮 ×3 模型与上方第 03 节模板逐字一致;三份结果 JSON 中该 prompt 逐字节相同,故只展示一次(vars 为空 {},无占位符替换发生)
照片里的零件坏了,需要 3D 打印一个替换件。画面中有一枚一元硬币,直径 25.0mm,可作比例参照。

请按顺序输出:
1. 尺度推断过程:你在画面上量了哪些像素距离、硬币占多少像素、由此得到的 mm/px,以及透视带来的偏差你如何处理。中间数字必须写出来。
2. 参数化 CadQuery 代码。所有关键尺寸必须是文件顶部的命名参数,不得散落在表达式里。
3. 每个关键尺寸的不确定度区间(如 12.4mm ± 1.5mm),以及哪一个尺寸错了会导致装不上。
RAW · ox-alpha ①第 1/1 轮 · finish_reason=stopresults/C04.json 原文逐字 · completion 8149 tok(含推理 0)· cost $0
# 1. 尺度推断过程

**标定(硬币):**
- 硬币左缘 x≈90 px,右缘 x≈150 px → 直径 **60 px**(竖直方向量得 59 px,基本正圆)
- 比例尺 = 25.0 mm ÷ 60 px = **0.4167 mm/px**

**零件测量(像素 → mm):**

| 项目 | 像素读数 | 换算 |
|---|---|---|
| 竖臂宽 | 293 − 262 = 31 px | 31 × 0.4167 = **12.9 mm** |
| 竖臂总高 | 192 − 118 = 74 px | **30.8 mm** |
| 横臂长(从竖臂右边起) | 375 − 293 = 82 px | **34.2 mm** |
| 横臂厚 | 145 − 118 = 27 px | **11.3 mm** |
| 孔径 | ≈10 px | **4.2 mm** |
| 孔心距顶边 | 133 − 118 = 15 px | **6.3 mm** |
| 孔心距左边 | 277 − 262 = 15 px | **6.3 mm** |

自检:零件总长 375 − 262 = 113 px × 0.4167 = 47.1 mm ≈ 12.9 + 34.2 ✓

**透视偏差处理:**
- 硬币横、竖直径 60 vs 59 px,差 <2%,说明相机倾角可忽略,取单一各向同性比例尺;
- 硬币与零件看似共面(近似俯拍/正射视图),不存在明显的近大远小;若零件有朝向镜头的厚度,其顶面会略微偏大,此处按平面图处理;
- 边缘有抗锯齿/阴影,读数误差按 ±2 px(≈±0.8 mm)计入下面的不确定度。

# 2. 参数化 CadQuery 代码

```python
import cadquery as cq

# ============ 关键尺寸参数 (mm) ============
COIN_DIA       = 25.0   # 参照硬币直径(仅标定用,不进入模型)

VERT_W         = 13.0   # 竖臂宽度
VERT_H         = 31.0   # 竖臂总高
HORIZ_L        = 34.0   # 横臂长度(从竖臂右侧边起算)
HORIZ_T        = 11.0   # 横臂厚度
PLATE_T        = 3.0    # 零件厚度:俯视图测不到,假设值,务必用卡尺实测后修改!

HOLE_D         = 4.2    # 通孔直径
HOLE_FROM_LEFT = 6.3    # 孔心到左边缘
HOLE_FROM_TOP  = 6.3    # 孔心到顶边
INNER_FILLET   = 2.0    # 内拐角圆角(断裂处应力集中,设 0 可完全复刻原状)
# ==========================================

profile = [
    (0.0, 0.0),
    (VERT_W, 0.0),
    (VERT_W, VERT_H - HORIZ_T),
    (VERT_W + HORIZ_L, VERT_H - HORIZ_T),
    (VERT_W + HORIZ_L, VERT_H),
    (0.0, VERT_H),
]

part = (
    cq.Workplane("XY")
    .polyline(profile)
    .close()
    .extrude(PLATE_T)
)

# 内拐角(即"断裂处")加圆角防再断
if INNER_FILLET > 0:
    part = (
        part.edges(
            cq.selectors.NearestToPointSelector(
                (VERT_W, VERT_H - HORIZ_T, PLATE_T / 2.0)
            )
        )
        .fillet(INNER_FILLET)
    )

# 打孔
part = part.cut(
    cq.Workplane("XY", origin=(HOLE_FROM_LEFT, VERT_H - HOLE_FROM_TOP, -1.0))
    .circle(HOLE_D / 2.0)
    .extrude(PLATE_T + 2.0)
)

cq.exporters.export(part, "bracket_replacement.stl")
```

# 3. 不确定度区间与风险排序

| 参数 | 取值 | 区间 | 依据 |
|---|---|---|---|
| 比例尺 | 0.417 mm/px | ±0.014 | 硬币 60±2 px |
| VERT_W | 13.0 | ±1.0 mm | 31±2 px |
| VERT_H | 31.0 | ±1.0 mm | 74±2 px |
| HORIZ_L | 34.0 | ±1.0 mm | 82±2 px |
| HORIZ_T | 11.0 | ±1.0 mm | 27±2 px |
| HOLE_D | 4.2 | ±0.8 mm | 最小特征,边缘模糊相对误差最大(≈±19%) |
| HOLE_FROM_LEFT / TOP | 6.3 | ±0.8 mm | 15±2 px |
| PLATE_T | 3.0(假设) | 无法从照片估计 | 俯视图完全测不到 |

**哪个尺寸错了会装不上(按危险程度):**

1. **HOLE_D 最致命**:孔径小 0.5 mm 螺栓就完全穿不过,大 0.8 mm 则没有咬合。打印前务必用卡尺量原孔,或按 4.0 mm 打印后铰孔配作。
2. **孔位(HOLE_FROM_LEFT/TOP)+ VERT_W**:两者误差会累计到孔的绝对位置,偏差 >0.5 mm 就可能对不上配合件的螺孔。
3. **VERT_W / HORIZ_T**:若竖臂需插入卡槽,超差 0.5 mm 以上会插不进或过松。
4. **PLATE_T**:若有安装深度(沉槽)要求,厚度错了同样装不上——这是照片唯一给不出的尺寸,必须实测。

另注:箭头所指“断裂处”在拐角,若横臂其实是断掉的残段(原长更长),HORIZ_L 需按配合件实测修正;代码里的 INNER_FILLET 建议保留,可显著降低同处再断的概率。

此正文来自以同一 PROMPT、同一张图片的重跑补齐:首次调用曾结束于空响应体(response.text = null、无 error 记录),页面当时如实标注为「请求失败」。除 HTML 转义外,上文本自 results/C04.json 逐字符照录,不作任何截断、转述或润色。

RAW · glm-5v-turbo ②第 1/1 轮 · finish_reason=stopresults/z-ai__glm-5v-turbo/C04.json 原文逐字 · completion 5082 tok(含推理 3011)· cost $0.0208896
这是基于您提供的图片进行的 3D 建模方案。

### 1. 尺度推断过程

由于无法直接操作图像文件获取精确像素坐标,以下是基于图像视觉比例的标准测量推演过程:

1.  **确立参照系**:
    *   参照物:一元硬币(¥1)。
    *   标准物理尺寸:直径 $D_{coin} = 25.0\text{ mm}$。
2.  **像素测量(模拟读数)**:
    *   在图像编辑软件中量取,假设图像分辨率下:
    *   **硬币直径** ($P_{coin}$):约占 **88 像素 (px)**。
    *   **零件总高度** (垂直段,$P_H$):约占 **105 px**。
    *   **零件总宽度** (水平段,$P_W$):约占 **130 px**。
    *   **零件料厚** (宽度/厚度,$P_T$):约占 **44 px**。
    *   **安装孔直径** ($P_{hole}$):约占 **16 px**。
    *   **孔心位置** (距左边缘 $P_{hx}$, 距上边缘 $P_{hy}$):分别约占 **18 px** 和 **16 px**。
3.  **计算比例系数 (Scale Factor)**:
    *   $$ \text{Ratio} = \frac{25.0\text{ mm}}{88\text{ px}} \approx \mathbf{0.284\text{ mm/px}} $$
4.  **换算实际尺寸 (mm)**:
    *   **总高度**:$105 \times 0.284 \approx \mathbf{29.8\text{ mm}}$ (取整 **30.0 mm**)
    *   **总宽度**:$130 \times 0.284 \approx \mathbf{36.9\text{ mm}}$ (取整 **37.0 mm**)
    *   **料厚**:$44 \times 0.284 \approx \mathbf{12.5\text{ mm}}$
    *   **孔径**:$16 \times 0.284 \approx \mathbf{4.5\text{ mm}}$ (推测为 M4 螺丝过孔或 M5 紧配合孔)
    *   **孔位 X** (距左): $18 \times 0.284 \approx \mathbf{5.1\text{ mm}}$
    *   **孔位 Y** (距上): $16 \times 0.284 \approx \mathbf{4.5\text{ mm}}$
5.  **透视偏差处理**:
    *   图片看似正投影(Orthographic),硬币与零件在同一平面上,无明显近大远小透视变形。
    *   **风险控制**:若拍摄时有微小俯角,垂直高度(30mm)可能会被低估 1-2%,水平宽度影响较小。建模时默认按正投影处理,打印后若发现略小可微调。

---

### 2. 参数化 CadQuery 代码

以下是完整的 CadQuery (OpenSCAD 风格或 Jupyter 风格均可运行) 代码。所有关键尺寸均已提取到顶部常量区。

```python
import cadquery as cq

# ==========================================
# 1. 关键尺寸参数 (Key Dimensions)
# ==========================================
# 外形轮廓尺寸 (单位: mm)
PART_HEIGHT = 30.0      # 垂直段总高度
PART_WIDTH  = 37.0      # 水平段总长度
THICKNESS   = 12.5      # 材料厚度 (垂直/水平臂的宽度)

# 安装孔参数
HOLE_DIAMETER = 4.5     # 孔直径 (建议根据实际螺丝调整,如 M4 用 4.2-4.5, M5 用 5.2)
HOLE_CENTER_X = 5.1     # 孔心距零件最左侧边缘的距离
HOLE_CENTER_Y = 4.5     # 孔心距零件最顶端边缘的距离

# 其他参数
DEPTH = 10.0            # 零件的 Z 轴深度 (垂直于屏幕方向,图片无法测得,需根据实际需求设定)

# ==========================================
# 2. 建模逻辑 (Modeling Logic)
# ==========================================

def create_bracket():
    # 初始化工作平面
    result = (
        cq.Workplane("XY")
        
        # --- 步骤 A: 构建 L 型主体 ---
        # 我们通过绘制两个矩形并合并来构建 L 型
        # 坐标原点 (0,0) 设定在零件的 "外直角" 处 (即左上角)
        
        # 1. 绘制垂直部分 (向下延伸)
        .rect(THICKNESS, PART_HEIGHT, centered=False) 
        # 2. 绘制水平部分 (向右延伸),注意 Y 轴起点要避开已画的部分,或者直接画个大矩形再切
        # 这里采用并集方式:移动工作平面到合适位置画第二个矩形
        .move(THICKNESS, PART_HEIGHT - THICKNESS) # 移动到垂直臂的右下角内侧
        .rect(PART_WIDTH - THICKNESS, THICKNESS, centered=False)
        
        # 将草图拉伸成实体
        .extrude(DEPTH)
        
        # --- 步骤 B: 打孔 ---
        # 定位到孔的位置 (基于外直角原点的偏移)
        # 注意:CadQuery 的孔默认是在面上操作,我们在顶面 (Z轴正面) 操作
        .faces(">Z") 
        .workplane()
        .transformed(offset=(HOLE_CENTER_X, -HOLE_CENTER_Y)) # Y轴负方向是因为通常坐标系向下为负或根据具体情况
        # 修正:如果在 rect(centered=False) 且原点在左上,Y轴正向通常是“向上”或“向下”取决于CAD设置
        # 假设标准 CAD 坐标:Y向上。那么 -HOLE_CENTER_Y 是向下的偏移
        .hole(HOLE_DIAMETER)
    )
    
    return result

# 生成模型
part = create_bracket()

# 可选:导出操作 (如果在本地环境运行)
# cq.exporters.export(part, 'replacement_bracket.step')
```

**代码说明:**
*   **坐标原点**:设定在零件的**左上角外沿**(断裂处指示的角落),这样方便通过 `HOLE_CENTER_X/Y` 直接控制孔的位置。
*   **构建方式**:使用两个矩形的布尔合并(Union)形成 L 型,这比从大方块中减去角落更符合“打印一个替换件”的直观逻辑。
*   **Z轴深度 (`DEPTH`)**:照片是 2D 的,无法得知零件有多厚(比如是 5mm 的板还是 20mm 的块)。代码中将此设为参数,**打印前请务必根据实物安装空间修改此值**(常见值为 5mm, 8mm, 10mm)。

---

### 3. 不确定度区间与关键尺寸分析

基于照片测量的局限性,各尺寸的不确定度区间及重要性如下:

| 尺寸参数 | 推断值 | 不确定度区间 | 重要性分析与后果 |
| :--- | :--- | :--- | :--- |
| **孔直径 (HOLE_DIAMETER)** | **4.5 mm** | **± 0.5 mm** | **🔴 极高 (致命)**<br>如果孔径 < 螺丝直径,螺丝拧不进;如果 > 螺丝太多,会导致松动。**建议**: 若知螺丝规格直接用标准钻头直径(如 M4->4.2mm, M5->5.2mm)。 |
| **孔心位置 (X, Y)** | **5.1, 4.5 mm** | **± 1.5 mm** | **🔴 高 (致命)**<br>这是安装定位基准。如果位置偏了,零件上的孔无法与设备上的螺纹孔对齐,导致**装不上**或强行安装后零件受力弯曲断裂。 |
| **总宽度 (PART_WIDTH)** | **37.0 mm** | **± 2.0 mm** | **🟡 中**<br>如果过长,可能会干涉周边其他零件;如果过短,可能接触不到对面连接点。 |
| **总高度 (PART_HEIGHT)** | **30.0 mm** | **± 2.0 mm** | **🟡 中**<br>同上,主要影响纵向装配空间。 |
| **厚度 (THICKNESS)** | **12.5 mm** | **± 1.5 mm** | **🟢 低**<br>只要不太离谱(比如变成 5mm 或 25mm),通常只影响强度,不影响安装。 |

**总结建议:**
**最容易导致“装不上”的错误是孔的位置 (X, Y) 和孔的大小。** 如果条件允许,建议先打印一个低填充率的“验证版”,仅测试孔位是否对齐,确认无误后再打印正式高强度版本。
RAW · kimi-k3 ③第 1/1 轮 · finish_reason=stopresults/moonshotai__kimi-k3/C04.json 原文逐字 · completion 17836 tok(含推理 16176)· cost $0.26907
## 1. 尺度推断过程

按显示图 `520 × 400 px` 读;坐标原点在左上,x 向右、y 向下。

- 一元硬币外缘:左 `x=90`,右 `x=150` → `Dx=60 px`;上 `y=272`,下 `y=330` → `Dy=58 px`。  
  硬币应为圆,但 `Dx/Dy = 60/58 = 1.034`,差 `2 px / 59 px ≈ 3.4%`。我取平均直径  
  `Dc = (60 + 58)/2 = 59 px`。已知 `Dc = 25.0 mm`,所以  
  `s = 25.0 / 59 = 0.4237288 mm/px`。  
  若坚持硬币正圆且横向 `60 px` 更可信,全部长度只会差 `60/59 - 1 = 1.69%`,我把它放进后面的不确定度,而不是改名义值。

- 零件外轮廓,黑边约 `2 px`:左面 `x=260`,立板右面/内角 `x=294`,横臂右端 `x=375`;上面 `y=120`,横臂下沿 `y=146`,立板底面 `y=193`。  
  因此:  
  立板宽 `= 294-260 = 34 px = 14.4068 mm`;  
  总高 `= 193-120 = 73 px = 30.9220 mm`;  
  横臂长,从立板右面到右端 `= 375-294 = 81 px = 34.3220 mm`;  
  横臂高 `= 146-120 = 26 px = 11.0169 mm`;  
  外轮廓总长 `= 375-260 = 115 px = 48.7288 mm`;  
  横臂以下立板段 `= 193-146 = 47 px = 19.9153 mm`。

- 小圆孔:圆外框约 `x=270→282`、`y=128→140`,中心 `(276,134)`;黑线线中心直径约 `11 px`,外缘约 `12 px`,内亮区约 `9 px`。按线中心取孔径:  
  孔心距左面 `= 276-260 = 16 px = 6.7797 mm`;  
  孔心距上面 `= 134-120 = 14 px = 5.9322 mm`;  
  孔径 `= 11 px = 4.6610 mm`,代码中取 `4.7 mm`,并注明要按真实销/螺钉改。

- 断裂标注红线约 `x=300`:距左面 `40 px = 16.9492 mm`,约比立板右面 `x=294` 靠右 `6 px = 2.5424 mm`。它在零件上方,是标注线不是实体边,所以只用来指示根部断裂区,不把 `x=300` 当轮廓边。

- 透视处理:零件与硬币中心相距约 `245 px ≈ 104 mm`,单个硬币不能解出深度差;若零件不在硬币同一平面,比例会变。这里零件边线基本横平竖直、硬币近圆,`Dx-Dy=2 px`,所以不做单应矩阵修正,采用平均币径,并给长度加保守余量:边线拾取约 `√2 × 1 px × s ≈ 0.60 mm`,再叠加约 `2%` 的不同平面/透视余量。若真实照片透视明显,应重拍:相机正对零件平面,硬币紧贴零件同一高度。

## 2. 参数化 CadQuery 代码

```python
import cadquery as cq

# ===== named parameters, mm =====
leg_w = 14.4            # vertical lug width, left face to right face
leg_h = 30.9            # total height, top edge to bottom edge
arm_len = 34.3          # horizontal arm length, from lug right face to free tip
arm_h = 11.0            # horizontal arm height in the image plane
plate_t = 6.0           # ASSUMED out-of-plane thickness; NOT visible, measure fracture face
hole_d = 4.7            # through-hole diameter; set to pin/screw + clearance if known
hole_x = 6.8            # hole center from left outer face
hole_y_from_top = 5.9   # hole center downward from top outer edge
overcut = 1.0           # through-cut margin

# ===== derived =====
hole_y = leg_h - hole_y_from_top

profile = (
    cq.Workplane("XY")
    .moveTo(0, 0)
    .lineTo(leg_w, 0)
    .lineTo(leg_w, leg_h - arm_h)
    .lineTo(leg_w + arm_len, leg_h - arm_h)
    .lineTo(leg_w + arm_len, leg_h)
    .lineTo(0, leg_h)
    .close()
    .extrude(plate_t)
)

hole_tool = (
    cq.Workplane("XY")
    .pushPoints([(hole_x, hole_y)])
    .circle(hole_d / 2.0)
    .extrude(plate_t + 2.0 * overcut)
    .translate((0, 0, -overcut))
)

result = profile.cut(hole_tool)

# cq.exporters.export(result, "replacement_l_plate.stl")
```

## 3. 关键尺寸不确定度与装配风险

| 参数 | 名义值 | 不确定度 | 说明 |
|---|---:|---:|---|
| `leg_w` | 14.4 mm | ±0.8 mm | 立板宽度;边线拾取和比例主导 |
| `leg_h` | 30.9 mm | ±1.0 mm | 总高;长尺寸受比例/透视余量影响更大 |
| `arm_len` | 34.3 mm | ±1.1 mm | 横臂长度;若有对接面,需按原件端面复核 |
| `arm_h` | 11.0 mm | ±0.8 mm | 横臂高度/根部宽度 |
| `plate_t` | 6.0 mm | ±3.0 mm | 照片不可见,纯占位;必须用断口/原件实测替换 |
| `hole_d` | 4.7 mm | ±0.8 mm | 由圆孔线中心估;若为间隙孔,应改成“销/螺钉径 + 0.2~0.4 mm”或打印后铰孔 |
| `hole_x` | 6.8 mm | ±0.7 mm | 孔心到左基准面 |
| `hole_y_from_top` | 5.9 mm | ±0.7 mm | 孔心到上基准边 |

最会导致“装不上”的是孔位:`hole_x` / `hole_y_from_top`。外轮廓错一点常可靠间隙、打磨或弹性变形吸收;孔心偏了,销/螺栓直接对不上。并列关键的是 `hole_d`:若它是紧配孔或螺钉孔,孔小了会直接穿不过;若该孔原本压配一个销,盲目加大也会松。若这个零件要插进某个槽,则 `plate_t` 也会变成装不进/太松的关键尺寸,但它不能从这张图推出,必须量断口。
得分明细 ① · stealth/ox-alpha(score 字段逐项)
维度(score 字段原名)满分实测得分得分说明(如实)
尺寸精度_近似未评分35null回复含带像素换算的尺寸推断(如总长 47.1mm、总高 30.8mm),但本机 cadquery/OCP 无法 import、维度退化为静态检查、未真实执行几何建模——如实留 null,不按回复文本自行估算给分。
使用参照物251.0输出含完整像素证据链:硬币标定 60 px → 0.4167 mm/px → 各尺寸逐一换算并写出中间数字(另附「47.1 ≈ 12.9+34.2 ✓」自检),满足判据记 1。(首跑空响应时此项曾记 0.0,重跑后按真实回复重算。)
参数化程度_近似近似判定201.0代码顶部以命名参数覆盖全部关键尺寸(VERT_W / VERT_H / HORIZ_L / HORIZ_T / PLATE_T / HOLE_D 等),静态检查判得 1;改参联动验证因 cadquery 环境限制未能真实执行(近似判定)。
可执行与成形未评分20null回复包含完整 CadQuery 代码,但 cadquery 在本机 Python 3.14 无法可靠 import,代码未被执行、STL 成形验证未进行,故留 null。

脚本四维均由打分脚本计算(judge 不参与),数值逐一取自 results/C04.json 的 score 字段,页面不作推算汇总:近似判定= 静态近似而非真实几何验证;未评分= null,缺失未被包装成 0 或近似值。score.note 原文:「本机 cadquery/OCP 在当前 Python 版本上无法 import,本维度退化为静态代码检查,未真实执行几何建模」;flags:approximate_static_check;score_error:null(打分过程本身无报错)。GLM-5V 与 Kimi K3 两份结果文件中的 score.note、flags、limitations 与上述逐字一致,score_error 同为 null。

三模型分数对比 SCORES · 同一维度并排(数值为各 results/*.json 的 score 字段原文;配色见图例)
使用参照物轴 0 – 1 · ×25 = 百分制
1.0
1.0
1.0
参数化程度_近似近似判定轴 0 – 1 · ×20 = 百分制
1.0
1.0
0.0
尺寸精度_近似未评分三模型均为 null
null · 未评分(需 cadquery 真实执行)
null · 未评分(需 cadquery 真实执行)
null · 未评分(需 cadquery 真实执行)
可执行与成形未评分三模型均为 null
null · 未评分(需 cadquery 真实执行)
null · 未评分(需 cadquery 真实执行)
null · 未评分(需 cadquery 真实执行)
  • · ox-alpha 使用参照物=1.0 · 参数化程度_近似=1.0:输出含完整像素证据链(硬币标定 60 px → 0.4167 mm/px → 各尺寸换算,并附「47.1 ≈ 12.9+34.2 ✓」自检),代码顶部命名参数覆盖全部关键尺寸;两项均为重跑补齐后按真实回复重算的结果(首跑空响应时同为 0.0)。(其像素测量与 manifest 真值对照:总长推得 47.1mm、总高推得 30.8mm,真值 48 / 30。)
  • · GLM-5V 使用参照物=1.0:输出含完整「像素读数 → mm/px → 尺寸换算」链,形式判据通过;但正文自述「无法直接操作图像文件获取精确像素坐标」,其像素数字是自称的模拟读数(如推断总宽 37.0mm——真值 48mm)。该维度按判据量的是「有没有留下像素证据链」,不保证读数真实性。
  • · Kimi K3 参数化程度_近似=0.0:为脚本静态检查的真实输出;而其回复中的代码顶部实际以命名参数列出了 leg_w / leg_h / arm_len 等。两处事实并存,页面按 JSON 原值呈现、不作修正。(其像素测量与 manifest 真值对照:外轮廓总长推得 48.73mm、总高推得 30.92mm,真值 48 / 30。)
  • · 两个几何维度(尺寸精度_近似 / 可执行与成形)在三份结果文件中均为 null——如实留空,不补数字。
方法论局限 METHOD CAVEAT(沿用全站对比页措辞)

三个模型的调用方式相同(同一套 run_batch.py 风格的 OpenRouter chat/completions 调用),但 stealth/ox-alpha 是强制深度推理的 stealth 模型,glm-5v-turbo 与 kimi-k3 的推理行为未特别配置——输出风格与推理深度可能天然不同。这是解读对比结果时要注意的局限,不是哪一方「作弊」。本案例恰好可见一斑:三份 usage 对推理开销的记录并不对称——kimi-k3 记 reasoning_tokens 16176、glm-5v-turbo 记 3011,ox-alpha 则记 0(completion 8149 tok 中未拆分出推理用量)。

怎么读这个结果 HOW TO READ

同一张图、同一段 PROMPT、同一套打分脚本,三个模型给出三种结局:ox-alpha 给出唯一附中间数字自检的证据链(47.1 ≈ 12.9+34.2 ✓),使用参照物与参数化程度两项均得 1.0,两个几何维度随环境限制如实留 null;GLM-5V 给出了形式完整的证据链但自认读数系「模拟」,照拿 使用参照物=1.0;Kimi K3 给出三者中最细的实测粒度、换算值与真值高度接近(外轮廓总长推得 48.73mm vs 真值 48),却在参数化程度静态检查上记 0。这正是本页坚持的呈现原则:宁缺毋假——null 不补数、异常不美化、分数只报告脚本真实算出的值(既包括首跑空响应时的如实披露,也包括重跑补齐后的如实更新)。要得到「尺寸精度 / 可执行与成形」的有效成绩,需修复本机 cadquery 依赖后重跑 run_batch + score。