@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.
Files changed (133) hide show
  1. package/{docs/CODE_PATTERNS.md → .github/instructions/code-patterns.instructions.md} +4 -1
  2. package/.github/instructions/exdxf.instruction.md +161 -0
  3. package/.github/instructions/tdd.instructions.md +271 -0
  4. package/.github/workflows/release.yml +4 -5
  5. package/.releaserc.json +1 -1
  6. package/.yarn/install-state.gz +0 -0
  7. package/CHANGELOG.md +59 -0
  8. package/CONTRIBUTING.md +16 -14
  9. package/PLAN.md +34 -84
  10. package/README.md +43 -8
  11. package/dist/dxf.js +1388 -376
  12. package/docs/DIMENSION_SUMMARY.md +11 -5
  13. package/docs/DXF_VERSION_SUPPORT.md +45 -0
  14. package/docs/ENTITY_SVG_ROADMAP.md +96 -0
  15. package/docs/EZDXF_REFERENCE_SITEMAP.md +55 -0
  16. package/docs/FIXTURE_VALIDATION_EZDXF.md +62 -0
  17. package/docs/README.md +22 -0
  18. package/docs/SVG_RENDERING_INTEGRATION_TESTS.md +119 -0
  19. package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.md +1 -1
  20. package/lib/Helper.cjs +2 -2
  21. package/lib/Helper.cjs.map +2 -2
  22. package/lib/Helper.js +2 -2
  23. package/lib/Helper.js.map +2 -2
  24. package/lib/denormalise.cjs +131 -91
  25. package/lib/denormalise.cjs.map +2 -2
  26. package/lib/denormalise.js +131 -91
  27. package/lib/denormalise.js.map +2 -2
  28. package/lib/dimensionToSVG.cjs +318 -53
  29. package/lib/dimensionToSVG.cjs.map +3 -3
  30. package/lib/dimensionToSVG.js +316 -52
  31. package/lib/dimensionToSVG.js.map +2 -2
  32. package/lib/handlers/entities.cjs +90 -26
  33. package/lib/handlers/entities.cjs.map +3 -3
  34. package/lib/handlers/entities.js +90 -26
  35. package/lib/handlers/entities.js.map +3 -3
  36. package/lib/handlers/entity/dgnUnderlay.cjs +106 -0
  37. package/lib/handlers/entity/dgnUnderlay.cjs.map +7 -0
  38. package/lib/handlers/entity/dgnUnderlay.js +71 -0
  39. package/lib/handlers/entity/dgnUnderlay.js.map +7 -0
  40. package/lib/handlers/entity/dimension.cjs +24 -0
  41. package/lib/handlers/entity/dimension.cjs.map +2 -2
  42. package/lib/handlers/entity/dimension.js +24 -0
  43. package/lib/handlers/entity/dimension.js.map +2 -2
  44. package/lib/handlers/entity/dwfUnderlay.cjs +106 -0
  45. package/lib/handlers/entity/dwfUnderlay.cjs.map +7 -0
  46. package/lib/handlers/entity/dwfUnderlay.js +71 -0
  47. package/lib/handlers/entity/dwfUnderlay.js.map +7 -0
  48. package/lib/handlers/entity/image.cjs +123 -0
  49. package/lib/handlers/entity/image.cjs.map +7 -0
  50. package/lib/handlers/entity/image.js +88 -0
  51. package/lib/handlers/entity/image.js.map +7 -0
  52. package/lib/handlers/entity/leader.cjs +148 -0
  53. package/lib/handlers/entity/leader.cjs.map +7 -0
  54. package/lib/handlers/entity/leader.js +113 -0
  55. package/lib/handlers/entity/leader.js.map +7 -0
  56. package/lib/handlers/entity/pdfUnderlay.cjs +106 -0
  57. package/lib/handlers/entity/pdfUnderlay.cjs.map +7 -0
  58. package/lib/handlers/entity/pdfUnderlay.js +71 -0
  59. package/lib/handlers/entity/pdfUnderlay.js.map +7 -0
  60. package/lib/handlers/entity/tolerance.cjs +90 -0
  61. package/lib/handlers/entity/tolerance.cjs.map +7 -0
  62. package/lib/handlers/entity/tolerance.js +55 -0
  63. package/lib/handlers/entity/tolerance.js.map +7 -0
  64. package/lib/handlers/objects.cjs +257 -136
  65. package/lib/handlers/objects.cjs.map +2 -2
  66. package/lib/handlers/objects.js +257 -136
  67. package/lib/handlers/objects.js.map +2 -2
  68. package/lib/toSVG.cjs +71 -8
  69. package/lib/toSVG.cjs.map +3 -3
  70. package/lib/toSVG.js +72 -9
  71. package/lib/toSVG.js.map +2 -2
  72. package/lib/types/dimension-entity.cjs.map +1 -1
  73. package/lib/types/entity.cjs.map +1 -1
  74. package/lib/types/image-entity.cjs +17 -0
  75. package/lib/types/image-entity.cjs.map +7 -0
  76. package/lib/types/image-entity.js +1 -0
  77. package/lib/types/image-entity.js.map +7 -0
  78. package/lib/types/index.cjs +8 -0
  79. package/lib/types/index.cjs.map +2 -2
  80. package/lib/types/index.js +4 -0
  81. package/lib/types/index.js.map +2 -2
  82. package/lib/types/leader-entity.cjs +17 -0
  83. package/lib/types/leader-entity.cjs.map +7 -0
  84. package/lib/types/leader-entity.js +1 -0
  85. package/lib/types/leader-entity.js.map +7 -0
  86. package/lib/types/options.cjs.map +1 -1
  87. package/lib/types/tables.cjs.map +1 -1
  88. package/lib/types/tolerance-entity.cjs +17 -0
  89. package/lib/types/tolerance-entity.cjs.map +7 -0
  90. package/lib/types/tolerance-entity.js +1 -0
  91. package/lib/types/tolerance-entity.js.map +7 -0
  92. package/lib/types/underlay-entity.cjs +17 -0
  93. package/lib/types/underlay-entity.cjs.map +7 -0
  94. package/lib/types/underlay-entity.js +1 -0
  95. package/lib/types/underlay-entity.js.map +7 -0
  96. package/lib/util/escapeXmlText.cjs +27 -0
  97. package/lib/util/escapeXmlText.cjs.map +7 -0
  98. package/lib/util/escapeXmlText.js +7 -0
  99. package/lib/util/escapeXmlText.js.map +7 -0
  100. package/package.json +13 -4
  101. package/playwright.config.cjs +20 -0
  102. package/src/Helper.ts +3 -3
  103. package/src/denormalise.ts +182 -116
  104. package/src/dimensionToSVG.ts +466 -54
  105. package/src/handlers/entities.ts +109 -34
  106. package/src/handlers/entity/dgnUnderlay.ts +94 -0
  107. package/src/handlers/entity/dimension.ts +27 -1
  108. package/src/handlers/entity/dwfUnderlay.ts +94 -0
  109. package/src/handlers/entity/image.ts +118 -0
  110. package/src/handlers/entity/leader.ts +153 -0
  111. package/src/handlers/entity/pdfUnderlay.ts +94 -0
  112. package/src/handlers/entity/tolerance.ts +75 -0
  113. package/src/handlers/objects.ts +323 -139
  114. package/src/toSVG.ts +98 -7
  115. package/src/types/dimension-entity.ts +11 -0
  116. package/src/types/entity.ts +10 -0
  117. package/src/types/image-entity.ts +35 -0
  118. package/src/types/index.ts +4 -0
  119. package/src/types/leader-entity.ts +40 -0
  120. package/src/types/options.ts +41 -0
  121. package/src/types/tables.ts +84 -0
  122. package/src/types/tolerance-entity.ts +20 -0
  123. package/src/types/underlay-entity.ts +35 -0
  124. package/src/util/escapeXmlText.ts +10 -0
  125. package/tools/browser_test_server.cjs +87 -0
  126. package/tools/ezdxf_generate_dimensions_all_types.py +246 -0
  127. package/tools/ezdxf_generate_dimensions_angular_3p.py +59 -0
  128. package/tools/ezdxf_generate_dimensions_large_scale.py +87 -0
  129. package/tools/ezdxf_regenerate_problem_fixtures.py +184 -0
  130. package/tools/ezdxf_validate_fixtures.py +165 -0
  131. package/docs/DIMENSION_SUMMARY.pt-BR.md +0 -248
  132. package/docs/IMPLEMENTED-2D-ENTITIES.pt-BR.md +0 -54
  133. package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.pt-BR.md +0 -169
@@ -3,19 +3,186 @@ import cloneDeep from 'lodash/cloneDeep'
3
3
  import logger from './util/logger'
4
4
 
5
5
  import type {
6
- ArcEntity,
7
- Block,
8
- CircleEntity,
9
- EllipseEntity,
10
- Entity,
11
- InsertEntity,
12
- LineEntity,
13
- ParsedDXF,
14
- PolylineEntity,
15
- SplineEntity,
16
- Transform,
6
+ ArcEntity,
7
+ Block,
8
+ CircleEntity,
9
+ DimensionEntity,
10
+ EllipseEntity,
11
+ Entity,
12
+ InsertEntity,
13
+ LineEntity,
14
+ MTextEntity,
15
+ ParsedDXF,
16
+ PolylineEntity,
17
+ SplineEntity,
18
+ TextEntity,
19
+ Transform,
17
20
  } from './types'
18
21
 
22
+ type BlockBasePointAdjuster = (entity: Entity, block: Block) => void
23
+
24
+ function adjustLineForBlockBasePoint(entity: Entity, block: Block): void {
25
+ const line = entity as LineEntity
26
+ line.start.x -= block.x
27
+ line.start.y -= block.y
28
+ line.end.x -= block.x
29
+ line.end.y -= block.y
30
+ }
31
+
32
+ function adjustPolylineForBlockBasePoint(entity: Entity, block: Block): void {
33
+ const poly = entity as PolylineEntity
34
+ for (const v of poly.vertices) {
35
+ if (v.x !== undefined) v.x -= block.x
36
+ if (v.y !== undefined) v.y -= block.y
37
+ }
38
+ }
39
+
40
+ function adjustCircleForBlockBasePoint(entity: Entity, block: Block): void {
41
+ const circle = entity as CircleEntity
42
+ circle.x -= block.x
43
+ circle.y -= block.y
44
+ }
45
+
46
+ function adjustEllipseForBlockBasePoint(entity: Entity, block: Block): void {
47
+ const ellipse = entity as EllipseEntity
48
+ ellipse.x -= block.x
49
+ ellipse.y -= block.y
50
+ }
51
+
52
+ function adjustArcForBlockBasePoint(entity: Entity, block: Block): void {
53
+ const arc = entity as ArcEntity
54
+ arc.x -= block.x
55
+ arc.y -= block.y
56
+ }
57
+
58
+ function adjustSplineForBlockBasePoint(entity: Entity, block: Block): void {
59
+ const spline = entity as SplineEntity
60
+ for (const cp of spline.controlPoints) {
61
+ cp.x -= block.x
62
+ cp.y -= block.y
63
+ }
64
+ }
65
+
66
+ function adjustTextForBlockBasePoint(entity: Entity, block: Block): void {
67
+ const text = entity as TextEntity
68
+ if (text.x !== undefined) text.x -= block.x
69
+ if (text.y !== undefined) text.y -= block.y
70
+ if (text.x2 !== undefined) text.x2 -= block.x
71
+ if (text.y2 !== undefined) text.y2 -= block.y
72
+ }
73
+
74
+ function adjustMTextForBlockBasePoint(entity: Entity, block: Block): void {
75
+ const mtext = entity as MTextEntity
76
+ if (mtext.x !== undefined) mtext.x -= block.x
77
+ if (mtext.y !== undefined) mtext.y -= block.y
78
+ }
79
+
80
+ function adjustDimensionForBlockBasePoint(entity: Entity, block: Block): void {
81
+ const dim = entity as DimensionEntity
82
+ dim.start.x -= block.x
83
+ dim.start.y -= block.y
84
+ dim.textMidpoint.x -= block.x
85
+ dim.textMidpoint.y -= block.y
86
+ dim.measureStart.x -= block.x
87
+ dim.measureStart.y -= block.y
88
+ dim.measureEnd.x -= block.x
89
+ dim.measureEnd.y -= block.y
90
+ }
91
+
92
+ const BLOCK_BASEPOINT_ADJUSTERS: Record<string, BlockBasePointAdjuster> = {
93
+ LINE: adjustLineForBlockBasePoint,
94
+ LWPOLYLINE: adjustPolylineForBlockBasePoint,
95
+ POLYLINE: adjustPolylineForBlockBasePoint,
96
+ CIRCLE: adjustCircleForBlockBasePoint,
97
+ ELLIPSE: adjustEllipseForBlockBasePoint,
98
+ ARC: adjustArcForBlockBasePoint,
99
+ SPLINE: adjustSplineForBlockBasePoint,
100
+ TEXT: adjustTextForBlockBasePoint,
101
+ MTEXT: adjustMTextForBlockBasePoint,
102
+ DIMENSION: adjustDimensionForBlockBasePoint,
103
+ }
104
+
105
+ function applyBlockBasePointAdjustment(entity: Entity, block: Block): void {
106
+ // https://github.com/bjnortier/dxf/issues/52
107
+ // See Issue 52. If we don't modify the entity coordinates here it creates an
108
+ // issue with the transformation matrices (which are only applied AFTER block
109
+ // insertion modifications has been applied).
110
+ const adjust = BLOCK_BASEPOINT_ADJUSTERS[entity.type]
111
+ if (adjust) adjust(entity, block)
112
+ }
113
+
114
+ function computeRectangularArrayVectors(insert: InsertEntity): {
115
+ rowVec: { x: number; y: number }
116
+ colVec: { x: number; y: number }
117
+ } {
118
+ const rowCount = insert.rowCount ?? 1
119
+ const columnCount = insert.columnCount ?? 1
120
+ const rowSpacing = insert.rowSpacing ?? 0
121
+ const columnSpacing = insert.columnSpacing ?? 0
122
+ const rotation = insert.rotation ?? 0
123
+
124
+ // It appears that the rectangular array is affected by rotation, but NOT by scale.
125
+ if (rowCount <= 1 && columnCount <= 1) {
126
+ return { rowVec: { x: 0, y: 0 }, colVec: { x: 0, y: 0 } }
127
+ }
128
+
129
+ const cos = Math.cos((rotation * Math.PI) / 180)
130
+ const sin = Math.sin((rotation * Math.PI) / 180)
131
+ return {
132
+ rowVec: { x: -sin * rowSpacing, y: cos * rowSpacing },
133
+ colVec: { x: cos * columnSpacing, y: sin * columnSpacing },
134
+ }
135
+ }
136
+
137
+ function expandInsert(
138
+ insert: InsertEntity,
139
+ blocksByName: Record<string, Block>,
140
+ transforms: Transform[],
141
+ gatherEntities: (entities: Entity[], transforms: Transform[]) => Entity[],
142
+ ): Entity[] {
143
+ const block = blocksByName[insert.block]
144
+ if (!block) {
145
+ logger.error('no block found for insert. block:', insert.block)
146
+ return []
147
+ }
148
+
149
+ const rowCount = insert.rowCount ?? 1
150
+ const columnCount = insert.columnCount ?? 1
151
+ const { rowVec, colVec } = computeRectangularArrayVectors(insert)
152
+
153
+ const current: Entity[] = []
154
+ for (let r = 0; r < rowCount; r++) {
155
+ for (let c = 0; c < columnCount; c++) {
156
+ const t: Transform = {
157
+ x: insert.x + rowVec.x * r + colVec.x * c,
158
+ y: insert.y + rowVec.y * r + colVec.y * c,
159
+ scaleX: insert.scaleX,
160
+ scaleY: insert.scaleY,
161
+ scaleZ: insert.scaleZ,
162
+ extrusionX: insert.extrusionX,
163
+ extrusionY: insert.extrusionY,
164
+ extrusionZ: insert.extrusionZ,
165
+ rotation: insert.rotation,
166
+ }
167
+
168
+ const transforms2 = transforms.slice(0)
169
+ transforms2.push(t)
170
+
171
+ // Use the insert layer
172
+ const blockEntities = block.entities.map((be: Entity) => {
173
+ const be2 = cloneDeep(be)
174
+ be2.layer = insert.layer
175
+ applyBlockBasePointAdjustment(be2, block)
176
+ return be2
177
+ })
178
+
179
+ current.push(...gatherEntities(blockEntities, transforms2))
180
+ }
181
+ }
182
+
183
+ return current
184
+ }
185
+
19
186
  export default function denormalise(parseResult: ParsedDXF): Entity[] {
20
187
  const blocksByName = parseResult.blocks.reduce(
21
188
  (acc: { [name: string]: Block }, b: Block) => {
@@ -29,113 +196,12 @@ export default function denormalise(parseResult: ParsedDXF): Entity[] {
29
196
  entities: Entity[],
30
197
  transforms: Transform[],
31
198
  ): Entity[] => {
32
- let current: Entity[] = []
199
+ const current: Entity[] = []
33
200
  for (const e of entities) {
34
201
  if (e.type === 'INSERT') {
35
- const insert = e as InsertEntity
36
- const block = blocksByName[insert.block]
37
- if (!block) {
38
- logger.error('no block found for insert. block:', insert.block)
39
- continue
40
- }
41
-
42
- const rowCount = insert.rowCount ?? 1
43
- const columnCount = insert.columnCount ?? 1
44
- const rowSpacing = insert.rowSpacing ?? 0
45
- const columnSpacing = insert.columnSpacing ?? 0
46
- const rotation = insert.rotation ?? 0
47
-
48
- // It appears that the rectangular array is affected by rotation, but NOT by scale.
49
- let rowVec: { x: number; y: number }
50
- let colVec: { x: number; y: number }
51
- if (rowCount > 1 || columnCount > 1) {
52
- const cos = Math.cos((rotation * Math.PI) / 180)
53
- const sin = Math.sin((rotation * Math.PI) / 180)
54
- rowVec = { x: -sin * rowSpacing, y: cos * rowSpacing }
55
- colVec = { x: cos * columnSpacing, y: sin * columnSpacing }
56
- } else {
57
- rowVec = { x: 0, y: 0 }
58
- colVec = { x: 0, y: 0 }
59
- }
60
-
61
- // For rectangular arrays, add the block entities for each location in the array
62
- for (let r = 0; r < rowCount; r++) {
63
- for (let c = 0; c < columnCount; c++) {
64
- // Adjust insert transform by row and column for rectangular arrays
65
- const t: Transform = {
66
- x: insert.x + rowVec.x * r + colVec.x * c,
67
- y: insert.y + rowVec.y * r + colVec.y * c,
68
- scaleX: insert.scaleX,
69
- scaleY: insert.scaleY,
70
- scaleZ: insert.scaleZ,
71
- extrusionX: insert.extrusionX,
72
- extrusionY: insert.extrusionY,
73
- extrusionZ: insert.extrusionZ,
74
- rotation: insert.rotation,
75
- }
76
- // Add the insert transform and recursively add entities
77
- const transforms2 = transforms.slice(0)
78
- transforms2.push(t)
79
-
80
- // Use the insert layer
81
- const blockEntities = block.entities.map((be: Entity) => {
82
- const be2 = cloneDeep(be)
83
- be2.layer = insert.layer
84
- // https://github.com/bjnortier/dxf/issues/52
85
- // See Issue 52. If we don't modify the
86
- // entity coordinates here it creates an issue with the
87
- // transformation matrices (which are only applied AFTER
88
- // block insertion modifications has been applied).
89
- switch (be2.type) {
90
- case 'LINE': {
91
- const line = be2 as LineEntity
92
- line.start.x -= block.x
93
- line.start.y -= block.y
94
- line.end.x -= block.x
95
- line.end.y -= block.y
96
- break
97
- }
98
- case 'LWPOLYLINE':
99
- case 'POLYLINE': {
100
- const poly = be2 as PolylineEntity
101
- for (const v of poly.vertices) {
102
- if (v.x !== undefined) v.x -= block.x
103
- if (v.y !== undefined) v.y -= block.y
104
- }
105
- break
106
- }
107
- case 'CIRCLE': {
108
- const circle = be2 as CircleEntity
109
- circle.x -= block.x
110
- circle.y -= block.y
111
- break
112
- }
113
- case 'ELLIPSE': {
114
- const ellipse = be2 as EllipseEntity
115
- ellipse.x -= block.x
116
- ellipse.y -= block.y
117
- break
118
- }
119
- case 'ARC': {
120
- const arc = be2 as ArcEntity
121
- arc.x -= block.x
122
- arc.y -= block.y
123
- break
124
- }
125
- case 'SPLINE': {
126
- const spline = be2 as SplineEntity
127
- for (const cp of spline.controlPoints) {
128
- cp.x -= block.x
129
- cp.y -= block.y
130
- }
131
- break
132
- }
133
- }
134
- return be2
135
- })
136
- current = current.concat(gatherEntities(blockEntities, transforms2))
137
- }
138
- }
202
+ current.push(
203
+ ...expandInsert(e as InsertEntity, blocksByName, transforms, gatherEntities),
204
+ )
139
205
  } else {
140
206
  // Top-level entity. Clone and add the transforms
141
207
  // The transforms are reversed so they occur in