> **本文回答**：内置编辑命令 —— MOVE / COPY / ERASE / MIRROR / OFFSET / SCALE / STRETCH / BREAK / TRIM / EXTEND / FILLET / ARRAY / EXPLODE / DRAWORDER。

## 一、调用

```js
mapcadLayer.executeCommand('MOVE');      // 选集 → 基点 → 目标点
mapcadLayer.executeCommand('COPY');      // 选集 → 基点 → 目标点（可多次重复）
mapcadLayer.executeCommand('MIRROR');    // 选集 → 镜像轴点 1 → 点 2 → 是否删除原件（1.0.1 恒保留原件，见第六节）
mapcadLayer.executeCommand('OFFSET');    // 距离 → 对象 → 侧边
mapcadLayer.executeCommand('SCALE');     // 选集 → 基点 → 比例因子
mapcadLayer.executeCommand('ERASE');     // 选集 → 回车
```

> **注意：没有独立 `ROTATE` 命令**，但 `SCALE` 内嵌旋转分支——比例提示下键入 `R` 进入"指定旋转角度 (度)"交互（选集 → 基点 → `R` → 角度）。纯代码用 `entity.rotate(center, angleRad)`（见 [entity/transform](../entity/transform.md)）。

## 二、命令表

| 命令 | 动作 | 提示流程 |
|---|---|---|
| `MOVE` | 平移 | 选集 → 基点 → 目标点 |
| `COPY` | 复制 | 选集 → 基点 → 目标点（可连续点） |
| `SCALE` | 缩放 | 选集 → 基点 → 比例 |
| `MIRROR` | 镜像 | 选集 → 轴点 1 → 轴点 2 → `Y/N` 删除原件（⚠️ 1.0.1 选 `Y` 也不删，恒保留原件） |
| `OFFSET` | 偏移 | 距离 → 对象 → 侧边点 |
| `STRETCH` | 拉伸 | 框选 → 基点 → 目标点 |
| `BREAK` | 打断 | 对象 → 第一个断点 → 第二个断点 |
| `TRIM` | 修剪 | 参考边 → 要修剪对象 |
| `EXTEND` | 延伸 | 参考边 → 要延伸对象 |
| `FILLET` | 圆角 | 半径 → 两条线 |
| `ARRAY` | 阵列 | 选集 → 类型 `R/P` → 行列数 / 间距（⚠️ 1.0.1 选 `P` 也走矩形阵列） |
| `EXPLODE` | 分解 | 选集（块引用 / **闭合**多段线，filter 限定） → 回车 |
| `DRAWORDER` | 绘制顺序 | 选集 → 按 `opts.action`（front/back/up/down，默认 front） |
| `ERASE` | 删除 | 选集 → 回车 |

## 三、MOVE 示例

```js
// 纯代码（不走命令）——move 签名是 move(from, to) 两个点：
const sel = mapcadLayer.getSelectedEntities();
sel.forEach(e => e.move([0, 0], [100, 50]));   // 位移 (100, 50)

// 命令：
mapcadLayer.executeCommand('MOVE');
// 命令栏："选择要移动的对象 [回车结束]:" → 点选后 Enter
// 命令栏："指定基点:" → 点
// 命令栏："指定目标点:" → 点
```

## 四、COPY 重复模式

`COPY` 命令**天生就是连续模式**：

```js
mapcadLayer.executeCommand('COPY');
// 选择要复制的对象 [回车结束]:
// 指定基点:
// 指定目标点 [回车结束]:   ← 每点一次生成一份，循环直到回车/Esc
```

没有 `M`(多重)/`A`(阵列)/`D`(位移) 关键字——1.0.1 实现里目标点输入就是无限循环，回车结束。要"阵列"效果用 `ARRAY` 命令。

## 五、OFFSET 距离 + 方向

```js
mapcadLayer.executeCommand('OFFSET');
// 指定偏移距离 或 [两点(P)]:
// 选择要偏移的对象 [回车结束]:
// 指定偏移方向的一侧:（在对象的哪一侧生成新对象）
```

关键字：**只有 `P`**（两点拾取距离，代替直接输入数值）。1.0.1 未实现 AutoCAD 的 `T`(通过)/`E`(删除)/`L`(图层) 选项。

支持偏移的实体类型：直线 / 圆弧 / 圆 / 多段线（其它类型 pick 不到）。可连续偏移多个对象，回车结束。

## 六、MIRROR 保留/删除

```js
mapcadLayer.executeCommand('MIRROR');
// 选集 → 轴点 1 → 轴点 2
// "是否删除源对象？[是(Y)/否(N)] <N>:" → 回车
```

> ⚠️ **1.0.1 中 `Y` 分支不可达**：命令判 `getKeyword` 结果 `status === 'keyword'`，而 `getKeyword` 选中关键字时返回的是 `status: 'ok'`——无论答 `Y` 还是 `N`，MIRROR **总是保留原件**、生成镜像副本。要"镜像并删原件"用代码：`um.recordModify(e); e.mirror(p1, p2);`（原地镜像，包在 `beginTransaction/endTransaction` 里可一次撤销）。

## 七、FILLET 圆角

```js
mapcadLayer.executeCommand('FILLET');
// 选择第一个对象 [半径(R)]:
// 选择第二个对象:
```

- `R` 设半径（半径值存模块级变量，会话内下次命令沿用）
- **只对两条直线（LineEnt）有效**——filter 限定 `instanceof LineEnt`，选不到多段线/圆弧
- 1.0.1 未实现 AutoCAD 的 `P`(多段线)/`T`(修剪)/`M`(多个) 选项；**一次命令只做一对线**，做完即结束（`while` 循环只包"选第一对象 + R"阶段）

## 八、ARRAY 两种

```js
mapcadLayer.executeCommand('ARRAY');
// 选集
// 输入阵列类型 [矩形(R)/极坐标(P)] <R>:
```

- 矩形（R）：行数 / 列数 / 行距 / 列距（行列间距支持 `P` 两点拾取）
- 极坐标（P）：中心点 / 项目数 / 填充角度——⚠️ **1.0.1 不可达**：同 MIRROR，命令判 `status === 'keyword'` 而 `getKeyword` 返回 `'ok'`，选 `P` 也走矩形阵列。极坐标阵列用代码：循环 `const c = e.clone(); c.rotate(center, i * step); mapcadLayer.addEntity(c);`（`rotate` 角度为弧度）。

注意：**没有路径（PA）阵列**——1.0.1 只写了 R / P 两种（实际只有 R 生效）。

## 九、EXPLODE 分解

filter 限定只有两类实体能被选中：

- **块引用 `BlockRefEnt`** → 展开为块内实体（`getNestEntities`：子实体 `color===0` 继承引用色、`lineType==='ByBlock'` 继承引用线型、ATTDEF 属性文本被属性值替换、`invisible` 属性定义跳过）
- **闭合 `PolylineEnt`**（`isClosed=true`；开口多段线选不中）→ 顶点逐个连成 **`LineEnt` 直线段**——⚠️ **bulge 弧段被拉直成弦**，不会生成 `ArcEnt`，弧信息丢失

`HatchEnt`、开口多段线、文字、标注等**均不可分解**（不在 filter 内）。

```js
mapcadLayer.executeCommand('EXPLODE');
// 选集 → 回车
```

## 十、DRAWORDER 顺序

```js
mapcadLayer.executeCommand('DRAWORDER');                    // 默认 front
mapcadLayer.executeCommand('DRAWORDER', { action: 'back' });
// 选集 → 立即执行，无二级选项提示
```

`action` 可选值：`front`(最前) / `back`(最后) / `up`(上移一层) / `down`(下移一层)，默认 `front`。顺序变化会记一条 undo。

## 十一、命令与实体几何变换的关系

命令背后最终调用的是实体的 `move / rotate / scale / mirror` 方法（见 [entity/transform](../entity/transform.md)）。只需要纯代码操作时直接调这些方法，更快。

## 十二、编辑命令 + 预选集

可以**先选中实体再执行命令**：

```js
mapcadLayer.store.setSelection([ent1.id, ent2.id]);   // 选集存 id
mapcadLayer.executeCommand('MOVE');
// 不会再提示"选集"，直接进入"基点"
```

## 十三、常见坑

1. **无选集直接启动 MOVE**：命令会先提示"选集"；选完 Enter 再下一步。
2. **TRIM 参考边必须包含相交**：没相交不会修剪。
3. **想交互旋转**：注册表里没有 ROTATE，但 `SCALE` 命令的 `R` 关键字就是旋转交互（角度单位：度）；纯代码用 `entity.rotate(center, angleRad)`（弧度）。
4. **EXPLODE 块引用后 BlockRef 消失**：分解后以块内实体形式存在；刷新选集拿原 BlockRefEnt 就拿不到了。
5. **FILLET 半径 0**：表示延伸到交点（不画圆角）；即 AutoCAD 的 "corner" 模式。

## 相关

- 变换方法 → [entity/transform](../entity/transform.md)
- 选择集 → [input-manager](input-manager.md)
- Undo / Redo → [undo-redo](undo-redo.md)
