@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.
- package/.eslintrc.json +1 -16
- package/.github/instructions/code-patterns.instructions.md +1 -1
- package/.github/instructions/exdxf.instruction.md +161 -0
- package/.github/instructions/tdd.instructions.md +271 -0
- package/.yarn/install-state.gz +0 -0
- package/ARCHITECTURE.md +163 -0
- package/CHANGELOG.md +39 -0
- package/CONTRIBUTING.md +16 -14
- package/README.md +113 -16
- package/{PLAN.md → ROADMAP.md} +244 -102
- package/dist/dxf.js +2212 -454
- package/docs/EZDXF_REFERENCE_SITEMAP.md +55 -0
- package/docs/FIXTURE_VALIDATION_EZDXF.md +62 -0
- package/lib/Helper.cjs +6 -2
- package/lib/Helper.cjs.map +3 -3
- package/lib/Helper.js +6 -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/entityToPolyline.cjs +95 -0
- package/lib/entityToPolyline.cjs.map +3 -3
- package/lib/entityToPolyline.js +95 -0
- package/lib/entityToPolyline.js.map +2 -2
- package/lib/handlers/entities.cjs +111 -27
- package/lib/handlers/entities.cjs.map +3 -3
- package/lib/handlers/entities.js +111 -27
- 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/mleader.cjs +69 -0
- package/lib/handlers/entity/mleader.cjs.map +7 -0
- package/lib/handlers/entity/mleader.js +34 -0
- package/lib/handlers/entity/mleader.js.map +7 -0
- package/lib/handlers/entity/mline.cjs +91 -0
- package/lib/handlers/entity/mline.cjs.map +7 -0
- package/lib/handlers/entity/mline.js +56 -0
- package/lib/handlers/entity/mline.js.map +7 -0
- package/lib/handlers/entity/oleframe.cjs +98 -0
- package/lib/handlers/entity/oleframe.cjs.map +7 -0
- package/lib/handlers/entity/oleframe.js +63 -0
- package/lib/handlers/entity/oleframe.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/ray.cjs +81 -0
- package/lib/handlers/entity/ray.cjs.map +7 -0
- package/lib/handlers/entity/ray.js +46 -0
- package/lib/handlers/entity/ray.js.map +7 -0
- package/lib/handlers/entity/region.cjs +67 -0
- package/lib/handlers/entity/region.cjs.map +7 -0
- package/lib/handlers/entity/region.js +32 -0
- package/lib/handlers/entity/region.js.map +7 -0
- package/lib/handlers/entity/shape.cjs +95 -0
- package/lib/handlers/entity/shape.cjs.map +7 -0
- package/lib/handlers/entity/shape.js +60 -0
- package/lib/handlers/entity/shape.js.map +7 -0
- package/lib/handlers/entity/table.cjs +71 -0
- package/lib/handlers/entity/table.cjs.map +7 -0
- package/lib/handlers/entity/table.js +36 -0
- package/lib/handlers/entity/table.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/entity/trace.cjs +101 -0
- package/lib/handlers/entity/trace.cjs.map +7 -0
- package/lib/handlers/entity/trace.js +66 -0
- package/lib/handlers/entity/trace.js.map +7 -0
- package/lib/handlers/entity/wipeout.cjs +122 -0
- package/lib/handlers/entity/wipeout.cjs.map +7 -0
- package/lib/handlers/entity/wipeout.js +87 -0
- package/lib/handlers/entity/wipeout.js.map +7 -0
- package/lib/handlers/entity/xline.cjs +81 -0
- package/lib/handlers/entity/xline.cjs.map +7 -0
- package/lib/handlers/entity/xline.js +46 -0
- package/lib/handlers/entity/xline.js.map +7 -0
- package/lib/handlers/objects.cjs +299 -136
- package/lib/handlers/objects.cjs.map +2 -2
- package/lib/handlers/objects.js +299 -136
- package/lib/handlers/objects.js.map +2 -2
- package/lib/handlers/tables.cjs +96 -17
- package/lib/handlers/tables.cjs.map +2 -2
- package/lib/handlers/tables.js +96 -17
- package/lib/handlers/tables.js.map +2 -2
- package/lib/index.cjs +5 -2
- package/lib/index.cjs.map +3 -3
- package/lib/index.js +18 -16
- package/lib/index.js.map +3 -3
- package/lib/toJson.cjs +29 -0
- package/lib/toJson.cjs.map +7 -0
- package/lib/toJson.js +9 -0
- package/lib/toJson.js.map +7 -0
- package/lib/toSVG.cjs +105 -11
- package/lib/toSVG.cjs.map +3 -3
- package/lib/toSVG.js +106 -12
- 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/helper.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 +28 -0
- package/lib/types/index.cjs.map +2 -2
- package/lib/types/index.js +14 -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/mleader-entity.cjs +17 -0
- package/lib/types/mleader-entity.cjs.map +7 -0
- package/lib/types/mleader-entity.js +1 -0
- package/lib/types/mleader-entity.js.map +7 -0
- package/lib/types/mline-entity.cjs +17 -0
- package/lib/types/mline-entity.cjs.map +7 -0
- package/lib/types/mline-entity.js +1 -0
- package/lib/types/mline-entity.js.map +7 -0
- package/lib/types/oleframe-entity.cjs +17 -0
- package/lib/types/oleframe-entity.cjs.map +7 -0
- package/lib/types/oleframe-entity.js +1 -0
- package/lib/types/oleframe-entity.js.map +7 -0
- package/lib/types/options.cjs.map +1 -1
- package/lib/types/ray-entity.cjs +17 -0
- package/lib/types/ray-entity.cjs.map +7 -0
- package/lib/types/ray-entity.js +1 -0
- package/lib/types/ray-entity.js.map +7 -0
- package/lib/types/region-entity.cjs +17 -0
- package/lib/types/region-entity.cjs.map +7 -0
- package/lib/types/region-entity.js +1 -0
- package/lib/types/region-entity.js.map +7 -0
- package/lib/types/shape-entity.cjs +17 -0
- package/lib/types/shape-entity.cjs.map +7 -0
- package/lib/types/shape-entity.js +1 -0
- package/lib/types/shape-entity.js.map +7 -0
- package/lib/types/table-entity.cjs +17 -0
- package/lib/types/table-entity.cjs.map +7 -0
- package/lib/types/table-entity.js +1 -0
- package/lib/types/table-entity.js.map +7 -0
- 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/trace-entity.cjs +17 -0
- package/lib/types/trace-entity.cjs.map +7 -0
- package/lib/types/trace-entity.js +1 -0
- package/lib/types/trace-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/types/wipeout-entity.cjs +17 -0
- package/lib/types/wipeout-entity.cjs.map +7 -0
- package/lib/types/wipeout-entity.js +1 -0
- package/lib/types/wipeout-entity.js.map +7 -0
- package/lib/types/xline-entity.cjs +17 -0
- package/lib/types/xline-entity.cjs.map +7 -0
- package/lib/types/xline-entity.js +1 -0
- package/lib/types/xline-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 +9 -18
- package/playwright.config.cjs +20 -0
- package/src/Helper.ts +8 -3
- package/src/denormalise.ts +182 -116
- package/src/dimensionToSVG.ts +466 -54
- package/src/entityToPolyline.ts +124 -2
- package/src/handlers/entities.ts +129 -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/mleader.ts +46 -0
- package/src/handlers/entity/mline.ts +74 -0
- package/src/handlers/entity/oleframe.ts +62 -0
- package/src/handlers/entity/pdfUnderlay.ts +94 -0
- package/src/handlers/entity/ray.ts +52 -0
- package/src/handlers/entity/region.ts +42 -0
- package/src/handlers/entity/shape.ts +73 -0
- package/src/handlers/entity/table.ts +49 -0
- package/src/handlers/entity/tolerance.ts +75 -0
- package/src/handlers/entity/trace.ts +72 -0
- package/src/handlers/entity/wipeout.ts +114 -0
- package/src/handlers/entity/xline.ts +52 -0
- package/src/handlers/objects.ts +379 -139
- package/src/handlers/tables.ts +134 -21
- package/src/index.ts +9 -18
- package/src/toJson.ts +8 -0
- package/src/toSVG.ts +143 -10
- package/src/types/dimension-entity.ts +11 -0
- package/src/types/entity.ts +30 -0
- package/src/types/helper.ts +2 -1
- package/src/types/image-entity.ts +35 -0
- package/src/types/index.ts +14 -0
- package/src/types/leader-entity.ts +40 -0
- package/src/types/mleader-entity.ts +8 -0
- package/src/types/mline-entity.ts +12 -0
- package/src/types/oleframe-entity.ts +40 -0
- package/src/types/options.ts +48 -0
- package/src/types/ray-entity.ts +12 -0
- package/src/types/region-entity.ts +11 -0
- package/src/types/shape-entity.ts +19 -0
- package/src/types/table-entity.ts +14 -0
- package/src/types/tables.ts +160 -0
- package/src/types/tolerance-entity.ts +20 -0
- package/src/types/trace-entity.ts +14 -0
- package/src/types/underlay-entity.ts +35 -0
- package/src/types/wipeout-entity.ts +20 -0
- package/src/types/xline-entity.ts +12 -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.md +0 -248
- package/docs/DIMENSION_SUMMARY.pt-BR.md +0 -248
- package/docs/IMPLEMENTED-2D-ENTITIES.md +0 -54
- package/docs/IMPLEMENTED-2D-ENTITIES.pt-BR.md +0 -54
- package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.md +0 -241
- package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.pt-BR.md +0 -169
package/lib/toSVG.cjs
CHANGED
|
@@ -37,6 +37,7 @@ var import_denormalise = __toESM(require("./denormalise"), 1);
|
|
|
37
37
|
var import_dimensionToSVG = __toESM(require("./dimensionToSVG"), 1);
|
|
38
38
|
var import_entityToPolyline = __toESM(require("./entityToPolyline"), 1);
|
|
39
39
|
var import_getRGBForEntity = __toESM(require("./getRGBForEntity"), 1);
|
|
40
|
+
var import_escapeXmlText = __toESM(require("./util/escapeXmlText"), 1);
|
|
40
41
|
var import_logger = __toESM(require("./util/logger"), 1);
|
|
41
42
|
var import_rgbToColorAttribute = __toESM(require("./util/rgbToColorAttribute"), 1);
|
|
42
43
|
var import_rotate = __toESM(require("./util/rotate"), 1);
|
|
@@ -93,6 +94,23 @@ const lwpolyline = (entity) => {
|
|
|
93
94
|
entity.transforms ?? []
|
|
94
95
|
);
|
|
95
96
|
};
|
|
97
|
+
const leader = (entity) => {
|
|
98
|
+
if (!entity.vertices || entity.vertices.length < 2) return null;
|
|
99
|
+
const bbox0 = entity.vertices.reduce(
|
|
100
|
+
(acc, p) => acc.expandByPoint({ x: p.x, y: p.y }),
|
|
101
|
+
new import_vecks.Box2()
|
|
102
|
+
);
|
|
103
|
+
const d = entity.vertices.reduce((acc, p, i) => {
|
|
104
|
+
acc += i === 0 ? "M" : "L";
|
|
105
|
+
acc += p.x + "," + p.y;
|
|
106
|
+
return acc;
|
|
107
|
+
}, "");
|
|
108
|
+
return (0, import_transformBoundingBoxAndElement.default)(
|
|
109
|
+
bbox0,
|
|
110
|
+
`<path d="${d}" />`,
|
|
111
|
+
entity.transforms ?? []
|
|
112
|
+
);
|
|
113
|
+
};
|
|
96
114
|
const circle = (entity) => {
|
|
97
115
|
const bbox0 = new import_vecks.Box2().expandByPoint({
|
|
98
116
|
x: entity.x + entity.r,
|
|
@@ -232,7 +250,7 @@ const text = (entity) => {
|
|
|
232
250
|
const textWidth = content.length * height * 0.6;
|
|
233
251
|
const bbox0 = new import_vecks.Box2().expandByPoint({ x, y }).expandByPoint({ x: x + textWidth, y: y + height });
|
|
234
252
|
const rotationDegrees = rotation * 180 / Math.PI;
|
|
235
|
-
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${content}</text>`;
|
|
253
|
+
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${(0, import_escapeXmlText.default)(content)}</text>`;
|
|
236
254
|
const { bbox, element } = addFlipXIfApplicable(entity, {
|
|
237
255
|
bbox: bbox0,
|
|
238
256
|
element: element0
|
|
@@ -248,15 +266,47 @@ const mtext = (entity) => {
|
|
|
248
266
|
const bbox0 = new import_vecks.Box2().expandByPoint({ x, y }).expandByPoint({ x: x + textWidth, y: y + height });
|
|
249
267
|
const rotation = entity.xAxisX !== void 0 && entity.xAxisY !== void 0 ? Math.atan2(entity.xAxisY, entity.xAxisX) : 0;
|
|
250
268
|
const rotationDegrees = rotation * 180 / Math.PI;
|
|
251
|
-
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${content}</text>`;
|
|
269
|
+
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${(0, import_escapeXmlText.default)(content)}</text>`;
|
|
270
|
+
const { bbox, element } = addFlipXIfApplicable(entity, {
|
|
271
|
+
bbox: bbox0,
|
|
272
|
+
element: element0
|
|
273
|
+
});
|
|
274
|
+
return (0, import_transformBoundingBoxAndElement.default)(bbox, element, entity.transforms ?? []);
|
|
275
|
+
};
|
|
276
|
+
const tolerance = (entity) => {
|
|
277
|
+
const x = entity.insertionPoint?.x ?? 0;
|
|
278
|
+
const y = entity.insertionPoint?.y ?? 0;
|
|
279
|
+
const height = 1;
|
|
280
|
+
const content = entity.text ?? "";
|
|
281
|
+
const rotation = entity.xAxisDirection ? Math.atan2(entity.xAxisDirection.y, entity.xAxisDirection.x) : 0;
|
|
282
|
+
const rotationDegrees = rotation * 180 / Math.PI;
|
|
283
|
+
const textWidth = content.length * height * 0.6;
|
|
284
|
+
const bbox0 = new import_vecks.Box2().expandByPoint({ x, y }).expandByPoint({ x: x + textWidth, y: y + height });
|
|
285
|
+
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${(0, import_escapeXmlText.default)(content)}</text>`;
|
|
252
286
|
const { bbox, element } = addFlipXIfApplicable(entity, {
|
|
253
287
|
bbox: bbox0,
|
|
254
288
|
element: element0
|
|
255
289
|
});
|
|
256
290
|
return (0, import_transformBoundingBoxAndElement.default)(bbox, element, entity.transforms ?? []);
|
|
257
291
|
};
|
|
258
|
-
const
|
|
259
|
-
const
|
|
292
|
+
const shape = (entity) => {
|
|
293
|
+
const x = entity.insertionPoint?.x ?? 0;
|
|
294
|
+
const y = entity.insertionPoint?.y ?? 0;
|
|
295
|
+
const height = entity.size ?? 1;
|
|
296
|
+
const rotation = entity.rotation ?? 0;
|
|
297
|
+
const content = entity.name ?? "";
|
|
298
|
+
const textWidth = content.length * height * 0.6;
|
|
299
|
+
const bbox0 = new import_vecks.Box2().expandByPoint({ x, y }).expandByPoint({ x: x + textWidth, y: y + height });
|
|
300
|
+
const rotationDegrees = rotation * 180 / Math.PI;
|
|
301
|
+
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${(0, import_escapeXmlText.default)(content)}</text>`;
|
|
302
|
+
const { bbox, element } = addFlipXIfApplicable(entity, {
|
|
303
|
+
bbox: bbox0,
|
|
304
|
+
element: element0
|
|
305
|
+
});
|
|
306
|
+
return (0, import_transformBoundingBoxAndElement.default)(bbox, element, entity.transforms ?? []);
|
|
307
|
+
};
|
|
308
|
+
const dimension = (entity, dimStyle, options, viewport) => {
|
|
309
|
+
const result = (0, import_dimensionToSVG.default)(entity, dimStyle, options, viewport);
|
|
260
310
|
return (0, import_transformBoundingBoxAndElement.default)(
|
|
261
311
|
result.bbox,
|
|
262
312
|
result.element,
|
|
@@ -295,7 +345,7 @@ const bezier = (entity) => {
|
|
|
295
345
|
const element = `<g>${paths.join("")}</g>`;
|
|
296
346
|
return (0, import_transformBoundingBoxAndElement.default)(bbox, element, entity.transforms ?? []);
|
|
297
347
|
};
|
|
298
|
-
const entityToBoundsAndElement = (entity, dimStyles) => {
|
|
348
|
+
const entityToBoundsAndElement = (entity, dimStyles, options, viewport) => {
|
|
299
349
|
switch (entity.type) {
|
|
300
350
|
case "CIRCLE":
|
|
301
351
|
return circle(entity);
|
|
@@ -311,7 +361,7 @@ const entityToBoundsAndElement = (entity, dimStyles) => {
|
|
|
311
361
|
const dimEntity = entity;
|
|
312
362
|
const styleName = typeof dimEntity.styleName === "string" ? dimEntity.styleName : void 0;
|
|
313
363
|
const dimStyle = styleName && dimStyles ? dimStyles[styleName] : void 0;
|
|
314
|
-
return dimension(dimEntity, dimStyle);
|
|
364
|
+
return dimension(dimEntity, dimStyle, options, viewport);
|
|
315
365
|
}
|
|
316
366
|
case "SPLINE": {
|
|
317
367
|
const splineEntity = entity;
|
|
@@ -329,33 +379,77 @@ const entityToBoundsAndElement = (entity, dimStyles) => {
|
|
|
329
379
|
}
|
|
330
380
|
}
|
|
331
381
|
case "LINE":
|
|
382
|
+
case "RAY":
|
|
383
|
+
case "XLINE":
|
|
332
384
|
case "POLYLINE": {
|
|
333
385
|
return polyline(entity);
|
|
334
386
|
}
|
|
387
|
+
case "SOLID":
|
|
388
|
+
case "TRACE": {
|
|
389
|
+
return polyline(entity);
|
|
390
|
+
}
|
|
335
391
|
case "LWPOLYLINE": {
|
|
336
392
|
return lwpolyline(entity);
|
|
337
393
|
}
|
|
394
|
+
case "WIPEOUT": {
|
|
395
|
+
return polyline(entity);
|
|
396
|
+
}
|
|
397
|
+
case "LEADER": {
|
|
398
|
+
return leader(entity);
|
|
399
|
+
}
|
|
400
|
+
case "TOLERANCE": {
|
|
401
|
+
return tolerance(entity);
|
|
402
|
+
}
|
|
403
|
+
case "SHAPE": {
|
|
404
|
+
return shape(entity);
|
|
405
|
+
}
|
|
338
406
|
default:
|
|
339
407
|
import_logger.default.warn("entity type not supported in SVG rendering:", entity.type);
|
|
340
408
|
return null;
|
|
341
409
|
}
|
|
342
410
|
};
|
|
343
|
-
function toSVG(parsed) {
|
|
411
|
+
function toSVG(parsed, options = {}) {
|
|
344
412
|
const entities = (0, import_denormalise.default)(parsed);
|
|
345
413
|
const dimStyles = parsed.tables.dimStyles;
|
|
414
|
+
const geometryBBox = entities.reduce((acc, entity) => {
|
|
415
|
+
if (entity.type === "DIMENSION") {
|
|
416
|
+
const bbox2 = (0, import_dimensionToSVG.getDimensionGeometryBBox)(entity);
|
|
417
|
+
if (bbox2.valid) {
|
|
418
|
+
acc.expandByPoint(bbox2.min);
|
|
419
|
+
acc.expandByPoint(bbox2.max);
|
|
420
|
+
}
|
|
421
|
+
return acc;
|
|
422
|
+
}
|
|
423
|
+
const boundsAndElement = entityToBoundsAndElement(entity, dimStyles, options);
|
|
424
|
+
if (boundsAndElement?.bbox.valid) {
|
|
425
|
+
acc.expandByPoint(boundsAndElement.bbox.min);
|
|
426
|
+
acc.expandByPoint(boundsAndElement.bbox.max);
|
|
427
|
+
}
|
|
428
|
+
return acc;
|
|
429
|
+
}, new import_vecks.Box2());
|
|
430
|
+
const viewport = geometryBBox.valid ? {
|
|
431
|
+
width: geometryBBox.max.x - geometryBBox.min.x,
|
|
432
|
+
height: geometryBBox.max.y - geometryBBox.min.y
|
|
433
|
+
} : {
|
|
434
|
+
width: 0,
|
|
435
|
+
height: 0
|
|
436
|
+
};
|
|
346
437
|
const { bbox, elements } = entities.reduce(
|
|
347
438
|
(acc, entity) => {
|
|
348
439
|
const rgb = (0, import_getRGBForEntity.default)(parsed.tables.layers, entity);
|
|
349
|
-
const boundsAndElement = entityToBoundsAndElement(entity, dimStyles);
|
|
440
|
+
const boundsAndElement = entityToBoundsAndElement(entity, dimStyles, options, viewport);
|
|
350
441
|
if (boundsAndElement) {
|
|
351
442
|
const { bbox: bbox2, element } = boundsAndElement;
|
|
352
443
|
if (bbox2.valid) {
|
|
353
444
|
acc.bbox.expandByPoint(bbox2.min);
|
|
354
445
|
acc.bbox.expandByPoint(bbox2.max);
|
|
355
446
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
447
|
+
const color = (0, import_rgbToColorAttribute.default)(rgb);
|
|
448
|
+
if (entity.type === "SOLID" || entity.type === "TRACE") {
|
|
449
|
+
acc.elements.push(`<g fill="${color}" stroke="none">${element}</g>`);
|
|
450
|
+
} else {
|
|
451
|
+
acc.elements.push(`<g stroke="${color}">${element}</g>`);
|
|
452
|
+
}
|
|
359
453
|
}
|
|
360
454
|
return acc;
|
|
361
455
|
},
|
package/lib/toSVG.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/toSVG.ts"],
|
|
4
|
-
"sourcesContent": ["import { Box2 } from 'vecks'\n\nimport denormalise from './denormalise'\nimport dimensionToSVG from './dimensionToSVG'\nimport entityToPolyline from './entityToPolyline'\nimport getRGBForEntity from './getRGBForEntity'\nimport logger from './util/logger'\nimport rgbToColorAttribute from './util/rgbToColorAttribute'\nimport rotate from './util/rotate'\nimport toPiecewiseBezier, { multiplicity } from './util/toPiecewiseBezier'\nimport transformBoundingBoxAndElement from './util/transformBoundingBoxAndElement'\n\nimport type {\n ArcEntity,\n CircleEntity,\n DimensionEntity,\n EllipseEntity,\n Entity,\n MTextEntity,\n ParsedDXF,\n SplineEntity,\n TextEntity,\n} from './types'\nimport type { BoundsAndElement } from './types/svg'\n\nconst addFlipXIfApplicable = (\n entity: Entity,\n { bbox, element }: BoundsAndElement,\n): BoundsAndElement => {\n if (entity.extrusionZ === -1) {\n return {\n bbox: new Box2()\n .expandByPoint({ x: -bbox.min.x, y: bbox.min.y })\n .expandByPoint({ x: -bbox.max.x, y: bbox.max.y }),\n element: `<g transform=\"matrix(-1 0 0 1 0 0)\">\n ${element}\n </g>`,\n }\n } else {\n return { bbox, element }\n }\n}\n\n/**\n * Create a <path /> element. Interpolates curved entities.\n */\nconst polyline = (entity: Entity): BoundsAndElement => {\n const vertices = entityToPolyline(entity as any)\n const bbox = vertices.reduce(\n (acc, [x, y]) => acc.expandByPoint({ x, y }),\n new Box2(),\n )\n const d = vertices.reduce((acc, point, i) => {\n acc += i === 0 ? 'M' : 'L'\n acc += point[0] + ',' + point[1]\n return acc\n }, '')\n // Empirically it appears that flipping horizontally does not apply to polyline\n return transformBoundingBoxAndElement(\n bbox,\n `<path d=\"${d}\" />`,\n entity.transforms ?? [],\n )\n}\n\n/**\n * Create a <path /> element. Interpolates curved entities.\n * lwpolyline is the same as polyline but addFlipXIfApplicable does apply\n */\nconst lwpolyline = (entity: Entity): BoundsAndElement => {\n const vertices = entityToPolyline(entity as any)\n const bbox0 = vertices.reduce(\n (acc, [x, y]) => acc.expandByPoint({ x, y }),\n new Box2(),\n )\n const d = vertices.reduce((acc, point, i) => {\n acc += i === 0 ? 'M' : 'L'\n acc += point[0] + ',' + point[1]\n return acc\n }, '')\n const element0 = `<path d=\"${d}\" />`\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(\n bbox,\n element,\n entity.transforms ?? [],\n )\n}\n\n\n/**\n * Create a <circle /> element for the CIRCLE entity.\n */\nconst circle = (entity: CircleEntity): BoundsAndElement => {\n const bbox0 = new Box2()\n .expandByPoint({\n x: entity.x + entity.r,\n y: entity.y + entity.r,\n })\n .expandByPoint({\n x: entity.x - entity.r,\n y: entity.y - entity.r,\n })\n const element0 = `<circle cx=\"${entity.x}\" cy=\"${entity.y}\" r=\"${entity.r}\" />`\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\ninterface EllipticArcParams {\n cx: number\n cy: number\n majorX: number\n majorY: number\n axisRatio: number\n startAngle: number\n endAngle: number\n flipX?: boolean\n}\n\n/**\n * Create a a <path d=\"A...\" /> or <ellipse /> element for the ARC or ELLIPSE\n * DXF entity (<ellipse /> if start and end point are the same).\n */\nconst ellipseOrArc = (params: EllipticArcParams): BoundsAndElement => {\n const { cx, cy, majorX, majorY, axisRatio, startAngle, endAngle } = params\n const rx = Math.hypot(majorX, majorY)\n const ry = axisRatio * rx\n const rotationAngle = -Math.atan2(-majorY, majorX)\n\n const bbox = bboxEllipseOrArc(params)\n\n if (\n Math.abs(startAngle - endAngle) < 1e-9 ||\n Math.abs(startAngle - endAngle + Math.PI * 2) < 1e-9\n ) {\n // Use a native <ellipse> when start and end angles are the same, and\n // arc paths with same start and end points don't render (at least on Safari)\n const element = `<g transform=\"rotate(${\n (rotationAngle / Math.PI) * 180\n } ${cx}, ${cy})\">\n <ellipse cx=\"${cx}\" cy=\"${cy}\" rx=\"${rx}\" ry=\"${ry}\" />\n </g>`\n return { bbox, element }\n } else {\n const startOffset = rotate(\n {\n x: Math.cos(startAngle) * rx,\n y: Math.sin(startAngle) * ry,\n },\n rotationAngle,\n )\n const startPoint = {\n x: cx + startOffset.x,\n y: cy + startOffset.y,\n }\n const endOffset = rotate(\n {\n x: Math.cos(endAngle) * rx,\n y: Math.sin(endAngle) * ry,\n },\n rotationAngle,\n )\n const endPoint = {\n x: cx + endOffset.x,\n y: cy + endOffset.y,\n }\n const adjustedEndAngle =\n endAngle < startAngle ? endAngle + Math.PI * 2 : endAngle\n const largeArcFlag = adjustedEndAngle - startAngle < Math.PI ? 0 : 1\n const d = `M ${startPoint.x} ${startPoint.y} A ${rx} ${ry} ${\n (rotationAngle / Math.PI) * 180\n } ${largeArcFlag} 1 ${endPoint.x} ${endPoint.y}`\n const element = `<path d=\"${d}\" />`\n return { bbox, element }\n }\n}\n\n/**\n * Compute the bounding box of an elliptical arc, given the DXF entity parameters\n */\n\nconst bboxEllipseOrArc = (params: EllipticArcParams): Box2 => {\n const { cx, cy, majorX, majorY, axisRatio } = params\n let { startAngle, endAngle } = params\n\n // The bounding box will be defined by the starting point of the ellipse, and ending point,\n // and any extrema on the ellipse that are between startAngle and endAngle.\n // The extrema are found by setting either the x or y component of the ellipse's\n // tangent vector to zero and solving for the angle.\n\n // Ensure start and end angles are > 0 and well-ordered\n while (startAngle < 0) startAngle += Math.PI * 2\n while (endAngle <= startAngle) endAngle += Math.PI * 2\n\n // When rotated, the extrema of the ellipse will be found at these angles\n const angles = []\n\n if (Math.abs(majorX) < 1e-12 || Math.abs(majorY) < 1e-12) {\n // Special case for majorX or majorY = 0\n for (let i = 0; i < 4; i++) {\n angles.push((i / 2) * Math.PI)\n }\n } else {\n // reference https://github.com/bjnortier/dxf/issues/47#issuecomment-545915042\n angles[0] = Math.atan((-majorY * axisRatio) / majorX) - Math.PI // Ensure angles < 0\n angles[1] = Math.atan((majorX * axisRatio) / majorY) - Math.PI\n angles[2] = angles[0] - Math.PI\n angles[3] = angles[1] - Math.PI\n }\n\n // Remove angles not falling between start and end\n for (let i = 4; i >= 0; i--) {\n while (angles[i] < startAngle) angles[i] += Math.PI * 2\n if (angles[i] > endAngle) {\n angles.splice(i, 1)\n }\n }\n\n // Also to consider are the starting and ending points:\n angles.push(startAngle, endAngle)\n\n // Compute points lying on the unit circle at these angles\n const pts = angles.map((a) => ({\n x: Math.cos(a),\n y: Math.sin(a),\n }))\n\n // Transformation matrix, formed by the major and minor axes\n const M = [\n [majorX, -majorY * axisRatio],\n [majorY, majorX * axisRatio],\n ]\n\n // Rotate, scale, and translate points\n const rotatedPts = pts.map((p) => ({\n x: p.x * M[0][0] + p.y * M[0][1] + cx,\n y: p.x * M[1][0] + p.y * M[1][1] + cy,\n }))\n\n // Compute extents of bounding box\n const bbox = rotatedPts.reduce((acc, p) => {\n acc.expandByPoint(p)\n return acc\n }, new Box2())\n\n return bbox\n}\n\n/**\n * An ELLIPSE is defined by the major axis, convert to X and Y radius with\n * a rotation angle\n */\nconst ellipse = (entity: EllipseEntity): BoundsAndElement => {\n const { bbox: bbox0, element: element0 } = ellipseOrArc({\n cx: entity.x,\n cy: entity.y,\n majorX: entity.majorX,\n majorY: entity.majorY,\n axisRatio: entity.axisRatio,\n startAngle: entity.startAngle,\n endAngle: entity.endAngle,\n })\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * An ARC is an ellipse with equal radii\n */\nconst arc = (entity: ArcEntity): BoundsAndElement => {\n const { bbox: bbox0, element: element0 } = ellipseOrArc({\n cx: entity.x,\n cy: entity.y,\n majorX: entity.r,\n majorY: 0,\n axisRatio: 1,\n startAngle: entity.startAngle,\n endAngle: entity.endAngle,\n flipX: entity.extrusionZ === -1,\n })\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * Create a <text /> element for TEXT entity\n */\nconst text = (entity: TextEntity): BoundsAndElement => {\n const x = entity.x ?? 0\n const y = entity.y ?? 0\n const height = entity.textHeight ?? 1\n const rotation = entity.rotation ?? 0\n const content = entity.string ?? ''\n\n // Estimate text bounding box (approximate)\n const textWidth = content.length * height * 0.6\n const bbox0 = new Box2()\n .expandByPoint({ x, y })\n .expandByPoint({ x: x + textWidth, y: y + height })\n\n const rotationDegrees = (rotation * 180) / Math.PI\n const element0 = `<text x=\"${x}\" y=\"${y}\" font-size=\"${height}\" transform=\"rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})\">${content}</text>`\n\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * Create a <text /> element for MTEXT entity\n */\nconst mtext = (entity: MTextEntity): BoundsAndElement => {\n const x = entity.x ?? 0\n const y = entity.y ?? 0\n const height = entity.nominalTextHeight ?? entity.textHeight ?? 1\n const content = entity.string ?? ''\n\n // Estimate text bounding box (approximate)\n const textWidth = (entity.refRectangleWidth ?? content.length * height * 0.6)\n const bbox0 = new Box2()\n .expandByPoint({ x, y })\n .expandByPoint({ x: x + textWidth, y: y + height })\n\n // Calculate rotation from x-axis direction\n const rotation = entity.xAxisX !== undefined && entity.xAxisY !== undefined\n ? Math.atan2(entity.xAxisY, entity.xAxisX)\n : 0\n const rotationDegrees = (rotation * 180) / Math.PI\n\n const element0 = `<text x=\"${x}\" y=\"${y}\" font-size=\"${height}\" transform=\"rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})\">${content}</text>`\n\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * Create dimension visualization with DIMSTYLE support\n */\nconst dimension = (\n entity: DimensionEntity,\n dimStyle?: any,\n): BoundsAndElement => {\n const result = dimensionToSVG(entity, dimStyle)\n return transformBoundingBoxAndElement(\n result.bbox,\n result.element,\n entity.transforms ?? [],\n )\n}\n\nexport const piecewiseToPaths = (\n k: number,\n knots: number[],\n controlPoints: Array<{ x: number; y: number }>,\n): string[] => {\n const paths: string[] = []\n let controlPointIndex = 0\n let knotIndex = k\n while (knotIndex < knots.length - k + 1) {\n const m = multiplicity(knots, knotIndex)\n const cp = controlPoints.slice(controlPointIndex, controlPointIndex + k)\n if (k === 4) {\n paths.push(\n `<path d=\"M ${cp[0].x} ${cp[0].y} C ${cp[1].x} ${cp[1].y} ${cp[2].x} ${cp[2].y} ${cp[3].x} ${cp[3].y}\" />`,\n )\n } else if (k === 3) {\n paths.push(\n `<path d=\"M ${cp[0].x} ${cp[0].y} Q ${cp[1].x} ${cp[1].y} ${cp[2].x} ${cp[2].y}\" />`,\n )\n }\n controlPointIndex += m\n knotIndex += m\n }\n return paths\n}\n\nconst bezier = (entity: SplineEntity): BoundsAndElement => {\n let bbox = new Box2()\n for (const p of entity.controlPoints) {\n bbox = bbox.expandByPoint(p)\n }\n const k = entity.degree + 1\n const piecewise = toPiecewiseBezier(k, entity.controlPoints, entity.knots)\n const paths = piecewiseToPaths(k, piecewise.knots, piecewise.controlPoints)\n const element = `<g>${paths.join('')}</g>`\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * Switch the appropriate function on entity type. CIRCLE, ARC and ELLIPSE\n * produce native SVG elements, the rest produce interpolated polylines.\n */\nconst entityToBoundsAndElement = (\n entity: Entity,\n dimStyles?: { [name: string]: any },\n): BoundsAndElement | null => {\n switch (entity.type) {\n case 'CIRCLE':\n return circle(entity as CircleEntity)\n case 'ELLIPSE':\n return ellipse(entity as EllipseEntity)\n case 'ARC':\n return arc(entity as ArcEntity)\n case 'TEXT':\n return text(entity as TextEntity)\n case 'MTEXT':\n return mtext(entity as MTextEntity)\n case 'DIMENSION': {\n const dimEntity = entity as DimensionEntity\n const styleName = typeof dimEntity.styleName === 'string'\n ? dimEntity.styleName\n : undefined\n const dimStyle = styleName && dimStyles\n ? dimStyles[styleName]\n : undefined\n return dimension(dimEntity, dimStyle)\n }\n case 'SPLINE': {\n const splineEntity = entity as SplineEntity\n const hasWeights = splineEntity.weights?.some((w: number) => w !== 1)\n if ((splineEntity.degree === 2 || splineEntity.degree === 3) && !hasWeights) {\n try {\n return bezier(splineEntity)\n } catch (err) {\n const error = err as Error\n logger.warn('bezier conversion failed, using polyline:', error.message)\n return polyline(entity)\n }\n } else {\n return polyline(entity)\n }\n }\n case 'LINE':\n case 'POLYLINE': {\n return polyline(entity)\n }\n case 'LWPOLYLINE': {\n return lwpolyline(entity)\n }\n default:\n logger.warn('entity type not supported in SVG rendering:', entity.type)\n return null\n }\n}\n\nexport default function toSVG(parsed: ParsedDXF): string {\n const entities = denormalise(parsed)\n const dimStyles = parsed.tables.dimStyles\n const { bbox, elements } = entities.reduce(\n (\n acc: { bbox: Box2; elements: string[] },\n entity: Entity,\n ): { bbox: Box2; elements: string[] } => {\n const rgb = getRGBForEntity(parsed.tables.layers, entity)\n const boundsAndElement = entityToBoundsAndElement(entity, dimStyles)\n // Ignore entities that don't produce SVG elements or have unsupported types\n if (boundsAndElement) {\n const { bbox, element } = boundsAndElement\n // Ignore invalid bounding boxes\n if (bbox.valid) {\n acc.bbox.expandByPoint(bbox.min)\n acc.bbox.expandByPoint(bbox.max)\n }\n acc.elements.push(\n `<g stroke=\"${rgbToColorAttribute(rgb)}\">${element}</g>`,\n )\n }\n return acc\n },\n {\n bbox: new Box2(),\n elements: [],\n },\n )\n\n const viewBox = bbox.valid\n ? {\n x: bbox.min.x,\n y: -bbox.max.y,\n width: bbox.max.x - bbox.min.x,\n height: bbox.max.y - bbox.min.y,\n }\n : {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n }\n return `<?xml version=\"1.0\"?>\n<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\"\n preserveAspectRatio=\"xMinYMin meet\"\n viewBox=\"${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}\"\n width=\"100%\" height=\"100%\"\n>\n <g stroke=\"#000000\" stroke-width=\"0.1%\" fill=\"none\" transform=\"matrix(1,0,0,-1,0,0)\">\n ${elements.join('\\n')}\n </g>\n</svg>`\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["entityToPolyline", "transformBoundingBoxAndElement", "rotate", "dimensionToSVG", "toPiecewiseBezier", "logger", "denormalise", "
|
|
4
|
+
"sourcesContent": ["import { Box2 } from 'vecks'\n\nimport denormalise from './denormalise'\nimport dimensionToSVG, { getDimensionGeometryBBox } from './dimensionToSVG'\nimport entityToPolyline from './entityToPolyline'\nimport getRGBForEntity from './getRGBForEntity'\nimport escapeXmlText from './util/escapeXmlText'\nimport logger from './util/logger'\nimport rgbToColorAttribute from './util/rgbToColorAttribute'\nimport rotate from './util/rotate'\nimport toPiecewiseBezier, { multiplicity } from './util/toPiecewiseBezier'\nimport transformBoundingBoxAndElement from './util/transformBoundingBoxAndElement'\n\nimport type {\n ArcEntity,\n CircleEntity,\n DimensionEntity,\n EllipseEntity,\n Entity,\n LeaderEntity,\n MTextEntity,\n ParsedDXF,\n ShapeEntity,\n SplineEntity,\n TextEntity,\n ToleranceEntity,\n ToSVGOptions,\n} from './types'\nimport type { BoundsAndElement } from './types/svg'\n\nconst addFlipXIfApplicable = (\n entity: Entity,\n { bbox, element }: BoundsAndElement,\n): BoundsAndElement => {\n if (entity.extrusionZ === -1) {\n return {\n bbox: new Box2()\n .expandByPoint({ x: -bbox.min.x, y: bbox.min.y })\n .expandByPoint({ x: -bbox.max.x, y: bbox.max.y }),\n element: `<g transform=\"matrix(-1 0 0 1 0 0)\">\n ${element}\n </g>`,\n }\n } else {\n return { bbox, element }\n }\n}\n\n/**\n * Create a <path /> element. Interpolates curved entities.\n */\nconst polyline = (entity: Entity): BoundsAndElement => {\n const vertices = entityToPolyline(entity as any)\n const bbox = vertices.reduce(\n (acc, [x, y]) => acc.expandByPoint({ x, y }),\n new Box2(),\n )\n const d = vertices.reduce((acc, point, i) => {\n acc += i === 0 ? 'M' : 'L'\n acc += point[0] + ',' + point[1]\n return acc\n }, '')\n // Empirically it appears that flipping horizontally does not apply to polyline\n return transformBoundingBoxAndElement(\n bbox,\n `<path d=\"${d}\" />`,\n entity.transforms ?? [],\n )\n}\n\n/**\n * Create a <path /> element. Interpolates curved entities.\n * lwpolyline is the same as polyline but addFlipXIfApplicable does apply\n */\nconst lwpolyline = (entity: Entity): BoundsAndElement => {\n const vertices = entityToPolyline(entity as any)\n const bbox0 = vertices.reduce(\n (acc, [x, y]) => acc.expandByPoint({ x, y }),\n new Box2(),\n )\n const d = vertices.reduce((acc, point, i) => {\n acc += i === 0 ? 'M' : 'L'\n acc += point[0] + ',' + point[1]\n return acc\n }, '')\n const element0 = `<path d=\"${d}\" />`\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(\n bbox,\n element,\n entity.transforms ?? [],\n )\n}\n\nconst leader = (entity: LeaderEntity): BoundsAndElement | null => {\n if (!entity.vertices || entity.vertices.length < 2) return null\n\n const bbox0 = entity.vertices.reduce(\n (acc, p) => acc.expandByPoint({ x: p.x, y: p.y }),\n new Box2(),\n )\n const d = entity.vertices.reduce((acc, p, i) => {\n acc += i === 0 ? 'M' : 'L'\n acc += p.x + ',' + p.y\n return acc\n }, '')\n\n return transformBoundingBoxAndElement(\n bbox0,\n `<path d=\"${d}\" />`,\n entity.transforms ?? [],\n )\n}\n\n\n/**\n * Create a <circle /> element for the CIRCLE entity.\n */\nconst circle = (entity: CircleEntity): BoundsAndElement => {\n const bbox0 = new Box2()\n .expandByPoint({\n x: entity.x + entity.r,\n y: entity.y + entity.r,\n })\n .expandByPoint({\n x: entity.x - entity.r,\n y: entity.y - entity.r,\n })\n const element0 = `<circle cx=\"${entity.x}\" cy=\"${entity.y}\" r=\"${entity.r}\" />`\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\ninterface EllipticArcParams {\n cx: number\n cy: number\n majorX: number\n majorY: number\n axisRatio: number\n startAngle: number\n endAngle: number\n flipX?: boolean\n}\n\n/**\n * Create a a <path d=\"A...\" /> or <ellipse /> element for the ARC or ELLIPSE\n * DXF entity (<ellipse /> if start and end point are the same).\n */\nconst ellipseOrArc = (params: EllipticArcParams): BoundsAndElement => {\n const { cx, cy, majorX, majorY, axisRatio, startAngle, endAngle } = params\n const rx = Math.hypot(majorX, majorY)\n const ry = axisRatio * rx\n const rotationAngle = -Math.atan2(-majorY, majorX)\n\n const bbox = bboxEllipseOrArc(params)\n\n if (\n Math.abs(startAngle - endAngle) < 1e-9 ||\n Math.abs(startAngle - endAngle + Math.PI * 2) < 1e-9\n ) {\n // Use a native <ellipse> when start and end angles are the same, and\n // arc paths with same start and end points don't render (at least on Safari)\n const element = `<g transform=\"rotate(${\n (rotationAngle / Math.PI) * 180\n } ${cx}, ${cy})\">\n <ellipse cx=\"${cx}\" cy=\"${cy}\" rx=\"${rx}\" ry=\"${ry}\" />\n </g>`\n return { bbox, element }\n } else {\n const startOffset = rotate(\n {\n x: Math.cos(startAngle) * rx,\n y: Math.sin(startAngle) * ry,\n },\n rotationAngle,\n )\n const startPoint = {\n x: cx + startOffset.x,\n y: cy + startOffset.y,\n }\n const endOffset = rotate(\n {\n x: Math.cos(endAngle) * rx,\n y: Math.sin(endAngle) * ry,\n },\n rotationAngle,\n )\n const endPoint = {\n x: cx + endOffset.x,\n y: cy + endOffset.y,\n }\n const adjustedEndAngle =\n endAngle < startAngle ? endAngle + Math.PI * 2 : endAngle\n const largeArcFlag = adjustedEndAngle - startAngle < Math.PI ? 0 : 1\n const d = `M ${startPoint.x} ${startPoint.y} A ${rx} ${ry} ${\n (rotationAngle / Math.PI) * 180\n } ${largeArcFlag} 1 ${endPoint.x} ${endPoint.y}`\n const element = `<path d=\"${d}\" />`\n return { bbox, element }\n }\n}\n\n/**\n * Compute the bounding box of an elliptical arc, given the DXF entity parameters\n */\n\nconst bboxEllipseOrArc = (params: EllipticArcParams): Box2 => {\n const { cx, cy, majorX, majorY, axisRatio } = params\n let { startAngle, endAngle } = params\n\n // The bounding box will be defined by the starting point of the ellipse, and ending point,\n // and any extrema on the ellipse that are between startAngle and endAngle.\n // The extrema are found by setting either the x or y component of the ellipse's\n // tangent vector to zero and solving for the angle.\n\n // Ensure start and end angles are > 0 and well-ordered\n while (startAngle < 0) startAngle += Math.PI * 2\n while (endAngle <= startAngle) endAngle += Math.PI * 2\n\n // When rotated, the extrema of the ellipse will be found at these angles\n const angles = []\n\n if (Math.abs(majorX) < 1e-12 || Math.abs(majorY) < 1e-12) {\n // Special case for majorX or majorY = 0\n for (let i = 0; i < 4; i++) {\n angles.push((i / 2) * Math.PI)\n }\n } else {\n // reference https://github.com/bjnortier/dxf/issues/47#issuecomment-545915042\n angles[0] = Math.atan((-majorY * axisRatio) / majorX) - Math.PI // Ensure angles < 0\n angles[1] = Math.atan((majorX * axisRatio) / majorY) - Math.PI\n angles[2] = angles[0] - Math.PI\n angles[3] = angles[1] - Math.PI\n }\n\n // Remove angles not falling between start and end\n for (let i = 4; i >= 0; i--) {\n while (angles[i] < startAngle) angles[i] += Math.PI * 2\n if (angles[i] > endAngle) {\n angles.splice(i, 1)\n }\n }\n\n // Also to consider are the starting and ending points:\n angles.push(startAngle, endAngle)\n\n // Compute points lying on the unit circle at these angles\n const pts = angles.map((a) => ({\n x: Math.cos(a),\n y: Math.sin(a),\n }))\n\n // Transformation matrix, formed by the major and minor axes\n const M = [\n [majorX, -majorY * axisRatio],\n [majorY, majorX * axisRatio],\n ]\n\n // Rotate, scale, and translate points\n const rotatedPts = pts.map((p) => ({\n x: p.x * M[0][0] + p.y * M[0][1] + cx,\n y: p.x * M[1][0] + p.y * M[1][1] + cy,\n }))\n\n // Compute extents of bounding box\n const bbox = rotatedPts.reduce((acc, p) => {\n acc.expandByPoint(p)\n return acc\n }, new Box2())\n\n return bbox\n}\n\n/**\n * An ELLIPSE is defined by the major axis, convert to X and Y radius with\n * a rotation angle\n */\nconst ellipse = (entity: EllipseEntity): BoundsAndElement => {\n const { bbox: bbox0, element: element0 } = ellipseOrArc({\n cx: entity.x,\n cy: entity.y,\n majorX: entity.majorX,\n majorY: entity.majorY,\n axisRatio: entity.axisRatio,\n startAngle: entity.startAngle,\n endAngle: entity.endAngle,\n })\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * An ARC is an ellipse with equal radii\n */\nconst arc = (entity: ArcEntity): BoundsAndElement => {\n const { bbox: bbox0, element: element0 } = ellipseOrArc({\n cx: entity.x,\n cy: entity.y,\n majorX: entity.r,\n majorY: 0,\n axisRatio: 1,\n startAngle: entity.startAngle,\n endAngle: entity.endAngle,\n flipX: entity.extrusionZ === -1,\n })\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * Create a <text /> element for TEXT entity\n */\nconst text = (entity: TextEntity): BoundsAndElement => {\n const x = entity.x ?? 0\n const y = entity.y ?? 0\n const height = entity.textHeight ?? 1\n const rotation = entity.rotation ?? 0\n const content = entity.string ?? ''\n\n // Estimate text bounding box (approximate)\n const textWidth = content.length * height * 0.6\n const bbox0 = new Box2()\n .expandByPoint({ x, y })\n .expandByPoint({ x: x + textWidth, y: y + height })\n\n const rotationDegrees = (rotation * 180) / Math.PI\n const element0 = `<text x=\"${x}\" y=\"${y}\" font-size=\"${height}\" transform=\"rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})\">${escapeXmlText(content)}</text>`\n\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * Create a <text /> element for MTEXT entity\n */\nconst mtext = (entity: MTextEntity): BoundsAndElement => {\n const x = entity.x ?? 0\n const y = entity.y ?? 0\n const height = entity.nominalTextHeight ?? entity.textHeight ?? 1\n const content = entity.string ?? ''\n\n // Estimate text bounding box (approximate)\n const textWidth = (entity.refRectangleWidth ?? content.length * height * 0.6)\n const bbox0 = new Box2()\n .expandByPoint({ x, y })\n .expandByPoint({ x: x + textWidth, y: y + height })\n\n // Calculate rotation from x-axis direction\n const rotation = entity.xAxisX !== undefined && entity.xAxisY !== undefined\n ? Math.atan2(entity.xAxisY, entity.xAxisX)\n : 0\n const rotationDegrees = (rotation * 180) / Math.PI\n const element0 = `<text x=\"${x}\" y=\"${y}\" font-size=\"${height}\" transform=\"rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})\">${escapeXmlText(content)}</text>`\n\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * Minimal <text /> fallback for TOLERANCE entities.\n * DXF uses special control codes; we preserve the raw string.\n */\nconst tolerance = (entity: ToleranceEntity): BoundsAndElement => {\n const x = entity.insertionPoint?.x ?? 0\n const y = entity.insertionPoint?.y ?? 0\n const height = 1\n const content = entity.text ?? ''\n\n const rotation = entity.xAxisDirection\n ? Math.atan2(entity.xAxisDirection.y, entity.xAxisDirection.x)\n : 0\n const rotationDegrees = (rotation * 180) / Math.PI\n\n const textWidth = content.length * height * 0.6\n const bbox0 = new Box2()\n .expandByPoint({ x, y })\n .expandByPoint({ x: x + textWidth, y: y + height })\n\n const element0 = `<text x=\"${x}\" y=\"${y}\" font-size=\"${height}\" transform=\"rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})\">${escapeXmlText(content)}</text>`\n\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * Minimal <text /> fallback for SHAPE entities.\n * Rendering SHX-based shapes is out of scope; we render the name as text.\n */\nconst shape = (entity: ShapeEntity): BoundsAndElement => {\n const x = entity.insertionPoint?.x ?? 0\n const y = entity.insertionPoint?.y ?? 0\n const height = entity.size ?? 1\n const rotation = entity.rotation ?? 0\n const content = entity.name ?? ''\n\n const textWidth = content.length * height * 0.6\n const bbox0 = new Box2()\n .expandByPoint({ x, y })\n .expandByPoint({ x: x + textWidth, y: y + height })\n\n const rotationDegrees = (rotation * 180) / Math.PI\n const element0 = `<text x=\"${x}\" y=\"${y}\" font-size=\"${height}\" transform=\"rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})\">${escapeXmlText(content)}</text>`\n\n const { bbox, element } = addFlipXIfApplicable(entity, {\n bbox: bbox0,\n element: element0,\n })\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * Create dimension visualization with DIMSTYLE support\n */\nconst dimension = (\n entity: DimensionEntity,\n dimStyle?: any,\n options?: ToSVGOptions,\n viewport?: { width: number; height: number },\n): BoundsAndElement => {\n const result = dimensionToSVG(entity, dimStyle, options, viewport)\n return transformBoundingBoxAndElement(\n result.bbox,\n result.element,\n entity.transforms ?? [],\n )\n}\n\nexport const piecewiseToPaths = (\n k: number,\n knots: number[],\n controlPoints: Array<{ x: number; y: number }>,\n): string[] => {\n const paths: string[] = []\n let controlPointIndex = 0\n let knotIndex = k\n while (knotIndex < knots.length - k + 1) {\n const m = multiplicity(knots, knotIndex)\n const cp = controlPoints.slice(controlPointIndex, controlPointIndex + k)\n if (k === 4) {\n paths.push(\n `<path d=\"M ${cp[0].x} ${cp[0].y} C ${cp[1].x} ${cp[1].y} ${cp[2].x} ${cp[2].y} ${cp[3].x} ${cp[3].y}\" />`,\n )\n } else if (k === 3) {\n paths.push(\n `<path d=\"M ${cp[0].x} ${cp[0].y} Q ${cp[1].x} ${cp[1].y} ${cp[2].x} ${cp[2].y}\" />`,\n )\n }\n controlPointIndex += m\n knotIndex += m\n }\n return paths\n}\n\nconst bezier = (entity: SplineEntity): BoundsAndElement => {\n let bbox = new Box2()\n for (const p of entity.controlPoints) {\n bbox = bbox.expandByPoint(p)\n }\n const k = entity.degree + 1\n const piecewise = toPiecewiseBezier(k, entity.controlPoints, entity.knots)\n const paths = piecewiseToPaths(k, piecewise.knots, piecewise.controlPoints)\n const element = `<g>${paths.join('')}</g>`\n return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? [])\n}\n\n/**\n * Switch the appropriate function on entity type. CIRCLE, ARC and ELLIPSE\n * produce native SVG elements, the rest produce interpolated polylines.\n */\nconst entityToBoundsAndElement = (\n entity: Entity,\n dimStyles?: { [name: string]: any },\n options?: ToSVGOptions,\n viewport?: { width: number; height: number },\n): BoundsAndElement | null => {\n switch (entity.type) {\n case 'CIRCLE':\n return circle(entity as CircleEntity)\n case 'ELLIPSE':\n return ellipse(entity as EllipseEntity)\n case 'ARC':\n return arc(entity as ArcEntity)\n case 'TEXT':\n return text(entity as TextEntity)\n case 'MTEXT':\n return mtext(entity as MTextEntity)\n case 'DIMENSION': {\n const dimEntity = entity as DimensionEntity\n const styleName = typeof dimEntity.styleName === 'string'\n ? dimEntity.styleName\n : undefined\n const dimStyle = styleName && dimStyles\n ? dimStyles[styleName]\n : undefined\n return dimension(dimEntity, dimStyle, options, viewport)\n }\n case 'SPLINE': {\n const splineEntity = entity as SplineEntity\n const hasWeights = splineEntity.weights?.some((w: number) => w !== 1)\n if ((splineEntity.degree === 2 || splineEntity.degree === 3) && !hasWeights) {\n try {\n return bezier(splineEntity)\n } catch (err) {\n const error = err as Error\n logger.warn('bezier conversion failed, using polyline:', error.message)\n return polyline(entity)\n }\n } else {\n return polyline(entity)\n }\n }\n case 'LINE':\n case 'RAY':\n case 'XLINE':\n case 'POLYLINE': {\n return polyline(entity)\n }\n case 'SOLID':\n case 'TRACE': {\n return polyline(entity)\n }\n case 'LWPOLYLINE': {\n return lwpolyline(entity)\n }\n case 'WIPEOUT': {\n return polyline(entity)\n }\n case 'LEADER': {\n return leader(entity as LeaderEntity)\n }\n case 'TOLERANCE': {\n return tolerance(entity as ToleranceEntity)\n }\n case 'SHAPE': {\n return shape(entity as ShapeEntity)\n }\n default:\n logger.warn('entity type not supported in SVG rendering:', entity.type)\n return null\n }\n}\n\nexport default function toSVG(parsed: ParsedDXF, options: ToSVGOptions = {}): string {\n const entities = denormalise(parsed)\n const dimStyles = parsed.tables.dimStyles\n\n const geometryBBox = entities.reduce((acc: Box2, entity: Entity): Box2 => {\n if (entity.type === 'DIMENSION') {\n const bbox = getDimensionGeometryBBox(entity as DimensionEntity)\n if (bbox.valid) {\n acc.expandByPoint(bbox.min)\n acc.expandByPoint(bbox.max)\n }\n return acc\n }\n\n const boundsAndElement = entityToBoundsAndElement(entity, dimStyles, options)\n if (boundsAndElement?.bbox.valid) {\n acc.expandByPoint(boundsAndElement.bbox.min)\n acc.expandByPoint(boundsAndElement.bbox.max)\n }\n return acc\n }, new Box2())\n\n const viewport = geometryBBox.valid\n ? {\n width: geometryBBox.max.x - geometryBBox.min.x,\n height: geometryBBox.max.y - geometryBBox.min.y,\n }\n : {\n width: 0,\n height: 0,\n }\n\n const { bbox, elements } = entities.reduce(\n (\n acc: { bbox: Box2; elements: string[] },\n entity: Entity,\n ): { bbox: Box2; elements: string[] } => {\n const rgb = getRGBForEntity(parsed.tables.layers, entity)\n const boundsAndElement = entityToBoundsAndElement(entity, dimStyles, options, viewport)\n // Ignore entities that don't produce SVG elements or have unsupported types\n if (boundsAndElement) {\n const { bbox, element } = boundsAndElement\n // Ignore invalid bounding boxes\n if (bbox.valid) {\n acc.bbox.expandByPoint(bbox.min)\n acc.bbox.expandByPoint(bbox.max)\n }\n const color = rgbToColorAttribute(rgb)\n if (entity.type === 'SOLID' || entity.type === 'TRACE') {\n acc.elements.push(`<g fill=\"${color}\" stroke=\"none\">${element}</g>`)\n } else {\n acc.elements.push(`<g stroke=\"${color}\">${element}</g>`)\n }\n }\n return acc\n },\n {\n bbox: new Box2(),\n elements: [],\n },\n )\n\n const viewBox = bbox.valid\n ? {\n x: bbox.min.x,\n y: -bbox.max.y,\n width: bbox.max.x - bbox.min.x,\n height: bbox.max.y - bbox.min.y,\n }\n : {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n }\n return `<?xml version=\"1.0\"?>\n<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\"\n preserveAspectRatio=\"xMinYMin meet\"\n viewBox=\"${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}\"\n width=\"100%\" height=\"100%\"\n>\n <g stroke=\"#000000\" stroke-width=\"0.1%\" fill=\"none\" transform=\"matrix(1,0,0,-1,0,0)\">\n ${elements.join('\\n')}\n </g>\n</svg>`\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAqB;AAErB,yBAAwB;AACxB,4BAAyD;AACzD,8BAA6B;AAC7B,6BAA4B;AAC5B,2BAA0B;AAC1B,oBAAmB;AACnB,iCAAgC;AAChC,oBAAmB;AACnB,+BAAgD;AAChD,4CAA2C;AAmB3C,MAAM,uBAAuB,CAC3B,QACA,EAAE,MAAM,QAAQ,MACK;AACrB,MAAI,OAAO,eAAe,IAAI;AAC5B,WAAO;AAAA,MACL,MAAM,IAAI,kBAAK,EACZ,cAAc,EAAE,GAAG,CAAC,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,EAAE,CAAC,EAC/C,cAAc,EAAE,GAAG,CAAC,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,EAAE,CAAC;AAAA,MAClD,SAAS;AAAA,UACL,OAAO;AAAA;AAAA,IAEb;AAAA,EACF,OAAO;AACL,WAAO,EAAE,MAAM,QAAQ;AAAA,EACzB;AACF;AAKA,MAAM,WAAW,CAAC,WAAqC;AACrD,QAAM,eAAW,wBAAAA,SAAiB,MAAa;AAC/C,QAAM,OAAO,SAAS;AAAA,IACpB,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,cAAc,EAAE,GAAG,EAAE,CAAC;AAAA,IAC3C,IAAI,kBAAK;AAAA,EACX;AACA,QAAM,IAAI,SAAS,OAAO,CAAC,KAAK,OAAO,MAAM;AAC3C,WAAO,MAAM,IAAI,MAAM;AACvB,WAAO,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC;AAC/B,WAAO;AAAA,EACT,GAAG,EAAE;AAEL,aAAO,sCAAAC;AAAA,IACL;AAAA,IACA,YAAY,CAAC;AAAA,IACb,OAAO,cAAc,CAAC;AAAA,EACxB;AACF;AAMA,MAAM,aAAa,CAAC,WAAqC;AACvD,QAAM,eAAW,wBAAAD,SAAiB,MAAa;AAC/C,QAAM,QAAQ,SAAS;AAAA,IACrB,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,cAAc,EAAE,GAAG,EAAE,CAAC;AAAA,IAC3C,IAAI,kBAAK;AAAA,EACX;AACA,QAAM,IAAI,SAAS,OAAO,CAAC,KAAK,OAAO,MAAM;AAC3C,WAAO,MAAM,IAAI,MAAM;AACvB,WAAO,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC;AAC/B,WAAO;AAAA,EACT,GAAG,EAAE;AACL,QAAM,WAAW,YAAY,CAAC;AAC9B,QAAM,EAAE,MAAM,QAAQ,IAAI,qBAAqB,QAAQ;AAAA,IACrD,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AACD,aAAO,sCAAAC;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,cAAc,CAAC;AAAA,EACxB;AACF;AAEA,MAAM,SAAS,CAAC,WAAkD;AAChE,MAAI,CAAC,OAAO,YAAY,OAAO,SAAS,SAAS,EAAG,QAAO;AAE3D,QAAM,QAAQ,OAAO,SAAS;AAAA,IAC5B,CAAC,KAAK,MAAM,IAAI,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,EAAE,CAAC;AAAA,IAChD,IAAI,kBAAK;AAAA,EACX;AACA,QAAM,IAAI,OAAO,SAAS,OAAO,CAAC,KAAK,GAAG,MAAM;AAC9C,WAAO,MAAM,IAAI,MAAM;AACvB,WAAO,EAAE,IAAI,MAAM,EAAE;AACrB,WAAO;AAAA,EACT,GAAG,EAAE;AAEL,aAAO,sCAAAA;AAAA,IACL;AAAA,IACA,YAAY,CAAC;AAAA,IACb,OAAO,cAAc,CAAC;AAAA,EACxB;AACF;AAMA,MAAM,SAAS,CAAC,WAA2C;AACzD,QAAM,QAAQ,IAAI,kBAAK,EACpB,cAAc;AAAA,IACb,GAAG,OAAO,IAAI,OAAO;AAAA,IACrB,GAAG,OAAO,IAAI,OAAO;AAAA,EACvB,CAAC,EACA,cAAc;AAAA,IACb,GAAG,OAAO,IAAI,OAAO;AAAA,IACrB,GAAG,OAAO,IAAI,OAAO;AAAA,EACvB,CAAC;AACH,QAAM,WAAW,eAAe,OAAO,CAAC,SAAS,OAAO,CAAC,QAAQ,OAAO,CAAC;AACzE,QAAM,EAAE,MAAM,QAAQ,IAAI,qBAAqB,QAAQ;AAAA,IACrD,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AACD,aAAO,sCAAAA,SAA+B,MAAM,SAAS,OAAO,cAAc,CAAC,CAAC;AAC9E;AAiBA,MAAM,eAAe,CAAC,WAAgD;AACpE,QAAM,EAAE,IAAI,IAAI,QAAQ,QAAQ,WAAW,YAAY,SAAS,IAAI;AACpE,QAAM,KAAK,KAAK,MAAM,QAAQ,MAAM;AACpC,QAAM,KAAK,YAAY;AACvB,QAAM,gBAAgB,CAAC,KAAK,MAAM,CAAC,QAAQ,MAAM;AAEjD,QAAM,OAAO,iBAAiB,MAAM;AAEpC,MACE,KAAK,IAAI,aAAa,QAAQ,IAAI,QAClC,KAAK,IAAI,aAAa,WAAW,KAAK,KAAK,CAAC,IAAI,MAChD;AAGA,UAAM,UAAU,wBACb,gBAAgB,KAAK,KAAM,GAC9B,IAAI,EAAE,KAAK,EAAE;AAAA,qBACI,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE;AAAA;AAEpD,WAAO,EAAE,MAAM,QAAQ;AAAA,EACzB,OAAO;AACL,UAAM,kBAAc,cAAAC;AAAA,MAClB;AAAA,QACE,GAAG,KAAK,IAAI,UAAU,IAAI;AAAA,QAC1B,GAAG,KAAK,IAAI,UAAU,IAAI;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AACA,UAAM,aAAa;AAAA,MACjB,GAAG,KAAK,YAAY;AAAA,MACpB,GAAG,KAAK,YAAY;AAAA,IACtB;AACA,UAAM,gBAAY,cAAAA;AAAA,MAChB;AAAA,QACE,GAAG,KAAK,IAAI,QAAQ,IAAI;AAAA,QACxB,GAAG,KAAK,IAAI,QAAQ,IAAI;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AACA,UAAM,WAAW;AAAA,MACf,GAAG,KAAK,UAAU;AAAA,MAClB,GAAG,KAAK,UAAU;AAAA,IACpB;AACA,UAAM,mBACJ,WAAW,aAAa,WAAW,KAAK,KAAK,IAAI;AACnD,UAAM,eAAe,mBAAmB,aAAa,KAAK,KAAK,IAAI;AACnE,UAAM,IAAI,KAAK,WAAW,CAAC,IAAI,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,IACtD,gBAAgB,KAAK,KAAM,GAC9B,IAAI,YAAY,MAAM,SAAS,CAAC,IAAI,SAAS,CAAC;AAC9C,UAAM,UAAU,YAAY,CAAC;AAC7B,WAAO,EAAE,MAAM,QAAQ;AAAA,EACzB;AACF;AAMA,MAAM,mBAAmB,CAAC,WAAoC;AAC5D,QAAM,EAAE,IAAI,IAAI,QAAQ,QAAQ,UAAU,IAAI;AAC9C,MAAI,EAAE,YAAY,SAAS,IAAI;AAQ/B,SAAO,aAAa,EAAG,eAAc,KAAK,KAAK;AAC/C,SAAO,YAAY,WAAY,aAAY,KAAK,KAAK;AAGrD,QAAM,SAAS,CAAC;AAEhB,MAAI,KAAK,IAAI,MAAM,IAAI,SAAS,KAAK,IAAI,MAAM,IAAI,OAAO;AAExD,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,aAAO,KAAM,IAAI,IAAK,KAAK,EAAE;AAAA,IAC/B;AAAA,EACF,OAAO;AAEL,WAAO,CAAC,IAAI,KAAK,KAAM,CAAC,SAAS,YAAa,MAAM,IAAI,KAAK;AAC7D,WAAO,CAAC,IAAI,KAAK,KAAM,SAAS,YAAa,MAAM,IAAI,KAAK;AAC5D,WAAO,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK;AAC7B,WAAO,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK;AAAA,EAC/B;AAGA,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,WAAO,OAAO,CAAC,IAAI,WAAY,QAAO,CAAC,KAAK,KAAK,KAAK;AACtD,QAAI,OAAO,CAAC,IAAI,UAAU;AACxB,aAAO,OAAO,GAAG,CAAC;AAAA,IACpB;AAAA,EACF;AAGA,SAAO,KAAK,YAAY,QAAQ;AAGhC,QAAM,MAAM,OAAO,IAAI,CAAC,OAAO;AAAA,IAC7B,GAAG,KAAK,IAAI,CAAC;AAAA,IACb,GAAG,KAAK,IAAI,CAAC;AAAA,EACf,EAAE;AAGF,QAAM,IAAI;AAAA,IACR,CAAC,QAAQ,CAAC,SAAS,SAAS;AAAA,IAC5B,CAAC,QAAQ,SAAS,SAAS;AAAA,EAC7B;AAGA,QAAM,aAAa,IAAI,IAAI,CAAC,OAAO;AAAA,IACjC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,IAAI;AAAA,IACnC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,IAAI;AAAA,EACrC,EAAE;AAGF,QAAM,OAAO,WAAW,OAAO,CAAC,KAAK,MAAM;AACzC,QAAI,cAAc,CAAC;AACnB,WAAO;AAAA,EACT,GAAG,IAAI,kBAAK,CAAC;AAEb,SAAO;AACT;AAMA,MAAM,UAAU,CAAC,WAA4C;AAC3D,QAAM,EAAE,MAAM,OAAO,SAAS,SAAS,IAAI,aAAa;AAAA,IACtD,IAAI,OAAO;AAAA,IACX,IAAI,OAAO;AAAA,IACX,QAAQ,OAAO;AAAA,IACf,QAAQ,OAAO;AAAA,IACf,WAAW,OAAO;AAAA,IAClB,YAAY,OAAO;AAAA,IACnB,UAAU,OAAO;AAAA,EACnB,CAAC;AACD,QAAM,EAAE,MAAM,QAAQ,IAAI,qBAAqB,QAAQ;AAAA,IACrD,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AACD,aAAO,sCAAAD,SAA+B,MAAM,SAAS,OAAO,cAAc,CAAC,CAAC;AAC9E;AAKA,MAAM,MAAM,CAAC,WAAwC;AACnD,QAAM,EAAE,MAAM,OAAO,SAAS,SAAS,IAAI,aAAa;AAAA,IACtD,IAAI,OAAO;AAAA,IACX,IAAI,OAAO;AAAA,IACX,QAAQ,OAAO;AAAA,IACf,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,YAAY,OAAO;AAAA,IACnB,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO,eAAe;AAAA,EAC/B,CAAC;AACD,QAAM,EAAE,MAAM,QAAQ,IAAI,qBAAqB,QAAQ;AAAA,IACrD,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AACD,aAAO,sCAAAA,SAA+B,MAAM,SAAS,OAAO,cAAc,CAAC,CAAC;AAC9E;AAKA,MAAM,OAAO,CAAC,WAAyC;AACrD,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,SAAS,OAAO,cAAc;AACpC,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,UAAU,OAAO,UAAU;AAGjC,QAAM,YAAY,QAAQ,SAAS,SAAS;AAC5C,QAAM,QAAQ,IAAI,kBAAK,EACpB,cAAc,EAAE,GAAG,EAAE,CAAC,EACtB,cAAc,EAAE,GAAG,IAAI,WAAW,GAAG,IAAI,OAAO,CAAC;AAEpD,QAAM,kBAAmB,WAAW,MAAO,KAAK;AAChD,QAAM,WAAW,YAAY,CAAC,QAAQ,CAAC,gBAAgB,MAAM,uBAAuB,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,6BAA6B,KAAK,CAAC,UAAM,qBAAAE,SAAc,OAAO,CAAC;AAE7K,QAAM,EAAE,MAAM,QAAQ,IAAI,qBAAqB,QAAQ;AAAA,IACrD,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AACD,aAAO,sCAAAF,SAA+B,MAAM,SAAS,OAAO,cAAc,CAAC,CAAC;AAC9E;AAKA,MAAM,QAAQ,CAAC,WAA0C;AACvD,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,SAAS,OAAO,qBAAqB,OAAO,cAAc;AAChE,QAAM,UAAU,OAAO,UAAU;AAGjC,QAAM,YAAa,OAAO,qBAAqB,QAAQ,SAAS,SAAS;AACzE,QAAM,QAAQ,IAAI,kBAAK,EACpB,cAAc,EAAE,GAAG,EAAE,CAAC,EACtB,cAAc,EAAE,GAAG,IAAI,WAAW,GAAG,IAAI,OAAO,CAAC;AAGpD,QAAM,WAAW,OAAO,WAAW,UAAa,OAAO,WAAW,SAC9D,KAAK,MAAM,OAAO,QAAQ,OAAO,MAAM,IACvC;AACJ,QAAM,kBAAmB,WAAW,MAAO,KAAK;AAChD,QAAM,WAAW,YAAY,CAAC,QAAQ,CAAC,gBAAgB,MAAM,uBAAuB,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,6BAA6B,KAAK,CAAC,UAAM,qBAAAE,SAAc,OAAO,CAAC;AAE7K,QAAM,EAAE,MAAM,QAAQ,IAAI,qBAAqB,QAAQ;AAAA,IACrD,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AACD,aAAO,sCAAAF,SAA+B,MAAM,SAAS,OAAO,cAAc,CAAC,CAAC;AAC9E;AAMA,MAAM,YAAY,CAAC,WAA8C;AAC/D,QAAM,IAAI,OAAO,gBAAgB,KAAK;AACtC,QAAM,IAAI,OAAO,gBAAgB,KAAK;AACtC,QAAM,SAAS;AACf,QAAM,UAAU,OAAO,QAAQ;AAE/B,QAAM,WAAW,OAAO,iBACpB,KAAK,MAAM,OAAO,eAAe,GAAG,OAAO,eAAe,CAAC,IAC3D;AACJ,QAAM,kBAAmB,WAAW,MAAO,KAAK;AAEhD,QAAM,YAAY,QAAQ,SAAS,SAAS;AAC5C,QAAM,QAAQ,IAAI,kBAAK,EACpB,cAAc,EAAE,GAAG,EAAE,CAAC,EACtB,cAAc,EAAE,GAAG,IAAI,WAAW,GAAG,IAAI,OAAO,CAAC;AAEpD,QAAM,WAAW,YAAY,CAAC,QAAQ,CAAC,gBAAgB,MAAM,uBAAuB,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,6BAA6B,KAAK,CAAC,UAAM,qBAAAE,SAAc,OAAO,CAAC;AAE7K,QAAM,EAAE,MAAM,QAAQ,IAAI,qBAAqB,QAAQ;AAAA,IACrD,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AACD,aAAO,sCAAAF,SAA+B,MAAM,SAAS,OAAO,cAAc,CAAC,CAAC;AAC9E;AAMA,MAAM,QAAQ,CAAC,WAA0C;AACvD,QAAM,IAAI,OAAO,gBAAgB,KAAK;AACtC,QAAM,IAAI,OAAO,gBAAgB,KAAK;AACtC,QAAM,SAAS,OAAO,QAAQ;AAC9B,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,UAAU,OAAO,QAAQ;AAE/B,QAAM,YAAY,QAAQ,SAAS,SAAS;AAC5C,QAAM,QAAQ,IAAI,kBAAK,EACpB,cAAc,EAAE,GAAG,EAAE,CAAC,EACtB,cAAc,EAAE,GAAG,IAAI,WAAW,GAAG,IAAI,OAAO,CAAC;AAEpD,QAAM,kBAAmB,WAAW,MAAO,KAAK;AAChD,QAAM,WAAW,YAAY,CAAC,QAAQ,CAAC,gBAAgB,MAAM,uBAAuB,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,6BAA6B,KAAK,CAAC,UAAM,qBAAAE,SAAc,OAAO,CAAC;AAE7K,QAAM,EAAE,MAAM,QAAQ,IAAI,qBAAqB,QAAQ;AAAA,IACrD,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AACD,aAAO,sCAAAF,SAA+B,MAAM,SAAS,OAAO,cAAc,CAAC,CAAC;AAC9E;AAKA,MAAM,YAAY,CAChB,QACA,UACA,SACA,aACqB;AACrB,QAAM,aAAS,sBAAAG,SAAe,QAAQ,UAAU,SAAS,QAAQ;AACjE,aAAO,sCAAAH;AAAA,IACL,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO,cAAc,CAAC;AAAA,EACxB;AACF;AAEO,MAAM,mBAAmB,CAC9B,GACA,OACA,kBACa;AACb,QAAM,QAAkB,CAAC;AACzB,MAAI,oBAAoB;AACxB,MAAI,YAAY;AAChB,SAAO,YAAY,MAAM,SAAS,IAAI,GAAG;AACvC,UAAM,QAAI,uCAAa,OAAO,SAAS;AACvC,UAAM,KAAK,cAAc,MAAM,mBAAmB,oBAAoB,CAAC;AACvE,QAAI,MAAM,GAAG;AACX,YAAM;AAAA,QACJ,cAAc,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;AAAA,MACtG;AAAA,IACF,WAAW,MAAM,GAAG;AAClB,YAAM;AAAA,QACJ,cAAc,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;AAAA,MAChF;AAAA,IACF;AACA,yBAAqB;AACrB,iBAAa;AAAA,EACf;AACA,SAAO;AACT;AAEA,MAAM,SAAS,CAAC,WAA2C;AACzD,MAAI,OAAO,IAAI,kBAAK;AACpB,aAAW,KAAK,OAAO,eAAe;AACpC,WAAO,KAAK,cAAc,CAAC;AAAA,EAC7B;AACA,QAAM,IAAI,OAAO,SAAS;AAC1B,QAAM,gBAAY,yBAAAI,SAAkB,GAAG,OAAO,eAAe,OAAO,KAAK;AACzE,QAAM,QAAQ,iBAAiB,GAAG,UAAU,OAAO,UAAU,aAAa;AAC1E,QAAM,UAAU,MAAM,MAAM,KAAK,EAAE,CAAC;AACpC,aAAO,sCAAAJ,SAA+B,MAAM,SAAS,OAAO,cAAc,CAAC,CAAC;AAC9E;AAMA,MAAM,2BAA2B,CAC/B,QACA,WACA,SACA,aAC4B;AAC5B,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,OAAO,MAAsB;AAAA,IACtC,KAAK;AACH,aAAO,QAAQ,MAAuB;AAAA,IACxC,KAAK;AACH,aAAO,IAAI,MAAmB;AAAA,IAChC,KAAK;AACH,aAAO,KAAK,MAAoB;AAAA,IAClC,KAAK;AACH,aAAO,MAAM,MAAqB;AAAA,IACpC,KAAK,aAAa;AAChB,YAAM,YAAY;AAClB,YAAM,YAAY,OAAO,UAAU,cAAc,WAC7C,UAAU,YACV;AACJ,YAAM,WAAW,aAAa,YAC1B,UAAU,SAAS,IACnB;AACJ,aAAO,UAAU,WAAW,UAAU,SAAS,QAAQ;AAAA,IACzD;AAAA,IACA,KAAK,UAAU;AACb,YAAM,eAAe;AACrB,YAAM,aAAa,aAAa,SAAS,KAAK,CAAC,MAAc,MAAM,CAAC;AACpE,WAAK,aAAa,WAAW,KAAK,aAAa,WAAW,MAAM,CAAC,YAAY;AAC3E,YAAI;AACF,iBAAO,OAAO,YAAY;AAAA,QAC5B,SAAS,KAAK;AACZ,gBAAM,QAAQ;AACd,wBAAAK,QAAO,KAAK,6CAA6C,MAAM,OAAO;AACtE,iBAAO,SAAS,MAAM;AAAA,QACxB;AAAA,MACF,OAAO;AACL,eAAO,SAAS,MAAM;AAAA,MACxB;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,YAAY;AACf,aAAO,SAAS,MAAM;AAAA,IACxB;AAAA,IACA,KAAK;AAAA,IACL,KAAK,SAAS;AACZ,aAAO,SAAS,MAAM;AAAA,IACxB;AAAA,IACA,KAAK,cAAc;AACjB,aAAO,WAAW,MAAM;AAAA,IAC1B;AAAA,IACA,KAAK,WAAW;AACd,aAAO,SAAS,MAAM;AAAA,IACxB;AAAA,IACA,KAAK,UAAU;AACb,aAAO,OAAO,MAAsB;AAAA,IACtC;AAAA,IACA,KAAK,aAAa;AAChB,aAAO,UAAU,MAAyB;AAAA,IAC5C;AAAA,IACA,KAAK,SAAS;AACZ,aAAO,MAAM,MAAqB;AAAA,IACpC;AAAA,IACA;AACE,oBAAAA,QAAO,KAAK,+CAA+C,OAAO,IAAI;AACtE,aAAO;AAAA,EACX;AACF;AAEe,SAAR,MAAuB,QAAmB,UAAwB,CAAC,GAAW;AACnF,QAAM,eAAW,mBAAAC,SAAY,MAAM;AACnC,QAAM,YAAY,OAAO,OAAO;AAEhC,QAAM,eAAe,SAAS,OAAO,CAAC,KAAW,WAAyB;AACxE,QAAI,OAAO,SAAS,aAAa;AAC/B,YAAMC,YAAO,gDAAyB,MAAyB;AAC/D,UAAIA,MAAK,OAAO;AACd,YAAI,cAAcA,MAAK,GAAG;AAC1B,YAAI,cAAcA,MAAK,GAAG;AAAA,MAC5B;AACA,aAAO;AAAA,IACT;AAEA,UAAM,mBAAmB,yBAAyB,QAAQ,WAAW,OAAO;AAC5E,QAAI,kBAAkB,KAAK,OAAO;AAChC,UAAI,cAAc,iBAAiB,KAAK,GAAG;AAC3C,UAAI,cAAc,iBAAiB,KAAK,GAAG;AAAA,IAC7C;AACA,WAAO;AAAA,EACT,GAAG,IAAI,kBAAK,CAAC;AAEb,QAAM,WAAW,aAAa,QAC1B;AAAA,IACE,OAAO,aAAa,IAAI,IAAI,aAAa,IAAI;AAAA,IAC7C,QAAQ,aAAa,IAAI,IAAI,aAAa,IAAI;AAAA,EAChD,IACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAEJ,QAAM,EAAE,MAAM,SAAS,IAAI,SAAS;AAAA,IAClC,CACE,KACA,WACuC;AACvC,YAAM,UAAM,uBAAAC,SAAgB,OAAO,OAAO,QAAQ,MAAM;AACxD,YAAM,mBAAmB,yBAAyB,QAAQ,WAAW,SAAS,QAAQ;AAEtF,UAAI,kBAAkB;AACpB,cAAM,EAAE,MAAAD,OAAM,QAAQ,IAAI;AAE1B,YAAIA,MAAK,OAAO;AACd,cAAI,KAAK,cAAcA,MAAK,GAAG;AAC/B,cAAI,KAAK,cAAcA,MAAK,GAAG;AAAA,QACjC;AACA,cAAM,YAAQ,2BAAAE,SAAoB,GAAG;AACrC,YAAI,OAAO,SAAS,WAAW,OAAO,SAAS,SAAS;AACtD,cAAI,SAAS,KAAK,YAAY,KAAK,mBAAmB,OAAO,MAAM;AAAA,QACrE,OAAO;AACL,cAAI,SAAS,KAAK,cAAc,KAAK,KAAK,OAAO,MAAM;AAAA,QACzD;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,MAAM,IAAI,kBAAK;AAAA,MACf,UAAU,CAAC;AAAA,IACb;AAAA,EACF;AAEA,QAAM,UAAU,KAAK,QACjB;AAAA,IACE,GAAG,KAAK,IAAI;AAAA,IACZ,GAAG,CAAC,KAAK,IAAI;AAAA,IACb,OAAO,KAAK,IAAI,IAAI,KAAK,IAAI;AAAA,IAC7B,QAAQ,KAAK,IAAI,IAAI,KAAK,IAAI;AAAA,EAChC,IACA;AAAA,IACE,GAAG;AAAA,IACH,GAAG;AAAA,IACH,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AACJ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,aAKI,QAAQ,CAAC,IAAI,QAAQ,CAAC,IAAI,QAAQ,KAAK,IAAI,QAAQ,MAAM;AAAA;AAAA;AAAA;AAAA,MAIhE,SAAS,KAAK,IAAI,CAAC;AAAA;AAAA;AAGzB;",
|
|
6
|
+
"names": ["entityToPolyline", "transformBoundingBoxAndElement", "rotate", "escapeXmlText", "dimensionToSVG", "toPiecewiseBezier", "logger", "denormalise", "bbox", "getRGBForEntity", "rgbToColorAttribute"]
|
|
7
7
|
}
|
package/lib/toSVG.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Box2 } from "vecks";
|
|
2
2
|
import denormalise from "./denormalise";
|
|
3
|
-
import dimensionToSVG from "./dimensionToSVG";
|
|
3
|
+
import dimensionToSVG, { getDimensionGeometryBBox } from "./dimensionToSVG";
|
|
4
4
|
import entityToPolyline from "./entityToPolyline";
|
|
5
5
|
import getRGBForEntity from "./getRGBForEntity";
|
|
6
|
+
import escapeXmlText from "./util/escapeXmlText";
|
|
6
7
|
import logger from "./util/logger";
|
|
7
8
|
import rgbToColorAttribute from "./util/rgbToColorAttribute";
|
|
8
9
|
import rotate from "./util/rotate";
|
|
@@ -59,6 +60,23 @@ const lwpolyline = (entity) => {
|
|
|
59
60
|
entity.transforms ?? []
|
|
60
61
|
);
|
|
61
62
|
};
|
|
63
|
+
const leader = (entity) => {
|
|
64
|
+
if (!entity.vertices || entity.vertices.length < 2) return null;
|
|
65
|
+
const bbox0 = entity.vertices.reduce(
|
|
66
|
+
(acc, p) => acc.expandByPoint({ x: p.x, y: p.y }),
|
|
67
|
+
new Box2()
|
|
68
|
+
);
|
|
69
|
+
const d = entity.vertices.reduce((acc, p, i) => {
|
|
70
|
+
acc += i === 0 ? "M" : "L";
|
|
71
|
+
acc += p.x + "," + p.y;
|
|
72
|
+
return acc;
|
|
73
|
+
}, "");
|
|
74
|
+
return transformBoundingBoxAndElement(
|
|
75
|
+
bbox0,
|
|
76
|
+
`<path d="${d}" />`,
|
|
77
|
+
entity.transforms ?? []
|
|
78
|
+
);
|
|
79
|
+
};
|
|
62
80
|
const circle = (entity) => {
|
|
63
81
|
const bbox0 = new Box2().expandByPoint({
|
|
64
82
|
x: entity.x + entity.r,
|
|
@@ -198,7 +216,7 @@ const text = (entity) => {
|
|
|
198
216
|
const textWidth = content.length * height * 0.6;
|
|
199
217
|
const bbox0 = new Box2().expandByPoint({ x, y }).expandByPoint({ x: x + textWidth, y: y + height });
|
|
200
218
|
const rotationDegrees = rotation * 180 / Math.PI;
|
|
201
|
-
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${content}</text>`;
|
|
219
|
+
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${escapeXmlText(content)}</text>`;
|
|
202
220
|
const { bbox, element } = addFlipXIfApplicable(entity, {
|
|
203
221
|
bbox: bbox0,
|
|
204
222
|
element: element0
|
|
@@ -214,15 +232,47 @@ const mtext = (entity) => {
|
|
|
214
232
|
const bbox0 = new Box2().expandByPoint({ x, y }).expandByPoint({ x: x + textWidth, y: y + height });
|
|
215
233
|
const rotation = entity.xAxisX !== void 0 && entity.xAxisY !== void 0 ? Math.atan2(entity.xAxisY, entity.xAxisX) : 0;
|
|
216
234
|
const rotationDegrees = rotation * 180 / Math.PI;
|
|
217
|
-
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${content}</text>`;
|
|
235
|
+
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${escapeXmlText(content)}</text>`;
|
|
236
|
+
const { bbox, element } = addFlipXIfApplicable(entity, {
|
|
237
|
+
bbox: bbox0,
|
|
238
|
+
element: element0
|
|
239
|
+
});
|
|
240
|
+
return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? []);
|
|
241
|
+
};
|
|
242
|
+
const tolerance = (entity) => {
|
|
243
|
+
const x = entity.insertionPoint?.x ?? 0;
|
|
244
|
+
const y = entity.insertionPoint?.y ?? 0;
|
|
245
|
+
const height = 1;
|
|
246
|
+
const content = entity.text ?? "";
|
|
247
|
+
const rotation = entity.xAxisDirection ? Math.atan2(entity.xAxisDirection.y, entity.xAxisDirection.x) : 0;
|
|
248
|
+
const rotationDegrees = rotation * 180 / Math.PI;
|
|
249
|
+
const textWidth = content.length * height * 0.6;
|
|
250
|
+
const bbox0 = new Box2().expandByPoint({ x, y }).expandByPoint({ x: x + textWidth, y: y + height });
|
|
251
|
+
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${escapeXmlText(content)}</text>`;
|
|
218
252
|
const { bbox, element } = addFlipXIfApplicable(entity, {
|
|
219
253
|
bbox: bbox0,
|
|
220
254
|
element: element0
|
|
221
255
|
});
|
|
222
256
|
return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? []);
|
|
223
257
|
};
|
|
224
|
-
const
|
|
225
|
-
const
|
|
258
|
+
const shape = (entity) => {
|
|
259
|
+
const x = entity.insertionPoint?.x ?? 0;
|
|
260
|
+
const y = entity.insertionPoint?.y ?? 0;
|
|
261
|
+
const height = entity.size ?? 1;
|
|
262
|
+
const rotation = entity.rotation ?? 0;
|
|
263
|
+
const content = entity.name ?? "";
|
|
264
|
+
const textWidth = content.length * height * 0.6;
|
|
265
|
+
const bbox0 = new Box2().expandByPoint({ x, y }).expandByPoint({ x: x + textWidth, y: y + height });
|
|
266
|
+
const rotationDegrees = rotation * 180 / Math.PI;
|
|
267
|
+
const element0 = `<text x="${x}" y="${y}" font-size="${height}" transform="rotate(${-rotationDegrees} ${x} ${y}) scale(1,-1) translate(0 ${-2 * y})">${escapeXmlText(content)}</text>`;
|
|
268
|
+
const { bbox, element } = addFlipXIfApplicable(entity, {
|
|
269
|
+
bbox: bbox0,
|
|
270
|
+
element: element0
|
|
271
|
+
});
|
|
272
|
+
return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? []);
|
|
273
|
+
};
|
|
274
|
+
const dimension = (entity, dimStyle, options, viewport) => {
|
|
275
|
+
const result = dimensionToSVG(entity, dimStyle, options, viewport);
|
|
226
276
|
return transformBoundingBoxAndElement(
|
|
227
277
|
result.bbox,
|
|
228
278
|
result.element,
|
|
@@ -261,7 +311,7 @@ const bezier = (entity) => {
|
|
|
261
311
|
const element = `<g>${paths.join("")}</g>`;
|
|
262
312
|
return transformBoundingBoxAndElement(bbox, element, entity.transforms ?? []);
|
|
263
313
|
};
|
|
264
|
-
const entityToBoundsAndElement = (entity, dimStyles) => {
|
|
314
|
+
const entityToBoundsAndElement = (entity, dimStyles, options, viewport) => {
|
|
265
315
|
switch (entity.type) {
|
|
266
316
|
case "CIRCLE":
|
|
267
317
|
return circle(entity);
|
|
@@ -277,7 +327,7 @@ const entityToBoundsAndElement = (entity, dimStyles) => {
|
|
|
277
327
|
const dimEntity = entity;
|
|
278
328
|
const styleName = typeof dimEntity.styleName === "string" ? dimEntity.styleName : void 0;
|
|
279
329
|
const dimStyle = styleName && dimStyles ? dimStyles[styleName] : void 0;
|
|
280
|
-
return dimension(dimEntity, dimStyle);
|
|
330
|
+
return dimension(dimEntity, dimStyle, options, viewport);
|
|
281
331
|
}
|
|
282
332
|
case "SPLINE": {
|
|
283
333
|
const splineEntity = entity;
|
|
@@ -295,33 +345,77 @@ const entityToBoundsAndElement = (entity, dimStyles) => {
|
|
|
295
345
|
}
|
|
296
346
|
}
|
|
297
347
|
case "LINE":
|
|
348
|
+
case "RAY":
|
|
349
|
+
case "XLINE":
|
|
298
350
|
case "POLYLINE": {
|
|
299
351
|
return polyline(entity);
|
|
300
352
|
}
|
|
353
|
+
case "SOLID":
|
|
354
|
+
case "TRACE": {
|
|
355
|
+
return polyline(entity);
|
|
356
|
+
}
|
|
301
357
|
case "LWPOLYLINE": {
|
|
302
358
|
return lwpolyline(entity);
|
|
303
359
|
}
|
|
360
|
+
case "WIPEOUT": {
|
|
361
|
+
return polyline(entity);
|
|
362
|
+
}
|
|
363
|
+
case "LEADER": {
|
|
364
|
+
return leader(entity);
|
|
365
|
+
}
|
|
366
|
+
case "TOLERANCE": {
|
|
367
|
+
return tolerance(entity);
|
|
368
|
+
}
|
|
369
|
+
case "SHAPE": {
|
|
370
|
+
return shape(entity);
|
|
371
|
+
}
|
|
304
372
|
default:
|
|
305
373
|
logger.warn("entity type not supported in SVG rendering:", entity.type);
|
|
306
374
|
return null;
|
|
307
375
|
}
|
|
308
376
|
};
|
|
309
|
-
function toSVG(parsed) {
|
|
377
|
+
function toSVG(parsed, options = {}) {
|
|
310
378
|
const entities = denormalise(parsed);
|
|
311
379
|
const dimStyles = parsed.tables.dimStyles;
|
|
380
|
+
const geometryBBox = entities.reduce((acc, entity) => {
|
|
381
|
+
if (entity.type === "DIMENSION") {
|
|
382
|
+
const bbox2 = getDimensionGeometryBBox(entity);
|
|
383
|
+
if (bbox2.valid) {
|
|
384
|
+
acc.expandByPoint(bbox2.min);
|
|
385
|
+
acc.expandByPoint(bbox2.max);
|
|
386
|
+
}
|
|
387
|
+
return acc;
|
|
388
|
+
}
|
|
389
|
+
const boundsAndElement = entityToBoundsAndElement(entity, dimStyles, options);
|
|
390
|
+
if (boundsAndElement?.bbox.valid) {
|
|
391
|
+
acc.expandByPoint(boundsAndElement.bbox.min);
|
|
392
|
+
acc.expandByPoint(boundsAndElement.bbox.max);
|
|
393
|
+
}
|
|
394
|
+
return acc;
|
|
395
|
+
}, new Box2());
|
|
396
|
+
const viewport = geometryBBox.valid ? {
|
|
397
|
+
width: geometryBBox.max.x - geometryBBox.min.x,
|
|
398
|
+
height: geometryBBox.max.y - geometryBBox.min.y
|
|
399
|
+
} : {
|
|
400
|
+
width: 0,
|
|
401
|
+
height: 0
|
|
402
|
+
};
|
|
312
403
|
const { bbox, elements } = entities.reduce(
|
|
313
404
|
(acc, entity) => {
|
|
314
405
|
const rgb = getRGBForEntity(parsed.tables.layers, entity);
|
|
315
|
-
const boundsAndElement = entityToBoundsAndElement(entity, dimStyles);
|
|
406
|
+
const boundsAndElement = entityToBoundsAndElement(entity, dimStyles, options, viewport);
|
|
316
407
|
if (boundsAndElement) {
|
|
317
408
|
const { bbox: bbox2, element } = boundsAndElement;
|
|
318
409
|
if (bbox2.valid) {
|
|
319
410
|
acc.bbox.expandByPoint(bbox2.min);
|
|
320
411
|
acc.bbox.expandByPoint(bbox2.max);
|
|
321
412
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
413
|
+
const color = rgbToColorAttribute(rgb);
|
|
414
|
+
if (entity.type === "SOLID" || entity.type === "TRACE") {
|
|
415
|
+
acc.elements.push(`<g fill="${color}" stroke="none">${element}</g>`);
|
|
416
|
+
} else {
|
|
417
|
+
acc.elements.push(`<g stroke="${color}">${element}</g>`);
|
|
418
|
+
}
|
|
325
419
|
}
|
|
326
420
|
return acc;
|
|
327
421
|
},
|