# 高级线型管理

自定义线型创建、复杂线型、LIN 文件加载、线型管理器 API。

## 概览

WebCAD 支持三种类型的线型元素：

| 元素类型 | 类 | 说明 |
|---------|---|------|
| 简单元素 | `SimpleLinetypeElement` | 实线、间隙、点 |
| 文字元素 | `TextLinetypeElement` | 嵌入文字 |
| 形状元素 | `ShapeLinetypeElement` | 嵌入 SHX 形状符号 |

---

## 简单线型

### SimpleLinetypeElement 参数说明

| 值 | 含义 |
|----|------|
| 正数 | 实线段长度（单位与图纸单位一致）|
| 负数 | 间隙长度（绝对值为间隙大小）|
| 0 | 点（在该位置绘制一个点）|

### 创建简单虚线

```javascript
const { LinetypeDefinition, SimpleLinetypeElement, Engine } = vjcad;

const ltManager = Engine.linetypeManager;

// 创建虚线：12单位实线，6单位间隙，循环...
const dashed = new LinetypeDefinition("MY_DASHED", "简单虚线 ---- ----");
dashed.addElement(new SimpleLinetypeElement(12));   // 12单位实线
dashed.addElement(new SimpleLinetypeElement(-6));   // 6单位间隙

ltManager.registerLinetype(dashed, "custom");
```

### 创建点划线

```javascript
// 点划线：实线 - 间隙 - 点 - 间隙，循环...
const dashdot = new LinetypeDefinition("MY_DASHDOT", "点划线 ____ . ____");
dashdot.addElement(new SimpleLinetypeElement(12));  // 实线
dashdot.addElement(new SimpleLinetypeElement(-3));  // 间隙
dashdot.addElement(new SimpleLinetypeElement(0));   // 点
dashdot.addElement(new SimpleLinetypeElement(-3));  // 间隙

ltManager.registerLinetype(dashdot, "custom");
```

### 创建双点划线

```javascript
// 双点划线：实线 - 间隙 - 点 - 间隙 - 点 - 间隙
const dashdotdot = new LinetypeDefinition("MY_DASHDOTDOT", "双点划线 ____ . . ____");
dashdotdot.addElement(new SimpleLinetypeElement(12));
dashdotdot.addElement(new SimpleLinetypeElement(-3));
dashdotdot.addElement(new SimpleLinetypeElement(0));   // 第一个点
dashdotdot.addElement(new SimpleLinetypeElement(-3));
dashdotdot.addElement(new SimpleLinetypeElement(0));   // 第二个点
dashdotdot.addElement(new SimpleLinetypeElement(-3));

ltManager.registerLinetype(dashdotdot, "custom");
```

### 创建边界线

```javascript
// 边界线：实线 - 间隙 - 实线 - 间隙 - 点 - 间隙
const border = new LinetypeDefinition("MY_BORDER", "边界线 __ __ . __ __ .");
border.addElement(new SimpleLinetypeElement(10));
border.addElement(new SimpleLinetypeElement(-4));
border.addElement(new SimpleLinetypeElement(10));
border.addElement(new SimpleLinetypeElement(-4));
border.addElement(new SimpleLinetypeElement(0));   // 点
border.addElement(new SimpleLinetypeElement(-4));

ltManager.registerLinetype(border, "custom");
```

---

## 复杂线型（带文字和形状）

### TextLinetypeElement 参数

```javascript
const { TextLinetypeElement, TextRotationMode } = vjcad;

new TextLinetypeElement(text, style, options);
```

| 参数 | 说明 |
|------|------|
| `text` | 显示的文字内容 |
| `style` | 文字样式名（如 "STANDARD"）|
| `options.scale` | 缩放比例（默认 1.0）|
| `options.rotation` | 旋转角度（度）|
| `options.rotationMode` | 旋转模式（见下表）|
| `options.xOffset` | X 方向偏移（正值沿线段方向）|
| `options.yOffset` | Y 方向偏移（负值向下，约 -scale*0.3 可使文字居中）|

### TextRotationMode 旋转模式

| 模式 | 说明 |
|------|------|
| `TextRotationMode.UPRIGHT` ("U") | 正立，文字始终易读 |
| `TextRotationMode.RELATIVE` ("R") | 相对，随线段角度旋转 |
| `TextRotationMode.ABSOLUTE` ("A") | 绝对，相对于原点旋转 |

### 创建带文字的管线线型

```javascript
const { 
    LinetypeDefinition, SimpleLinetypeElement, 
    TextLinetypeElement, TextRotationMode, Engine 
} = vjcad;

const ltManager = Engine.linetypeManager;

// 热水管线型：----HW----HW----
const hotWater = new LinetypeDefinition("HOT_WATER", "热水管 ----HW----");
hotWater.addElement(new SimpleLinetypeElement(15));    // 15单位实线
hotWater.addElement(new SimpleLinetypeElement(-2));    // 文字前间隙
hotWater.addElement(new TextLinetypeElement("HW", "STANDARD", {
    scale: 2.0,
    rotationMode: TextRotationMode.UPRIGHT,  // 文字始终正立
    yOffset: -0.6
}));
hotWater.addElement(new SimpleLinetypeElement(-8));    // 文字后间隙（需容纳文字宽度）

ltManager.registerLinetype(hotWater, "complex");

// 燃气管线型：----GAS----GAS----
const gasLine = new LinetypeDefinition("GAS_LINE", "燃气管 ----GAS----");
gasLine.addElement(new SimpleLinetypeElement(12));
gasLine.addElement(new SimpleLinetypeElement(-2));
gasLine.addElement(new TextLinetypeElement("GAS", "STANDARD", {
    scale: 1.5,
    rotationMode: TextRotationMode.UPRIGHT,
    yOffset: -0.45
}));
gasLine.addElement(new SimpleLinetypeElement(-8));

ltManager.registerLinetype(gasLine, "complex");
```

### ShapeLinetypeElement 参数

```javascript
const { ShapeLinetypeElement } = vjcad;

new ShapeLinetypeElement(shapeName, shapeFile, options);
```

| 参数 | 说明 |
|------|------|
| `shapeName` | SHX 形状名称 |
| `shapeFile` | SHX 形状文件名 |
| `options` | 与 TextLinetypeElement 相同 |

### 创建带形状符号的线型

```javascript
const { ShapeLinetypeElement, TextRotationMode } = vjcad;

// 流向线：带箭头
const flowArrow = new LinetypeDefinition("FLOW_ARROW", "流向线 -->-->-->");
flowArrow.addElement(new SimpleLinetypeElement(12));
flowArrow.addElement(new SimpleLinetypeElement(-1));
flowArrow.addElement(new ShapeLinetypeElement("ARROW", "ltypeshp.shx", {
    scale: 0.8,
    rotation: 0,
    rotationMode: TextRotationMode.RELATIVE  // 随线段方向旋转
}));
flowArrow.addElement(new SimpleLinetypeElement(-1));

ltManager.registerLinetype(flowArrow, "complex");

// 轨道线：带方块
const track = new LinetypeDefinition("TRACK", "轨道线 --□--□--");
track.addElement(new SimpleLinetypeElement(10));
track.addElement(new SimpleLinetypeElement(-2));
track.addElement(new ShapeLinetypeElement("BOX", "ltypeshp.shx", {
    scale: 1.2,
    rotationMode: TextRotationMode.UPRIGHT  // 方块保持正立
}));
track.addElement(new SimpleLinetypeElement(-2));

ltManager.registerLinetype(track, "complex");
```

---

## 从 LIN 文件加载

### LIN 文件格式

```
;; 注释以分号开头
*线型名称,描述
A,模式元素1,模式元素2,...

*ACAD_ISO02W100,ISO 虚线 ____ ____
A,12,-3

*ACAD_ISO07W100,ISO 点划线 ____ . ____
A,24,-3,0,-3
```

### 使用 LinetypeParser

```javascript
const { LinetypeParser, Engine } = vjcad;

const ltManager = Engine.linetypeManager;

// .lin 格式定义字符串
const linDefinitions = `
*MY_DASHED,我的虚线 ____ ____
A,12,-3

*MY_DOTTED,我的点线 . . . .
A,0,-6

*MY_DIVIDE,我的分隔线 ____  .  ____
A,12.7,-6.35,0,-6.35
`;

// 解析 .lin 格式
const parser = new LinetypeParser();
const definitions = parser.parse(linDefinitions);

console.log(`解析出 ${definitions.length} 个线型定义`);

// 注册解析出的线型
for (const def of definitions) {
    if (parser.validateDefinition(def)) {
        ltManager.registerLinetype(def, "imported");
        console.log(`已注册: ${def.name}`);
    }
}

// 或使用便捷方法一次性加载
const loadedCount = ltManager.loadFromLinDefinitions(linDefinitions, "imported");
console.log(`加载了 ${loadedCount} 个线型`);
```

---

## LinetypeManager API

### 获取管理器

```javascript
const ltManager = Engine.linetypeManager;
```

### 注册与获取

```javascript
// 注册线型
ltManager.registerLinetype(definition, "category");

// 获取线型定义
const def = ltManager.getLinetype("HIDDEN");
console.log(def.name);         // 线型名
console.log(def.description);  // 描述
console.log(def.elements);     // 元素数组
console.log(def.patternLength);// 模式长度
console.log(def.isComplex);    // 是否复杂线型

// 检查是否存在
const exists = ltManager.hasLinetype("MY_LINETYPE");

// 删除线型（不能删除内置线型）
ltManager.removeLinetype("MY_LINETYPE");
```

### 批量操作

```javascript
// 获取所有线型名称
const allNames = ltManager.getAllLinetypeNames();
const categoryNames = ltManager.getAllLinetypeNames("custom");

// 获取所有线型定义
const allDefs = ltManager.getAllLinetypes();

// 导出为 .lin 格式
const linString = ltManager.exportToLinFormat(["MY_LINE1", "MY_LINE2"]);
const categoryLin = ltManager.exportToLinFormat(null, "custom");
```

### 分类管理

```javascript
// 获取所有分类
const categories = ltManager.getCategories();
// 返回: ["builtin", "custom", "complex", "imported", ...]

// 检查是否为内置线型
const isBuiltin = ltManager.isBuiltinLinetype("CONTINUOUS");  // true
```

### 维护操作

```javascript
// 清除所有自定义线型
ltManager.clearCustomLinetypes();

// 重置为默认状态
ltManager.reset();

// 获取统计信息
const stats = ltManager.getStatistics();
console.log(stats.total);      // 总线型数
console.log(stats.categories); // 每个分类的数量
```

### JSON 序列化

```javascript
// 导出为 JSON
const jsonDef = definition.toJSON();

// 从 JSON 恢复
const restoredDef = LinetypeDefinition.fromJSON(jsonDef);
```

---

## 使用线型

### 应用到实体

```javascript
const line = new LineEnt([0, 0], [100, 0]);
line.setDefaults();
line.lineType = "HOT_WATER";      // 线型名称
line.lineTypeScale = 1.0;         // 线型比例

Engine.addEntities(line);
```

### 线型比例说明

| lineTypeScale | 效果 |
|---------------|------|
| 0.5 | 更密（元素更小）|
| 1.0 | 默认 |
| 2.0 | 更稀（元素更大）|

**提示**：ISO 线型通常需要调整比例（如 0.5）才能正常显示。

---

## 内置线型

`LinetypeManager` 只内置注册 4 种线型（名称大小写不敏感）：

| 名称 | 描述 |
|------|------|
| `CONTINUOUS` | 实线（默认）|
| `HIDDEN` | 虚线 |
| `CENTER` | 中心线 |
| `PHANTOM` | 幻影线 |

另有别名映射：`DASHED` / `DASHED1-3` / `DOT` → 按 `Hidden` 绘制，`CENTER1/2` → `Center`，`PHANTOM1/2` → `Phantom`。`DASHDOT`、`BORDER`、`DIVIDE` 等**不是内置线型**——须先 `loadFromLinDefinitions(LIN文本)` 或 `registerLinetype()`（打开的图纸若自带线型定义会随文档加载），否则未注册的线型名一律画成实线。

---

## 完整示例

```javascript
const { 
    MainView, initCadContainer, LineEnt, Engine,
    LinetypeDefinition, SimpleLinetypeElement,
    TextLinetypeElement, TextRotationMode
} = vjcad;

// 初始化
const cadView = new MainView({...});
initCadContainer("map", cadView);
await cadView.onLoad();

const ltManager = Engine.linetypeManager;

// 1. 创建简单线型
const myDash = new LinetypeDefinition("MY_DASH", "自定义虚线");
myDash.addElement(new SimpleLinetypeElement(10));
myDash.addElement(new SimpleLinetypeElement(-5));
ltManager.registerLinetype(myDash, "custom");

// 2. 创建复杂线型（带文字）
const pipeLine = new LinetypeDefinition("PIPE", "管道线");
pipeLine.addElement(new SimpleLinetypeElement(12));
pipeLine.addElement(new SimpleLinetypeElement(-2));
pipeLine.addElement(new TextLinetypeElement("P", "STANDARD", {
    scale: 2.0,
    rotationMode: TextRotationMode.UPRIGHT,
    yOffset: -0.6
}));
pipeLine.addElement(new SimpleLinetypeElement(-4));
ltManager.registerLinetype(pipeLine, "complex");

// 3. 应用线型
const line1 = new LineEnt([0, 0], [200, 0]);
line1.setDefaults();
line1.lineType = "MY_DASH";
line1.lineTypeScale = 1.0;
Engine.addEntities(line1);

const line2 = new LineEnt([0, 30], [200, 30]);
line2.setDefaults();
line2.lineType = "PIPE";
line2.lineTypeScale = 1.0;
Engine.addEntities(line2);

Engine.zoomExtents();
```
