@linkiez/dxf-renew 5.3.1 → 7.1.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/{docs/CODE_PATTERNS.md → .github/instructions/code-patterns.instructions.md} +4 -1
- package/.github/instructions/exdxf.instruction.md +161 -0
- package/.github/instructions/tdd.instructions.md +271 -0
- package/.github/workflows/release.yml +4 -5
- package/.releaserc.json +1 -1
- package/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +59 -0
- package/CONTRIBUTING.md +16 -14
- package/PLAN.md +34 -84
- package/README.md +43 -8
- package/dist/dxf.js +1388 -376
- package/docs/DIMENSION_SUMMARY.md +11 -5
- package/docs/DXF_VERSION_SUPPORT.md +45 -0
- package/docs/ENTITY_SVG_ROADMAP.md +96 -0
- package/docs/EZDXF_REFERENCE_SITEMAP.md +55 -0
- package/docs/FIXTURE_VALIDATION_EZDXF.md +62 -0
- package/docs/README.md +22 -0
- package/docs/SVG_RENDERING_INTEGRATION_TESTS.md +119 -0
- package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.md +1 -1
- package/lib/Helper.cjs +2 -2
- package/lib/Helper.cjs.map +2 -2
- package/lib/Helper.js +2 -2
- package/lib/Helper.js.map +2 -2
- package/lib/denormalise.cjs +131 -91
- package/lib/denormalise.cjs.map +2 -2
- package/lib/denormalise.js +131 -91
- package/lib/denormalise.js.map +2 -2
- package/lib/dimensionToSVG.cjs +318 -53
- package/lib/dimensionToSVG.cjs.map +3 -3
- package/lib/dimensionToSVG.js +316 -52
- package/lib/dimensionToSVG.js.map +2 -2
- package/lib/handlers/entities.cjs +90 -26
- package/lib/handlers/entities.cjs.map +3 -3
- package/lib/handlers/entities.js +90 -26
- package/lib/handlers/entities.js.map +3 -3
- package/lib/handlers/entity/dgnUnderlay.cjs +106 -0
- package/lib/handlers/entity/dgnUnderlay.cjs.map +7 -0
- package/lib/handlers/entity/dgnUnderlay.js +71 -0
- package/lib/handlers/entity/dgnUnderlay.js.map +7 -0
- package/lib/handlers/entity/dimension.cjs +24 -0
- package/lib/handlers/entity/dimension.cjs.map +2 -2
- package/lib/handlers/entity/dimension.js +24 -0
- package/lib/handlers/entity/dimension.js.map +2 -2
- package/lib/handlers/entity/dwfUnderlay.cjs +106 -0
- package/lib/handlers/entity/dwfUnderlay.cjs.map +7 -0
- package/lib/handlers/entity/dwfUnderlay.js +71 -0
- package/lib/handlers/entity/dwfUnderlay.js.map +7 -0
- package/lib/handlers/entity/image.cjs +123 -0
- package/lib/handlers/entity/image.cjs.map +7 -0
- package/lib/handlers/entity/image.js +88 -0
- package/lib/handlers/entity/image.js.map +7 -0
- package/lib/handlers/entity/leader.cjs +148 -0
- package/lib/handlers/entity/leader.cjs.map +7 -0
- package/lib/handlers/entity/leader.js +113 -0
- package/lib/handlers/entity/leader.js.map +7 -0
- package/lib/handlers/entity/pdfUnderlay.cjs +106 -0
- package/lib/handlers/entity/pdfUnderlay.cjs.map +7 -0
- package/lib/handlers/entity/pdfUnderlay.js +71 -0
- package/lib/handlers/entity/pdfUnderlay.js.map +7 -0
- package/lib/handlers/entity/tolerance.cjs +90 -0
- package/lib/handlers/entity/tolerance.cjs.map +7 -0
- package/lib/handlers/entity/tolerance.js +55 -0
- package/lib/handlers/entity/tolerance.js.map +7 -0
- package/lib/handlers/objects.cjs +257 -136
- package/lib/handlers/objects.cjs.map +2 -2
- package/lib/handlers/objects.js +257 -136
- package/lib/handlers/objects.js.map +2 -2
- package/lib/toSVG.cjs +71 -8
- package/lib/toSVG.cjs.map +3 -3
- package/lib/toSVG.js +72 -9
- package/lib/toSVG.js.map +2 -2
- package/lib/types/dimension-entity.cjs.map +1 -1
- package/lib/types/entity.cjs.map +1 -1
- package/lib/types/image-entity.cjs +17 -0
- package/lib/types/image-entity.cjs.map +7 -0
- package/lib/types/image-entity.js +1 -0
- package/lib/types/image-entity.js.map +7 -0
- package/lib/types/index.cjs +8 -0
- package/lib/types/index.cjs.map +2 -2
- package/lib/types/index.js +4 -0
- package/lib/types/index.js.map +2 -2
- package/lib/types/leader-entity.cjs +17 -0
- package/lib/types/leader-entity.cjs.map +7 -0
- package/lib/types/leader-entity.js +1 -0
- package/lib/types/leader-entity.js.map +7 -0
- package/lib/types/options.cjs.map +1 -1
- package/lib/types/tables.cjs.map +1 -1
- package/lib/types/tolerance-entity.cjs +17 -0
- package/lib/types/tolerance-entity.cjs.map +7 -0
- package/lib/types/tolerance-entity.js +1 -0
- package/lib/types/tolerance-entity.js.map +7 -0
- package/lib/types/underlay-entity.cjs +17 -0
- package/lib/types/underlay-entity.cjs.map +7 -0
- package/lib/types/underlay-entity.js +1 -0
- package/lib/types/underlay-entity.js.map +7 -0
- package/lib/util/escapeXmlText.cjs +27 -0
- package/lib/util/escapeXmlText.cjs.map +7 -0
- package/lib/util/escapeXmlText.js +7 -0
- package/lib/util/escapeXmlText.js.map +7 -0
- package/package.json +13 -4
- package/playwright.config.cjs +20 -0
- package/src/Helper.ts +3 -3
- package/src/denormalise.ts +182 -116
- package/src/dimensionToSVG.ts +466 -54
- package/src/handlers/entities.ts +109 -34
- package/src/handlers/entity/dgnUnderlay.ts +94 -0
- package/src/handlers/entity/dimension.ts +27 -1
- package/src/handlers/entity/dwfUnderlay.ts +94 -0
- package/src/handlers/entity/image.ts +118 -0
- package/src/handlers/entity/leader.ts +153 -0
- package/src/handlers/entity/pdfUnderlay.ts +94 -0
- package/src/handlers/entity/tolerance.ts +75 -0
- package/src/handlers/objects.ts +323 -139
- package/src/toSVG.ts +98 -7
- package/src/types/dimension-entity.ts +11 -0
- package/src/types/entity.ts +10 -0
- package/src/types/image-entity.ts +35 -0
- package/src/types/index.ts +4 -0
- package/src/types/leader-entity.ts +40 -0
- package/src/types/options.ts +41 -0
- package/src/types/tables.ts +84 -0
- package/src/types/tolerance-entity.ts +20 -0
- package/src/types/underlay-entity.ts +35 -0
- package/src/util/escapeXmlText.ts +10 -0
- package/tools/browser_test_server.cjs +87 -0
- package/tools/ezdxf_generate_dimensions_all_types.py +246 -0
- package/tools/ezdxf_generate_dimensions_angular_3p.py +59 -0
- package/tools/ezdxf_generate_dimensions_large_scale.py +87 -0
- package/tools/ezdxf_regenerate_problem_fixtures.py +184 -0
- package/tools/ezdxf_validate_fixtures.py +165 -0
- package/docs/DIMENSION_SUMMARY.pt-BR.md +0 -248
- package/docs/IMPLEMENTED-2D-ENTITIES.pt-BR.md +0 -54
- package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.pt-BR.md +0 -169
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { DXFTuple } from '../../types'
|
|
2
|
+
|
|
3
|
+
import common from './common'
|
|
4
|
+
|
|
5
|
+
export const TYPE = 'PDFUNDERLAY'
|
|
6
|
+
|
|
7
|
+
interface UnderlayEntity {
|
|
8
|
+
type: typeof TYPE
|
|
9
|
+
|
|
10
|
+
insertionPoint: { x: number; y: number; z: number }
|
|
11
|
+
scale: { x: number; y: number; z: number }
|
|
12
|
+
normal: { x: number; y: number; z: number }
|
|
13
|
+
|
|
14
|
+
underlayDefinitionHandle?: string
|
|
15
|
+
rotation?: number
|
|
16
|
+
flags?: number
|
|
17
|
+
contrast?: number
|
|
18
|
+
fade?: number
|
|
19
|
+
|
|
20
|
+
[key: string]: unknown
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const process = (tuples: DXFTuple[]): UnderlayEntity => {
|
|
24
|
+
return tuples.reduce(
|
|
25
|
+
(entity, tuple) => {
|
|
26
|
+
const type = tuple[0]
|
|
27
|
+
const value = tuple[1]
|
|
28
|
+
|
|
29
|
+
switch (type) {
|
|
30
|
+
case 340:
|
|
31
|
+
entity.underlayDefinitionHandle = String(value)
|
|
32
|
+
break
|
|
33
|
+
|
|
34
|
+
case 10:
|
|
35
|
+
entity.insertionPoint.x = value as number
|
|
36
|
+
break
|
|
37
|
+
case 20:
|
|
38
|
+
entity.insertionPoint.y = value as number
|
|
39
|
+
break
|
|
40
|
+
case 30:
|
|
41
|
+
entity.insertionPoint.z = value as number
|
|
42
|
+
break
|
|
43
|
+
|
|
44
|
+
case 41:
|
|
45
|
+
entity.scale.x = value as number
|
|
46
|
+
break
|
|
47
|
+
case 42:
|
|
48
|
+
entity.scale.y = value as number
|
|
49
|
+
break
|
|
50
|
+
case 43:
|
|
51
|
+
entity.scale.z = value as number
|
|
52
|
+
break
|
|
53
|
+
|
|
54
|
+
case 50:
|
|
55
|
+
entity.rotation = value as number
|
|
56
|
+
break
|
|
57
|
+
|
|
58
|
+
case 210:
|
|
59
|
+
entity.normal.x = value as number
|
|
60
|
+
break
|
|
61
|
+
case 220:
|
|
62
|
+
entity.normal.y = value as number
|
|
63
|
+
break
|
|
64
|
+
case 230:
|
|
65
|
+
entity.normal.z = value as number
|
|
66
|
+
break
|
|
67
|
+
|
|
68
|
+
case 280:
|
|
69
|
+
entity.flags = value as number
|
|
70
|
+
break
|
|
71
|
+
case 281:
|
|
72
|
+
entity.contrast = value as number
|
|
73
|
+
break
|
|
74
|
+
case 282:
|
|
75
|
+
entity.fade = value as number
|
|
76
|
+
break
|
|
77
|
+
|
|
78
|
+
default:
|
|
79
|
+
Object.assign(entity, common(type, value))
|
|
80
|
+
break
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return entity
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
type: TYPE,
|
|
87
|
+
insertionPoint: { x: 0, y: 0, z: 0 },
|
|
88
|
+
scale: { x: 1, y: 1, z: 1 },
|
|
89
|
+
normal: { x: 0, y: 0, z: 1 },
|
|
90
|
+
} as UnderlayEntity,
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default { TYPE, process }
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { DXFTuple } from '../../types'
|
|
2
|
+
|
|
3
|
+
import common from './common'
|
|
4
|
+
|
|
5
|
+
export const TYPE = 'TOLERANCE'
|
|
6
|
+
|
|
7
|
+
interface ToleranceEntity {
|
|
8
|
+
type: typeof TYPE
|
|
9
|
+
|
|
10
|
+
insertionPoint: { x: number; y: number; z: number }
|
|
11
|
+
text?: string
|
|
12
|
+
dimensionStyleName?: string
|
|
13
|
+
xAxisDirection?: { x: number; y: number; z: number }
|
|
14
|
+
|
|
15
|
+
[key: string]: unknown
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function ensureVector3(
|
|
19
|
+
entity: ToleranceEntity,
|
|
20
|
+
key: 'insertionPoint' | 'xAxisDirection',
|
|
21
|
+
): { x: number; y: number; z: number } {
|
|
22
|
+
entity[key] ??= { x: 0, y: 0, z: 0 }
|
|
23
|
+
return entity[key] as { x: number; y: number; z: number }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const process = (tuples: DXFTuple[]): ToleranceEntity => {
|
|
27
|
+
return tuples.reduce(
|
|
28
|
+
(entity, tuple) => {
|
|
29
|
+
const code = tuple[0]
|
|
30
|
+
const value = tuple[1]
|
|
31
|
+
|
|
32
|
+
switch (code) {
|
|
33
|
+
case 3:
|
|
34
|
+
entity.dimensionStyleName = String(value)
|
|
35
|
+
break
|
|
36
|
+
|
|
37
|
+
case 10:
|
|
38
|
+
ensureVector3(entity, 'insertionPoint').x = value as number
|
|
39
|
+
break
|
|
40
|
+
case 20:
|
|
41
|
+
ensureVector3(entity, 'insertionPoint').y = value as number
|
|
42
|
+
break
|
|
43
|
+
case 30:
|
|
44
|
+
ensureVector3(entity, 'insertionPoint').z = value as number
|
|
45
|
+
break
|
|
46
|
+
|
|
47
|
+
case 1:
|
|
48
|
+
entity.text = String(value)
|
|
49
|
+
break
|
|
50
|
+
|
|
51
|
+
case 11:
|
|
52
|
+
ensureVector3(entity, 'xAxisDirection').x = value as number
|
|
53
|
+
break
|
|
54
|
+
case 21:
|
|
55
|
+
ensureVector3(entity, 'xAxisDirection').y = value as number
|
|
56
|
+
break
|
|
57
|
+
case 31:
|
|
58
|
+
ensureVector3(entity, 'xAxisDirection').z = value as number
|
|
59
|
+
break
|
|
60
|
+
|
|
61
|
+
default:
|
|
62
|
+
Object.assign(entity, common(code, value))
|
|
63
|
+
break
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return entity
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
type: TYPE,
|
|
70
|
+
insertionPoint: { x: 0, y: 0, z: 0 },
|
|
71
|
+
} as ToleranceEntity,
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export default { TYPE, process }
|
package/src/handlers/objects.ts
CHANGED
|
@@ -1,152 +1,336 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
DictionaryObject,
|
|
3
|
+
DXFTuple,
|
|
4
|
+
ImageDefObject,
|
|
5
|
+
ImageDefReactorObject,
|
|
6
|
+
LayoutInternal,
|
|
7
|
+
ParsedObjects,
|
|
8
|
+
UnderlayDefinitionObject,
|
|
9
|
+
XRecordObject,
|
|
10
|
+
} from '../types'
|
|
2
11
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let layout: LayoutInternal | undefined
|
|
12
|
+
type ObjectGroup = DXFTuple[]
|
|
13
|
+
|
|
14
|
+
function groupObjectsByZero(tuples: DXFTuple[]): ObjectGroup[] {
|
|
15
|
+
const groups: ObjectGroup[] = []
|
|
16
|
+
let current: ObjectGroup | undefined
|
|
9
17
|
|
|
10
18
|
for (const tuple of tuples) {
|
|
19
|
+
const code = tuple[0]
|
|
20
|
+
if (code === 0) {
|
|
21
|
+
if (current && current.length > 0) groups.push(current)
|
|
22
|
+
current = [tuple]
|
|
23
|
+
continue
|
|
24
|
+
}
|
|
25
|
+
if (!current) continue
|
|
26
|
+
current.push(tuple)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (current && current.length > 0) groups.push(current)
|
|
30
|
+
return groups
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const LAYOUT_FLOAT_FIELDS: Record<number, keyof LayoutInternal> = {
|
|
34
|
+
10: 'minLimitX',
|
|
35
|
+
20: 'minLimitY',
|
|
36
|
+
11: 'maxLimitX',
|
|
37
|
+
21: 'maxLimitY',
|
|
38
|
+
12: 'x',
|
|
39
|
+
22: 'y',
|
|
40
|
+
32: 'z',
|
|
41
|
+
14: 'minX',
|
|
42
|
+
24: 'minY',
|
|
43
|
+
34: 'minZ',
|
|
44
|
+
15: 'maxX',
|
|
45
|
+
25: 'maxY',
|
|
46
|
+
35: 'maxZ',
|
|
47
|
+
146: 'elevation',
|
|
48
|
+
13: 'ucsX',
|
|
49
|
+
23: 'ucsY',
|
|
50
|
+
33: 'ucsZ',
|
|
51
|
+
16: 'ucsXaxisX',
|
|
52
|
+
26: 'ucsXaxisY',
|
|
53
|
+
36: 'ucsXaxisZ',
|
|
54
|
+
17: 'ucsYaxisX',
|
|
55
|
+
27: 'ucsYaxisY',
|
|
56
|
+
37: 'ucsYaxisZ',
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const LAYOUT_DIRECT_FIELDS: Record<number, keyof LayoutInternal> = {
|
|
60
|
+
1: 'name',
|
|
61
|
+
5: 'handle',
|
|
62
|
+
71: 'tabOrder',
|
|
63
|
+
330: 'tableRecord',
|
|
64
|
+
331: 'lastActiveViewport',
|
|
65
|
+
333: 'shadePlot',
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const LAYOUT_UCS_TYPE: Record<number, LayoutInternal['ucsType']> = {
|
|
69
|
+
0: 'NOT ORTHOGRAPHIC',
|
|
70
|
+
1: 'TOP',
|
|
71
|
+
2: 'BOTTOM',
|
|
72
|
+
3: 'FRONT',
|
|
73
|
+
4: 'BACK',
|
|
74
|
+
5: 'LEFT',
|
|
75
|
+
6: 'RIGHT',
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
type LayoutParseState = {
|
|
79
|
+
state: 'IDLE' | 'layout' | 'AcDbLayout'
|
|
80
|
+
layout?: LayoutInternal
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function consumeLayoutStartTuple(current: LayoutParseState, tuple: DXFTuple): LayoutParseState {
|
|
84
|
+
if (tuple[1] === 'LAYOUT') return { state: 'layout', layout: {} }
|
|
85
|
+
return { state: 'IDLE', layout: current.layout }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function consumeLayoutSubclassTuple(current: LayoutParseState, tuple: DXFTuple): LayoutParseState {
|
|
89
|
+
if (tuple[0] === 100 && tuple[1] === 'AcDbLayout') return { state: 'AcDbLayout', layout: current.layout }
|
|
90
|
+
return current
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function applyLayoutFieldTuple(layout: LayoutInternal, tuple: DXFTuple): void {
|
|
94
|
+
const type = tuple[0]
|
|
95
|
+
const value = tuple[1]
|
|
96
|
+
|
|
97
|
+
const floatKey = LAYOUT_FLOAT_FIELDS[type]
|
|
98
|
+
if (floatKey) {
|
|
99
|
+
;(layout as any)[floatKey] = Number.parseFloat(String(value))
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const directKey = LAYOUT_DIRECT_FIELDS[type]
|
|
104
|
+
if (directKey) {
|
|
105
|
+
;(layout as any)[directKey] = value
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (type === 70) {
|
|
110
|
+
layout.flag = value === 1 ? 'PSLTSCALE' : 'LIMCHECK'
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (type === 76) {
|
|
115
|
+
const ucsType = LAYOUT_UCS_TYPE[Number(value)]
|
|
116
|
+
if (ucsType) layout.ucsType = ucsType
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function consumeLayoutTuple(current: LayoutParseState, tuple: DXFTuple): LayoutParseState {
|
|
121
|
+
if (tuple[0] === 0) return consumeLayoutStartTuple(current, tuple)
|
|
122
|
+
|
|
123
|
+
if (current.state === 'layout') return consumeLayoutSubclassTuple(current, tuple)
|
|
124
|
+
|
|
125
|
+
if (current.state === 'AcDbLayout' && current.layout) applyLayoutFieldTuple(current.layout, tuple)
|
|
126
|
+
return current
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function parseLayoutObject(group: ObjectGroup): LayoutInternal | undefined {
|
|
130
|
+
let current: LayoutParseState = { state: 'IDLE' }
|
|
131
|
+
for (const tuple of group) current = consumeLayoutTuple(current, tuple)
|
|
132
|
+
return current.layout
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function parseDictionaryObject(group: ObjectGroup): DictionaryObject | undefined {
|
|
136
|
+
if (group[0]?.[1] !== 'DICTIONARY') return undefined
|
|
137
|
+
|
|
138
|
+
const dict: DictionaryObject = {
|
|
139
|
+
type: 'DICTIONARY',
|
|
140
|
+
entries: {},
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let pendingKey: string | undefined
|
|
144
|
+
for (const tuple of group.slice(1)) {
|
|
11
145
|
const type = tuple[0]
|
|
12
146
|
const value = tuple[1]
|
|
13
|
-
|
|
14
|
-
|
|
147
|
+
|
|
148
|
+
if (type === 5) {
|
|
149
|
+
dict.handle = value
|
|
150
|
+
continue
|
|
15
151
|
}
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
objects.layouts.push(layout)
|
|
152
|
+
if (type === 330) {
|
|
153
|
+
dict.ownerHandle = value
|
|
154
|
+
continue
|
|
20
155
|
}
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
case 100:
|
|
25
|
-
if (value === 'AcDbLayout') state = 'AcDbLayout'
|
|
26
|
-
break
|
|
27
|
-
}
|
|
156
|
+
if (type === 3) {
|
|
157
|
+
pendingKey = String(value)
|
|
158
|
+
continue
|
|
28
159
|
}
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
case 1:
|
|
33
|
-
layout.name = value
|
|
34
|
-
break
|
|
35
|
-
case 5:
|
|
36
|
-
layout.handle = value
|
|
37
|
-
break
|
|
38
|
-
case 10:
|
|
39
|
-
layout.minLimitX = Number.parseFloat(String(value))
|
|
40
|
-
break
|
|
41
|
-
case 20:
|
|
42
|
-
layout.minLimitY = Number.parseFloat(String(value))
|
|
43
|
-
break
|
|
44
|
-
case 11:
|
|
45
|
-
layout.maxLimitX = Number.parseFloat(String(value))
|
|
46
|
-
break
|
|
47
|
-
case 21:
|
|
48
|
-
layout.maxLimitY = Number.parseFloat(String(value))
|
|
49
|
-
break
|
|
50
|
-
case 12:
|
|
51
|
-
layout.x = Number.parseFloat(String(value))
|
|
52
|
-
break
|
|
53
|
-
case 22:
|
|
54
|
-
layout.y = Number.parseFloat(String(value))
|
|
55
|
-
break
|
|
56
|
-
case 32:
|
|
57
|
-
layout.z = Number.parseFloat(String(value))
|
|
58
|
-
break
|
|
59
|
-
case 14:
|
|
60
|
-
layout.minX = Number.parseFloat(String(value))
|
|
61
|
-
break
|
|
62
|
-
case 24:
|
|
63
|
-
layout.minY = Number.parseFloat(String(value))
|
|
64
|
-
break
|
|
65
|
-
case 34:
|
|
66
|
-
layout.minZ = Number.parseFloat(String(value))
|
|
67
|
-
break
|
|
68
|
-
case 15:
|
|
69
|
-
layout.maxX = Number.parseFloat(String(value))
|
|
70
|
-
break
|
|
71
|
-
case 25:
|
|
72
|
-
layout.maxY = Number.parseFloat(String(value))
|
|
73
|
-
break
|
|
74
|
-
case 35:
|
|
75
|
-
layout.maxZ = Number.parseFloat(String(value))
|
|
76
|
-
break
|
|
77
|
-
case 70:
|
|
78
|
-
layout.flag = value === 1 ? 'PSLTSCALE' : 'LIMCHECK'
|
|
79
|
-
break
|
|
80
|
-
case 71:
|
|
81
|
-
layout.tabOrder = value
|
|
82
|
-
break
|
|
83
|
-
case 146:
|
|
84
|
-
layout.elevation = Number.parseFloat(String(value))
|
|
85
|
-
break
|
|
86
|
-
case 13:
|
|
87
|
-
layout.ucsX = Number.parseFloat(String(value))
|
|
88
|
-
break
|
|
89
|
-
case 23:
|
|
90
|
-
layout.ucsY = Number.parseFloat(String(value))
|
|
91
|
-
break
|
|
92
|
-
case 33:
|
|
93
|
-
layout.ucsZ = Number.parseFloat(String(value))
|
|
94
|
-
break
|
|
95
|
-
case 16:
|
|
96
|
-
layout.ucsXaxisX = Number.parseFloat(String(value))
|
|
97
|
-
break
|
|
98
|
-
case 26:
|
|
99
|
-
layout.ucsXaxisY = Number.parseFloat(String(value))
|
|
100
|
-
break
|
|
101
|
-
case 36:
|
|
102
|
-
layout.ucsXaxisZ = Number.parseFloat(String(value))
|
|
103
|
-
break
|
|
104
|
-
case 17:
|
|
105
|
-
layout.ucsYaxisX = Number.parseFloat(String(value))
|
|
106
|
-
break
|
|
107
|
-
case 27:
|
|
108
|
-
layout.ucsYaxisY = Number.parseFloat(String(value))
|
|
109
|
-
break
|
|
110
|
-
case 37:
|
|
111
|
-
layout.ucsYaxisZ = Number.parseFloat(String(value))
|
|
112
|
-
break
|
|
113
|
-
case 76:
|
|
114
|
-
switch (value) {
|
|
115
|
-
case 0:
|
|
116
|
-
layout.ucsType = 'NOT ORTHOGRAPHIC'
|
|
117
|
-
break
|
|
118
|
-
case 1:
|
|
119
|
-
layout.ucsType = 'TOP'
|
|
120
|
-
break
|
|
121
|
-
case 2:
|
|
122
|
-
layout.ucsType = 'BOTTOM'
|
|
123
|
-
break
|
|
124
|
-
case 3:
|
|
125
|
-
layout.ucsType = 'FRONT'
|
|
126
|
-
break
|
|
127
|
-
case 4:
|
|
128
|
-
layout.ucsType = 'BACK'
|
|
129
|
-
break
|
|
130
|
-
case 5:
|
|
131
|
-
layout.ucsType = 'LEFT'
|
|
132
|
-
break
|
|
133
|
-
case 6:
|
|
134
|
-
layout.ucsType = 'RIGHT'
|
|
135
|
-
break
|
|
136
|
-
}
|
|
137
|
-
break
|
|
138
|
-
case 330:
|
|
139
|
-
layout.tableRecord = value
|
|
140
|
-
break
|
|
141
|
-
case 331:
|
|
142
|
-
layout.lastActiveViewport = value
|
|
143
|
-
break
|
|
144
|
-
case 333:
|
|
145
|
-
layout.shadePlot = value
|
|
146
|
-
break
|
|
147
|
-
}
|
|
160
|
+
if ((type === 350 || type === 360) && pendingKey) {
|
|
161
|
+
dict.entries[pendingKey] = String(value)
|
|
162
|
+
pendingKey = undefined
|
|
148
163
|
}
|
|
149
164
|
}
|
|
150
165
|
|
|
166
|
+
return dict
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function parseXRecordObject(group: ObjectGroup): XRecordObject | undefined {
|
|
170
|
+
if (group[0]?.[1] !== 'XRECORD') return undefined
|
|
171
|
+
|
|
172
|
+
const tuples = group.slice(1)
|
|
173
|
+
|
|
174
|
+
const xRecord: XRecordObject = {
|
|
175
|
+
type: 'XRECORD',
|
|
176
|
+
tuples,
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
for (const tuple of tuples) {
|
|
180
|
+
const type = tuple[0]
|
|
181
|
+
const value = tuple[1]
|
|
182
|
+
|
|
183
|
+
if (type === 5) xRecord.handle = value
|
|
184
|
+
if (type === 330) xRecord.ownerHandle = value
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return xRecord
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function parseImageDefObject(group: ObjectGroup): ImageDefObject | undefined {
|
|
191
|
+
if (group[0]?.[1] !== 'IMAGEDEF') return undefined
|
|
192
|
+
|
|
193
|
+
const tuples = group.slice(1)
|
|
194
|
+
|
|
195
|
+
const imageDef: ImageDefObject = {
|
|
196
|
+
type: 'IMAGEDEF',
|
|
197
|
+
tuples,
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
for (const tuple of tuples) {
|
|
201
|
+
const type = tuple[0]
|
|
202
|
+
const value = tuple[1]
|
|
203
|
+
|
|
204
|
+
if (type === 5) imageDef.handle = value
|
|
205
|
+
if (type === 330 && imageDef.ownerHandle === undefined) imageDef.ownerHandle = value
|
|
206
|
+
if (type === 1) imageDef.fileName = String(value)
|
|
207
|
+
if (type === 10) imageDef.pixelSizeX = Number(value)
|
|
208
|
+
if (type === 20) imageDef.pixelSizeY = Number(value)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return imageDef
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function parseImageDefReactorObject(group: ObjectGroup): ImageDefReactorObject | undefined {
|
|
215
|
+
if (group[0]?.[1] !== 'IMAGEDEF_REACTOR') return undefined
|
|
216
|
+
|
|
217
|
+
const tuples = group.slice(1)
|
|
218
|
+
|
|
219
|
+
const reactor: ImageDefReactorObject = {
|
|
220
|
+
type: 'IMAGEDEF_REACTOR',
|
|
221
|
+
tuples,
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
for (const tuple of tuples) {
|
|
225
|
+
const type = tuple[0]
|
|
226
|
+
const value = tuple[1]
|
|
227
|
+
|
|
228
|
+
if (type === 5) reactor.handle = value
|
|
229
|
+
if (type === 330) reactor.imageHandle = value
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return reactor
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const UNDERLAY_DEFINITION_OBJECT_TYPES = new Set([
|
|
236
|
+
'UNDERLAYDEFINITION',
|
|
237
|
+
'PDFDEFINITION',
|
|
238
|
+
'DWFDEFINITION',
|
|
239
|
+
'DGNDEFINITION',
|
|
240
|
+
])
|
|
241
|
+
|
|
242
|
+
function parseUnderlayDefinitionObject(group: ObjectGroup): UnderlayDefinitionObject | undefined {
|
|
243
|
+
const objectType = group[0]?.[1]
|
|
244
|
+
if (typeof objectType !== 'string') return undefined
|
|
245
|
+
if (!UNDERLAY_DEFINITION_OBJECT_TYPES.has(objectType)) return undefined
|
|
246
|
+
|
|
247
|
+
const tuples = group.slice(1)
|
|
248
|
+
|
|
249
|
+
const def: UnderlayDefinitionObject = {
|
|
250
|
+
type: objectType as UnderlayDefinitionObject['type'],
|
|
251
|
+
tuples,
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
for (const tuple of tuples) {
|
|
255
|
+
const type = tuple[0]
|
|
256
|
+
const value = tuple[1]
|
|
257
|
+
|
|
258
|
+
if (type === 5) def.handle = value
|
|
259
|
+
if (type === 330 && def.ownerHandle === undefined) def.ownerHandle = value
|
|
260
|
+
if (type === 1) def.fileName = String(value)
|
|
261
|
+
if (type === 2) def.underlayName = String(value)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return def
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
type ObjectGroupHandler = (objects: ParsedObjects, group: ObjectGroup) => void
|
|
268
|
+
|
|
269
|
+
const OBJECT_GROUP_HANDLERS: Record<string, ObjectGroupHandler> = {
|
|
270
|
+
LAYOUT: (objects, group) => {
|
|
271
|
+
const layout = parseLayoutObject(group)
|
|
272
|
+
if (layout) objects.layouts.push(layout)
|
|
273
|
+
},
|
|
274
|
+
DICTIONARY: (objects, group) => {
|
|
275
|
+
const dict = parseDictionaryObject(group)
|
|
276
|
+
const handle = dict?.handle ? String(dict.handle) : undefined
|
|
277
|
+
if (dict && handle) objects.dictionaries![handle] = dict
|
|
278
|
+
},
|
|
279
|
+
XRECORD: (objects, group) => {
|
|
280
|
+
const xRecord = parseXRecordObject(group)
|
|
281
|
+
const handle = xRecord?.handle ? String(xRecord.handle) : undefined
|
|
282
|
+
if (xRecord && handle) objects.xRecords![handle] = xRecord
|
|
283
|
+
},
|
|
284
|
+
IMAGEDEF: (objects, group) => {
|
|
285
|
+
const imageDef = parseImageDefObject(group)
|
|
286
|
+
const handle = imageDef?.handle ? String(imageDef.handle) : undefined
|
|
287
|
+
if (imageDef && handle) objects.imageDefs![handle] = imageDef
|
|
288
|
+
},
|
|
289
|
+
IMAGEDEF_REACTOR: (objects, group) => {
|
|
290
|
+
const reactor = parseImageDefReactorObject(group)
|
|
291
|
+
const handle = reactor?.handle ? String(reactor.handle) : undefined
|
|
292
|
+
if (reactor && handle) objects.imageDefReactors![handle] = reactor
|
|
293
|
+
},
|
|
294
|
+
UNDERLAYDEFINITION: (objects, group) => {
|
|
295
|
+
const def = parseUnderlayDefinitionObject(group)
|
|
296
|
+
const handle = def?.handle ? String(def.handle) : undefined
|
|
297
|
+
if (def && handle) objects.underlayDefinitions![handle] = def
|
|
298
|
+
},
|
|
299
|
+
PDFDEFINITION: (objects, group) => {
|
|
300
|
+
const def = parseUnderlayDefinitionObject(group)
|
|
301
|
+
const handle = def?.handle ? String(def.handle) : undefined
|
|
302
|
+
if (def && handle) objects.underlayDefinitions![handle] = def
|
|
303
|
+
},
|
|
304
|
+
DWFDEFINITION: (objects, group) => {
|
|
305
|
+
const def = parseUnderlayDefinitionObject(group)
|
|
306
|
+
const handle = def?.handle ? String(def.handle) : undefined
|
|
307
|
+
if (def && handle) objects.underlayDefinitions![handle] = def
|
|
308
|
+
},
|
|
309
|
+
DGNDEFINITION: (objects, group) => {
|
|
310
|
+
const def = parseUnderlayDefinitionObject(group)
|
|
311
|
+
const handle = def?.handle ? String(def.handle) : undefined
|
|
312
|
+
if (def && handle) objects.underlayDefinitions![handle] = def
|
|
313
|
+
},
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export default function parseObjects(tuples: DXFTuple[]): ParsedObjects {
|
|
317
|
+
const objects: ParsedObjects = {
|
|
318
|
+
layouts: [],
|
|
319
|
+
dictionaries: {},
|
|
320
|
+
xRecords: {},
|
|
321
|
+
imageDefs: {},
|
|
322
|
+
imageDefReactors: {},
|
|
323
|
+
underlayDefinitions: {},
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const groups = groupObjectsByZero(tuples)
|
|
327
|
+
for (const group of groups) {
|
|
328
|
+
const objectType = group[0]?.[1]
|
|
329
|
+
if (typeof objectType !== 'string') continue
|
|
330
|
+
|
|
331
|
+
const handler = OBJECT_GROUP_HANDLERS[objectType]
|
|
332
|
+
if (handler) handler(objects, group)
|
|
333
|
+
}
|
|
334
|
+
|
|
151
335
|
return objects
|
|
152
336
|
}
|