> **本文回答**：自动成图 = 把"任意一个绘图需求"按 **拆解 → 图层 → 按层建实体 → 标注 → 撤销组 + 批量提交** 五步走的工程范式。本页只讲**通用思路**——具体实体 API、几何工具、视图缩放等只链接不复述。

## 一、自动成图心智模型

```mermaid
flowchart LR
    Req["需求<br/>(自然语言/规格)"] --> Decompose["拆解<br/>外形/孔/标注/文字/填充/装饰"]
    Decompose --> LayerPlan["图层规划<br/>OUTLINE/HOLE/CENTER/DIM/HATCH/TEXT"]
    LayerPlan --> Build["按层逐组建实体<br/>setCurrentLayer + setDefaults"]
    Build --> Anno["标注/中心线/引线/文字"]
    Anno --> Commit["addEntities + regen + zoomExtents<br/>包在一组撤销里"]
```

五步骨架（可直接套用）：

```js
async function autoDraw(spec) {
  Engine.startUndoRecord('AUTO_DRAW');                // 整张图作为一组撤销
  try {
    ensureLayers();                                   // ① 图层
    const entities = [];
    entities.push(...buildOutline(spec));             // ② 外形
    entities.push(...buildFeatures(spec));            // ③ 孔/特征/阵列
    entities.push(...buildHatches(spec));             // ④ 填充
    entities.push(...buildAnnotations(spec));         // ⑤ 标注/文字/引线
    Engine.addEntities(entities);                     // 一次性提交
    Engine.regen();
    Engine.zoomExtents();
  } finally {
    Engine.endUndoRecord();                           // 异常也保证关组
  }
}
```

API 来源：[undo/group](../undo/group.md)、[entity/create-entities](../entity/create-entities.md)、[view/zoom](../view/zoom.md)。

## 二、需求拆解决策树（关键词 → 实体）

任意需求都先按下表把"自然语言"映射到"图形要素 / 实体类":

| 需求中出现 | 图形要素 | 用什么实体 | 链接 |
|---|---|---|---|
| 矩形 / 板 / 框 | 外形 | `PolylineEnt`（闭合，可带 bulge 圆角） | [entity/polyline](../entity/polyline.md) |
| 圆 / 通孔 / Φ X | 孔 / 特征 | `CircleEnt` | [entity/line-arc-circle](../entity/line-arc-circle.md) |
| 弧 / 圆角 R / 倒角 | 外形 | `PolylineEnt` 带 bulge / `ArcEnt` | [entity/polyline](../entity/polyline.md)、[entity/line-arc-circle](../entity/line-arc-circle.md) |
| 中心 / 周围阵列 / N 个 | 阵列 | 循环 + `Point2D` 计算 | 见本页第五节 |
| 标尺寸 / 标注 / 公差 | 标注 | `LinearDimensionEnt` 等 7 类 | [entity/dimension-mleader](../entity/dimension-mleader.md) |
| 文字 / 标签 / 注释 | 文字 | `TextEnt` / `MTextEnt` | [entity/text-mtext](../entity/text-mtext.md) |
| 填充 / 阴影 / 图案 | 填充 | `HatchEnt` + `setLoops` | [entity/hatch-solid](../entity/hatch-solid.md) |
| 实色填充（箭头 / 三角 / 四边） | 填充 | `SolidEnt` | [entity/hatch-solid](../entity/hatch-solid.md) |
| 重复部件 / 符号 / 出现 ≥ 2 次 | 块 | `doc.blocks.add` + `InsertEnt` | [entity/block-insert](../entity/block-insert.md) |
| 引线 / 注释指向 | 引线 | `MLeaderEnt` | [entity/dimension-mleader](../entity/dimension-mleader.md) |
| 曲线 / 函数图 / 等高线 | 路径 | `PolylineEnt` 折线 / `SplineEnt` | [entity/polyline](../entity/polyline.md)、[entity/spline-ellipse](../entity/spline-ellipse.md) |
| 网格 / 刻度 | 装饰 | `LineEnt` 循环（GRID 图层） | [entity/line-arc-circle](../entity/line-arc-circle.md) |
| 中心线 / 虚线 / 隐藏线 | 装饰 | `LineEnt` + `lineType='CENTER'/'HIDDEN'` | [property/color-linetype](../property/color-linetype.md) |
| 椭圆 / 椭圆弧 | 外形 | `EllipseEnt`（可设 `startAngle/endAngle`） | [entity/spline-ellipse](../entity/spline-ellipse.md) |
| 图像 / 位图 | 引用 | `ImageRefEnt` + `ImageSource` | [entity/image](../entity/image.md) |
| 已有 SVG | 导入 | `IMPORTSVG` 命令 | [insert/svg-import](../insert/svg-import.md) |

> 把映射结果**写进注释**或 `writeMessage(...)`（vjcad 顶层调试通道，详见 [trouble/overview](../trouble/overview.md)），让用户能复核 AI 的拆解假设是否正确（例如"周围 4 个孔" = 四角 vs 四边中点）。

## 三、图层规划（通用方案）

不论画什么，先按用途分图层。颜色优先用 ACI 索引（1~7、8 灰、256 ByLayer），保持深 / 浅主题兼容。

| 用途 | 建议名 | ACI | 线型 |
|---|---|---|---|
| 外轮廓 | `OUTLINE` | 7（白/黑随主题） | `CONTINUOUS` |
| 孔 / 切口 | `HOLE` | 1（红） | `CONTINUOUS` |
| 中心线 | `CENTER` | 4（青） | `CENTER` |
| 隐藏线 | `HIDDEN` | 2（黄） | `HIDDEN` |
| 标注 | `DIM` | 3（绿） | `CONTINUOUS` |
| 文字 / 标签 | `TEXT` | 7 | `CONTINUOUS` |
| 填充 | `HATCH` | 8（深灰） | `CONTINUOUS` |
| 网格 / 辅助 | `GRID` | 8 | `CONTINUOUS` |
| 装饰 / 不打印 | `AUX` | 8 | `CONTINUOUS` |

**确保图层存在**（幂等）：

```js
function ensureLayers() {
  const defs = [
    { name: 'OUTLINE', color: 7, lineType: 'CONTINUOUS' },
    { name: 'HOLE',    color: 1, lineType: 'CONTINUOUS' },
    { name: 'CENTER',  color: 4, lineType: 'CENTER'     },
    { name: 'HIDDEN',  color: 2, lineType: 'HIDDEN'     },
    { name: 'DIM',     color: 3, lineType: 'CONTINUOUS' },
    { name: 'TEXT',    color: 7, lineType: 'CONTINUOUS' },
    { name: 'HATCH',   color: 8, lineType: 'CONTINUOUS' },
    { name: 'GRID',    color: 8, lineType: 'CONTINUOUS' }
  ];
  for (const d of defs) {
    if (!Engine.currentDoc.layers.itemByName(d.name)) {
      Engine.createLayer(d.name, d);
    }
  }
}
```

**切到当前图层 + 用 `setDefaults` 让新建实体落到这一层**：

```js
Engine.setCurrentLayer('OUTLINE');         // 切 CLAYER
Engine.CECOLOR = 256;                      // ByLayer：颜色随层
Engine.CELTYPE = 'ByLayer';                // 线型随层

const outline = new PolylineEnt();
outline.setPoints([[0, 0], [80, 0], [80, 60], [0, 60]]);
outline.isClosed = true;
outline.setDefaults();                     // 应用 CECOLOR / CELTYPE / CLAYER
```

API 来源：[layer/create-switch](../layer/create-switch.md)、[layer/layer-states](../layer/layer-states.md)、[property/set-defaults](../property/set-defaults.md)、[property/color-linetype](../property/color-linetype.md)。

> 想让"图层颜色 / 线型"自动覆盖所有实体：把 `Engine.CECOLOR = 256`（ByLayer）、`Engine.CELTYPE = 'ByLayer'`，再 `setDefaults()`。后续只改图层颜色 / 线型，所有该层实体一起变。

## 四、实体创建套路（自动成图最常用范式）

每条范式都是 **`new XxxEnt(...) → 设置参数 → setDefaults()` → 推入 `entities`**。详细字段见各 entity 子页。

### 4.1 直线 `LineEnt`（网格 / 刻度 / 引线）

```js
const ln = new LineEnt([x1, y1], [x2, y2]);
ln.setDefaults();
entities.push(ln);
```

批量画线（如网格）：循环 push，一次性 `Engine.addEntities(arr)`，**不要在循环里逐个 add 也不要循环里 regen**。详见 [entity/line-arc-circle](../entity/line-arc-circle.md)。

### 4.2 圆 / 弧（孔 / 圆角）

```js
const c = new CircleEnt([cx, cy], r);
c.setDefaults();

const arc = new ArcEnt([cx, cy], r, startAngRad, endAngRad);   // 弧度，不是度
arc.setDefaults();

// 三点定弧（已知端点 + 中间点）——参数必须是 Point2D，传 [x,y] 数组会得 NaN
const arc2 = new ArcEnt();
arc2.initBy3Pt(new Point2D(0, 0), new Point2D(50, 50), new Point2D(100, 0));
arc2.setDefaults();
```

详见 [entity/line-arc-circle](../entity/line-arc-circle.md)。

### 4.3 多段线 `PolylineEnt`（外形 / 折线 / 曲线拟合）

**简单矩形 / 多边形（无圆角）**：

```js
const pl = new PolylineEnt();
pl.setPoints([[0, 0], [80, 0], [80, 60], [0, 60]]);
pl.isClosed = true;
pl.setDefaults();
```

**圆角矩形（用 bulge 表示 90° 弧）**——`bulge = tan(π/8) ≈ 0.4142` 表 90° 弧；每个直角拐点替换为 2 个切点：

```js
const r = 5, w = 80, h = 60;
const minX = -w/2, maxX = w/2, minY = -h/2, maxY = h/2;
const bulge = Math.tan(Math.PI / 8);

const rect = new PolylineEnt();
rect.bulgePoints.add(new BulgePoint(new Point2D(minX + r, minY), 0));
rect.bulgePoints.add(new BulgePoint(new Point2D(maxX - r, minY), bulge));
rect.bulgePoints.add(new BulgePoint(new Point2D(maxX, minY + r), 0));
rect.bulgePoints.add(new BulgePoint(new Point2D(maxX, maxY - r), bulge));
rect.bulgePoints.add(new BulgePoint(new Point2D(maxX - r, maxY), 0));
rect.bulgePoints.add(new BulgePoint(new Point2D(minX + r, maxY), bulge));
rect.bulgePoints.add(new BulgePoint(new Point2D(minX, maxY - r), 0));
rect.bulgePoints.add(new BulgePoint(new Point2D(minX, minY + r), bulge));
rect.isClosed = true;
rect.setDefaults();
```

**正多边形 / 函数曲线**——逐点 `addVertex`：

```js
const pl = new PolylineEnt();
const N = 200;
for (let i = 0; i <= N; i++) {
  const x = -10 + (20 * i) / N;
  pl.addVertex([x, Math.sin(x)]);
}
pl.isClosed = false;
pl.setDefaults();
```

详见 [entity/polyline](../entity/polyline.md)。

### 4.4 文字 `TextEnt` / `MTextEnt`（标签 / 注释）

```js
// 单行
const t = new TextEnt();
t.insertionPoint = [x, y];
t.text = '说明文字';
t.height = 8;
t.styleName = 'simkai';     // 见 setup/fonts；默认字体可省
t.setDefaults();

// 多行
const mt = new MTextEnt();
mt.insertionPoint = [x, y];
mt.text = '第一行\n第二行';
mt.height = 10;
mt.setDefaults();
```

字体 / 样式预先配在 `MainView` 构造配置的 `fonts` 数组，详见 [setup/fonts](../setup/fonts.md)、[entity/text-mtext](../entity/text-mtext.md)。

### 4.5 标注（按需求选 7 类）

| 需求里说的 | 用 | 关键参数 |
|---|---|---|
| 长 / 宽 / 距离 | `LinearDimensionEnt` | `(p1, p2, textPos, angleRad)` |
| 倾斜的尺寸 | `AlignedDimensionEnt` | `(p1, p2, textPos)` |
| 半径 R | `RadialDimensionEnt` | `(center, ptOnCircle, leaderLen)` |
| 直径 Φ | `DiametricDimensionEnt` | `(p1, p2)` 直径两端 |
| 角度 ° | `AngleDimensionEnt` | `(vertex, p1, p2, arcRadius)` |
| 弧长 | `ArcDimensionEnt` | `(center, p1, p2, textPos)` |
| X / Y 坐标 | `OrdinateDimensionEnt` | `(origin, pt, textPos, 'x'/'y'/'xy')` |

```js
import { Point2D } from 'vjcad';

const dim = new LinearDimensionEnt(
  new Point2D(0, 0),
  new Point2D(80, 0),
  new Point2D(40, -15),    // 文字位置（决定标注线偏移方向 / 距离）
  0                         // 弧度，0 = 水平测量
);
dim.setDefaults();
```

**层叠避让**：多条平行标注在**构造时**按递增 `step` 给不同的第三参（尺寸线位置点），建议 `step ≥ 字高 × 2`：

```js
const step = 15;
const spans = [[0, 80], [0, 200]];                 // 每条标注的测量起止 x
const dims = spans.map(([x1, x2], i) => new LinearDimensionEnt(
  new Point2D(x1, 0),
  new Point2D(x2, 0),
  new Point2D((x1 + x2) / 2, -15 - i * step),     // 尺寸线逐条下移
  0
));
```

> 不要事后 `move` 标注来错开：标注族的 `move` 只收 `Point2D`（传 `[x,y]` 得 NaN），而且会把测量点 `startPoint/endPoint` 一起平移，标注就不再量原几何。

详见 [entity/dimension-mleader](../entity/dimension-mleader.md)。

### 4.6 填充 `HatchEnt`（图案）/ `SolidEnt`（实色）

**图案填充**——边界用 `Edge / Edges + EdgeType.Polyline + bulgePoints`：

```js
import { HatchEnt, PolylineEnt, Edge, Edges, EdgeType } from 'vjcad';

const boundary = new PolylineEnt();
boundary.setPoints([[0, 0], [80, 0], [80, 60], [0, 60]]);
boundary.isClosed = true;
boundary.setDefaults();

const hatch = new HatchEnt();
hatch.patternName = 'ANSI31';

const edge = new Edge();
edge.edgeType = EdgeType.Polyline;
edge.bulgePoints = boundary.bulgePoints.clone();   // 必须 clone
const edges = new Edges();
edges.add(edge);
hatch.setLoops(edges);

hatch.setDefaults();
entities.push(boundary, hatch);
```

**实色填充（三角 / 四边 / 箭头）**——`SolidEnt(p1, p2, p3, p4)` 顺序按四边形（三角让 `p3 === p4`）：

```js
const solid = new SolidEnt([0, 0], [10, 0], [10, 8], [0, 8]);
solid.setDefaults();
```

详见 [entity/hatch-solid](../entity/hatch-solid.md)。

### 4.7 块 `InsertEnt`（同形状出现 ≥ 2 次时）

判定：**同一形状要出现 ≥ 2 次**就用块；只出现 1 次直接画，不必搞块。

```js
const doc = Engine.currentDoc;
const blockName = 'PIN';

let blockDef = doc.blocks.itemByName(blockName);
if (!blockDef) {
  blockDef = doc.blocks.add(blockName);
  blockDef.basePoint = [0, 0];
  const c = new CircleEnt([0, 0], 4);
  c.setDefaults();
  blockDef.addEntity(c);                    // ⚠️ 块内实体的 setDefaults 不能省
}

// 复用：N 个孔 → N 个 InsertEnt
const ins = new InsertEnt();
ins.blockId        = blockDef.blockId;       // 不是 blockName 字符串
ins.insertionPoint = [10, 10];
ins.scaleFactor    = 1;                       // 只有统一缩放；无 xScaleFactor / yScaleFactor
ins.rotation       = 0;                       // 弧度
ins.setDefaults();
entities.push(ins);
```

属性文字（`tag` 占位 → 插入时填值）、计数命令 `COUNTBLOCK`、替换命令 `REPLACEBLOCK` 见 [entity/block-insert](../entity/block-insert.md)。

### 4.8 引线 `MLeaderEnt`（指向标注）

```js
import { MLeaderEnt, MLeaderContentType, Point2D } from 'vjcad';

const ml = new MLeaderEnt();
ml.contentType  = MLeaderContentType.MText;
ml.textContent  = '说明';
ml.textPosition = new Point2D(textX, textY);
ml.textHeight   = 6;
ml.addLeaderLine(new Point2D(arrowX, arrowY));   // 箭头端
ml.setDefaults();
```

详见 [entity/dimension-mleader](../entity/dimension-mleader.md)。

### 4.9 样条 `SplineEnt`（光滑曲线）

```js
const sp = new SplineEnt();
sp.setControlPoints([[0, 0], [20, 30], [60, 30], [80, 0]]);
sp.setDefaults();
```

详见 [entity/spline-ellipse](../entity/spline-ellipse.md)。

## 五、阵列 / 对称 / 等分（通用算法）

只是数学公式，无新 API；用前面的实体范式 + 循环。

**矩形阵列**：

```js
for (let i = 0; i < cols; i++) {
  for (let j = 0; j < rows; j++) {
    entities.push(makeOne([ox + i * dx, oy + j * dy]));
  }
}
```

**圆形阵列**（绕中心 N 等分）：

```js
for (let i = 0; i < n; i++) {
  const a = (i * 2 * Math.PI) / n;
  entities.push(makeOne([cx + r * Math.cos(a), cy + r * Math.sin(a)]));
}
```

**矩形四角孔**（最常见）：

```js
const pad = 8;
[[pad, pad], [w-pad, pad], [w-pad, h-pad], [pad, h-pad]]
  .forEach(([cx, cy]) => entities.push(makeHole([cx, cy])));
```

**镜像复制**（先建一半，再 mirror 出另一半）：

```js
const half = buildHalf();
const mirrored = half.map(e => {
  const c = e.clone();
  c.mirror(new Point2D(0, -1), new Point2D(0, 1));   // 关于 X 轴
  return c;
});
entities.push(...half, ...mirrored);
```

**等距等分**（坐标轴刻度 / 折线段）：

```js
const N = 20;
for (let i = 0; i <= N; i++) {
  const t = i / N;
  const x = x0 + (x1 - x0) * t;
  // 在 x 处画刻度...
}
```

API 来源：[edit/move-copy](../edit/move-copy.md)、[edit/mirror](../edit/mirror.md)、[geometry/point-bounds](../geometry/point-bounds.md)。

## 六、撤销组 + 批量提交（必做）

自动成图必须把整张图作为**一组撤销**——否则用户按一次 Ctrl+Z 只能退掉最后一个实体。

```js
Engine.startUndoRecord('AUTO_DRAW_PLATE');     // 描述会显示在历史 / tooltip
try {
  // …构造 entities…
  Engine.addEntities(entities);                 // 一次性提交
} finally {
  Engine.endUndoRecord();                       // 异常也要关组
}

Engine.regen();                                 // 渲染一次（不要在循环里调）
Engine.zoomExtents();                           // 视图收尾一次
```

> 嵌套安全：`Engine.startUndoRecord` 是引用计数，子函数里再调一次也只算一组。详见 [undo/group](../undo/group.md)。

**实体数量极大（千级）**：再加 `eventManager.suspendEvents` 提速：

```js
Engine.startUndoRecord('BIG');
Engine.eventManager.suspendEvents();
try {
  for (let i = 0; i < 5000; i++) entities.push(makeOne(i));
  Engine.addEntities(entities);
} finally {
  Engine.eventManager.resumeEvents();
  Engine.endUndoRecord();
}
Engine.regen();
Engine.zoomExtents();
```

API 来源：[undo/group](../undo/group.md)、[event/listen](../event/listen.md)。

## 七、收尾 & 验证

收尾固定四步：

1. `Engine.regen()`——重新渲染一次（图层 / 线型变了用 `Engine.regen(true)` 强制刷新）。
2. `Engine.zoomExtents()`——或 `Engine.zoomToEntities(entities)` / `Engine.zoomToFit(entities)` 聚焦到本次绘制的范围（无 `zoomToBounds`；缩放到矩形用 `zoomExtents(undefined,{wcsBounds:[...]})`）。
3. 可选 `message.success('已生成 ' + entities.length + ' 个实体')`（`message` 是 vjcad 顶层导出的提示通道）反馈用户，详见 [ui/dialogs](../ui/dialogs.md)。
4. 可选返回 `entities` / 一些"句柄实体"，便于调用方继续操作（如再次 mirror、再标注、做选中高亮）。

API 来源：[view/zoom](../view/zoom.md)、[view/pan-redraw](../view/pan-redraw.md)、[ui/dialogs](../ui/dialogs.md)。

## 八、综合红旗

| # | 红旗 | 描述 / 修复 |
|---|---|---|
| 1 | 在 `cadView.onLoad()` 之前调 `autoDraw` | `Engine` 还没装好；先 `await cadView.onLoad()` 再画 |
| 2 | 没有 `setDefaults()` | 实体不吸 `Engine.CECOLOR / CELTYPE / CLAYER`，颜色 / 图层错乱 |
| 3 | `setDefaults` 之后才 `setCurrentLayer` | 顺序倒了；先切层再 `setDefaults` |
| 4 | 没用 `startUndoRecord / endUndoRecord` | 用户撤销体验割裂，一次只退一个 |
| 5 | 没用 `try/finally` 关组 | 任意异常 → 撤销组永远没关 → 后续操作全归到这个组 |
| 6 | 循环里 `regen` / `zoomExtents` | 卡顿 / 视图来回跳；只在批量结束后调一次 |
| 7 | `addEntities` 在循环里逐个调 | 应收集到数组一次性 `Engine.addEntities(arr)` |
| 8 | 用块但忘 `doc.blocks.add` 直接 `new InsertEnt()` | 块定义不存在；先 `add` 或 `itemByName` 拿到 `blockDef` |
| 9 | `ins.blockId = blockName`（字符串） | 错；要 `ins.blockId = blockDef.blockId` |
| 10 | `Hatch` 边界点直接引用不 clone | `bulgePoints.clone()` 不能省；回路由 `hatch.setLoops()` 自动闭合（`Edge` 无 `isClosed`），边界多段线的 `isClosed` 只影响轮廓线本身 |
| 11 | `lineType: 'CENTER'` 但项目没加载 CENTER 线型 | 显示成实线；自定义线型时先用 LineType 管理器加载，详见 [property/color-linetype](../property/color-linetype.md) |
| 12 | 标注 `LinearDimensionEnt(...)` 第四参传度数 | 实际是**弧度**，用 `Math.PI/2` 表示 90° |
| 13 | `MLeaderEnt` 没设 `textPosition` 或 `addLeaderLine` | 引线渲染不出 |
| 14 | 自然语言"周围 4 个孔"理解为四角 vs 四边中点 | 没有上下文时**默认四角**，并把假设用 `writeMessage(...)` 输出让用户复核 |
| 15 | 多条平行标注重叠 | 构造时按 `step` 递增第三参（尺寸线位置，≥ 字高 × 2），别事后 `move` 标注 |
| 16 | 颜色想要 RGB 直接 `ent.color = 0xFF8000` | 应加标记位 `0x1000000 + 0xFF8000`，或用 `ColorConverter.createRgbColorIndexFromHexStr('#FF8000')` |
| 17 | 把 `mirror([0, 0], [1, 0])` 当作"沿 X 轴" | 是"过点 (0,0) 和 (1,0) 的镜像线"，就是 X 轴；OK，但理解为"两点定线"更准确 |
| 18 | 调 `clone()` 后忘了 `Engine.addEntities` | 副本只在内存里，没进图纸 |

## 九、源约束（反编造）

- 所有实体类、构造签名、字段都必须能在 [vjcad skill 实体页](../entity/overview.md)、[edit/](../edit/overview.md)、[property/](../property/overview.md)、[layer/](../layer/overview.md) 或对应 `vjcad/example/*` 文件里找到。**不存在的方法不要捏造**。
- 自然语言"四角孔" → "四角"是经验法则，但**写进代码前先用 `writeMessage(...)` 把假设说出来**，让用户能复核。
- 颜色优先 ACI 索引（`1~7` 标准色 / `256` ByLayer）；要 RGB 真彩色时用 `ColorConverter.createRgbColorIndex / createRgbColorIndexFromHexStr / createRgbColorIndexFromComponents`，详见 [property/color-linetype](../property/color-linetype.md)。
- 字段命名歧义（如 `lineType` vs `linetypeName`、`viewMode` vs `viewerMode`、`move(dx,dy)` vs `move(from,to)`）按 [trouble/source-conflicts](../trouble/source-conflicts.md) 的策略：**示例代码（runnable）优先**。

## 十、综合示例索引

下面 4 个示例是把本页"五步骨架"贴到不同复杂度的真实需求上，按复杂度递增——读完本页再看示例，能直接对照"哪一步对应哪几行代码"：

| # | 示例 | 复杂度 | 主要难点 | 文件 |
|---|---|---|---|---|
| 1 | 80×60 圆角板 + 5 孔 + 标注 | 简单 | 圆角矩形 bulge、角孔与圆角间隙 | [examples/plate-and-cat](examples/plate-and-cat.md)（示例 A） |
| 2 | 可爱小猫（细节丰富） | 中 | 多图层艺术构图、`SolidEnt` 三角、`HatchEnt` 蝴蝶结 | [examples/plate-and-cat](examples/plate-and-cat.md)（示例 B） |
| 3 | DN15 内螺纹黄铜截止阀（剖视 + 侧视） | 中-复杂 | 剖切区 Hatch、螺纹循环、双视图布局 | [examples/valve](examples/valve.md) |
| 4 | 通风过滤装置三视图 | 复杂 | 三视图绝对坐标、四线型混排、链式标注、中文 MText | [examples/ventilation-three-views](examples/ventilation-three-views.md) |

每个示例文件都按以下八段写：① 摘要 → ② 需求拆解（NL → 图层 + 实体清单）→ ③ mermaid 步骤图 → ④ 完整可运行代码（套用本页五步骨架）→ ⑤ 关键技术点 → ⑥ 标注布局规则 → ⑦ 红旗 / 反例 → ⑧ 来源。

> 推荐顺序：先看 [examples/plate-and-cat](examples/plate-and-cat.md) 体会"工程图与艺术图共用同一骨架"，再看 [examples/valve](examples/valve.md) 体会"剖视 + 多视图布局"，最后看 [examples/ventilation-three-views](examples/ventilation-three-views.md) 体会"复杂三视图 + 标注链"。

## 参考（官方文档 MCP）

- 文档：`vjcad/doc/guide/quick-start.md`、`vjcad/doc/entity/index.md`、`vjcad/doc/layer/layers.md`、`vjcad/doc/property/index.md`、`vjcad/doc/undo/index.md`、`vjcad/doc/undo/undo-redo.md`、`vjcad/doc/event/event-usage.md`、`vjcad/doc/view/index.md`
- 示例：`vjcad/example/entity/all/01entities.js`、`vjcad/example/entity/polyline/02rectangle.js`、`vjcad/example/entity/hatch/01create.js`、`vjcad/example/entity/block/01create.js`、`vjcad/example/entity/block/02insert.js`、`vjcad/example/entity/dimension/01linear.js`、`vjcad/example/entity/mleader/01create.js`、`vjcad/example/edit/01move.js`、`vjcad/example/edit/05mirror.js`、`vjcad/example/layer/01create.js`、`vjcad/example/layer/02switch.js`、`vjcad/example/property/01color.js`、`vjcad/example/property/03linetype.js`、`vjcad/example/property/06setdefaults.js`、`vjcad/example/undo/03group.js`、`vjcad/example/undo/04description.js`、`vjcad/example/view/01zoomextents.js`、`vjcad/example/comprehensive/01section.js`
- 内部交叉：[entity/create-entities](../entity/create-entities.md)、[entity/polyline](../entity/polyline.md)、[entity/hatch-solid](../entity/hatch-solid.md)、[entity/block-insert](../entity/block-insert.md)、[entity/dimension-mleader](../entity/dimension-mleader.md)、[entity/text-mtext](../entity/text-mtext.md)、[entity/line-arc-circle](../entity/line-arc-circle.md)、[entity/spline-ellipse](../entity/spline-ellipse.md)、[edit/move-copy](../edit/move-copy.md)、[edit/mirror](../edit/mirror.md)、[layer/create-switch](../layer/create-switch.md)、[layer/layer-states](../layer/layer-states.md)、[property/set-defaults](../property/set-defaults.md)、[property/color-linetype](../property/color-linetype.md)、[undo/group](../undo/group.md)、[event/listen](../event/listen.md)、[view/zoom](../view/zoom.md)、[trouble/source-conflicts](../trouble/source-conflicts.md)
- 综合示例(推荐实现前先看下相关示例)：[examples/plate-and-cat](examples/plate-and-cat.md)、[examples/valve](examples/valve.md)、[examples/ventilation-three-views](examples/ventilation-three-views.md)
