# 块、符号与组

块定义与插入、符号管理、组实体。

---

## 创建块定义

```javascript
const { LineEnt, CircleEnt, Engine } = vjcad;

const doc = Engine.currentDoc;
const blockName = "MySymbol";

// 检查是否已存在
let blockDef = doc.blocks.itemByName(blockName);
if (!blockDef) {
    blockDef = doc.blocks.add(blockName);
    blockDef.basePoint = [0, 0];  // 基点

    // 添加块内实体
    const line1 = new LineEnt([-10, 0], [10, 0]);
    const line2 = new LineEnt([0, -10], [0, 10]);
    const circle = new CircleEnt([0, 0], 5);

    line1.setDefaults();
    line2.setDefaults();
    circle.setDefaults();

    blockDef.addEntity(line1);
    blockDef.addEntity(line2);
    blockDef.addEntity(circle);
}
```

---

## 插入块引用（InsertEnt）

```javascript
const { InsertEnt, Engine } = vjcad;

const insert = new InsertEnt();
insert.blockId = blockDef.blockId;      // 块ID（必须）
insert.insertionPoint = [50, 50];       // 插入点
insert.scaleFactor = 1.5;               // 缩放因子
insert.rotation = Math.PI / 4;          // 旋转角度（弧度）
insert.setDefaults();
insert.color = 5;
Engine.addEntities(insert);
```

| 属性 | 说明 |
|------|------|
| `blockId` | 块ID（必须，从 `blockDef.blockId` 获取） |
| `insertionPoint` | 插入点 |
| `scaleFactor` | 缩放因子 |
| `rotation` | 旋转角度（弧度） |

---

## 炸开块

```javascript
const explodedEnts = insert.getNestEnts(true);
explodedEnts.forEach(ent => Engine.addEntities(ent));
Engine.eraseEntities(insert);
```

---

## 符号管理

### 从本地存储加载符号

```javascript
const {
    getLocalStorageService,
    parseSymbolVcadData,
    mergeSymbolToDocument,
    Point2D, Engine
} = vjcad;

const localService = getLocalStorageService();

// 获取分类和符号列表
const categories = await localService.getLocalSymbolCategories();
const symbols = await localService.getLocalSymbolList(categories[0].id);
const symbol = await localService.getLocalSymbol(symbols[0].id);
// 返回 { record: ILocalSymbolRecord, vcadData: string }——basePoint 在 record 上

// 解析符号数据
const symbolDoc = await parseSymbolVcadData(symbol.vcadData);

// 合并到文档——内部逐个 Engine.pcanvas.addEntity，**不记撤销**，需自己包撤销组并补记
Engine.undoManager.start_undoMark('插入符号');
try {
    const addedEntities = mergeSymbolToDocument(
        symbolDoc,
        new Point2D(100, 100),    // 插入点
        symbol.record.basePoint,   // 基点（record.basePoint，不是 symbol.basePoint）
        1.5,                       // 缩放
        45,                        // 旋转（度）
        false                      // clearSourceInfo
    );
    if (addedEntities.length) Engine.undoManager.added_undoMark(addedEntities);   // 内置插入命令同此写法
} finally {
    Engine.undoManager.end_undoMark();
}

Engine.zoomExtents();
```

### 交互式插入符号

```javascript
const { insertSymbolInteractive } = vjcad;

const entities = await insertSymbolInteractive(
    symbol.vcadData, basePoint,   // 首参是 vcad JSON 字符串，不是符号记录对象
    { allowScale: true, allowRotation: true, clearSourceInfo: false }
);
```

### 创建本地符号

```javascript
const {
    getLocalStorageService,
    buildSymbolVcadData,
    generateThumbnailFromEntities
} = vjcad;

const localService = getLocalStorageService();

// 创建分类
const category = await localService.createLocalSymbolCategory("我的符号");

// 生成符号数据
const vcadData = await buildSymbolVcadData(entities, false);
const thumbnail = await generateThumbnailFromEntities(entities, 128, 128);

// 保存符号
const symbol = await localService.saveLocalSymbol({
    categoryId: category.id,
    name: "十字符号",
    basePoint: [0, 0],
    thumbnail: thumbnail,
    vcadData: vcadData
});
```

---

## GroupEnt — 组

### 创建组

```javascript
const { GroupEnt, LineEnt, CircleEnt, Engine } = vjcad;

const line = new LineEnt([0, 0], [100, 0]);
const circle = new CircleEnt([50, 50], 20);
line.setDefaults();
circle.setDefaults();

const group = new GroupEnt("MyGroup", [line, circle]);
group.setDefaults();
Engine.addEntities(group);
```

### 访问组内实体

```javascript
group.items.forEach((item, index) => {
    console.log(`${index}: ${item.type}`);
});
```

### 炸开组

```javascript
const explodedEntities = group.explode();
explodedEntities.forEach(ent => Engine.addEntities(ent));
Engine.eraseEntities(group);
Engine.regen(true);
```

### 命令方式

```javascript
await Engine.editor.executerWithOp('GROUP');     // 创建组
await Engine.editor.executerWithOp('UNGROUP');   // 取消组
```
