TkAstral3D/packages/sdk/lib/dxf/parser/entities/hatch.ts
2025-10-04 23:36:07 +08:00

347 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import DxfArrayScanner, {IGroup} from '../DxfArrayScanner';
import * as helpers from '../ParseHelpers'
import IGeometry, {IEntity, IPoint} from './geomtry';
export interface IHatchEntity extends IEntity {
boundaryLoops: any[];
definitionLines: any[];
seedPoints: any[];
patternName: string;
isSolid: boolean;
hatchStyle: string;
patternType: number;
patternAngle: number;
patternScale: number;
}
export default class Hatch implements IGeometry {
public ForEntityName = 'HATCH' as const;
public parseEntity(scanner: DxfArrayScanner, curr: IGroup) {
let entity = {type: curr.value} as IHatchEntity;
let numBoundaryLoops = 0;
let numDefinitionLines = 0;
let numSeedPoints = 0;
curr = scanner.next();
while (!scanner.isEOF()) {
if (curr.code === 0) break;
while (numBoundaryLoops > 0) {
const loop = ParseBoundaryLoop(curr, scanner)
if (loop) {
entity.boundaryLoops.push(loop);
numBoundaryLoops--;
curr = scanner.next();
} else {
numBoundaryLoops = 0
}
}
while (numDefinitionLines > 0) {
const line = ParseDefinitionLine(curr, scanner)
if (line) {
entity.definitionLines.push(line);
numDefinitionLines--;
curr = scanner.next();
} else {
numDefinitionLines = 0
}
}
while (numSeedPoints > 0) {
const pt = ParseSeedPoint(curr, scanner);
if (pt) {
entity.seedPoints.push(pt);
numSeedPoints--;
curr = scanner.next();
} else {
numSeedPoints = 0
}
}
if (curr.code === 0) break;
switch (curr.code) {
case 2: // 填充图案名
entity.patternName = curr.value as string;
break;
case 70: // 实体填充标志(实体填充 = 1图案填充 = 0
entity.isSolid = curr.value != 0;
break;
case 91: // 边界路径(环)数
numBoundaryLoops = curr.value as number;
if (numBoundaryLoops > 0) {
entity.boundaryLoops = []
}
break;
/**
* 图案填充样式:
* 0 = 对“奇数奇偶校验”区域进行图案填充(普通样式)
* 1 = 仅对最外层区域进行图案填充(“外部”样式)
* 2 = 对整个区域进行图案填充(“忽略”样式)
*/
case 75:
entity.hatchStyle = curr.value as string;
break;
/**
* 填充图案类型:
* 0 = 用户定义1 = 预定义2 = 自定义
*/
case 76:
entity.patternType = curr.value as number;
break;
case 52: // 填充图案角度(仅限图案填充)
entity.patternAngle = (curr.value as number) * Math.PI / 180;
break;
case 41: // 填充图案比例或间距(仅限图案填充)
entity.patternScale = curr.value as number;
break;
case 78: // 图案定义直线数
numDefinitionLines = curr.value as number;
if (numDefinitionLines > 0) {
entity.definitionLines = []
}
break;
case 98: // 种子点数
numSeedPoints = curr.value as number;
if (numSeedPoints > 0) {
entity.seedPoints = []
}
break;
default: // 检查通用实体属性
helpers.checkCommonEntityProperties(entity, curr, scanner);
break;
}
curr = scanner.next();
}
return entity;
};
}
function ParseBoundaryLoop(curr: IGroup, scanner: DxfArrayScanner) {
let entity:any = null
const ParsePolyline = () => {
const pl: { vertices: IPoint[], isClosed: boolean } = {vertices: [], isClosed: false};
let numVertices = 0;
while (true) {
if (numVertices > 0) {
for (let i = 0; i < numVertices; i++) {
if (curr.code != 10) {
break
}
const p = helpers.parsePoint(scanner)
curr = scanner.next();
if (curr.code == 42) {
// @ts-ignore
p.bulge = curr.value;
curr = scanner.next();
}
pl.vertices.push(p)
}
return pl
}
switch (curr.code) {
case 73:
pl.isClosed = curr.value as boolean;
break;
case 93:
numVertices = curr.value as number;
break;
default:
return pl;
}
curr = scanner.next();
}
}
const ParseEdge = () => {
if (curr.code != 72) {
return null
}
const e:any = {type: curr.value}
curr = scanner.next();
const isSpline = e.type == 4;
while (true) {
switch (curr.code) {
case 10:
if (isSpline) {
if (!e.controlPoints) {
e.controlPoints = [];
}
e.controlPoints.push(helpers.parsePoint(scanner));
} else {
e.start = helpers.parsePoint(scanner);
}
break;
case 11:
if (isSpline) {
if (!e.fitPoints) {
e.fitPoints = [];
}
e.fitPoints.push(helpers.parsePoint(scanner));
} else {
e.end = helpers.parsePoint(scanner);
}
break;
case 40:
if (isSpline) {
if (!e.knotValues) {
e.knotValues = [];
}
e.knotValues.push(curr.value);
} else {
e.radius = curr.value;
}
break;
case 50:
e.startAngle = (curr.value as number) * Math.PI / 180;
break;
case 51:
e.endAngle = (curr.value as number) * Math.PI / 180;
break;
case 73:
if (isSpline) {
e.rational = curr.value;
} else {
e.isCcw = curr.value;
}
break;
case 74:
e.periodic = curr.value;
break;
case 94:
e.degreeOfSplineCurve = curr.value;
break;
//XXX暂时忽略一些群体主要是样条
case 95:
case 96:
case 42:
case 97:
break;
default:
return e
}
curr = scanner.next();
}
}
let polylineParsed = false;
let numEdges = 0;
let numSourceRefs = 0;
while (true) {
if (!entity) {
if (curr.code != 92) {
return null;
}
entity = {type: curr.value};
curr = scanner.next();
}
if ((entity.type & 2) && !polylineParsed) {
entity.polyline = ParsePolyline()
polylineParsed = true
}
while (numEdges) {
const edge = ParseEdge();
if (edge) {
entity.edges.push(edge);
numEdges--;
} else {
numEdges = 0;
}
}
while (numSourceRefs) {
if (curr.code == 330) {
entity.sourceRefs.push(curr.value);
numSourceRefs--;
curr = scanner.next();
} else {
numSourceRefs = 0
}
}
switch (curr.code) {
case 93:
numEdges = curr.value as number;
if (numEdges > 0) {
entity.edges = []
}
break;
case 97:
numSourceRefs = curr.value as number;
if (numSourceRefs > 0) {
entity.sourceRefs = []
}
break;
default:
scanner.rewind();
return entity;
}
curr = scanner.next();
}
}
function ParseDefinitionLine(curr: IGroup, scanner: DxfArrayScanner) {
/* 假设总是从53组开始. */
if (curr.code != 53) {
return null
}
const entity:any = {
angle: (curr.value as number) * Math.PI / 180,
base: {x: 0, y: 0},
offset: {x: 0, y: 0}
};
curr = scanner.next();
let numDashes = 0;
while (true) {
switch (curr.code) {
case 43:
entity.base.x = curr.value as number;
break;
case 44:
entity.base.y = curr.value as number;
break;
case 45:
entity.offset.x = curr.value as number;
break;
case 46:
entity.offset.y = curr.value as number;
break;
case 49:
if (numDashes > 0) {
entity.dashes.push(curr.value);
numDashes--;
}
break;
case 79:
numDashes = curr.value as number;
if (curr.value) {
entity.dashes = []
}
break;
default:
scanner.rewind();
return entity;
}
curr = scanner.next();
}
}
function ParseSeedPoint(curr: IGroup, scanner: DxfArrayScanner) {
if (curr.code != 10) {
return null
}
return helpers.parsePoint(scanner);
}