> **本文回答**：`Engine.getPoint(options)` / 顶层 `getPoint(options)` 返回 `{ status, value, stringResult, numberValue }`；`status === InputStatusEnum.OK` 时 `value` 是 `Point2D`。常用 `PointInputOptions` 字段：`message / keywords / useBasePoint / basePoint / useOsnap / callback / allowNumberResult / ignoreOrthomode / forceOrthomode / hideRubberBand`（`useOrthoMode` 字段存在但从不被读取）。

## 一、最小一个点

```js
class GetPointDemoCommand {
  async main() {
    const point = await this.getOnePoint();
    if (point) await this.getMultiplePoints();
    Engine.zoomExtents();
  }

  async getOnePoint() {
    const opt = new PointInputOptions('指定点位置:');
    const r = await getPoint(opt);
    if (r.status === InputStatusEnum.OK) {
      const p = r.value;
      const marker = new CircleEnt([p.x, p.y], 5);
      marker.setDefaults();
      Engine.addEntities(marker);
      return p;
    }
    return null;
  }

  async getMultiplePoints() {
    const points = [];
    for (let i = 0; i < 3; i++) {
      const opt = new PointInputOptions(`指定第${i + 1}个点 (共3个):`);
      const r = await getPoint(opt);
      if (r.status === InputStatusEnum.OK) {
        points.push(r.value);
      } else {
        break;
      }
    }
    return points;
  }
}
```

MCP 参考：`vjcad/example/input/01getpoint.js`。

## 二、`PointInputOptions` 字段

> 引自 `vjcad/doc/command/api-reference.md`：

| 属性 | 类型 | 说明 |
|---|---|---|
| `message` | `string` | 提示消息（构造参数 `new PointInputOptions(message)` 也可设置） |
| `keywords` | `string[]` | 关键字列表（命令行可输入这些关键字代替点） |
| `useBasePoint` | `boolean` | 是否使用基点（橡皮筋线） |
| `basePoint` | `Point2D` | 基点坐标 |
| `useOsnap` | `boolean` | 是否启用对象捕捉 |
| `callback` | `(canvasPt) => void` | 鼠标移动回调（参数是画布坐标） |
| `allowNumberResult` | `boolean` | 是否允许数字输入 |
| `useOrthoMode` | `boolean` | **无效**：`PointPrompt` 从不读取；忽略正交用 `ignoreOrthomode = true` |
| `ignoreOrthomode` | `boolean` | 忽略 `ORTHOMODE`（即使正交开着也自由取点） |
| `forceOrthomode` | `boolean` | 是否强制正交 |
| `hideRubberBand` | `boolean` | 是否隐藏橡皮筋线 |

## 三、返回值 `InputResult` 字段（`getPoint` 实际返回 `InputResult`，非 `PointInputResult`——后者是 `getCorner` 的返回类型，无 `numberValue`）

| 属性 | 类型 | 说明 |
|---|---|---|
| `status` | `number` | `InputStatusEnum.OK / Cancel / Keyword / None / IsNumber / ...`（交互式空回车：有 `defaultKeyword` → `Keyword`，否则 `None`；不返回 `EnterOrSpace`） |
| `value` | `Point2D` | 点坐标（OK 时） |
| `stringResult` | `string` | 关键字结果（Keyword 时） |
| `numberValue` | `number` | 数字结果（需 `allowNumberResult`） |

## 四、状态分支处理（含关键字）

```js
const opt = new PointInputOptions('指定点 [设置(S)/退出(E)]:');
opt.keywords = ['S', 'E'];

const r = await Engine.getPoint(opt);
switch (r.status) {
  case InputStatusEnum.OK:
    console.log('点:', r.value);
    break;
  case InputStatusEnum.Keyword:
    console.log('关键字:', r.stringResult);
    if (r.stringResult === 'S') { /* 设置 */ }
    if (r.stringResult === 'E') { /* 退出 */ }
    break;
  case InputStatusEnum.Cancel:
    console.log('用户取消');
    break;
}
```

MCP 参考：`vjcad/doc/guide/quick-start.md`（"带关键字的输入"小节）、`vjcad/example/input/06getkeyword.js`。

## 反例

- 直接 `r.value.x` 不判状态：用户取消时**不会报错**——`value` 是新建的 `Point2D(0, 0)`，代码会悄悄用原点继续执行。
- 用 `r.value` 判 truthy：`Cancel` / `Keyword` 时 `value` 也是 `Point2D(0, 0)`（truthy）；必须按 `status` 判断。

## 参考（官方文档 MCP）

- 文档：`vjcad/doc/command/api-reference.md`、`vjcad/doc/guide/quick-start.md`
- 示例：`vjcad/example/input/01getpoint.js`、`vjcad/example/input/06getkeyword.js`

## 无交互自动化

`PointInputOptions` 有两个隐藏字段：`isAutomation` 与 `automateStr`。置 `isAutomation=true` 后 `getPoint` **不进入交互等待**，直接按 `automateStr` 解析返回（PointPrompt.main 首分支）：

| automateStr | 结果 |
|---|---|
| `"123.5,456.25"` | `status=OK`，`value=Point2D(123.5, 456.25)` |
| `""`（空串） | `status=Enter`（值 `1`，不是 `EnterOrSpace`）；**不会**套用 `defaultKeyword`（交互式空回车才返回 `Keyword`(defaultKeyword) / `None`） |
| `"u"` 等关键字 | `status=Keyword`，`stringResult` 为**大写**（自动 toUpperCase 比较） |
| `"5"`（单数字且 `useBasePoint=true`） | `value = Point2D(base.x + 5, base.y)`——**沿 +X 偏移**，不是极轴方向 |
| 非法/不能解析 | `status=Cancel` |

```js
const opt = new PointInputOptions("指定点:");
opt.isAutomation = true;
opt.automateStr = "100,50";
const r = await getPoint(opt); // 立即返回，不等待用户
```

**脚本模式**：`Engine.editor.isAutomate = true` 时，`editor.getPoint` 会从 `editor.scriptRowStack` 逐行取输入——自动跳过空行和 `;`/`//` 开头的注释行。这是命令脚本（SCR）的驱动机制，也可用于无头测试。

**不对称坑位**：自动化只有 `getPoint` 有。`getEntity`/`getSelections`/`getString`/`getReal`/`getKeyword`/`getInteger` 的 Editor 入口**都不走** `scriptRowStack`——它们无可编程喂入，只能真实交互，或用 `PickUtils.getEntityInPickboxInSpace` 这类程序化拾取代替。

## 程序化拾取代替交互

```js
// PickUtils.getEntityInPickboxInSpace(items, bounds, useIndex, isWcs)
const box = new BoundingBox(new Point2D(minX, minY), new Point2D(maxX, maxY));
const picked = PickUtils.getEntityInPickboxInSpace(
  Engine.currentSpace.items.filter(e => e.isAlive), box, false, true); // WCS 框
```

- `useIndex=true` 走空间索引（`Engine.spatialIndexManager`）——实体可能未入索引导致漏拾；`useIndex=false` 为全量遍历（从后往前，**后绘制者优先**）。
- `editor.getEntityInPickbox(items, box)` 便捷形态只收 **DCS**（屏幕像素）框；若用 `Engine.trans.WcsToDcs` 手转 WCS 框，注意屏幕 Y 轴向下——`minPoint`/`maxPoint` 的 y 会互换，须自行归一化，否则命中为空。
