唯杰地图 logo唯杰地图
VJMAP
EN

填充图案

vjcad/references/quickref/hatch-pattern.md 11.2 KB466 行
原文

填充实体(HatchEnt)的完整使用指南,包含内置图案、自定义图案、边界创建。

概览

WebCAD 内置 80+ 种填充图案,涵盖 ANSI、ISO、JIS 标准以及各种材质图案。


基本用法

创建填充

const { HatchEnt, PolylineEnt, Engine, Edge, Edges, EdgeType } = vjcad;

// 1. 创建闭合边界
const boundary = new PolylineEnt();
boundary.addVertex([0, 0]);
boundary.addVertex([100, 0]);
boundary.addVertex([100, 60]);
boundary.addVertex([0, 60]);
boundary.isClosed = true;
boundary.setDefaults();

// 2. 创建填充实体
const hatch = new HatchEnt();
hatch.patternName = "SOLID";  // 图案名称
hatch.patternScale = 1;       // 图案比例

// 3. 从多段线创建边界
const edge = new Edge();
edge.edgeType = EdgeType.Polyline;
edge.bulgePoints = boundary.bulgePoints.clone();

const edges = new Edges();
edges.add(edge);

// 4. 设置边界
hatch.setLoops(edges);
hatch.setDefaults();
hatch.color = 3;  // 绿色

// 5. 添加到画布
Engine.addEntities([boundary, hatch]);
Engine.zoomExtents();

填充属性

属性 说明
patternName 图案名称(如 "SOLID", "ANSI31")
patternScale 图案比例(默认 1)
patternAngle 图案角度(弧度,与其他实体 rotate 一致;Math.PI/4 = 45°)
color 填充颜色

内置图案

获取所有图案名称

const patternManager = Engine.patternManager;
const allPatternNames = patternManager.getAllPatternNames();
console.log(`共有 ${allPatternNames.length} 个填充图案`);

实心填充

图案名 说明
SOLID 实心填充

ANSI 图案(美国标准)

图案名 说明
ANSI31 铁、砖和石 (45° 斜线)
ANSI32 钢
ANSI33 青铜、黄铜和紫铜
ANSI34 塑料和橡胶
ANSI35 耐火砖和耐火材质
ANSI36 大理石、板岩和玻璃
ANSI37 铅、锌、镁和绝缘体 (交叉斜线)
ANSI38 铝

AR 图案(建筑)

图案名 说明
AR-B816 8x16 块砖顺砌
AR-B816C 8x16 块砖顺砌(带灰泥接缝)
AR-B88 8x8 块砖顺砌
AR-BRELM 标准砖块英式堆砌
AR-BRSTD 标准砖块顺砌
AR-CONC 随机点和石头图案(混凝土)
AR-HBONE 人字形图案
AR-PARQ1 镶木地板图案
AR-RROOF 屋顶木瓦图案
AR-RSHKE 屋顶实木瓦图案
AR-SAND 随机点图案(沙地)

ISO 图案(国际标准)

图案名 说明
ACAD_ISO02W100 划线
ACAD_ISO03W100 划、空格线
ACAD_ISO04W100 长划、点线
ACAD_ISO05W100 长划、双点线
ACAD_ISO06W100 长划、三点线
ACAD_ISO07W100 点线
ACAD_ISO08W100 长划、短划线
ACAD_ISO09W100 长划、双短划线
ACAD_ISO10W100 划、点线
ACAD_ISO11W100 双划、点线
ACAD_ISO12W100 划、双点线
ACAD_ISO13W100 双划、双点线
ACAD_ISO14W100 划、三点线
ACAD_ISO15W100 双划、三点线

JIS 图案

图案名 说明
JIS_LC_8 LC 图案 (@8)
JIS_LC_8A LC 图案 (@8 变体)
JIS_LC_20 LC 图案 (@20)
JIS_LC_20A LC 图案 (@20 变体)
JIS_RC_10 RC 图案 (@10)
JIS_RC_15 RC 图案 (@15)
JIS_RC_18 RC 图案 (@18)
JIS_RC_30 RC 图案 (@30)
JIS_STN_1E 石材图案 (@1)
JIS_STN_2.5 石材图案 (@2.5)
JIS_WOOD 木材图案

材质图案

图案名 说明
ANGLE 角钢
BOX 方钢
BRASS 黄铜
BRICK 砖
BRSTONE 砖和石
CLAY 粘土
CORK 软木
CROSS 十字形
DASH 划线
DOLMIT 地壳岩层
DOTS 点
EARTH 地面
ESCHER Escher 图案
FLEX 软性材质
GRASS 草地
GRATE 格栅
GRAVEL 沙砾
HEX 六边形
HONEY 蜂巢
HOUND 犬牙交错
INSUL 绝缘材质
LINE 平行水平线
MUDST 泥沙
NET 水平/垂直栅格
NET3 网状 0-60-120
PLAST 塑料
PLASTI 塑料(变体)
SACNCR 混凝土
SQUARE 小方块
STARS 六芒星
STEEL 钢
SWAMP 沼泽
TRANS 热传递材质
TRIANG 等边三角形
ZIGZAG 锯齿
GOST_GLASS 玻璃 (GOST)
GOST_WOOD 木材 (GOST)
GOST_GROUND 地面 (GOST)

边界类型

多段线边界

const boundary = new PolylineEnt();
boundary.setPoints([[0, 0], [60, 0], [60, 50], [30, 70], [0, 50]]);
boundary.isClosed = true;
boundary.setDefaults();

const edges = new Edges();
const edge = new Edge();
edge.edgeType = EdgeType.Polyline;
edge.bulgePoints = boundary.bulgePoints.clone();
edges.add(edge);

hatch.setLoops(edges);

圆形边界

const { CircleEnt } = vjcad;

const circle = new CircleEnt([100, 50], 30);
circle.setDefaults();

const edges = new Edges();
const edge = new Edge();
edge.edgeType = EdgeType.Circle;
edge.center = circle.center.clone();
edge.radius = circle.radius;
edges.add(edge);

hatch.setLoops(edges);

带孔填充(外边界 + 内边界)

// 外边界(矩形)
const outerRect = new PolylineEnt();
outerRect.setPoints([[0, 0], [100, 0], [100, 80], [0, 80]]);
outerRect.isClosed = true;
outerRect.setDefaults();

// 内边界(圆形孔)
const innerCircle = new CircleEnt([50, 40], 20);
innerCircle.setDefaults();

// 创建 Edges(外边界 + 内边界)
const allEdges = new Edges();

// 外边界
const outerEdge = new Edge();
outerEdge.edgeType = EdgeType.Polyline;
outerEdge.bulgePoints = outerRect.bulgePoints.clone();
allEdges.add(outerEdge);

// 内边界(孔)
const innerEdge = new Edge();
innerEdge.edgeType = EdgeType.Circle;
innerEdge.center = innerCircle.center.clone();
innerEdge.radius = innerCircle.radius;
allEdges.add(innerEdge);

// 设置边界
hatch.setLoops(allEdges);

图案比例

自动计算比例

const { calculateHatchPatternScale } = vjcad;

// 计算边界大小
const bbox = boundary.boundingBox();
const boundsSize = Math.max(bbox.maxX - bbox.minX, bbox.maxY - bbox.minY);

// 获取图案定义
const patternDef = Engine.patternManager.getPattern(patternName);

// 自动计算合适的比例
const autoScale = calculateHatchPatternScale(boundsSize, patternName, patternDef);

hatch.patternScale = autoScale;

手动设置比例

hatch.patternScale = 2;  // 放大 2 倍
hatch.patternScale = 0.5; // 缩小一半

自定义图案

PAT 格式说明

*图案名称,图案描述
角度,X原点,Y原点,deltaX,deltaY[,线型定义...]
  • 角度: 线条绘制方向(度),0=水平向右,90=垂直向上
  • X原点/Y原点: 第一条线的起点坐标
  • deltaX: 沿线条方向的偏移量
  • deltaY: 垂直于线条方向的偏移量(行间距)
  • 线型定义: 可选的虚线模式(正数=实线,负数=空隙,0=点)

注册自定义图案

最简单:直接把 PAT 文本交给内置解析器(可含多个 *图案,返回成功加载的数量):

const count = Engine.patternManager.loadFromPATDefinitions(`*MY_PATTERN,我的自定义图案
45,0,0,0,5
135,0,0,0,5`, "custom");

也可以自己解析后 registerPattern:

// PAT 格式字符串
const patString = `*MY_PATTERN,我的自定义图案
45,0,0,0,5
135,0,0,0,5`;

// 解析 PAT 格式
function parsePatternString(patString) {
    const lines = patString.trim().split('\n');
    const headerMatch = lines[0].match(/^\*([^,]+),(.*)$/);
    
    const name = headerMatch[1].trim();
    const description = headerMatch[2].trim();
    
    const patternLines = [];
    for (let i = 1; i < lines.length; i++) {
        const line = lines[i].trim();
        if (!line || line.startsWith(';')) continue;
        
        const parts = line.split(',').map(p => parseFloat(p.trim()));
        patternLines.push({
            angle: parts[0],
            xOrigin: parts[1],
            yOrigin: parts[2],
            deltaX: parts[3],
            deltaY: parts[4],
            dashes: parts.slice(5)
        });
    }
    
    return { name, description, lines: patternLines };
}

// 注册图案
const patternDef = parsePatternString(patString);
Engine.patternManager.registerPattern(patternDef, "custom");

PatternManager API

获取管理器

const patternManager = Engine.patternManager;

常用方法

// 获取所有图案名称
const allNames = patternManager.getAllPatternNames();
const categoryNames = patternManager.getAllPatternNames("builtin");

// 获取图案定义
const patternDef = patternManager.getPattern("ANSI31");
console.log(patternDef.name);
console.log(patternDef.description);
console.log(patternDef.lines);  // 线定义数组

// 检查图案是否存在
const exists = patternManager.hasPattern("MY_PATTERN");

// 注册自定义图案
patternManager.registerPattern(definition, "custom");

// 获取分类
const categories = patternManager.getCategories();

// 获取统计信息
const stats = patternManager.getStatistics();

完整示例:图案表

const { 
    HatchEnt, PolylineEnt, TextEnt, 
    Engine, Edge, Edges, EdgeType 
} = vjcad;

const patternManager = Engine.patternManager;
const allPatternNames = patternManager.getAllPatternNames();

const COLS = 6;
const CELL_WIDTH = 80;
const CELL_HEIGHT = 60;
const PADDING = 10;

function createEdgesFromPolyline(polyline) {
    const edges = new Edges();
    const edge = new Edge();
    edge.edgeType = EdgeType.Polyline;
    edge.bulgePoints = polyline.bulgePoints.clone();
    edges.add(edge);
    return edges;
}

const allEntities = [];

allPatternNames.forEach((patternName, i) => {
    const col = i % COLS;
    const row = Math.floor(i / COLS);
    const x = col * (CELL_WIDTH + PADDING);
    const y = -row * (CELL_HEIGHT + PADDING + 20);
    
    // 边界
    const boundary = new PolylineEnt();
    boundary.addVertex([x, y]);
    boundary.addVertex([x + CELL_WIDTH, y]);
    boundary.addVertex([x + CELL_WIDTH, y + CELL_HEIGHT]);
    boundary.addVertex([x, y + CELL_HEIGHT]);
    boundary.isClosed = true;
    boundary.setDefaults();
    allEntities.push(boundary);
    
    // 填充
    const hatch = new HatchEnt();
    hatch.patternName = patternName;
    hatch.patternScale = patternName === "SOLID" ? 1 : 5;
    hatch.setLoops(createEdgesFromPolyline(boundary));
    hatch.setDefaults();
    hatch.color = patternName === "SOLID" ? 3 : 2;
    allEntities.push(hatch);
    
    // 标签
    const label = new TextEnt();
    label.insertionPoint = [x, y - 8];
    label.text = patternName;
    label.height = 5;
    label.setDefaults();
    allEntities.push(label);
});

Engine.addEntities(allEntities);
Engine.zoomExtents();

命令方式

// HATCH 命令:选择边界并填充
await Engine.editor.executerWithOp('HATCH');

// EHATCH 命令:编辑现有填充(注册名是 EHATCH,不是 HATCHEDIT)
await Engine.editor.executerWithOp('EHATCH');