ofs-dxf-ts 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +411 -0
- package/CHANGELOG.md +26 -0
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/core/dxf-builder.d.ts +348 -0
- package/dist/core/dxf-builder.js +549 -0
- package/dist/core/dxf-document.d.ts +220 -0
- package/dist/core/dxf-document.js +529 -0
- package/dist/core/dxf-entities.d.ts +327 -0
- package/dist/core/dxf-entities.js +22 -0
- package/dist/core/dxf-serializer.d.ts +48 -0
- package/dist/core/dxf-serializer.js +595 -0
- package/dist/core/hatch-patterns.d.ts +15 -0
- package/dist/core/hatch-patterns.js +214 -0
- package/dist/core/modelspace.d.ts +106 -0
- package/dist/core/modelspace.js +351 -0
- package/dist/geometry/math.utils.d.ts +8 -0
- package/dist/geometry/math.utils.js +43 -0
- package/dist/geometry/offset.utils.d.ts +32 -0
- package/dist/geometry/offset.utils.js +87 -0
- package/dist/geometry/polyline.utils.d.ts +10 -0
- package/dist/geometry/polyline.utils.js +63 -0
- package/dist/geometry/text.utils.d.ts +15 -0
- package/dist/geometry/text.utils.js +28 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +29 -0
- package/dist/parser/auto-cad-color-index.d.ts +8 -0
- package/dist/parser/auto-cad-color-index.js +265 -0
- package/dist/parser/dim-style-codes.d.ts +5 -0
- package/dist/parser/dim-style-codes.js +32 -0
- package/dist/parser/dxf-parser.d.ts +16 -0
- package/dist/parser/dxf-parser.js +824 -0
- package/dist/parser/entities/3dface.d.ts +5 -0
- package/dist/parser/entities/3dface.js +76 -0
- package/dist/parser/entities/arc.d.ts +5 -0
- package/dist/parser/entities/arc.js +34 -0
- package/dist/parser/entities/attdef.d.ts +5 -0
- package/dist/parser/entities/attdef.js +86 -0
- package/dist/parser/entities/attribute.d.ts +5 -0
- package/dist/parser/entities/attribute.js +106 -0
- package/dist/parser/entities/circle.d.ts +5 -0
- package/dist/parser/entities/circle.js +40 -0
- package/dist/parser/entities/dimension.d.ts +5 -0
- package/dist/parser/entities/dimension.js +65 -0
- package/dist/parser/entities/ellipse.d.ts +5 -0
- package/dist/parser/entities/ellipse.js +42 -0
- package/dist/parser/entities/hatch.d.ts +5 -0
- package/dist/parser/entities/hatch.js +321 -0
- package/dist/parser/entities/insert.d.ts +5 -0
- package/dist/parser/entities/insert.js +52 -0
- package/dist/parser/entities/line.d.ts +5 -0
- package/dist/parser/entities/line.js +30 -0
- package/dist/parser/entities/lwpolyline.d.ts +5 -0
- package/dist/parser/entities/lwpolyline.js +101 -0
- package/dist/parser/entities/mtext.d.ts +5 -0
- package/dist/parser/entities/mtext.js +54 -0
- package/dist/parser/entities/point.d.ts +5 -0
- package/dist/parser/entities/point.js +30 -0
- package/dist/parser/entities/polyline.d.ts +5 -0
- package/dist/parser/entities/polyline.js +85 -0
- package/dist/parser/entities/solid.d.ts +5 -0
- package/dist/parser/entities/solid.js +35 -0
- package/dist/parser/entities/spline.d.ts +5 -0
- package/dist/parser/entities/spline.js +69 -0
- package/dist/parser/entities/text.d.ts +5 -0
- package/dist/parser/entities/text.js +47 -0
- package/dist/parser/entities/vertex.d.ts +5 -0
- package/dist/parser/entities/vertex.js +59 -0
- package/dist/parser/extended-data-parser.d.ts +18 -0
- package/dist/parser/extended-data-parser.js +100 -0
- package/dist/parser/index.d.ts +10 -0
- package/dist/parser/index.js +9 -0
- package/dist/parser/log.d.ts +14 -0
- package/dist/parser/log.js +39 -0
- package/dist/parser/parse-helpers.d.ts +23 -0
- package/dist/parser/parse-helpers.js +128 -0
- package/dist/parser/scanner.d.ts +29 -0
- package/dist/parser/scanner.js +143 -0
- package/dist/parser/types.d.ts +78 -0
- package/dist/parser/types.js +5 -0
- package/dist/symbols/slope-symbol.d.ts +21 -0
- package/dist/symbols/slope-symbol.js +81 -0
- package/dist/symbols/structures.d.ts +9 -0
- package/dist/symbols/structures.js +120 -0
- package/dist/template/blank-document.d.ts +13 -0
- package/dist/template/blank-document.js +13 -0
- package/dist/template/block-registry.d.ts +16 -0
- package/dist/template/block-registry.js +135 -0
- package/dist/template/index.d.ts +17 -0
- package/dist/template/index.js +17 -0
- package/dist/template/template-injector.d.ts +45 -0
- package/dist/template/template-injector.js +487 -0
- package/dist/template/template-reader.d.ts +28 -0
- package/dist/template/template-reader.js +80 -0
- package/dist/types/index.d.ts +24 -0
- package/dist/types/index.js +8 -0
- package/package.json +59 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as helpers from '../parse-helpers.js';
|
|
2
|
+
import VertexParser from './vertex.js';
|
|
3
|
+
export default class Polyline {
|
|
4
|
+
static ForEntityName = 'POLYLINE';
|
|
5
|
+
parseEntity(scanner, curr) {
|
|
6
|
+
const entity = { type: curr.value, vertices: [] };
|
|
7
|
+
curr = scanner.next();
|
|
8
|
+
while (true) {
|
|
9
|
+
if (curr.code === 0)
|
|
10
|
+
break;
|
|
11
|
+
switch (curr.code) {
|
|
12
|
+
case 10: // always 0
|
|
13
|
+
break;
|
|
14
|
+
case 20: // always 0
|
|
15
|
+
break;
|
|
16
|
+
case 30: // elevation
|
|
17
|
+
break;
|
|
18
|
+
case 39: // thickness
|
|
19
|
+
entity.thickness = curr.value;
|
|
20
|
+
break;
|
|
21
|
+
case 40: // start width
|
|
22
|
+
break;
|
|
23
|
+
case 41: // end width
|
|
24
|
+
break;
|
|
25
|
+
case 70:
|
|
26
|
+
entity.shape = (curr.value & 1) !== 0;
|
|
27
|
+
entity.includesCurveFitVertices = (curr.value & 2) !== 0;
|
|
28
|
+
entity.includesSplineFitVertices = (curr.value & 4) !== 0;
|
|
29
|
+
entity.is3dPolyline = (curr.value & 8) !== 0;
|
|
30
|
+
entity.is3dPolygonMesh = (curr.value & 16) !== 0;
|
|
31
|
+
entity.is3dPolygonMeshClosed = (curr.value & 32) !== 0; // 32 = The polygon mesh is closed in the N direction
|
|
32
|
+
entity.isPolyfaceMesh = (curr.value & 64) !== 0;
|
|
33
|
+
entity.hasContinuousLinetypePattern = (curr.value & 128) !== 0;
|
|
34
|
+
break;
|
|
35
|
+
case 71: // Polygon mesh M vertex count
|
|
36
|
+
break;
|
|
37
|
+
case 72: // Polygon mesh N vertex count
|
|
38
|
+
break;
|
|
39
|
+
case 73: // Smooth surface M density
|
|
40
|
+
break;
|
|
41
|
+
case 74: // Smooth surface N density
|
|
42
|
+
break;
|
|
43
|
+
case 75: // Curves and smooth surface type
|
|
44
|
+
break;
|
|
45
|
+
case 210:
|
|
46
|
+
entity.extrusionDirection = helpers.parsePoint(scanner);
|
|
47
|
+
break;
|
|
48
|
+
default:
|
|
49
|
+
helpers.checkCommonEntityProperties(entity, curr, scanner);
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
curr = scanner.next();
|
|
53
|
+
}
|
|
54
|
+
entity.vertices = parsePolylineVertices(scanner, curr);
|
|
55
|
+
return entity;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function parsePolylineVertices(scanner, curr) {
|
|
59
|
+
const vertexParser = new VertexParser();
|
|
60
|
+
const vertices = [];
|
|
61
|
+
while (!scanner.isEOF()) {
|
|
62
|
+
if (curr.code === 0) {
|
|
63
|
+
if (curr.value === 'VERTEX') {
|
|
64
|
+
vertices.push(vertexParser.parseEntity(scanner, curr));
|
|
65
|
+
curr = scanner.lastReadGroup;
|
|
66
|
+
}
|
|
67
|
+
else if (curr.value === 'SEQEND') {
|
|
68
|
+
parseSeqEnd(scanner, curr);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return vertices;
|
|
74
|
+
}
|
|
75
|
+
function parseSeqEnd(scanner, curr) {
|
|
76
|
+
const entity = { type: curr.value };
|
|
77
|
+
curr = scanner.next();
|
|
78
|
+
while (true) {
|
|
79
|
+
if (curr.code == 0)
|
|
80
|
+
break;
|
|
81
|
+
helpers.checkCommonEntityProperties(entity, curr, scanner);
|
|
82
|
+
curr = scanner.next();
|
|
83
|
+
}
|
|
84
|
+
return entity;
|
|
85
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as helpers from '../parse-helpers.js';
|
|
2
|
+
export default class Solid {
|
|
3
|
+
static ForEntityName = 'SOLID';
|
|
4
|
+
parseEntity(scanner, currentGroup) {
|
|
5
|
+
const entity = { type: currentGroup.value };
|
|
6
|
+
entity.points = [];
|
|
7
|
+
currentGroup = scanner.next();
|
|
8
|
+
while (true) {
|
|
9
|
+
if (currentGroup.code === 0)
|
|
10
|
+
break;
|
|
11
|
+
switch (currentGroup.code) {
|
|
12
|
+
case 10:
|
|
13
|
+
entity.points[0] = helpers.parsePoint(scanner);
|
|
14
|
+
break;
|
|
15
|
+
case 11:
|
|
16
|
+
entity.points[1] = helpers.parsePoint(scanner);
|
|
17
|
+
break;
|
|
18
|
+
case 12:
|
|
19
|
+
entity.points[2] = helpers.parsePoint(scanner);
|
|
20
|
+
break;
|
|
21
|
+
case 13:
|
|
22
|
+
entity.points[3] = helpers.parsePoint(scanner);
|
|
23
|
+
break;
|
|
24
|
+
case 210:
|
|
25
|
+
entity.extrusionDirection = helpers.parsePoint(scanner);
|
|
26
|
+
break;
|
|
27
|
+
default: // check common entity attributes
|
|
28
|
+
helpers.checkCommonEntityProperties(entity, currentGroup, scanner);
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
currentGroup = scanner.next();
|
|
32
|
+
}
|
|
33
|
+
return entity;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as helpers from '../parse-helpers.js';
|
|
2
|
+
export default class Spline {
|
|
3
|
+
static ForEntityName = 'SPLINE';
|
|
4
|
+
parseEntity(scanner, curr) {
|
|
5
|
+
const entity = { type: curr.value };
|
|
6
|
+
curr = scanner.next();
|
|
7
|
+
while (true) {
|
|
8
|
+
if (curr.code === 0)
|
|
9
|
+
break;
|
|
10
|
+
switch (curr.code) {
|
|
11
|
+
case 10:
|
|
12
|
+
if (!entity.controlPoints)
|
|
13
|
+
entity.controlPoints = [];
|
|
14
|
+
entity.controlPoints.push(helpers.parsePoint(scanner));
|
|
15
|
+
break;
|
|
16
|
+
case 11:
|
|
17
|
+
if (!entity.fitPoints)
|
|
18
|
+
entity.fitPoints = [];
|
|
19
|
+
entity.fitPoints.push(helpers.parsePoint(scanner));
|
|
20
|
+
break;
|
|
21
|
+
case 12:
|
|
22
|
+
entity.startTangent = helpers.parsePoint(scanner);
|
|
23
|
+
break;
|
|
24
|
+
case 13:
|
|
25
|
+
entity.endTangent = helpers.parsePoint(scanner);
|
|
26
|
+
break;
|
|
27
|
+
case 40:
|
|
28
|
+
if (!entity.knotValues)
|
|
29
|
+
entity.knotValues = [];
|
|
30
|
+
entity.knotValues.push(curr.value);
|
|
31
|
+
break;
|
|
32
|
+
case 70:
|
|
33
|
+
if ((curr.value & 1) != 0)
|
|
34
|
+
entity.closed = true;
|
|
35
|
+
if ((curr.value & 2) != 0)
|
|
36
|
+
entity.periodic = true;
|
|
37
|
+
if ((curr.value & 4) != 0)
|
|
38
|
+
entity.rational = true;
|
|
39
|
+
if ((curr.value & 8) != 0)
|
|
40
|
+
entity.planar = true;
|
|
41
|
+
if ((curr.value & 16) != 0) {
|
|
42
|
+
entity.planar = true;
|
|
43
|
+
entity.linear = true;
|
|
44
|
+
}
|
|
45
|
+
break;
|
|
46
|
+
case 71:
|
|
47
|
+
entity.degreeOfSplineCurve = curr.value;
|
|
48
|
+
break;
|
|
49
|
+
case 72:
|
|
50
|
+
entity.numberOfKnots = curr.value;
|
|
51
|
+
break;
|
|
52
|
+
case 73:
|
|
53
|
+
entity.numberOfControlPoints = curr.value;
|
|
54
|
+
break;
|
|
55
|
+
case 74:
|
|
56
|
+
entity.numberOfFitPoints = curr.value;
|
|
57
|
+
break;
|
|
58
|
+
case 210:
|
|
59
|
+
entity.extrusionDirection = helpers.parsePoint(scanner);
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
helpers.checkCommonEntityProperties(entity, curr, scanner);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
curr = scanner.next();
|
|
66
|
+
}
|
|
67
|
+
return entity;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as helpers from '../parse-helpers.js';
|
|
2
|
+
export default class Text {
|
|
3
|
+
static ForEntityName = 'TEXT';
|
|
4
|
+
parseEntity(scanner, curr) {
|
|
5
|
+
const entity = { type: curr.value };
|
|
6
|
+
curr = scanner.next();
|
|
7
|
+
while (true) {
|
|
8
|
+
if (curr.code === 0)
|
|
9
|
+
break;
|
|
10
|
+
switch (curr.code) {
|
|
11
|
+
case 10: // X coordinate of 'first alignment point'
|
|
12
|
+
entity.startPoint = helpers.parsePoint(scanner);
|
|
13
|
+
break;
|
|
14
|
+
case 11: // X coordinate of 'second alignment point'
|
|
15
|
+
entity.endPoint = helpers.parsePoint(scanner);
|
|
16
|
+
break;
|
|
17
|
+
case 40: // Text height
|
|
18
|
+
entity.textHeight = curr.value;
|
|
19
|
+
break;
|
|
20
|
+
case 41:
|
|
21
|
+
entity.xScale = curr.value;
|
|
22
|
+
break;
|
|
23
|
+
case 50: // Rotation in degrees
|
|
24
|
+
entity.rotation = curr.value;
|
|
25
|
+
break;
|
|
26
|
+
case 7: // Text style name
|
|
27
|
+
entity.styleName = curr.value;
|
|
28
|
+
break;
|
|
29
|
+
case 1: // Text
|
|
30
|
+
entity.text = curr.value;
|
|
31
|
+
break;
|
|
32
|
+
// NOTE: 72 and 73 are meaningless without 11 (second alignment point)
|
|
33
|
+
case 72: // Horizontal alignment
|
|
34
|
+
entity.halign = curr.value;
|
|
35
|
+
break;
|
|
36
|
+
case 73: // Vertical alignment
|
|
37
|
+
entity.valign = curr.value;
|
|
38
|
+
break;
|
|
39
|
+
default: // check common entity attributes
|
|
40
|
+
helpers.checkCommonEntityProperties(entity, curr, scanner);
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
curr = scanner.next();
|
|
44
|
+
}
|
|
45
|
+
return entity;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as helpers from '../parse-helpers.js';
|
|
2
|
+
export default class Vertex {
|
|
3
|
+
static ForEntityName = 'VERTEX';
|
|
4
|
+
parseEntity(scanner, curr) {
|
|
5
|
+
const entity = { type: curr.value };
|
|
6
|
+
curr = scanner.next();
|
|
7
|
+
while (true) {
|
|
8
|
+
if (curr.code === 0)
|
|
9
|
+
break;
|
|
10
|
+
switch (curr.code) {
|
|
11
|
+
case 10: // X
|
|
12
|
+
entity.x = curr.value;
|
|
13
|
+
break;
|
|
14
|
+
case 20: // Y
|
|
15
|
+
entity.y = curr.value;
|
|
16
|
+
break;
|
|
17
|
+
case 30: // Z
|
|
18
|
+
entity.z = curr.value;
|
|
19
|
+
break;
|
|
20
|
+
case 40: // start width
|
|
21
|
+
break;
|
|
22
|
+
case 41: // end width
|
|
23
|
+
break;
|
|
24
|
+
case 42: // bulge
|
|
25
|
+
if (curr.value != 0)
|
|
26
|
+
entity.bulge = curr.value;
|
|
27
|
+
break;
|
|
28
|
+
case 70: // flags
|
|
29
|
+
entity.curveFittingVertex = (curr.value & 1) !== 0;
|
|
30
|
+
entity.curveFitTangent = (curr.value & 2) !== 0;
|
|
31
|
+
entity.splineVertex = (curr.value & 8) !== 0;
|
|
32
|
+
entity.splineControlPoint = (curr.value & 16) !== 0;
|
|
33
|
+
entity.threeDPolylineVertex = (curr.value & 32) !== 0;
|
|
34
|
+
entity.threeDPolylineMesh = (curr.value & 64) !== 0;
|
|
35
|
+
entity.polyfaceMeshVertex = (curr.value & 128) !== 0;
|
|
36
|
+
break;
|
|
37
|
+
case 50: // curve fit tangent direction
|
|
38
|
+
break;
|
|
39
|
+
case 71: // polyface mesh vertex index
|
|
40
|
+
entity.faces = [curr.value];
|
|
41
|
+
break;
|
|
42
|
+
case 72: // polyface mesh vertex index
|
|
43
|
+
entity.faces[1] = curr.value;
|
|
44
|
+
break;
|
|
45
|
+
case 73: // polyface mesh vertex index
|
|
46
|
+
entity.faces[2] = curr.value;
|
|
47
|
+
break;
|
|
48
|
+
case 74: // polyface mesh vertex index
|
|
49
|
+
entity.faces[3] = curr.value;
|
|
50
|
+
break;
|
|
51
|
+
default:
|
|
52
|
+
helpers.checkCommonEntityProperties(entity, curr, scanner);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
curr = scanner.next();
|
|
56
|
+
}
|
|
57
|
+
return entity;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DxfEntity, DxfGroup } from './types.js';
|
|
2
|
+
export default class ExtendedDataParser {
|
|
3
|
+
private appName;
|
|
4
|
+
private appNameWarningShown;
|
|
5
|
+
private lastString;
|
|
6
|
+
private sectionStack;
|
|
7
|
+
private failure;
|
|
8
|
+
/**
|
|
9
|
+
* Feed next token.
|
|
10
|
+
* @return True if new parser instance should be created for this token.
|
|
11
|
+
*/
|
|
12
|
+
Feed(curr: DxfGroup): boolean;
|
|
13
|
+
/** Finalize XDATA section parsing. */
|
|
14
|
+
Finish(entity: DxfEntity): void;
|
|
15
|
+
private get _currentSection();
|
|
16
|
+
private _CreateSection;
|
|
17
|
+
private _CreateValue;
|
|
18
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import log from './log.js';
|
|
2
|
+
export default class ExtendedDataParser {
|
|
3
|
+
appName = null;
|
|
4
|
+
appNameWarningShown = false;
|
|
5
|
+
lastString = null;
|
|
6
|
+
sectionStack = [this._CreateSection()];
|
|
7
|
+
failure = false;
|
|
8
|
+
/**
|
|
9
|
+
* Feed next token.
|
|
10
|
+
* @return True if new parser instance should be created for this token.
|
|
11
|
+
*/
|
|
12
|
+
Feed(curr) {
|
|
13
|
+
if (!this.appName) {
|
|
14
|
+
if (curr.code === 1001) {
|
|
15
|
+
this.appName = curr.value;
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (!this.appNameWarningShown) {
|
|
19
|
+
this.appNameWarningShown = true;
|
|
20
|
+
log.warn('XDATA section does not start with application name');
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (curr.code === 1001) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (this.failure) {
|
|
28
|
+
/* Ignore all the rest content in case of parsing failure. */
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
if (curr.code === 1000) {
|
|
32
|
+
if (this.lastString) {
|
|
33
|
+
log.warn('XDATA section unused string: ' + this.lastString);
|
|
34
|
+
}
|
|
35
|
+
this.lastString = curr.value;
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const curSection = this._currentSection;
|
|
39
|
+
if (curr.code === 1002) {
|
|
40
|
+
if (curr.value === '{') {
|
|
41
|
+
if (!this.lastString) {
|
|
42
|
+
log.warn('Unnamed XDATA section encountered');
|
|
43
|
+
this.failure = true;
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const newSection = this._CreateSection();
|
|
47
|
+
curSection[this.lastString] = newSection;
|
|
48
|
+
this.lastString = null;
|
|
49
|
+
this.sectionStack.push(newSection);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (curr.value === '}') {
|
|
53
|
+
if (this.sectionStack.length < 2) {
|
|
54
|
+
log.warn('Unmatched XDATA section closing');
|
|
55
|
+
this.failure = true;
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
this.sectionStack.length = this.sectionStack.length - 1;
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
log.warn('Bad XDATA section control string encountered: ' + curr.value);
|
|
62
|
+
this.failure = true;
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (this.lastString !== null) {
|
|
66
|
+
curSection.values.push(this._CreateValue(1000, this.lastString));
|
|
67
|
+
this.lastString = null;
|
|
68
|
+
}
|
|
69
|
+
curSection.values.push(this._CreateValue(curr.code, curr.value));
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
/** Finalize XDATA section parsing. */
|
|
73
|
+
Finish(entity) {
|
|
74
|
+
if (this.failure) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (this.appName) {
|
|
78
|
+
let xdata;
|
|
79
|
+
if (Object.prototype.hasOwnProperty.call(entity, 'xdata')) {
|
|
80
|
+
xdata = entity.xdata;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
xdata = {};
|
|
84
|
+
entity.xdata = xdata;
|
|
85
|
+
}
|
|
86
|
+
xdata[this.appName] = this.sectionStack[0];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
get _currentSection() {
|
|
90
|
+
return this.sectionStack[this.sectionStack.length - 1];
|
|
91
|
+
}
|
|
92
|
+
_CreateSection() {
|
|
93
|
+
return {
|
|
94
|
+
values: [],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
_CreateValue(code, value) {
|
|
98
|
+
return { code, value };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal DXF parser — TypeScript port of the `dxf-parser` npm package
|
|
3
|
+
* (MIT-licensed, original JS source kept in parser-raw/ for reference).
|
|
4
|
+
* Replaces the external dependency so the library stays dependency-light
|
|
5
|
+
* and fully browser-compatible.
|
|
6
|
+
*/
|
|
7
|
+
export { default as DxfParser } from './dxf-parser.js';
|
|
8
|
+
export { default as DxfArrayScanner } from './scanner.js';
|
|
9
|
+
export * as ParseHelpers from './parse-helpers.js';
|
|
10
|
+
export type { DxfGroup, DxfPoint, DxfEntity, DxfBlock, ParsedDxf, GroupValue, IScanner, IEntityParser, IEntityParserType, } from './types.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal DXF parser — TypeScript port of the `dxf-parser` npm package
|
|
3
|
+
* (MIT-licensed, original JS source kept in parser-raw/ for reference).
|
|
4
|
+
* Replaces the external dependency so the library stays dependency-light
|
|
5
|
+
* and fully browser-compatible.
|
|
6
|
+
*/
|
|
7
|
+
export { default as DxfParser } from './dxf-parser.js';
|
|
8
|
+
export { default as DxfArrayScanner } from './scanner.js';
|
|
9
|
+
export * as ParseHelpers from './parse-helpers.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal internal logger replacing the `loglevel` dependency of the original
|
|
3
|
+
* dxf-parser. Default level is 'error', matching the original's
|
|
4
|
+
* `log.setLevel('error')`, so debug/info/warn output stays suppressed.
|
|
5
|
+
*/
|
|
6
|
+
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
7
|
+
declare const log: {
|
|
8
|
+
setLevel(level: LogLevel): void;
|
|
9
|
+
debug(...args: unknown[]): void;
|
|
10
|
+
info(...args: unknown[]): void;
|
|
11
|
+
warn(...args: unknown[]): void;
|
|
12
|
+
error(...args: unknown[]): void;
|
|
13
|
+
};
|
|
14
|
+
export default log;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal internal logger replacing the `loglevel` dependency of the original
|
|
3
|
+
* dxf-parser. Default level is 'error', matching the original's
|
|
4
|
+
* `log.setLevel('error')`, so debug/info/warn output stays suppressed.
|
|
5
|
+
*/
|
|
6
|
+
const LEVEL_ORDER = {
|
|
7
|
+
trace: 0,
|
|
8
|
+
debug: 1,
|
|
9
|
+
info: 2,
|
|
10
|
+
warn: 3,
|
|
11
|
+
error: 4,
|
|
12
|
+
silent: 5,
|
|
13
|
+
};
|
|
14
|
+
let currentLevel = 'error';
|
|
15
|
+
function enabled(level) {
|
|
16
|
+
return LEVEL_ORDER[level] >= LEVEL_ORDER[currentLevel];
|
|
17
|
+
}
|
|
18
|
+
const log = {
|
|
19
|
+
setLevel(level) {
|
|
20
|
+
currentLevel = level;
|
|
21
|
+
},
|
|
22
|
+
debug(...args) {
|
|
23
|
+
if (enabled('debug'))
|
|
24
|
+
console.debug(...args);
|
|
25
|
+
},
|
|
26
|
+
info(...args) {
|
|
27
|
+
if (enabled('info'))
|
|
28
|
+
console.info(...args);
|
|
29
|
+
},
|
|
30
|
+
warn(...args) {
|
|
31
|
+
if (enabled('warn'))
|
|
32
|
+
console.warn(...args);
|
|
33
|
+
},
|
|
34
|
+
error(...args) {
|
|
35
|
+
if (enabled('error'))
|
|
36
|
+
console.error(...args);
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
export default log;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DxfEntity, DxfGroup, DxfPoint, IScanner } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the truecolor value of the given AutoCad color index value
|
|
4
|
+
* @return truecolor value as a number
|
|
5
|
+
*/
|
|
6
|
+
export declare function getAcadColor(index: number): number;
|
|
7
|
+
/**
|
|
8
|
+
* Parses the 2D or 3D coordinate, vector, or point. When complete,
|
|
9
|
+
* the scanner remains on the last group of the coordinate.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parsePoint(scanner: IScanner): DxfPoint;
|
|
12
|
+
/** Some entities may contain embedded object which is started by group 101. All the rest data until
|
|
13
|
+
* end of entity should not be interpreted as entity attributes. There is no documentation for this
|
|
14
|
+
* feature.
|
|
15
|
+
*/
|
|
16
|
+
export declare function skipEmbeddedObject(scanner: IScanner): void;
|
|
17
|
+
/**
|
|
18
|
+
* Attempts to parse codes common to all entities. Returns true if the group
|
|
19
|
+
* was handled by this function.
|
|
20
|
+
* @param entity - the entity currently being parsed
|
|
21
|
+
* @param curr - the current group being parsed
|
|
22
|
+
*/
|
|
23
|
+
export declare function checkCommonEntityProperties(entity: DxfEntity, curr: DxfGroup, scanner: IScanner): boolean;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import AUTO_CAD_COLOR_INDEX from './auto-cad-color-index.js';
|
|
2
|
+
import ExtendedDataParser from './extended-data-parser.js';
|
|
3
|
+
/**
|
|
4
|
+
* Returns the truecolor value of the given AutoCad color index value
|
|
5
|
+
* @return truecolor value as a number
|
|
6
|
+
*/
|
|
7
|
+
export function getAcadColor(index) {
|
|
8
|
+
return AUTO_CAD_COLOR_INDEX[index];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Parses the 2D or 3D coordinate, vector, or point. When complete,
|
|
12
|
+
* the scanner remains on the last group of the coordinate.
|
|
13
|
+
*/
|
|
14
|
+
export function parsePoint(scanner) {
|
|
15
|
+
const point = {};
|
|
16
|
+
// Reread group for the first coordinate
|
|
17
|
+
scanner.rewind();
|
|
18
|
+
let curr = scanner.next();
|
|
19
|
+
let code = curr.code;
|
|
20
|
+
point.x = curr.value;
|
|
21
|
+
code += 10;
|
|
22
|
+
curr = scanner.next();
|
|
23
|
+
if (curr.code !== code)
|
|
24
|
+
throw new Error('Expected code for point value to be ' + code +
|
|
25
|
+
' but got ' + curr.code + '.');
|
|
26
|
+
point.y = curr.value;
|
|
27
|
+
code += 10;
|
|
28
|
+
curr = scanner.next();
|
|
29
|
+
if (curr.code !== code) {
|
|
30
|
+
// Only the x and y are specified. Don't read z.
|
|
31
|
+
scanner.rewind(); // Let the calling code advance off the point
|
|
32
|
+
return point;
|
|
33
|
+
}
|
|
34
|
+
point.z = curr.value;
|
|
35
|
+
return point;
|
|
36
|
+
}
|
|
37
|
+
/** Some entities may contain embedded object which is started by group 101. All the rest data until
|
|
38
|
+
* end of entity should not be interpreted as entity attributes. There is no documentation for this
|
|
39
|
+
* feature.
|
|
40
|
+
*/
|
|
41
|
+
export function skipEmbeddedObject(scanner) {
|
|
42
|
+
/* Ensure proper start group. */
|
|
43
|
+
scanner.rewind();
|
|
44
|
+
let curr = scanner.next();
|
|
45
|
+
if (curr.code !== 101) {
|
|
46
|
+
throw new Error('Bad call for skipEmbeddedObject()');
|
|
47
|
+
}
|
|
48
|
+
do {
|
|
49
|
+
curr = scanner.next();
|
|
50
|
+
} while (curr.code !== 0);
|
|
51
|
+
scanner.rewind();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Attempts to parse codes common to all entities. Returns true if the group
|
|
55
|
+
* was handled by this function.
|
|
56
|
+
* @param entity - the entity currently being parsed
|
|
57
|
+
* @param curr - the current group being parsed
|
|
58
|
+
*/
|
|
59
|
+
export function checkCommonEntityProperties(entity, curr, scanner) {
|
|
60
|
+
let xdataParser = null;
|
|
61
|
+
while (curr.code >= 1000) {
|
|
62
|
+
if (xdataParser == null) {
|
|
63
|
+
xdataParser = new ExtendedDataParser();
|
|
64
|
+
}
|
|
65
|
+
if (xdataParser.Feed(curr)) {
|
|
66
|
+
xdataParser.Finish(entity);
|
|
67
|
+
xdataParser = null;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
curr = scanner.next();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (xdataParser) {
|
|
74
|
+
xdataParser.Finish(entity);
|
|
75
|
+
/* Groups following XDATA should be parsed on next iteration. */
|
|
76
|
+
scanner.rewind();
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
switch (curr.code) {
|
|
80
|
+
case 0:
|
|
81
|
+
entity.type = curr.value;
|
|
82
|
+
break;
|
|
83
|
+
case 5:
|
|
84
|
+
entity.handle = curr.value;
|
|
85
|
+
break;
|
|
86
|
+
case 6:
|
|
87
|
+
entity.lineType = curr.value;
|
|
88
|
+
break;
|
|
89
|
+
case 8: // Layer name
|
|
90
|
+
entity.layer = curr.value;
|
|
91
|
+
break;
|
|
92
|
+
case 48:
|
|
93
|
+
entity.lineTypeScale = curr.value;
|
|
94
|
+
break;
|
|
95
|
+
case 60:
|
|
96
|
+
entity.hidden = !!curr.value;
|
|
97
|
+
break;
|
|
98
|
+
case 62: // Acad Index Color. 0 inherits ByBlock. 256 inherits ByLayer. Default is bylayer
|
|
99
|
+
entity.colorIndex = curr.value;
|
|
100
|
+
entity.color = getAcadColor(Math.abs(curr.value));
|
|
101
|
+
break;
|
|
102
|
+
case 67:
|
|
103
|
+
entity.inPaperSpace = curr.value !== 0;
|
|
104
|
+
break;
|
|
105
|
+
case 100:
|
|
106
|
+
//ignore
|
|
107
|
+
break;
|
|
108
|
+
case 330:
|
|
109
|
+
entity.ownerHandle = curr.value;
|
|
110
|
+
break;
|
|
111
|
+
case 347:
|
|
112
|
+
entity.materialObjectHandle = curr.value;
|
|
113
|
+
break;
|
|
114
|
+
case 370:
|
|
115
|
+
//From https://www.woutware.com/Forum/Topic/955/lineweight?returnUrl=%2FForum%2FUserPosts%3FuserId%3D478262319
|
|
116
|
+
// An integer representing 100th of mm, must be one of the following values:
|
|
117
|
+
// 0, 5, 9, 13, 15, 18, 20, 25, 30, 35, 40, 50, 53, 60, 70, 80, 90, 100, 106, 120, 140, 158, 200, 211.
|
|
118
|
+
// -3 = STANDARD, -2 = BYLAYER, -1 = BYBLOCK
|
|
119
|
+
entity.lineweight = curr.value;
|
|
120
|
+
break;
|
|
121
|
+
case 420: // TrueColor Color
|
|
122
|
+
entity.color = curr.value;
|
|
123
|
+
break;
|
|
124
|
+
default:
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
return true;
|
|
128
|
+
}
|