> **本文回答**：偏移 / 裁剪 / 延长是 vjcad 三大实体级算法。命令版用 `OFFSET / TRIM / EXTEND`；编程版可直接调几何工具或自行实现，详见 `vjcad/example/geometry/10offset.js / 11trim.js / 12extend.js`。

## 一、偏移（OFFSET）

```
命令: OFFSET
指定偏移距离 <上次值>: <输入距离>
选择要偏移的对象: <选择对象>
指定要偏移的那一侧上的点: <点击方向>
```

代码触发：

```js
Engine.editor.executerWithOp('OFFSET');
// 或脚本
Engine.editor.automate(`OFFSET\n10\n... `);
```

MCP 参考：`vjcad/doc/edit/edit-commands.md`。

> 自定义偏移命令的完整模板见 `vjcad/doc/selection/entity-selection.md` 中 "OffsetCommand 完整命令示例（偏移命令-循环选择）"。该模板用 `Engine.OFFSETDIST` 系统变量保存上次距离，用 `getEntity` 循环选实体并 `getPoint` 选偏移方向。

## 二、裁剪（TRIM）

`vjcad/example/geometry/11trim.js` 演示基于交点的实体裁剪算法（按选中边界 + 选中目标 → 求交点 → 在 pickPoint 那段截断）。

完整自定义命令骨架（来自文档）：

```js
class TrimCommand {
  async main() {
    Engine.undoManager.start_undoMark();
    try {
      // 1. 选边界
      const bRes = await getSelections(new SelectionInputOptions());
      if (bRes.status !== InputStatusEnum.OK) return;
      const boundaries = bRes.value;

      // 2. 循环选要修剪的实体
      Engine.pcanvas.highLightEntities(boundaries);
      while (true) {
        const r = await getEntity(new SelectionSetInputOptions('选择要修剪的对象:'));
        if (r.status === InputStatusEnum.OK) {
          this.trimEntity(r.pickedEntity, r.pickedPoint, boundaries);
          Engine.pcanvas.regen();
        } else if (r.status === InputStatusEnum.EnterOrSpace ||
                   r.status === InputStatusEnum.Cancel) {
          break;
        }
      }
    } finally {
      Engine.undoManager.end_undoMark();
      Engine.pcanvas.clearHighLight();
    }
  }

  trimEntity(ent, pickPt, boundaries) {
    if (ent.type === 'LINE') this.trimLine(ent, pickPt, boundaries);
    else if (ent.type === 'ARC') this.trimArc(ent, pickPt, boundaries);
    // ... 其他类型按需扩展
  }
}
```

MCP 参考：`vjcad/doc/selection/entity-selection.md`、`vjcad/example/geometry/11trim.js`。

> 命令版 `TRIM` 可直接用 `Engine.editor.executerWithOp('TRIM')` 触发。

## 三、延长（EXTEND）

`vjcad/example/geometry/12extend.js` 演示了实体延长到边界的算法。流程相似：选边界 + 选要延长的目标 → 求交点 → 把端点替换为该交点。

```js
Engine.editor.executerWithOp('EXTEND');
```

## 四、几何工具的相关核心

| 算法 | 工具 |
|---|---|
| 求交点（裁剪 / 延长依赖） | `GeometryCalculator.{A}To{B}` （[intersection](intersection.md)） |
| 边界框粗筛（性能） | `entity.boundingBox()` + 简单矩形相交 |
| 空间索引（百万级） | `SpatialIndex`（[spatial-index](spatial-index.md)） |
| 偏移端点判断（用哪一侧） | `GeometryCalculator.witchSidePointToLine(lineStart, lineEnd, point)`（[distance-angle](distance-angle.md)） |

## 反例

- `OFFSET` 写脚本时把距离单位当 mm：vjcad 的"偏移距离"是绘图单位，与文档单位一致。
- `TRIM` / `EXTEND` 算法没有对自定义实体做分支：对 `CustomEntityBase` 的实体先转成内嵌真实实体（`buildNestEnts()`）再处理。
- 一次性删除 trim 后的旧实体：应用 `Engine.eraseEntities` + 新实体 `Engine.addEntities`，外加一次 `regen`。

## 参考（官方文档 MCP）

- 文档：`vjcad/doc/edit/edit-commands.md`、`vjcad/doc/selection/entity-selection.md`、`vjcad/doc/geometry/calculations.md`
- 示例：`vjcad/example/geometry/10offset.js`、`11trim.js`、`12extend.js`
