> **本文回答**：实体的增、删、改、查、选中生命周期 —— `addEntity` / `deleteEntity` / `getEntities` / 选择集 / `changed()`。

## 一、添加实体

```js
const line = new LineEnt([0, 0], [100, 0]);
line.color = 0xff0000;
mapcadLayer.addEntity(line);
```

`addEntity` 会：

1. 对 `type==="INSERT"` 的实体先 `setBlocksRef(this.blocks)` 注入块表引用
2. 放入内部 store（实体 `id` 在**构造时**已由 `EntityBase` 生成，addEntity 不改 id）
3. 触发 `entity:added` 事件（store 内发射）
4. 标脏 → 下一帧重绘

批量添加：

```js
const ents = [line1, line2, circle, text];
ents.forEach(e => mapcadLayer.addEntity(e));
```

**大量实体（万级）**：1.0.1 **没有"暂停自动重绘"的 API**——同步循环里连续 `addEntity` 本身就由 rAF 合并到下一帧一次渲染（每条仍会发 `entity:added` 并记一条 undo）；量再大就分批或改用 GeoJSON 源渲染，见 [batch/](../batch/overview.md)。

## 二、删除实体

```js
mapcadLayer.deleteEntity(entity.id);
```

或直接用 store：

```js
mapcadLayer.store.delete(entity.id);
```

清空：

```js
mapcadLayer.store.getAllIds().forEach(id => mapcadLayer.store.delete(id));
// 或整体替换文档：mapcadLayer.fromJSON({ ...空文档 })
```

## 三、按 id 取实体

```js
const ent = mapcadLayer.store.get(id);
```

## 四、枚举所有实体

```js
const all = mapcadLayer.getEntities();
console.log(`共 ${all.length} 个实体`);

all.filter(e => e.type === 'LINE').forEach(line => {
  line.color = 0x00ff00;
  line.styleChanged();
});
```

## 五、选中操作

```js
const selected = mapcadLayer.getSelectedEntities();
selected.forEach(e => { e.color = 0xffff00; e.styleChanged(); });   // 改样式要标脏
mapcadLayer.clearSelection();
```

程序化选中：

```js
mapcadLayer.store.setSelection([entity.id]);      // 单选（覆盖全集）
mapcadLayer.store.setSelection(ids);              // 批量
mapcadLayer.store.setSelection(mapcadLayer.store.getAllIds()); // 全选
mapcadLayer.store.clearSelection();               // 清空
```

> 选中集由 `EntityStore`（`_selectedIds`）管理，变化时发 `selection:changed` 事件，详见 [event/bus-selection](../event/bus-selection.md)。

## 六、通知系统重绘

| 调用 | 适用场景 | 代价 |
|---|---|---|
| `entity.styleChanged()` | 仅改 `color` / `lineWidth` / `effect_*`（透明度类字段不在快路径） | 小 |
| `entity.changed()` | 改几何（端点、半径、顶点…） | 中（会重算空间索引） |
| `mapcadLayer.getEntities().forEach(e => e.changed())` | 全量标脏（少用） | 大 |

```js
entity.color = 0xff0000;
entity.styleChanged();          // 仅样式

// 以 LineEnt 为例，几何字段（startPoint 等）改完要标脏：
line.startPoint = new Point2D(10, 10);   // line: LineEnt
entity.changed();               // 几何变化
```

**不调会怎样**：属性已改但画面没动。

## 七、克隆

```js
const copy = entity.clone();
copy.color = 0xffff00;
mapcadLayer.addEntity(copy);
```

`clone()` 生成新 `id`，深拷贝几何和样式。

## 八、可见性

```js
entity.visible = false;
entity.changed();            // visible 不在 styleChanged 快路径
```

批量隐藏某图层：

```js
mapcadLayer.getEntities()
  .filter(e => e.layerId === '标注层')   // 字段是 layerId，不是 layer
  .forEach(e => { e.visible = false; e.changed(); });
```

## 九、层级

```js
mapcadLayer.moveToFront([id1, id2]);
mapcadLayer.moveToBack([id1]);
mapcadLayer.moveUp(ids);
mapcadLayer.moveDown(ids);
```

参数省略时作用于选中集。

## 十、撤销 / 重做

```js
mapcadLayer.undo();
mapcadLayer.redo();
```

只有**增删**（`store.add`/`store.delete`，含 `addEntity`/`deleteEntity`）自动进撤销栈；**改属性不会**——程序化修改要先 `undoManager.recordModify(ent)` 再改（见 [drawing/undo-redo](../drawing/undo-redo.md)）。批量操作可包成 transaction：

```js
mapcadLayer.undoManager.beginTransaction();  // 批量导入
ents.forEach(e => mapcadLayer.addEntity(e));
mapcadLayer.undoManager.endTransaction();
```

## 十一、常见坑

1. **addEntity 后调 clone 要再 addEntity**：clone 不会自动加入。
2. **changed vs styleChanged**：反方向用错后果不同——`styleChanged()` 只回写 `color`/`line_width`/`effect_*`；改 `visible`/`fillColor`/`fillOpacity`/`layerId`/`lineType` 等调了 `styleChanged()` **画面不变（静默无效）**。反之 `changed()` 改样式只是性能浪费。
3. **delete 了还保留引用**：store 清了但你的数组里仍有对象 → 内存泄漏。
4. **地图未就绪就 addEntity**：先 `await map.onLoad()` 再 `map.addControl(cad)`；MapCadLayer 没有 `ready()` API，`addControl` 即触发 `onAdd`。
