# SVG 导入

将 SVG 矢量图形导入到 WebCAD 中，转换为 CAD 实体。

## 概览

| 方式 | 说明 |
|------|------|
| `IMPORTSVG` 命令 | 打开对话框，可视化配置导入选项 |
| `parseSvgToWebcad()` API | 程序化解析 SVG 内容 |

---

## 命令方式

### IMPORTSVG 命令

```javascript
await Engine.editor.executerWithOp('IMPORTSVG');
```

命令会打开导入对话框，支持以下功能：

1. **输入方式**
   - 选择本地 SVG 文件
   - 直接粘贴 SVG 内容

2. **显示设置**
   - 显示线宽
   - 启用填充
   - 线宽缩放比例

3. **颜色处理**
   - 白色处理方式
   - 黑色处理方式

4. **插入选项**
   - 允许缩放
   - 允许旋转

5. **实时预览**
   - SVG 原始效果
   - WebCAD 转换效果

---

## API 方式

### 完整流程

```javascript
const { 
    Engine, Point2D, 
    getWebCadCoreService, CadDocument, regen 
} = vjcad;

// 1. SVG 内容
const svgContent = `
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200">
    <rect x="20" y="20" width="60" height="40" fill="none" stroke="#ff0000" stroke-width="2"/>
    <circle cx="150" cy="50" r="30" fill="none" stroke="#00ff00" stroke-width="2"/>
    <line x1="20" y1="100" x2="180" y2="100" stroke="#0000ff" stroke-width="2"/>
</svg>
`;

// 2. 初始化 WASM 服务
const wasmService = getWebCadCoreService();
await wasmService.initWasm();

// 3. 解析 SVG 为 WebCAD 数据
const webcadData = await wasmService.parseSvgToWebcad(
    svgContent,
    0,    // whiteColorProcessing
    0,    // blackColorProcessing
    0,    // enableFill
    1,    // displayLineWeight
    1.0   // lineWeightScale
);

if (!webcadData) {
    throw new Error("SVG 解析失败");
}

// 4. 解析 WebCAD 数据
const parsedData = JSON.parse(webcadData);
const entities = parsedData.entities || [];

// 5. 计算边界和基点
let basePoint = [0, 0];
const bbox = parsedData.bounds;
if (bbox && bbox.length === 4) {
    const [minX, minY, maxX, maxY] = bbox;
    basePoint = [(minX + maxX) / 2, (minY + maxY) / 2];
}

// 6. 构建临时文档数据
const docData = {
    appName: "WebCAD SVG Import",
    docVer: 0.3,
    dbBlocks: {
        "*Model": {
            blockId: "*Model",
            name: "*Model",
            isLayout: false,
            basePoint: [0, 0],
            lookPt: [0, 0],
            twistAngle: 0,
            zoom: 1,
            UCSXANG: 0,
            UCSORG: [0, 0],
            items: entities
        }
    },
    dbLayers: [{
        name: "0",
        layerId: "0",
        layerOn: true,
        color: 7,
        lineType: "Continuous",
        lineWeight: -3,
        plottable: true
    }],
    dbTextStyles: [],
    dbLayouts: [{
        layoutId: 0,
        name: "Model",
        spaceName: "*Model"
    }]
};

// 7. 创建临时文档
const symbolDoc = new CadDocument();
await symbolDoc.fromDb(docData);

// 8. 合并实体到当前文档
const insertPoint = new Point2D(0, 0);
const basePt = new Point2D(basePoint[0], basePoint[1]);

const modelBlock = symbolDoc.blocks.itemByName("*Model");

for (const entity of modelBlock.items) {
    if (!entity.isAlive) continue;
    
    const cloned = entity.clone();
    cloned.move(basePt, insertPoint);
    Engine.addEntities(cloned);
}

// 9. 刷新视图
regen();
Engine.zoomExtents();
```

---

## parseSvgToWebcad 参数

```javascript
wasmService.parseSvgToWebcad(
    svgContent,           // SVG 内容字符串
    whiteColorProcessing, // 白色处理方式
    blackColorProcessing, // 黑色处理方式
    enableFill,           // 是否启用填充
    displayLineWeight,    // 是否显示线宽
    lineWeightScale       // 线宽缩放比例
);
```

### 颜色处理方式

| 值 | 说明 |
|----|------|
| 0 | 原样保留 |
| 1 | 自动反色（白变黑，黑变白）|
| 2 | 过滤排除（不导入该颜色）|

### 填充和线宽

| 参数 | 值 | 说明 |
|------|---|------|
| `enableFill` | 0 | 不启用填充 |
| `enableFill` | 1 | 启用填充 |
| `displayLineWeight` | 0 | 不显示线宽 |
| `displayLineWeight` | 1 | 显示线宽 |
| `lineWeightScale` | 1.0 | 线宽 1:1 |
| `lineWeightScale` | 2.0 | 线宽放大 2 倍 |

---

## 支持的 SVG 元素

| 元素 | 转换为 |
|------|--------|
| `<line>` | LineEnt |
| `<rect>` | PolylineEnt |
| `<circle>` | CircleEnt |
| `<ellipse>` | EllipseEnt |
| `<polyline>` | PolylineEnt |
| `<polygon>` | PolylineEnt (闭合) |
| `<path>` | PolylineEnt / SplineEnt |
| `<text>` | TextEnt |

---

## 返回数据格式

`parseSvgToWebcad()` 返回 JSON 字符串，解析后包含：

```javascript
{
    entities: [...],  // 实体数组
    bounds: [minX, minY, maxX, maxY]  // 边界范围
}
```

---

## 简化封装示例

```javascript
const { Engine, Point2D, getWebCadCoreService, CadDocument, regen } = vjcad;

/**
 * 导入 SVG 内容到当前文档
 * @param svgContent SVG 内容字符串
 * @param insertPoint 插入点（可选，默认原点）
 * @param options 导入选项
 */
async function importSvg(svgContent, insertPoint = new Point2D(0, 0), options = {}) {
    const {
        whiteColorProcessing = 0,
        blackColorProcessing = 0,
        enableFill = 0,
        displayLineWeight = 1,
        lineWeightScale = 1.0
    } = options;
    
    // 初始化 WASM
    const wasmService = getWebCadCoreService();
    await wasmService.initWasm();
    
    // 解析 SVG
    const webcadData = await wasmService.parseSvgToWebcad(
        svgContent,
        whiteColorProcessing,
        blackColorProcessing,
        enableFill,
        displayLineWeight,
        lineWeightScale
    );
    
    if (!webcadData) {
        throw new Error("SVG 解析失败");
    }
    
    const parsedData = JSON.parse(webcadData);
    const entities = parsedData.entities || [];
    
    if (entities.length === 0) {
        throw new Error("没有解析到任何实体");
    }
    
    // 计算基点
    let basePoint = [0, 0];
    if (parsedData.bounds?.length === 4) {
        const [minX, minY, maxX, maxY] = parsedData.bounds;
        basePoint = [(minX + maxX) / 2, (minY + maxY) / 2];
    }
    
    // 构建临时文档
    const docData = {
        appName: "WebCAD SVG Import",
        docVer: 0.3,
        dbBlocks: {
            "*Model": {
                blockId: "*Model",
                name: "*Model",
                isLayout: false,
                basePoint: [0, 0],
                lookPt: [0, 0],
                twistAngle: 0,
                zoom: 1,
                UCSXANG: 0,
                UCSORG: [0, 0],
                items: entities
            }
        },
        dbLayers: [{
            name: "0", layerId: "0", layerOn: true,
            color: 7, lineType: "Continuous", lineWeight: -3, plottable: true
        }],
        dbTextStyles: [],
        dbLayouts: [{ layoutId: 0, name: "Model", spaceName: "*Model" }]
    };
    
    const symbolDoc = new CadDocument();
    await symbolDoc.fromDb(docData);
    
    // 合并实体
    const modelBlock = symbolDoc.blocks.itemByName("*Model");
    const basePt = new Point2D(basePoint[0], basePoint[1]);
    const addedEntities = [];
    
    for (const entity of modelBlock.items) {
        if (!entity.isAlive) continue;
        
        const cloned = entity.clone();
        cloned.move(basePt, insertPoint);
        Engine.addEntities(cloned);
        addedEntities.push(cloned);
    }
    
    regen();
    return addedEntities;
}

// 使用示例
const svgContent = `<svg>...</svg>`;
const entities = await importSvg(svgContent, new Point2D(100, 100), {
    enableFill: 1,
    lineWeightScale: 2.0
});
console.log(`导入了 ${entities.length} 个实体`);
```

---

## 从文件导入

```javascript
// 创建文件输入
const input = document.createElement('input');
input.type = 'file';
input.accept = '.svg';

input.onchange = async (e) => {
    const file = e.target.files[0];
    if (!file) return;
    
    // 读取文件内容
    const reader = new FileReader();
    reader.onload = async (event) => {
        const svgContent = event.target.result;
        
        // 导入 SVG
        const entities = await importSvg(svgContent);
        console.log(`从 ${file.name} 导入了 ${entities.length} 个实体`);
        
        Engine.zoomExtents();
    };
    reader.readAsText(file);
};

// 触发文件选择
input.click();
```

---

## 注意事项

1. **WASM 初始化**：首次调用需要初始化 WASM 服务
2. **颜色映射**：SVG 颜色会自动映射到 CAD 颜色索引
3. **复杂路径**：复杂的 `<path>` 元素可能转换为多段线或样条曲线
4. **文字处理**：SVG 文字需要对应字体支持
5. **渐变/滤镜**：不支持 SVG 的渐变、滤镜等高级效果
