@linkiez/dxf-renew 7.0.0 → 7.2.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 (252) hide show
  1. package/.eslintrc.json +1 -16
  2. package/.github/instructions/code-patterns.instructions.md +1 -1
  3. package/.github/instructions/exdxf.instruction.md +161 -0
  4. package/.github/instructions/tdd.instructions.md +271 -0
  5. package/.yarn/install-state.gz +0 -0
  6. package/ARCHITECTURE.md +163 -0
  7. package/CHANGELOG.md +39 -0
  8. package/CONTRIBUTING.md +16 -14
  9. package/README.md +113 -16
  10. package/{PLAN.md → ROADMAP.md} +244 -102
  11. package/dist/dxf.js +2212 -454
  12. package/docs/EZDXF_REFERENCE_SITEMAP.md +55 -0
  13. package/docs/FIXTURE_VALIDATION_EZDXF.md +62 -0
  14. package/lib/Helper.cjs +6 -2
  15. package/lib/Helper.cjs.map +3 -3
  16. package/lib/Helper.js +6 -2
  17. package/lib/Helper.js.map +2 -2
  18. package/lib/denormalise.cjs +131 -91
  19. package/lib/denormalise.cjs.map +2 -2
  20. package/lib/denormalise.js +131 -91
  21. package/lib/denormalise.js.map +2 -2
  22. package/lib/dimensionToSVG.cjs +318 -53
  23. package/lib/dimensionToSVG.cjs.map +3 -3
  24. package/lib/dimensionToSVG.js +316 -52
  25. package/lib/dimensionToSVG.js.map +2 -2
  26. package/lib/entityToPolyline.cjs +95 -0
  27. package/lib/entityToPolyline.cjs.map +3 -3
  28. package/lib/entityToPolyline.js +95 -0
  29. package/lib/entityToPolyline.js.map +2 -2
  30. package/lib/handlers/entities.cjs +111 -27
  31. package/lib/handlers/entities.cjs.map +3 -3
  32. package/lib/handlers/entities.js +111 -27
  33. package/lib/handlers/entities.js.map +3 -3
  34. package/lib/handlers/entity/dgnUnderlay.cjs +106 -0
  35. package/lib/handlers/entity/dgnUnderlay.cjs.map +7 -0
  36. package/lib/handlers/entity/dgnUnderlay.js +71 -0
  37. package/lib/handlers/entity/dgnUnderlay.js.map +7 -0
  38. package/lib/handlers/entity/dimension.cjs +24 -0
  39. package/lib/handlers/entity/dimension.cjs.map +2 -2
  40. package/lib/handlers/entity/dimension.js +24 -0
  41. package/lib/handlers/entity/dimension.js.map +2 -2
  42. package/lib/handlers/entity/dwfUnderlay.cjs +106 -0
  43. package/lib/handlers/entity/dwfUnderlay.cjs.map +7 -0
  44. package/lib/handlers/entity/dwfUnderlay.js +71 -0
  45. package/lib/handlers/entity/dwfUnderlay.js.map +7 -0
  46. package/lib/handlers/entity/image.cjs +123 -0
  47. package/lib/handlers/entity/image.cjs.map +7 -0
  48. package/lib/handlers/entity/image.js +88 -0
  49. package/lib/handlers/entity/image.js.map +7 -0
  50. package/lib/handlers/entity/leader.cjs +148 -0
  51. package/lib/handlers/entity/leader.cjs.map +7 -0
  52. package/lib/handlers/entity/leader.js +113 -0
  53. package/lib/handlers/entity/leader.js.map +7 -0
  54. package/lib/handlers/entity/mleader.cjs +69 -0
  55. package/lib/handlers/entity/mleader.cjs.map +7 -0
  56. package/lib/handlers/entity/mleader.js +34 -0
  57. package/lib/handlers/entity/mleader.js.map +7 -0
  58. package/lib/handlers/entity/mline.cjs +91 -0
  59. package/lib/handlers/entity/mline.cjs.map +7 -0
  60. package/lib/handlers/entity/mline.js +56 -0
  61. package/lib/handlers/entity/mline.js.map +7 -0
  62. package/lib/handlers/entity/oleframe.cjs +98 -0
  63. package/lib/handlers/entity/oleframe.cjs.map +7 -0
  64. package/lib/handlers/entity/oleframe.js +63 -0
  65. package/lib/handlers/entity/oleframe.js.map +7 -0
  66. package/lib/handlers/entity/pdfUnderlay.cjs +106 -0
  67. package/lib/handlers/entity/pdfUnderlay.cjs.map +7 -0
  68. package/lib/handlers/entity/pdfUnderlay.js +71 -0
  69. package/lib/handlers/entity/pdfUnderlay.js.map +7 -0
  70. package/lib/handlers/entity/ray.cjs +81 -0
  71. package/lib/handlers/entity/ray.cjs.map +7 -0
  72. package/lib/handlers/entity/ray.js +46 -0
  73. package/lib/handlers/entity/ray.js.map +7 -0
  74. package/lib/handlers/entity/region.cjs +67 -0
  75. package/lib/handlers/entity/region.cjs.map +7 -0
  76. package/lib/handlers/entity/region.js +32 -0
  77. package/lib/handlers/entity/region.js.map +7 -0
  78. package/lib/handlers/entity/shape.cjs +95 -0
  79. package/lib/handlers/entity/shape.cjs.map +7 -0
  80. package/lib/handlers/entity/shape.js +60 -0
  81. package/lib/handlers/entity/shape.js.map +7 -0
  82. package/lib/handlers/entity/table.cjs +71 -0
  83. package/lib/handlers/entity/table.cjs.map +7 -0
  84. package/lib/handlers/entity/table.js +36 -0
  85. package/lib/handlers/entity/table.js.map +7 -0
  86. package/lib/handlers/entity/tolerance.cjs +90 -0
  87. package/lib/handlers/entity/tolerance.cjs.map +7 -0
  88. package/lib/handlers/entity/tolerance.js +55 -0
  89. package/lib/handlers/entity/tolerance.js.map +7 -0
  90. package/lib/handlers/entity/trace.cjs +101 -0
  91. package/lib/handlers/entity/trace.cjs.map +7 -0
  92. package/lib/handlers/entity/trace.js +66 -0
  93. package/lib/handlers/entity/trace.js.map +7 -0
  94. package/lib/handlers/entity/wipeout.cjs +122 -0
  95. package/lib/handlers/entity/wipeout.cjs.map +7 -0
  96. package/lib/handlers/entity/wipeout.js +87 -0
  97. package/lib/handlers/entity/wipeout.js.map +7 -0
  98. package/lib/handlers/entity/xline.cjs +81 -0
  99. package/lib/handlers/entity/xline.cjs.map +7 -0
  100. package/lib/handlers/entity/xline.js +46 -0
  101. package/lib/handlers/entity/xline.js.map +7 -0
  102. package/lib/handlers/objects.cjs +299 -136
  103. package/lib/handlers/objects.cjs.map +2 -2
  104. package/lib/handlers/objects.js +299 -136
  105. package/lib/handlers/objects.js.map +2 -2
  106. package/lib/handlers/tables.cjs +96 -17
  107. package/lib/handlers/tables.cjs.map +2 -2
  108. package/lib/handlers/tables.js +96 -17
  109. package/lib/handlers/tables.js.map +2 -2
  110. package/lib/index.cjs +5 -2
  111. package/lib/index.cjs.map +3 -3
  112. package/lib/index.js +18 -16
  113. package/lib/index.js.map +3 -3
  114. package/lib/toJson.cjs +29 -0
  115. package/lib/toJson.cjs.map +7 -0
  116. package/lib/toJson.js +9 -0
  117. package/lib/toJson.js.map +7 -0
  118. package/lib/toSVG.cjs +105 -11
  119. package/lib/toSVG.cjs.map +3 -3
  120. package/lib/toSVG.js +106 -12
  121. package/lib/toSVG.js.map +2 -2
  122. package/lib/types/dimension-entity.cjs.map +1 -1
  123. package/lib/types/entity.cjs.map +1 -1
  124. package/lib/types/helper.cjs.map +1 -1
  125. package/lib/types/image-entity.cjs +17 -0
  126. package/lib/types/image-entity.cjs.map +7 -0
  127. package/lib/types/image-entity.js +1 -0
  128. package/lib/types/image-entity.js.map +7 -0
  129. package/lib/types/index.cjs +28 -0
  130. package/lib/types/index.cjs.map +2 -2
  131. package/lib/types/index.js +14 -0
  132. package/lib/types/index.js.map +2 -2
  133. package/lib/types/leader-entity.cjs +17 -0
  134. package/lib/types/leader-entity.cjs.map +7 -0
  135. package/lib/types/leader-entity.js +1 -0
  136. package/lib/types/leader-entity.js.map +7 -0
  137. package/lib/types/mleader-entity.cjs +17 -0
  138. package/lib/types/mleader-entity.cjs.map +7 -0
  139. package/lib/types/mleader-entity.js +1 -0
  140. package/lib/types/mleader-entity.js.map +7 -0
  141. package/lib/types/mline-entity.cjs +17 -0
  142. package/lib/types/mline-entity.cjs.map +7 -0
  143. package/lib/types/mline-entity.js +1 -0
  144. package/lib/types/mline-entity.js.map +7 -0
  145. package/lib/types/oleframe-entity.cjs +17 -0
  146. package/lib/types/oleframe-entity.cjs.map +7 -0
  147. package/lib/types/oleframe-entity.js +1 -0
  148. package/lib/types/oleframe-entity.js.map +7 -0
  149. package/lib/types/options.cjs.map +1 -1
  150. package/lib/types/ray-entity.cjs +17 -0
  151. package/lib/types/ray-entity.cjs.map +7 -0
  152. package/lib/types/ray-entity.js +1 -0
  153. package/lib/types/ray-entity.js.map +7 -0
  154. package/lib/types/region-entity.cjs +17 -0
  155. package/lib/types/region-entity.cjs.map +7 -0
  156. package/lib/types/region-entity.js +1 -0
  157. package/lib/types/region-entity.js.map +7 -0
  158. package/lib/types/shape-entity.cjs +17 -0
  159. package/lib/types/shape-entity.cjs.map +7 -0
  160. package/lib/types/shape-entity.js +1 -0
  161. package/lib/types/shape-entity.js.map +7 -0
  162. package/lib/types/table-entity.cjs +17 -0
  163. package/lib/types/table-entity.cjs.map +7 -0
  164. package/lib/types/table-entity.js +1 -0
  165. package/lib/types/table-entity.js.map +7 -0
  166. package/lib/types/tables.cjs.map +1 -1
  167. package/lib/types/tolerance-entity.cjs +17 -0
  168. package/lib/types/tolerance-entity.cjs.map +7 -0
  169. package/lib/types/tolerance-entity.js +1 -0
  170. package/lib/types/tolerance-entity.js.map +7 -0
  171. package/lib/types/trace-entity.cjs +17 -0
  172. package/lib/types/trace-entity.cjs.map +7 -0
  173. package/lib/types/trace-entity.js +1 -0
  174. package/lib/types/trace-entity.js.map +7 -0
  175. package/lib/types/underlay-entity.cjs +17 -0
  176. package/lib/types/underlay-entity.cjs.map +7 -0
  177. package/lib/types/underlay-entity.js +1 -0
  178. package/lib/types/underlay-entity.js.map +7 -0
  179. package/lib/types/wipeout-entity.cjs +17 -0
  180. package/lib/types/wipeout-entity.cjs.map +7 -0
  181. package/lib/types/wipeout-entity.js +1 -0
  182. package/lib/types/wipeout-entity.js.map +7 -0
  183. package/lib/types/xline-entity.cjs +17 -0
  184. package/lib/types/xline-entity.cjs.map +7 -0
  185. package/lib/types/xline-entity.js +1 -0
  186. package/lib/types/xline-entity.js.map +7 -0
  187. package/lib/util/escapeXmlText.cjs +27 -0
  188. package/lib/util/escapeXmlText.cjs.map +7 -0
  189. package/lib/util/escapeXmlText.js +7 -0
  190. package/lib/util/escapeXmlText.js.map +7 -0
  191. package/package.json +9 -18
  192. package/playwright.config.cjs +20 -0
  193. package/src/Helper.ts +8 -3
  194. package/src/denormalise.ts +182 -116
  195. package/src/dimensionToSVG.ts +466 -54
  196. package/src/entityToPolyline.ts +124 -2
  197. package/src/handlers/entities.ts +129 -34
  198. package/src/handlers/entity/dgnUnderlay.ts +94 -0
  199. package/src/handlers/entity/dimension.ts +27 -1
  200. package/src/handlers/entity/dwfUnderlay.ts +94 -0
  201. package/src/handlers/entity/image.ts +118 -0
  202. package/src/handlers/entity/leader.ts +153 -0
  203. package/src/handlers/entity/mleader.ts +46 -0
  204. package/src/handlers/entity/mline.ts +74 -0
  205. package/src/handlers/entity/oleframe.ts +62 -0
  206. package/src/handlers/entity/pdfUnderlay.ts +94 -0
  207. package/src/handlers/entity/ray.ts +52 -0
  208. package/src/handlers/entity/region.ts +42 -0
  209. package/src/handlers/entity/shape.ts +73 -0
  210. package/src/handlers/entity/table.ts +49 -0
  211. package/src/handlers/entity/tolerance.ts +75 -0
  212. package/src/handlers/entity/trace.ts +72 -0
  213. package/src/handlers/entity/wipeout.ts +114 -0
  214. package/src/handlers/entity/xline.ts +52 -0
  215. package/src/handlers/objects.ts +379 -139
  216. package/src/handlers/tables.ts +134 -21
  217. package/src/index.ts +9 -18
  218. package/src/toJson.ts +8 -0
  219. package/src/toSVG.ts +143 -10
  220. package/src/types/dimension-entity.ts +11 -0
  221. package/src/types/entity.ts +30 -0
  222. package/src/types/helper.ts +2 -1
  223. package/src/types/image-entity.ts +35 -0
  224. package/src/types/index.ts +14 -0
  225. package/src/types/leader-entity.ts +40 -0
  226. package/src/types/mleader-entity.ts +8 -0
  227. package/src/types/mline-entity.ts +12 -0
  228. package/src/types/oleframe-entity.ts +40 -0
  229. package/src/types/options.ts +48 -0
  230. package/src/types/ray-entity.ts +12 -0
  231. package/src/types/region-entity.ts +11 -0
  232. package/src/types/shape-entity.ts +19 -0
  233. package/src/types/table-entity.ts +14 -0
  234. package/src/types/tables.ts +160 -0
  235. package/src/types/tolerance-entity.ts +20 -0
  236. package/src/types/trace-entity.ts +14 -0
  237. package/src/types/underlay-entity.ts +35 -0
  238. package/src/types/wipeout-entity.ts +20 -0
  239. package/src/types/xline-entity.ts +12 -0
  240. package/src/util/escapeXmlText.ts +10 -0
  241. package/tools/browser_test_server.cjs +87 -0
  242. package/tools/ezdxf_generate_dimensions_all_types.py +246 -0
  243. package/tools/ezdxf_generate_dimensions_angular_3p.py +59 -0
  244. package/tools/ezdxf_generate_dimensions_large_scale.py +87 -0
  245. package/tools/ezdxf_regenerate_problem_fixtures.py +184 -0
  246. package/tools/ezdxf_validate_fixtures.py +165 -0
  247. package/docs/DIMENSION_SUMMARY.md +0 -248
  248. package/docs/DIMENSION_SUMMARY.pt-BR.md +0 -248
  249. package/docs/IMPLEMENTED-2D-ENTITIES.md +0 -54
  250. package/docs/IMPLEMENTED-2D-ENTITIES.pt-BR.md +0 -54
  251. package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.md +0 -241
  252. package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.pt-BR.md +0 -169
@@ -9,8 +9,13 @@ import type {
9
9
  EllipseEntity,
10
10
  EntityToPolylineOptions,
11
11
  HandlerVertex,
12
+ LeaderEntity,
12
13
  LineEntity,
14
+ RayEntity,
15
+ ShapeEntity,
13
16
  SplineEntity,
17
+ WipeoutEntity,
18
+ XLineEntity,
14
19
  } from './types'
15
20
  import type { PointTuple } from './types/common'
16
21
 
@@ -35,7 +40,17 @@ interface LocalPolylineEntity {
35
40
 
36
41
  type Entity =
37
42
  | LineEntity
43
+ | LeaderEntity
44
+ | RayEntity
45
+ | XLineEntity
46
+ | ShapeEntity
47
+ | WipeoutEntity
38
48
  | (LocalPolylineEntity & { type: 'LWPOLYLINE' | 'POLYLINE' })
49
+ | {
50
+ type: 'SOLID' | 'TRACE'
51
+ corners?: Array<{ x: number; y: number }>
52
+ points?: Array<{ x: number; y: number }>
53
+ }
39
54
  | CircleEntity
40
55
  | EllipseEntity
41
56
  | ArcEntity
@@ -151,7 +166,7 @@ export const interpolateBSpline = (
151
166
  return polyline
152
167
  }
153
168
 
154
- export const polyfaceOutline = (entity: LocalPolylineEntity): Point[][] => {
169
+ export const polyfaceOutline = (entity: LocalPolylineEntity): Point[][] => { // NOSONAR
155
170
  const vertices: Array<{ x: number; y: number }> = []
156
171
  const faces: Array<{ indices: number[]; hiddens: boolean[] }> = []
157
172
 
@@ -219,13 +234,21 @@ export const polyfaceOutline = (entity: LocalPolylineEntity): Point[][] => {
219
234
  * the DXF in SVG, Canvas, WebGL etc., without depending on native support
220
235
  * of primitive objects (ellispe, spline etc.)
221
236
  */
222
- export default function entityToPolyline(
237
+ export default function entityToPolyline( // NOSONAR
223
238
  entity: Entity,
224
239
  options?: EntityToPolylineOptions,
225
240
  ): Point[] {
226
241
  options = options || {}
227
242
  let polyline: Point[] | undefined
228
243
 
244
+ const INFINITE_LINE_LENGTH = 1000
245
+
246
+ const normalize2 = (x: number, y: number): { x: number; y: number } | null => {
247
+ const len = Math.hypot(x, y)
248
+ if (len === 0) return null
249
+ return { x: x / len, y: y / len }
250
+ }
251
+
229
252
  if (entity.type === 'LINE') {
230
253
  polyline = [
231
254
  [entity.start.x, entity.start.y],
@@ -233,6 +256,92 @@ export default function entityToPolyline(
233
256
  ]
234
257
  }
235
258
 
259
+ if (entity.type === 'LEADER') {
260
+ if (entity.vertices.length >= 2) {
261
+ polyline = entity.vertices.map((v) => [v.x, v.y])
262
+ } else {
263
+ logger.warn('LEADER entity with insufficient vertices')
264
+ polyline = []
265
+ }
266
+ }
267
+
268
+ if (entity.type === 'RAY') {
269
+ const dir = normalize2(entity.direction.x, entity.direction.y)
270
+ if (dir === null) {
271
+ logger.warn('RAY entity with zero direction vector')
272
+ polyline = []
273
+ } else {
274
+ polyline = [
275
+ [entity.start.x, entity.start.y],
276
+ [
277
+ entity.start.x + dir.x * INFINITE_LINE_LENGTH,
278
+ entity.start.y + dir.y * INFINITE_LINE_LENGTH,
279
+ ],
280
+ ]
281
+ }
282
+ }
283
+
284
+ if (entity.type === 'XLINE') {
285
+ const dir = normalize2(entity.direction.x, entity.direction.y)
286
+ if (dir === null) {
287
+ logger.warn('XLINE entity with zero direction vector')
288
+ polyline = []
289
+ } else {
290
+ polyline = [
291
+ [
292
+ entity.basePoint.x - dir.x * INFINITE_LINE_LENGTH,
293
+ entity.basePoint.y - dir.y * INFINITE_LINE_LENGTH,
294
+ ],
295
+ [
296
+ entity.basePoint.x + dir.x * INFINITE_LINE_LENGTH,
297
+ entity.basePoint.y + dir.y * INFINITE_LINE_LENGTH,
298
+ ],
299
+ ]
300
+ }
301
+ }
302
+
303
+ if (entity.type === 'SHAPE') {
304
+ const x = entity.insertionPoint?.x ?? 0
305
+ const y = entity.insertionPoint?.y ?? 0
306
+ const size = entity.size ?? 0
307
+ const scaleX = entity.relativeXScale ?? 1
308
+ const length = size * scaleX
309
+ polyline = [
310
+ [x, y],
311
+ [x + length, y],
312
+ ]
313
+ }
314
+
315
+ if (entity.type === 'WIPEOUT') {
316
+ const verts = entity.clipBoundaryVertices
317
+ if (!verts || verts.length < 2) {
318
+ logger.warn('WIPEOUT entity with missing clip boundary vertices')
319
+ polyline = []
320
+ } else {
321
+ const insX = entity.insertionPoint?.x ?? 0
322
+ const insY = entity.insertionPoint?.y ?? 0
323
+
324
+ const ux = entity.uVector?.x ?? 1
325
+ const uy = entity.uVector?.y ?? 0
326
+
327
+ const vx = entity.vVector?.x ?? 0
328
+ const vy = entity.vVector?.y ?? 1
329
+
330
+ polyline = verts.map((p) => [
331
+ insX + ux * p.x + vx * p.y,
332
+ insY + uy * p.x + vy * p.y,
333
+ ])
334
+
335
+ if (polyline.length > 0) {
336
+ const first = polyline[0]
337
+ const last = polyline[polyline.length - 1]
338
+ if (first[0] !== last[0] || first[1] !== last[1]) {
339
+ polyline.push(first)
340
+ }
341
+ }
342
+ }
343
+ }
344
+
236
345
  if (entity.type === 'LWPOLYLINE' || entity.type === 'POLYLINE') {
237
346
  polyline = []
238
347
  if (entity.polyfaceMesh) {
@@ -330,6 +439,19 @@ export default function entityToPolyline(
330
439
  )
331
440
  }
332
441
 
442
+ if (entity.type === 'SOLID' || entity.type === 'TRACE') {
443
+ const corners = entity.corners ?? entity.points
444
+ if (corners && corners.length >= 4) {
445
+ polyline = [
446
+ [corners[0].x, corners[0].y],
447
+ [corners[1].x, corners[1].y],
448
+ [corners[2].x, corners[2].y],
449
+ [corners[3].x, corners[3].y],
450
+ [corners[0].x, corners[0].y],
451
+ ]
452
+ }
453
+ }
454
+
333
455
  if (!polyline) {
334
456
  logger.warn('unsupported entity for converting to polyline:', entity.type)
335
457
  return []
@@ -1,28 +1,44 @@
1
1
  import type { DXFTuple } from '../types/dxf'
2
2
  import type { Entity } from '../types/entity'
3
- import type { PolylineEntity } from '../types/polyline-entity'
3
+ import type { PolylineEntity, Vertex } from '../types/polyline-entity'
4
4
 
5
5
  import logger from '../util/logger'
6
6
  import arc from './entity/arc'
7
7
  import attdef from './entity/attdef'
8
8
  import attrib from './entity/attrib'
9
9
  import circle from './entity/circle'
10
+ import dgnUnderlay from './entity/dgnUnderlay'
10
11
  import dimension from './entity/dimension'
12
+ import dwfUnderlay from './entity/dwfUnderlay'
11
13
  import ellipse from './entity/ellipse'
12
14
  import hatch from './entity/hatch'
15
+ import image from './entity/image'
13
16
  import insert from './entity/insert'
17
+ import leader from './entity/leader'
14
18
  import line from './entity/line'
15
19
  import lwpolyline from './entity/lwpolyline'
20
+ import mleader from './entity/mleader'
21
+ import mline from './entity/mline'
16
22
  import mtext from './entity/mtext'
17
23
  import ole2Frame from './entity/ole2Frame'
24
+ import oleFrame from './entity/oleframe'
25
+ import pdfUnderlay from './entity/pdfUnderlay'
18
26
  import point from './entity/point'
19
27
  import polyline from './entity/polyline'
28
+ import ray from './entity/ray'
29
+ import region from './entity/region'
30
+ import shape from './entity/shape'
20
31
  import solid from './entity/solid'
21
32
  import spline from './entity/spline'
33
+ import table from './entity/table'
22
34
  import text from './entity/text'
23
35
  import threeDFace from './entity/threeDFace'
36
+ import tolerance from './entity/tolerance'
37
+ import trace from './entity/trace'
24
38
  import vertex from './entity/vertex'
25
39
  import viewport from './entity/viewport'
40
+ import wipeout from './entity/wipeout'
41
+ import xline from './entity/xline'
26
42
 
27
43
  interface EntityHandler {
28
44
  TYPE: string
@@ -33,15 +49,28 @@ const handlers: Record<string, EntityHandler> = [
33
49
  point,
34
50
  line,
35
51
  lwpolyline,
52
+ mline,
53
+ mleader,
36
54
  polyline,
37
55
  vertex,
38
56
  circle,
39
57
  arc,
40
58
  ellipse,
41
59
  spline,
60
+ table,
42
61
  solid,
62
+ trace,
43
63
  hatch,
64
+ image,
65
+ leader,
66
+ ray,
67
+ region,
68
+ dwfUnderlay,
69
+ dgnUnderlay,
70
+ pdfUnderlay,
71
+ shape,
44
72
  mtext,
73
+ tolerance,
45
74
  attdef,
46
75
  attrib,
47
76
  text,
@@ -50,6 +79,9 @@ const handlers: Record<string, EntityHandler> = [
50
79
  threeDFace,
51
80
  viewport,
52
81
  ole2Frame,
82
+ oleFrame,
83
+ xline,
84
+ wipeout,
53
85
  ].reduce((acc, mod) => {
54
86
  acc[mod.TYPE] = mod
55
87
  return acc
@@ -61,8 +93,102 @@ const handlers: Record<string, EntityHandler> = [
61
93
  * @param tuples - Array of DXF tuples representing entities
62
94
  * @returns Array of parsed entities
63
95
  */
96
+ class EntityGroupProcessor {
97
+ private readonly entities: Entity[] = []
98
+ private currentPolyline: PolylineEntity | undefined
99
+
100
+ getEntities(): Entity[] {
101
+ return this.entities
102
+ }
103
+
104
+ finalize(): void {
105
+ this.flushOpenPolyline('DXF ended with an open POLYLINE (missing SEQEND); flushing open polyline')
106
+ }
107
+
108
+ processGroup(tuples: DXFTuple[]): void {
109
+ const entityType = String(tuples[0][1])
110
+ const contentTuples = tuples.slice(1)
111
+
112
+ switch (entityType) {
113
+ case 'SEQEND':
114
+ this.endSequence()
115
+ break
116
+ case 'POLYLINE':
117
+ this.startPolyline(contentTuples)
118
+ break
119
+ case 'VERTEX':
120
+ this.addVertex(contentTuples)
121
+ break
122
+ default:
123
+ this.addEntity(entityType, contentTuples)
124
+ break
125
+ }
126
+ }
127
+
128
+ private parseEntity(entityType: string, contentTuples: DXFTuple[]): Entity | undefined {
129
+ const handler = handlers[entityType]
130
+ if (!handler) {
131
+ logger.warn('unsupported type in ENTITIES section:', entityType)
132
+ return undefined
133
+ }
134
+ return handler.process(contentTuples)
135
+ }
136
+
137
+ private flushOpenPolyline(reason: string): void {
138
+ if (!this.currentPolyline) return
139
+ logger.warn(reason)
140
+ this.currentPolyline = undefined
141
+ }
142
+
143
+ private endSequence(): void {
144
+ // SEQEND may also terminate other sequences (e.g. INSERT attributes).
145
+ // Only treat it as significant when we're inside a POLYLINE sequence.
146
+ this.currentPolyline = undefined
147
+ }
148
+
149
+ private startPolyline(contentTuples: DXFTuple[]): void {
150
+ this.flushOpenPolyline(
151
+ 'POLYLINE started while previous POLYLINE is still open; flushing previous polyline',
152
+ )
153
+
154
+ const e = this.parseEntity('POLYLINE', contentTuples)
155
+ if (!e) return
156
+
157
+ this.currentPolyline = e as PolylineEntity
158
+ this.entities.push(e)
159
+ }
160
+
161
+ private addVertex(contentTuples: DXFTuple[]): void {
162
+ const e = this.parseEntity('VERTEX', contentTuples)
163
+ if (!e) return
164
+
165
+ if (!this.currentPolyline) {
166
+ logger.error('ignoring invalid VERTEX entity')
167
+ return
168
+ }
169
+
170
+ this.currentPolyline.vertices.push(e as Vertex)
171
+ }
172
+
173
+ private addEntity(entityType: string, contentTuples: DXFTuple[]): void {
174
+ this.flushOpenPolyline('POLYLINE sequence ended without SEQEND; flushing open polyline')
175
+
176
+ const e = this.parseEntity(entityType, contentTuples)
177
+ if (!e) return
178
+ this.entities.push(e)
179
+ }
180
+ }
181
+
182
+ function processEntityGroups(entityGroups: DXFTuple[][]): Entity[] {
183
+ const processor = new EntityGroupProcessor()
184
+ for (const tuples of entityGroups) {
185
+ processor.processGroup(tuples)
186
+ }
187
+ processor.finalize()
188
+ return processor.getEntities()
189
+ }
190
+
64
191
  export default function parseEntities(tuples: DXFTuple[]): Entity[] {
65
- const entities: Entity[] = []
66
192
  const entityGroups: DXFTuple[][] = []
67
193
  let currentEntityTuples: DXFTuple[] = []
68
194
 
@@ -76,36 +202,5 @@ export default function parseEntities(tuples: DXFTuple[]): Entity[] {
76
202
  currentEntityTuples.push(tuple)
77
203
  }
78
204
 
79
- let currentPolyline: PolylineEntity | undefined
80
- for (const tuples of entityGroups) {
81
- const entityType = tuples[0][1]
82
- const contentTuples = tuples.slice(1)
83
-
84
- if (entityType in handlers) {
85
- const e = handlers[entityType].process(contentTuples)
86
- // "POLYLINE" cannot be parsed in isolation, it is followed by
87
- // N "VERTEX" entities and ended with a "SEQEND" entity.
88
- // Essentially we convert POLYLINE to LWPOLYLINE - the extra
89
- // vertex flags are not supported
90
- if (entityType === 'POLYLINE') {
91
- currentPolyline = e as PolylineEntity
92
- entities.push(e)
93
- } else if (entityType === 'VERTEX') {
94
- if (currentPolyline) {
95
- currentPolyline.vertices.push(e as any)
96
- } else {
97
- logger.error('ignoring invalid VERTEX entity')
98
- }
99
- } else if (entityType === 'SEQEND') {
100
- currentPolyline = undefined
101
- } else {
102
- // All other entities
103
- entities.push(e)
104
- }
105
- } else {
106
- logger.warn('unsupported type in ENTITIES section:', entityType)
107
- }
108
- }
109
-
110
- return entities
205
+ return processEntityGroups(entityGroups)
111
206
  }
@@ -0,0 +1,94 @@
1
+ import type { DXFTuple } from '../../types'
2
+
3
+ import common from './common'
4
+
5
+ export const TYPE = 'DGNUNDERLAY'
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 }
@@ -15,6 +15,8 @@ interface DimensionEntity {
15
15
  type: typeof TYPE
16
16
  block?: string
17
17
  start: Point3D
18
+ angleVertex?: Point3D
19
+ arcPoint?: Point3D
18
20
  textMidpoint: Point3D
19
21
  measureStart: Point3D
20
22
  measureEnd: Point3D
@@ -89,6 +91,30 @@ export const process = (tuples: DXFTuple[]): DimensionEntity => {
89
91
  case 34:
90
92
  entity.measureEnd.z = value as number
91
93
  break
94
+ case 15:
95
+ entity.angleVertex = entity.angleVertex || { x: 0, y: 0, z: 0 }
96
+ entity.angleVertex.x = value as number
97
+ break
98
+ case 25:
99
+ entity.angleVertex = entity.angleVertex || { x: 0, y: 0, z: 0 }
100
+ entity.angleVertex.y = value as number
101
+ break
102
+ case 35:
103
+ entity.angleVertex = entity.angleVertex || { x: 0, y: 0, z: 0 }
104
+ entity.angleVertex.z = value as number
105
+ break
106
+ case 16:
107
+ entity.arcPoint = entity.arcPoint || { x: 0, y: 0, z: 0 }
108
+ entity.arcPoint.x = value as number
109
+ break
110
+ case 26:
111
+ entity.arcPoint = entity.arcPoint || { x: 0, y: 0, z: 0 }
112
+ entity.arcPoint.y = value as number
113
+ break
114
+ case 36:
115
+ entity.arcPoint = entity.arcPoint || { x: 0, y: 0, z: 0 }
116
+ entity.arcPoint.z = value as number
117
+ break
92
118
  case 50:
93
119
  entity.rotation = value as number
94
120
  break
@@ -177,7 +203,7 @@ function parseBitCombinationsFromValue(value: number): BitCombinationsResult {
177
203
  let ordinateType = false
178
204
  let userDefinedLocation = false
179
205
 
180
- // ToDo: Solve in some more clever way??
206
+ // Note: keep this logic explicit; DXF stores flags as bit combinations.
181
207
  if (value > 6) {
182
208
  const alt1 = value - 32
183
209
  const alt2 = value - 64
@@ -0,0 +1,94 @@
1
+ import type { DXFTuple } from '../../types'
2
+
3
+ import common from './common'
4
+
5
+ export const TYPE = 'DWFUNDERLAY'
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 }