@ifc-lite/drawing-2d 1.18.6 → 1.19.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/README.md +23 -0
- package/dist/dxf/aci-colors.d.ts +4 -0
- package/dist/dxf/aci-colors.d.ts.map +1 -0
- package/dist/dxf/aci-colors.js +74 -0
- package/dist/dxf/aci-colors.js.map +1 -0
- package/dist/dxf/convert.d.ts +32 -0
- package/dist/dxf/convert.d.ts.map +1 -0
- package/dist/dxf/convert.js +382 -0
- package/dist/dxf/convert.js.map +1 -0
- package/dist/dxf/geom.d.ts +70 -0
- package/dist/dxf/geom.d.ts.map +1 -0
- package/dist/dxf/geom.js +194 -0
- package/dist/dxf/geom.js.map +1 -0
- package/dist/dxf/index.d.ts +13 -0
- package/dist/dxf/index.d.ts.map +1 -0
- package/dist/dxf/index.js +44 -0
- package/dist/dxf/index.js.map +1 -0
- package/dist/dxf/parser.d.ts +9 -0
- package/dist/dxf/parser.d.ts.map +1 -0
- package/dist/dxf/parser.js +903 -0
- package/dist/dxf/parser.js.map +1 -0
- package/dist/dxf/types.d.ts +255 -0
- package/dist/dxf/types.d.ts.map +1 -0
- package/dist/dxf/types.js +10 -0
- package/dist/dxf/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/svg-exporter.d.ts +23 -0
- package/dist/svg-exporter.d.ts.map +1 -1
- package/dist/svg-exporter.js +80 -1
- package/dist/svg-exporter.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -126,6 +126,29 @@ import {
|
|
|
126
126
|
|
|
127
127
|
Each renderer returns SVG fragments that you wrap in your own `<svg>` document — see the [2D Drawings Guide](https://ifclite.dev/docs/guide/drawing-2d/) for a worked sheet-composition example.
|
|
128
128
|
|
|
129
|
+
## DXF reference underlays
|
|
130
|
+
|
|
131
|
+
Import an existing DXF drawing (site plan, survey, coordination set) as a reference layer beneath a generated floor plan. `importDxf` parses ASCII DXF — `LINE`, `LWPOLYLINE`/`POLYLINE` (with bulge arcs), `CIRCLE`, `ARC`, `ELLIPSE`, `SPLINE`, `SOLID`/`TRACE`, `HATCH`, `TEXT`/`MTEXT`, `DIMENSION` blocks, and `INSERT`/`BLOCK` references — into world-plan geometry (metres, +Y = north; DXF and IFC are both Z-up) with per-layer visibility and resolved ACI/true colours and lineweights. `$INSUNITS` drives the unit conversion; unitless files with large extents are assumed to be millimetres (with a warning).
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { importDxf, exportToSVG } from '@ifc-lite/drawing-2d';
|
|
135
|
+
|
|
136
|
+
const underlay = importDxf(dxfFileText, 'site-plan.dxf');
|
|
137
|
+
// underlay.layers[n].paths / .fills / .texts, underlay.bounds, underlay.warnings
|
|
138
|
+
|
|
139
|
+
// Composite beneath an exported floor plan:
|
|
140
|
+
const svg = exportToSVG(drawing, {
|
|
141
|
+
underlays: [{
|
|
142
|
+
underlay,
|
|
143
|
+
placement: { offsetX: 0, offsetY: 0, rotationDeg: 0, scale: 1 },
|
|
144
|
+
layerVisibility: { 'A-SITE': true },
|
|
145
|
+
opacity: 0.8,
|
|
146
|
+
}],
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Unsupported entity types are counted in `underlay.skipped` rather than failing the import; parse problems (missing blocks, spline approximations, unknown units) surface in `underlay.warnings`.
|
|
151
|
+
|
|
129
152
|
## API
|
|
130
153
|
|
|
131
154
|
See the [2D Drawings Guide](https://ifclite.dev/docs/guide/drawing-2d/) and [API Reference](https://ifclite.dev/docs/api/typescript/#ifc-litedrawing-2d).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aci-colors.d.ts","sourceRoot":"","sources":["../../src/dxf/aci-colors.ts"],"names":[],"mappings":"AA+DA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI9C"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* AutoCAD Color Index (ACI) → CSS colour.
|
|
6
|
+
*
|
|
7
|
+
* Indices 1-9 and 250-255 use the exact classic values. The 240 chromatic
|
|
8
|
+
* entries (10-249) are generated from the ACI band structure — 24 hue bands
|
|
9
|
+
* of 10 entries, alternating full/washed saturation over 5 brightness steps.
|
|
10
|
+
* That reproduces the classic table closely (visually indistinguishable for
|
|
11
|
+
* an underlay) without embedding 240 literals.
|
|
12
|
+
*
|
|
13
|
+
* ACI 7 is "white/black" (paper-dependent); the 2D canvas and SVG exports
|
|
14
|
+
* draw on white, so it maps to black.
|
|
15
|
+
*/
|
|
16
|
+
function hsvToRgbInt(hueDeg, s, v) {
|
|
17
|
+
const c = v * s;
|
|
18
|
+
const hp = (((hueDeg % 360) + 360) % 360) / 60;
|
|
19
|
+
const x = c * (1 - Math.abs((hp % 2) - 1));
|
|
20
|
+
let r = 0;
|
|
21
|
+
let g = 0;
|
|
22
|
+
let b = 0;
|
|
23
|
+
if (hp < 1)
|
|
24
|
+
[r, g, b] = [c, x, 0];
|
|
25
|
+
else if (hp < 2)
|
|
26
|
+
[r, g, b] = [x, c, 0];
|
|
27
|
+
else if (hp < 3)
|
|
28
|
+
[r, g, b] = [0, c, x];
|
|
29
|
+
else if (hp < 4)
|
|
30
|
+
[r, g, b] = [0, x, c];
|
|
31
|
+
else if (hp < 5)
|
|
32
|
+
[r, g, b] = [x, 0, c];
|
|
33
|
+
else
|
|
34
|
+
[r, g, b] = [c, 0, x];
|
|
35
|
+
const m = v - c;
|
|
36
|
+
const to255 = (f) => Math.round((f + m) * 255);
|
|
37
|
+
return (to255(r) << 16) | (to255(g) << 8) | to255(b);
|
|
38
|
+
}
|
|
39
|
+
function buildAciTable() {
|
|
40
|
+
const t = new Array(256).fill(0x000000);
|
|
41
|
+
t[1] = 0xff0000; // red
|
|
42
|
+
t[2] = 0xffff00; // yellow
|
|
43
|
+
t[3] = 0x00ff00; // green
|
|
44
|
+
t[4] = 0x00ffff; // cyan
|
|
45
|
+
t[5] = 0x0000ff; // blue
|
|
46
|
+
t[6] = 0xff00ff; // magenta
|
|
47
|
+
t[7] = 0x000000; // white/black → black on a white canvas
|
|
48
|
+
t[8] = 0x414141;
|
|
49
|
+
t[9] = 0x808080;
|
|
50
|
+
const brightness = [1.0, 0.8, 0.6, 0.5, 0.35];
|
|
51
|
+
for (let i = 10; i <= 249; i++) {
|
|
52
|
+
const c = i - 10;
|
|
53
|
+
const hue = Math.floor(c / 10) * 15;
|
|
54
|
+
const v = brightness[Math.floor((c % 10) / 2)];
|
|
55
|
+
const s = c % 2 === 1 ? 0.45 : 1.0;
|
|
56
|
+
t[i] = hsvToRgbInt(hue, s, v);
|
|
57
|
+
}
|
|
58
|
+
const grays = [0x333333, 0x505050, 0x696969, 0x828282, 0xbebebe, 0xffffff];
|
|
59
|
+
for (let i = 0; i < grays.length; i++)
|
|
60
|
+
t[250 + i] = grays[i];
|
|
61
|
+
return t;
|
|
62
|
+
}
|
|
63
|
+
const ACI_TABLE = buildAciTable();
|
|
64
|
+
export function rgbIntToCss(rgb) {
|
|
65
|
+
return `#${(rgb & 0xffffff).toString(16).padStart(6, '0')}`;
|
|
66
|
+
}
|
|
67
|
+
/** Resolve an ACI colour number (1-255) to a CSS hex colour. */
|
|
68
|
+
export function aciToCss(index) {
|
|
69
|
+
const i = Math.trunc(index);
|
|
70
|
+
if (i < 1 || i > 255 || !Number.isFinite(i))
|
|
71
|
+
return '#000000';
|
|
72
|
+
return rgbIntToCss(ACI_TABLE[i]);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=aci-colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aci-colors.js","sourceRoot":"","sources":["../../src/dxf/aci-colors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a parsed DXF document into a reference underlay (issue #1782):
|
|
3
|
+
* tessellate entities, expand INSERT/DIMENSION blocks, resolve ACI/true
|
|
4
|
+
* colours per layer, and scale $INSUNITS to metres. Output is in WORLD
|
|
5
|
+
* plan coordinates (metres, +Y = north; DXF and IFC are both Z-up).
|
|
6
|
+
* Consumers map world → drawing space themselves — for a plan view that
|
|
7
|
+
* is `(x - shiftX, -(y - shiftY))` with the render-frame origin shift.
|
|
8
|
+
*/
|
|
9
|
+
import type { Point2D } from '../types.js';
|
|
10
|
+
import type { DxfDocument, DxfPlacement, DxfUnderlay } from './types.js';
|
|
11
|
+
export interface DxfConvertOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Override the unit conversion (drawing units → metres). When set, the
|
|
14
|
+
* file's $INSUNITS is ignored. Used by `importDxf`'s unitless-mm
|
|
15
|
+
* heuristic and available for callers that know the drawing's units.
|
|
16
|
+
*/
|
|
17
|
+
metersPerUnit?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Convert a parsed DXF document to a reference underlay.
|
|
21
|
+
* `name` labels the underlay (typically the file name).
|
|
22
|
+
*/
|
|
23
|
+
export declare function convertDxfToUnderlay(doc: DxfDocument, name?: string, options?: DxfConvertOptions): DxfUnderlay;
|
|
24
|
+
/**
|
|
25
|
+
* Apply a user placement to an underlay point in DRAWING space — i.e.
|
|
26
|
+
* after the world → drawing mapping (`x_d = x - shiftX`,
|
|
27
|
+
* `y_d = -(y - shiftY)` for a plan view). Rotation is counter-clockwise
|
|
28
|
+
* as seen on the plan (drawing space renders with +y downward on screen,
|
|
29
|
+
* hence the transposed rotation matrix).
|
|
30
|
+
*/
|
|
31
|
+
export declare function applyDxfPlacement(p: Point2D, placement: DxfPlacement): Point2D;
|
|
32
|
+
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/dxf/convert.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAuB,MAAM,aAAa,CAAC;AAehE,OAAO,KAAK,EACV,WAAW,EAGX,YAAY,EACZ,WAAW,EAGZ,MAAM,YAAY,CAAC;AAqDpB,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,SAAQ,EAAE,OAAO,GAAE,iBAAsB,GAAG,WAAW,CA+DjH;AAmTD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,CAU9E"}
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { aciToCss, rgbIntToCss } from './aci-colors.js';
|
|
5
|
+
import { expandBulgedVertices, matApply, matMultiply, matTRS, matTranslate, sampleArc, sampleCircle, sampleEllipse, tessellateSpline, MAT_IDENTITY, } from './geom.js';
|
|
6
|
+
/** $INSUNITS → metres. Unknown codes fall back to 1 with a warning. */
|
|
7
|
+
const INSUNITS_TO_METRES = {
|
|
8
|
+
0: 1, // unitless: assume metres (adjustable via placement scale)
|
|
9
|
+
1: 0.0254, // inches
|
|
10
|
+
2: 0.3048, // feet
|
|
11
|
+
3: 1609.344, // miles
|
|
12
|
+
4: 0.001, // millimetres
|
|
13
|
+
5: 0.01, // centimetres
|
|
14
|
+
6: 1, // metres
|
|
15
|
+
7: 1000, // kilometres
|
|
16
|
+
8: 2.54e-8, // microinches
|
|
17
|
+
9: 2.54e-5, // mils
|
|
18
|
+
10: 0.9144, // yards
|
|
19
|
+
11: 1e-10, // angstroms
|
|
20
|
+
12: 1e-9, // nanometres
|
|
21
|
+
13: 1e-6, // microns
|
|
22
|
+
14: 0.1, // decimetres
|
|
23
|
+
15: 10, // decametres
|
|
24
|
+
16: 100, // hectometres
|
|
25
|
+
};
|
|
26
|
+
/** Recursion guard for nested INSERTs. */
|
|
27
|
+
const MAX_BLOCK_DEPTH = 8;
|
|
28
|
+
/** Total block-instance expansion cap against pathological grids/nesting. */
|
|
29
|
+
const MAX_BLOCK_INSTANCES = 100_000;
|
|
30
|
+
const CONTINUOUS_LINETYPES = new Set(['', 'CONTINUOUS', 'BYLAYER', 'BYBLOCK']);
|
|
31
|
+
/**
|
|
32
|
+
* Convert a parsed DXF document to a reference underlay.
|
|
33
|
+
* `name` labels the underlay (typically the file name).
|
|
34
|
+
*/
|
|
35
|
+
export function convertDxfToUnderlay(doc, name = 'DXF', options = {}) {
|
|
36
|
+
const warnings = [...doc.warnings];
|
|
37
|
+
let unitScale;
|
|
38
|
+
if (options.metersPerUnit !== undefined && options.metersPerUnit > 0) {
|
|
39
|
+
unitScale = options.metersPerUnit;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
const fromHeader = INSUNITS_TO_METRES[doc.insunits];
|
|
43
|
+
if (fromHeader === undefined) {
|
|
44
|
+
warnings.push(`Unknown $INSUNITS value ${doc.insunits}; drawing units treated as metres.`);
|
|
45
|
+
unitScale = 1;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
unitScale = fromHeader;
|
|
49
|
+
}
|
|
50
|
+
if (doc.insunits === 0) {
|
|
51
|
+
warnings.push('DXF has no $INSUNITS; drawing units treated as metres (adjust with the underlay scale).');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const state = {
|
|
55
|
+
doc,
|
|
56
|
+
unitScale,
|
|
57
|
+
layers: new Map(),
|
|
58
|
+
layerInfos: doc.layers,
|
|
59
|
+
bounds: { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity },
|
|
60
|
+
warnings,
|
|
61
|
+
instanceCount: 0,
|
|
62
|
+
instanceCapHit: false,
|
|
63
|
+
};
|
|
64
|
+
const ctx = {
|
|
65
|
+
m: MAT_IDENTITY,
|
|
66
|
+
byBlockColor: null,
|
|
67
|
+
insertLayer: null,
|
|
68
|
+
depth: 0,
|
|
69
|
+
stack: [],
|
|
70
|
+
};
|
|
71
|
+
emitEntities(doc.entities, ctx, state);
|
|
72
|
+
const bounds = Number.isFinite(state.bounds.minX)
|
|
73
|
+
? {
|
|
74
|
+
min: { x: state.bounds.minX, y: state.bounds.minY },
|
|
75
|
+
max: { x: state.bounds.maxX, y: state.bounds.maxY },
|
|
76
|
+
}
|
|
77
|
+
: { min: { x: 0, y: 0 }, max: { x: 0, y: 0 } };
|
|
78
|
+
// Stable layer order: DXF table order first, then referenced-only layers.
|
|
79
|
+
const ordered = [];
|
|
80
|
+
for (const layerName of doc.layers.keys()) {
|
|
81
|
+
const bucket = state.layers.get(layerName);
|
|
82
|
+
if (bucket)
|
|
83
|
+
ordered.push(bucket);
|
|
84
|
+
}
|
|
85
|
+
for (const [layerName, bucket] of state.layers) {
|
|
86
|
+
if (!doc.layers.has(layerName))
|
|
87
|
+
ordered.push(bucket);
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
name,
|
|
91
|
+
layers: ordered.filter((l) => l.paths.length > 0 || l.fills.length > 0 || l.texts.length > 0),
|
|
92
|
+
bounds,
|
|
93
|
+
unitScale,
|
|
94
|
+
skipped: { ...doc.skipped },
|
|
95
|
+
warnings: state.warnings,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
99
|
+
// EMISSION
|
|
100
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
101
|
+
function getBucket(state, layerName) {
|
|
102
|
+
let bucket = state.layers.get(layerName);
|
|
103
|
+
if (!bucket) {
|
|
104
|
+
const info = state.layerInfos.get(layerName);
|
|
105
|
+
const color = info
|
|
106
|
+
? info.trueColor !== undefined
|
|
107
|
+
? rgbIntToCss(info.trueColor)
|
|
108
|
+
: aciToCss(info.colorNumber)
|
|
109
|
+
: '#000000';
|
|
110
|
+
bucket = {
|
|
111
|
+
name: layerName,
|
|
112
|
+
color,
|
|
113
|
+
visible: info ? info.visible : true,
|
|
114
|
+
paths: [],
|
|
115
|
+
fills: [],
|
|
116
|
+
texts: [],
|
|
117
|
+
};
|
|
118
|
+
state.layers.set(layerName, bucket);
|
|
119
|
+
}
|
|
120
|
+
return bucket;
|
|
121
|
+
}
|
|
122
|
+
/** Resolve an entity's CSS colour given its layer and BYBLOCK context. */
|
|
123
|
+
function resolveColor(entity, layerColor, ctx) {
|
|
124
|
+
if (entity.trueColor !== undefined)
|
|
125
|
+
return rgbIntToCss(entity.trueColor);
|
|
126
|
+
const cn = entity.colorNumber;
|
|
127
|
+
if (cn === 0)
|
|
128
|
+
return ctx.byBlockColor ?? layerColor; // BYBLOCK
|
|
129
|
+
if (cn >= 1 && cn <= 255)
|
|
130
|
+
return aciToCss(cn);
|
|
131
|
+
return layerColor; // BYLAYER (256) and anything unexpected
|
|
132
|
+
}
|
|
133
|
+
function isDashed(entity, layerInfo) {
|
|
134
|
+
const lt = (entity.linetype ?? '').trim().toUpperCase();
|
|
135
|
+
if (lt && lt !== 'BYLAYER') {
|
|
136
|
+
return lt !== 'CONTINUOUS' && lt !== 'BYBLOCK';
|
|
137
|
+
}
|
|
138
|
+
const layerLt = (layerInfo?.linetype ?? '').trim().toUpperCase();
|
|
139
|
+
return !CONTINUOUS_LINETYPES.has(layerLt);
|
|
140
|
+
}
|
|
141
|
+
/** Map a DXF-space point through the block chain into world metres. */
|
|
142
|
+
function toWorld(state, ctx, x, y) {
|
|
143
|
+
const p = matApply(ctx.m, x, y);
|
|
144
|
+
const wx = p.x * state.unitScale;
|
|
145
|
+
const wy = p.y * state.unitScale;
|
|
146
|
+
if (wx < state.bounds.minX)
|
|
147
|
+
state.bounds.minX = wx;
|
|
148
|
+
if (wx > state.bounds.maxX)
|
|
149
|
+
state.bounds.maxX = wx;
|
|
150
|
+
if (wy < state.bounds.minY)
|
|
151
|
+
state.bounds.minY = wy;
|
|
152
|
+
if (wy > state.bounds.maxY)
|
|
153
|
+
state.bounds.maxY = wy;
|
|
154
|
+
return { x: wx, y: wy };
|
|
155
|
+
}
|
|
156
|
+
/** Lineweight in mm: entity group 370, else the layer default. */
|
|
157
|
+
function resolveWidthMm(entity, layerInfo) {
|
|
158
|
+
return entity.lineweightMm ?? layerInfo?.lineweightMm;
|
|
159
|
+
}
|
|
160
|
+
function emitEntities(entities, ctx, state) {
|
|
161
|
+
for (const entity of entities) {
|
|
162
|
+
if (entity.invisible)
|
|
163
|
+
continue;
|
|
164
|
+
const effLayerName = entity.layer === '0' && ctx.insertLayer ? ctx.insertLayer : entity.layer;
|
|
165
|
+
const bucket = getBucket(state, effLayerName);
|
|
166
|
+
const layerInfo = state.layerInfos.get(effLayerName);
|
|
167
|
+
const color = resolveColor(entity, bucket.color, ctx);
|
|
168
|
+
const colorOverride = color !== bucket.color ? color : undefined;
|
|
169
|
+
const mirror = entity.extrusionZ < 0 ? -1 : 1;
|
|
170
|
+
const dashed = isDashed(entity, layerInfo) || undefined;
|
|
171
|
+
const widthMm = resolveWidthMm(entity, layerInfo);
|
|
172
|
+
const pushPath = (pts, closed) => {
|
|
173
|
+
if (pts.length < 2)
|
|
174
|
+
return;
|
|
175
|
+
bucket.paths.push({
|
|
176
|
+
points: pts.map((p) => toWorld(state, ctx, p.x * mirror, p.y)),
|
|
177
|
+
closed,
|
|
178
|
+
color: colorOverride,
|
|
179
|
+
dashed,
|
|
180
|
+
widthMm,
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
switch (entity.kind) {
|
|
184
|
+
case 'line':
|
|
185
|
+
// LINE coordinates are WCS; the OCS mirror does not apply.
|
|
186
|
+
bucket.paths.push({
|
|
187
|
+
points: [toWorld(state, ctx, entity.x1, entity.y1), toWorld(state, ctx, entity.x2, entity.y2)],
|
|
188
|
+
closed: false,
|
|
189
|
+
color: colorOverride,
|
|
190
|
+
dashed,
|
|
191
|
+
widthMm,
|
|
192
|
+
});
|
|
193
|
+
break;
|
|
194
|
+
case 'polyline':
|
|
195
|
+
pushPath(expandBulgedVertices(entity.vertices, entity.closed), entity.closed);
|
|
196
|
+
break;
|
|
197
|
+
case 'spline':
|
|
198
|
+
pushPath(tessellateSpline(entity.degree, entity.knots, entity.controlPoints, entity.fitPoints), entity.closed);
|
|
199
|
+
break;
|
|
200
|
+
case 'circle':
|
|
201
|
+
pushPath(sampleCircle(entity.cx, entity.cy, entity.r), true);
|
|
202
|
+
break;
|
|
203
|
+
case 'arc': {
|
|
204
|
+
// Mirrored OCS also mirrors angles: θ → 180° − θ.
|
|
205
|
+
const start = mirror < 0 ? 180 - entity.endDeg : entity.startDeg;
|
|
206
|
+
const end = mirror < 0 ? 180 - entity.startDeg : entity.endDeg;
|
|
207
|
+
const pts = sampleArc(entity.cx * mirror, entity.cy, entity.r, start, end);
|
|
208
|
+
if (pts.length >= 2) {
|
|
209
|
+
bucket.paths.push({
|
|
210
|
+
points: pts.map((p) => toWorld(state, ctx, p.x, p.y)),
|
|
211
|
+
closed: false,
|
|
212
|
+
color: colorOverride,
|
|
213
|
+
dashed,
|
|
214
|
+
widthMm,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
case 'solid': {
|
|
220
|
+
const ring = entity.corners.map((p) => toWorld(state, ctx, p.x * mirror, p.y));
|
|
221
|
+
if (ring.length >= 3) {
|
|
222
|
+
bucket.fills.push({ polygon: { outer: ring, holes: [] }, color: colorOverride, pattern: false });
|
|
223
|
+
}
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
case 'ellipse':
|
|
227
|
+
pushPath(sampleEllipse(entity.cx, entity.cy, entity.majorX, entity.majorY, entity.ratio, entity.startParam, entity.endParam), Math.abs(entity.endParam - entity.startParam) >= Math.PI * 2 - 1e-9);
|
|
228
|
+
break;
|
|
229
|
+
case 'hatch': {
|
|
230
|
+
if (entity.paths.length === 0)
|
|
231
|
+
break;
|
|
232
|
+
const rings = entity.paths
|
|
233
|
+
.map((path) => expandBulgedVertices(path.vertices, true).map((p) => toWorld(state, ctx, p.x * mirror, p.y)))
|
|
234
|
+
.filter((ring) => ring.length >= 3);
|
|
235
|
+
if (rings.length === 0)
|
|
236
|
+
break;
|
|
237
|
+
// Largest ring is the outer boundary; the rest render as holes.
|
|
238
|
+
let outerIdx = 0;
|
|
239
|
+
let outerArea = -1;
|
|
240
|
+
rings.forEach((ring, idx) => {
|
|
241
|
+
const area = Math.abs(ringArea(ring));
|
|
242
|
+
if (area > outerArea) {
|
|
243
|
+
outerArea = area;
|
|
244
|
+
outerIdx = idx;
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
const polygon = {
|
|
248
|
+
outer: rings[outerIdx],
|
|
249
|
+
holes: rings.filter((_, idx) => idx !== outerIdx),
|
|
250
|
+
};
|
|
251
|
+
bucket.fills.push({ polygon, color: colorOverride, pattern: !entity.solid });
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
case 'text': {
|
|
255
|
+
if (!entity.text.trim())
|
|
256
|
+
break;
|
|
257
|
+
const anchor = toWorld(state, ctx, entity.x * mirror, entity.y);
|
|
258
|
+
const rad = (entity.rotationDeg * Math.PI) / 180;
|
|
259
|
+
const tip = toWorld(state, ctx, (entity.x + Math.cos(rad)) * mirror, entity.y + Math.sin(rad));
|
|
260
|
+
let dirX = tip.x - anchor.x;
|
|
261
|
+
let dirY = tip.y - anchor.y;
|
|
262
|
+
const len = Math.hypot(dirX, dirY);
|
|
263
|
+
if (len > 1e-12) {
|
|
264
|
+
dirX /= len;
|
|
265
|
+
dirY /= len;
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
dirX = 1;
|
|
269
|
+
dirY = 0;
|
|
270
|
+
}
|
|
271
|
+
const scaleEstimate = Math.sqrt(Math.abs(ctx.m[0] * ctx.m[3] - ctx.m[1] * ctx.m[2]));
|
|
272
|
+
const text = {
|
|
273
|
+
position: anchor,
|
|
274
|
+
text: entity.text,
|
|
275
|
+
height: entity.height * scaleEstimate * state.unitScale,
|
|
276
|
+
dirX,
|
|
277
|
+
dirY,
|
|
278
|
+
align: entity.hAlign,
|
|
279
|
+
valign: entity.vAlign,
|
|
280
|
+
color: colorOverride,
|
|
281
|
+
};
|
|
282
|
+
bucket.texts.push(text);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
case 'insert':
|
|
286
|
+
emitInsert(entity, ctx, state, effLayerName, color);
|
|
287
|
+
break;
|
|
288
|
+
case 'dimension': {
|
|
289
|
+
const block = entity.blockName ? state.doc.blocks.get(entity.blockName) : undefined;
|
|
290
|
+
if (!block) {
|
|
291
|
+
state.doc.skipped['DIMENSION'] = (state.doc.skipped['DIMENSION'] ?? 0) + 1;
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
if (ctx.depth >= MAX_BLOCK_DEPTH || ctx.stack.includes(block.name))
|
|
295
|
+
break;
|
|
296
|
+
// Dimension block geometry is already in the dimension's WCS.
|
|
297
|
+
emitEntities(block.entities, {
|
|
298
|
+
m: ctx.m,
|
|
299
|
+
byBlockColor: color,
|
|
300
|
+
insertLayer: effLayerName,
|
|
301
|
+
depth: ctx.depth + 1,
|
|
302
|
+
stack: [...ctx.stack, block.name],
|
|
303
|
+
}, state);
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function emitInsert(entity, ctx, state, effLayerName, resolvedColor) {
|
|
310
|
+
const block = state.doc.blocks.get(entity.blockName);
|
|
311
|
+
if (!block) {
|
|
312
|
+
state.warnings.push(`INSERT references missing block "${entity.blockName}".`);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (ctx.depth >= MAX_BLOCK_DEPTH) {
|
|
316
|
+
state.warnings.push(`Block nesting deeper than ${MAX_BLOCK_DEPTH} levels; "${entity.blockName}" truncated.`);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (ctx.stack.includes(entity.blockName)) {
|
|
320
|
+
state.warnings.push(`Recursive block reference "${entity.blockName}" skipped.`);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const mirror = entity.extrusionZ < 0 ? -1 : 1;
|
|
324
|
+
const cols = Math.min(entity.columnCount, 1024);
|
|
325
|
+
const rows = Math.min(entity.rowCount, 1024);
|
|
326
|
+
for (let row = 0; row < rows; row++) {
|
|
327
|
+
for (let col = 0; col < cols; col++) {
|
|
328
|
+
if (state.instanceCount >= MAX_BLOCK_INSTANCES) {
|
|
329
|
+
if (!state.instanceCapHit) {
|
|
330
|
+
state.instanceCapHit = true;
|
|
331
|
+
state.warnings.push(`Block instance limit (${MAX_BLOCK_INSTANCES}) reached; remaining inserts ignored.`);
|
|
332
|
+
}
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
state.instanceCount++;
|
|
336
|
+
// insert translation ∘ rotation ∘ scale ∘ grid offset ∘ base-point shift
|
|
337
|
+
let local = matTRS(entity.x * mirror, entity.y, mirror < 0 ? -entity.rotationDeg : entity.rotationDeg, entity.scaleX * mirror, entity.scaleY);
|
|
338
|
+
if (col !== 0 || row !== 0) {
|
|
339
|
+
local = matMultiply(local, matTranslate(col * entity.columnSpacing, row * entity.rowSpacing));
|
|
340
|
+
}
|
|
341
|
+
local = matMultiply(local, matTranslate(-block.baseX, -block.baseY));
|
|
342
|
+
emitEntities(block.entities, {
|
|
343
|
+
m: matMultiply(ctx.m, local),
|
|
344
|
+
byBlockColor: resolvedColor,
|
|
345
|
+
insertLayer: effLayerName,
|
|
346
|
+
depth: ctx.depth + 1,
|
|
347
|
+
stack: [...ctx.stack, entity.blockName],
|
|
348
|
+
}, state);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function ringArea(ring) {
|
|
353
|
+
let area = 0;
|
|
354
|
+
for (let i = 0; i < ring.length; i++) {
|
|
355
|
+
const a = ring[i];
|
|
356
|
+
const b = ring[(i + 1) % ring.length];
|
|
357
|
+
area += a.x * b.y - b.x * a.y;
|
|
358
|
+
}
|
|
359
|
+
return area / 2;
|
|
360
|
+
}
|
|
361
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
362
|
+
// PLACEMENT
|
|
363
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
364
|
+
/**
|
|
365
|
+
* Apply a user placement to an underlay point in DRAWING space — i.e.
|
|
366
|
+
* after the world → drawing mapping (`x_d = x - shiftX`,
|
|
367
|
+
* `y_d = -(y - shiftY)` for a plan view). Rotation is counter-clockwise
|
|
368
|
+
* as seen on the plan (drawing space renders with +y downward on screen,
|
|
369
|
+
* hence the transposed rotation matrix).
|
|
370
|
+
*/
|
|
371
|
+
export function applyDxfPlacement(p, placement) {
|
|
372
|
+
const rad = (placement.rotationDeg * Math.PI) / 180;
|
|
373
|
+
const c = Math.cos(rad);
|
|
374
|
+
const s = Math.sin(rad);
|
|
375
|
+
const x = p.x * placement.scale;
|
|
376
|
+
const y = p.y * placement.scale;
|
|
377
|
+
return {
|
|
378
|
+
x: x * c + y * s + placement.offsetX,
|
|
379
|
+
y: -x * s + y * c + placement.offsetY,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../../src/dxf/convert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Geometry helpers for DXF import: arc/bulge tessellation and 2D affine
|
|
3
|
+
* transforms. Shared by the parser (HATCH edge paths) and the converter
|
|
4
|
+
* (entity tessellation, block expansion).
|
|
5
|
+
*/
|
|
6
|
+
import type { DxfVertex } from './types.js';
|
|
7
|
+
export declare function arcSegmentCount(sweepRad: number): number;
|
|
8
|
+
/**
|
|
9
|
+
* Sample a circular arc from `startDeg` to `endDeg` (degrees, CCW from +X).
|
|
10
|
+
* When `endDeg <= startDeg` the arc wraps through 360 (DXF convention).
|
|
11
|
+
* Includes both endpoints.
|
|
12
|
+
*/
|
|
13
|
+
export declare function sampleArc(cx: number, cy: number, r: number, startDeg: number, endDeg: number): Array<{
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
}>;
|
|
17
|
+
/** Sample a full circle (closed loop; last point NOT repeated). */
|
|
18
|
+
export declare function sampleCircle(cx: number, cy: number, r: number): Array<{
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* Sample an elliptical arc. `startParam`/`endParam` are parametric angles in
|
|
24
|
+
* radians; the point at parameter t is `c + major·cos(t) + minor·sin(t)`
|
|
25
|
+
* where `minor = ratio · perp(major)`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function sampleEllipse(cx: number, cy: number, majorX: number, majorY: number, ratio: number, startParam: number, endParam: number): Array<{
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Expand a polyline vertex loop with bulges into a flat point list.
|
|
33
|
+
* A bulge b = tan(sweep/4) describes the arc from a vertex to the next one
|
|
34
|
+
* (positive = CCW). Closed loops also expand the bulge of the last vertex
|
|
35
|
+
* (arc back to the first). Includes the first point; for closed loops the
|
|
36
|
+
* first point is not repeated at the end.
|
|
37
|
+
*/
|
|
38
|
+
export declare function expandBulgedVertices(vertices: DxfVertex[], closed: boolean): Array<{
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* Sample a SPLINE entity as a polyline. Fit points win when present (they
|
|
44
|
+
* lie on the curve); otherwise a clamped B-spline is evaluated with de
|
|
45
|
+
* Boor's algorithm. Degenerate knot vectors fall back to the control
|
|
46
|
+
* polygon.
|
|
47
|
+
*/
|
|
48
|
+
export declare function tessellateSpline(degree: number, knots: number[], controlPoints: Array<{
|
|
49
|
+
x: number;
|
|
50
|
+
y: number;
|
|
51
|
+
}>, fitPoints: Array<{
|
|
52
|
+
x: number;
|
|
53
|
+
y: number;
|
|
54
|
+
}>, segmentsPerSpan?: number): Array<{
|
|
55
|
+
x: number;
|
|
56
|
+
y: number;
|
|
57
|
+
}>;
|
|
58
|
+
/** Column-major 2D affine: x' = a·x + c·y + tx, y' = b·x + d·y + ty. */
|
|
59
|
+
export type Mat2d = [number, number, number, number, number, number];
|
|
60
|
+
export declare const MAT_IDENTITY: Mat2d;
|
|
61
|
+
/** Compose so that `m2` is applied first, then `m1`. */
|
|
62
|
+
export declare function matMultiply(m1: Mat2d, m2: Mat2d): Mat2d;
|
|
63
|
+
export declare function matApply(m: Mat2d, x: number, y: number): {
|
|
64
|
+
x: number;
|
|
65
|
+
y: number;
|
|
66
|
+
};
|
|
67
|
+
/** translate(tx,ty) ∘ rotate(deg CCW) ∘ scale(sx,sy). */
|
|
68
|
+
export declare function matTRS(tx: number, ty: number, rotationDeg: number, sx: number, sy: number): Mat2d;
|
|
69
|
+
export declare function matTranslate(tx: number, ty: number): Mat2d;
|
|
70
|
+
//# sourceMappingURL=geom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geom.d.ts","sourceRoot":"","sources":["../../src/dxf/geom.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAO5C,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,MAAM,EACT,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAYjC;AAED,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAQ/F;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAejC;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,SAAS,EAAE,EACrB,MAAM,EAAE,OAAO,GACd,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAiDjC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EAAE,EACf,aAAa,EAAE,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAC9C,SAAS,EAAE,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAC1C,eAAe,SAAI,GAClB,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAmBjC;AAoCD,wEAAwE;AACxE,MAAM,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAErE,eAAO,MAAM,YAAY,EAAE,KAA0B,CAAC;AAEtD,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,GAAG,KAAK,CASvD;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAEjF;AAED,yDAAyD;AACzD,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,KAAK,CAKjG;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,KAAK,CAE1D"}
|