lineadraw 0.10.0 → 0.11.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 +18 -7
- package/bin/lineadraw.mjs +60 -10
- package/dist/bridge.d.ts +1 -0
- package/dist/bridge.js +1 -1
- package/dist/{chunk-YYJAXJOY.js → chunk-7UFXC7OI.js} +1680 -141
- package/dist/chunk-7UFXC7OI.js.map +1 -0
- package/dist/chunk-FDLANLIC.js +1161 -0
- package/dist/chunk-FDLANLIC.js.map +1 -0
- package/dist/chunk-M3EDRSHW.js +81 -0
- package/dist/chunk-M3EDRSHW.js.map +1 -0
- package/dist/chunk-MYP7RUYK.js +9 -0
- package/dist/chunk-MYP7RUYK.js.map +1 -0
- package/dist/{chunk-L2CWZAKW.js → chunk-RNA2RDGL.js} +13 -6
- package/dist/chunk-RNA2RDGL.js.map +1 -0
- package/dist/dist-56K6CNML.js +188 -0
- package/dist/dist-56K6CNML.js.map +1 -0
- package/dist/dist-IEN64QSV.js +10 -0
- package/dist/dist-IEN64QSV.js.map +1 -0
- package/dist/emscripten-module-Q67P5WYC-ITCU5LXL.js +2424 -0
- package/dist/emscripten-module-Q67P5WYC-ITCU5LXL.js.map +1 -0
- package/dist/{exportDxf-C4CLQCC3.js → exportDxf-6XTXQ4XN.js} +2 -2
- package/dist/ffi-SHMEF5YV.js +82 -0
- package/dist/ffi-SHMEF5YV.js.map +1 -0
- package/dist/module-ES6BEMUI-BJFWC656.js +14 -0
- package/dist/module-ES6BEMUI-BJFWC656.js.map +1 -0
- package/dist/module-asyncify-2EFITU5U-7F5WZXRA.js +9 -0
- package/dist/module-asyncify-2EFITU5U-7F5WZXRA.js.map +1 -0
- package/dist/sdk.d.ts +868 -95
- package/dist/sdk.js +619 -558
- package/dist/sdk.js.map +1 -1
- package/lineadraw.d.ts +162 -8
- package/package.json +2 -2
- package/dist/chunk-L2CWZAKW.js.map +0 -1
- package/dist/chunk-YYJAXJOY.js.map +0 -1
- /package/dist/{exportDxf-C4CLQCC3.js.map → exportDxf-6XTXQ4XN.js.map} +0 -0
package/dist/sdk.js
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BridgeError,
|
|
3
|
-
DEFAULT_BRIDGE_PORT,
|
|
4
|
-
bridgeFilePath,
|
|
5
|
-
connectEditors,
|
|
6
|
-
createBridge
|
|
7
|
-
} from "./chunk-L2CWZAKW.js";
|
|
8
1
|
import {
|
|
9
2
|
ADVANCE_TABLES,
|
|
10
3
|
ANSI31_BASE_SPACING,
|
|
@@ -13,6 +6,7 @@ import {
|
|
|
13
6
|
ColorSchema,
|
|
14
7
|
DEFAULT_DIM_STYLE,
|
|
15
8
|
DEFAULT_TEXT_STYLE,
|
|
9
|
+
DimStyleOverrideSchema,
|
|
16
10
|
DimStyleSchema,
|
|
17
11
|
EXTRACTED_EXTRAS,
|
|
18
12
|
EXTRACTED_RANGES,
|
|
@@ -24,18 +18,28 @@ import {
|
|
|
24
18
|
PX_TO_MM,
|
|
25
19
|
REAL_FACES,
|
|
26
20
|
REFERENCE_FORMATS,
|
|
21
|
+
TextStyleOverrideSchema,
|
|
27
22
|
TextStyleSchema,
|
|
28
23
|
Vec2Schema,
|
|
29
24
|
aciToHex,
|
|
30
25
|
acquireInputTable,
|
|
31
26
|
add,
|
|
32
27
|
angle,
|
|
28
|
+
angleInArc,
|
|
33
29
|
approximateTextMeasurer,
|
|
30
|
+
arcEndPoint,
|
|
31
|
+
arcFrom3Points,
|
|
32
|
+
arcMidPoint,
|
|
33
|
+
arcStartPoint,
|
|
34
|
+
arcSweep,
|
|
34
35
|
arcToBeziers,
|
|
36
|
+
arrowLineStart,
|
|
35
37
|
assertKnownStyleOverrideKeys,
|
|
36
38
|
blockDefinitionExists,
|
|
37
39
|
blockPivot,
|
|
38
40
|
blockScriptId,
|
|
41
|
+
bulgeFrom3Points,
|
|
42
|
+
bulgeToArc,
|
|
39
43
|
bytesToDataUrl,
|
|
40
44
|
checkNamedInputs,
|
|
41
45
|
cleanRichText,
|
|
@@ -43,6 +47,7 @@ import {
|
|
|
43
47
|
closestPointOnSegment,
|
|
44
48
|
computeHatchLines,
|
|
45
49
|
computePatternGeometry,
|
|
50
|
+
curveTolerance,
|
|
46
51
|
dataUrlBytes,
|
|
47
52
|
decodeTextEscapes,
|
|
48
53
|
dimFontFace,
|
|
@@ -51,6 +56,7 @@ import {
|
|
|
51
56
|
dimensionRawToLabels,
|
|
52
57
|
dimensionRawToOffset,
|
|
53
58
|
dist,
|
|
59
|
+
distToArc,
|
|
54
60
|
documentBlocks,
|
|
55
61
|
documentObjectResolver,
|
|
56
62
|
dot,
|
|
@@ -59,10 +65,12 @@ import {
|
|
|
59
65
|
effectiveTextFont,
|
|
60
66
|
ellipseArcToBeziers,
|
|
61
67
|
embeddedAssetId,
|
|
68
|
+
emitLoopPath,
|
|
62
69
|
ensureScriptTranspiler,
|
|
63
70
|
estimatePatternSegments,
|
|
64
71
|
executeScriptModule,
|
|
65
72
|
expandWithBlockDependents,
|
|
73
|
+
findBlockScript,
|
|
66
74
|
fontFace,
|
|
67
75
|
fontFromDxfStyle,
|
|
68
76
|
fromAngle,
|
|
@@ -73,6 +81,8 @@ import {
|
|
|
73
81
|
getHatchPattern,
|
|
74
82
|
getLineType,
|
|
75
83
|
hashAsset,
|
|
84
|
+
hatchArea,
|
|
85
|
+
hatchLoop,
|
|
76
86
|
hatchPatternKey,
|
|
77
87
|
hexToRgb,
|
|
78
88
|
hostedClosure,
|
|
@@ -80,14 +90,20 @@ import {
|
|
|
80
90
|
inputLabel,
|
|
81
91
|
inputPoints,
|
|
82
92
|
inputRefs,
|
|
93
|
+
interpolateClosed,
|
|
94
|
+
interpolateFitPoints,
|
|
83
95
|
invalidateBlockCache,
|
|
84
96
|
isRequiredInput,
|
|
97
|
+
isValidNurbs,
|
|
85
98
|
len,
|
|
86
99
|
lineSegments,
|
|
87
100
|
lineTypeKey,
|
|
88
101
|
lineWeightToMm,
|
|
89
102
|
linearAxis,
|
|
90
103
|
listBlockMeta,
|
|
104
|
+
loopCorners,
|
|
105
|
+
loopCurves,
|
|
106
|
+
loopPolygon,
|
|
91
107
|
mapInputValues,
|
|
92
108
|
matApply,
|
|
93
109
|
matIdentity,
|
|
@@ -97,15 +113,19 @@ import {
|
|
|
97
113
|
mirrorObject,
|
|
98
114
|
mtextFontFlags,
|
|
99
115
|
mtextWidthFactor,
|
|
100
|
-
norm,
|
|
101
116
|
normAngle,
|
|
102
117
|
normalizeSpans,
|
|
118
|
+
nurbsToBeziers,
|
|
119
|
+
onSandboxReset,
|
|
120
|
+
paintArrowhead,
|
|
103
121
|
paramMismatch,
|
|
104
122
|
parseFontFace,
|
|
105
123
|
parseInputTable,
|
|
106
124
|
parseParamsExport,
|
|
107
125
|
perp,
|
|
126
|
+
pointOnArc,
|
|
108
127
|
realFace,
|
|
128
|
+
releaseScriptModule,
|
|
109
129
|
remapBlockInputRefs,
|
|
110
130
|
renderDashes,
|
|
111
131
|
resolveDocumentObject,
|
|
@@ -115,14 +135,17 @@ import {
|
|
|
115
135
|
rgbToHex,
|
|
116
136
|
richTextBlock,
|
|
117
137
|
rotateObject,
|
|
138
|
+
sampleNurbs,
|
|
118
139
|
scale,
|
|
119
140
|
scaleObjectUniform,
|
|
120
141
|
scanScriptId,
|
|
121
142
|
scriptTranspilerReady,
|
|
122
143
|
selectionFits,
|
|
123
144
|
signedArcSweep,
|
|
145
|
+
splineThrough,
|
|
124
146
|
sub,
|
|
125
147
|
tableLayout,
|
|
148
|
+
tessellateArc,
|
|
126
149
|
testBlockDefinition,
|
|
127
150
|
textArrowSize,
|
|
128
151
|
textArrowType,
|
|
@@ -134,108 +157,25 @@ import {
|
|
|
134
157
|
textWidth,
|
|
135
158
|
translateObject,
|
|
136
159
|
valueParams,
|
|
160
|
+
verticesToLoop,
|
|
137
161
|
withEmptyLists
|
|
138
|
-
} from "./chunk-
|
|
162
|
+
} from "./chunk-7UFXC7OI.js";
|
|
139
163
|
import {
|
|
140
164
|
embeddedPdfFonts
|
|
141
165
|
} from "./chunk-L4FNH35X.js";
|
|
166
|
+
import {
|
|
167
|
+
BridgeError,
|
|
168
|
+
DEFAULT_BRIDGE_PORT,
|
|
169
|
+
bridgeFilePath,
|
|
170
|
+
connectEditors,
|
|
171
|
+
createBridge
|
|
172
|
+
} from "./chunk-RNA2RDGL.js";
|
|
142
173
|
import "./chunk-PZ5AY32C.js";
|
|
143
174
|
|
|
144
175
|
// src/document.ts
|
|
145
176
|
import { readFile, writeFile } from "fs/promises";
|
|
146
177
|
import { dirname, isAbsolute, resolve } from "path";
|
|
147
178
|
|
|
148
|
-
// ../core/src/geometry/arcs.ts
|
|
149
|
-
var arcSweep = (a) => {
|
|
150
|
-
const s = normAngle(a.endAngle - a.startAngle);
|
|
151
|
-
return s === 0 ? Math.PI * 2 : s;
|
|
152
|
-
};
|
|
153
|
-
var pointOnArc = (a, angle2) => ({
|
|
154
|
-
x: a.center.x + Math.cos(angle2) * a.radius,
|
|
155
|
-
y: a.center.y + Math.sin(angle2) * a.radius
|
|
156
|
-
});
|
|
157
|
-
var arcStartPoint = (a) => pointOnArc(a, a.startAngle);
|
|
158
|
-
var arcEndPoint = (a) => pointOnArc(a, a.endAngle);
|
|
159
|
-
var arcMidPoint = (a) => pointOnArc(a, a.startAngle + arcSweep(a) / 2);
|
|
160
|
-
var angleInArc = (a, angle2) => normAngle(angle2 - a.startAngle) <= arcSweep(a) + 1e-12;
|
|
161
|
-
var bulgeToArc = (a, b, bulge) => {
|
|
162
|
-
if (Math.abs(bulge) < 1e-12) return null;
|
|
163
|
-
const chord = dist(a, b);
|
|
164
|
-
if (chord < 1e-12) return null;
|
|
165
|
-
const sweep = 4 * Math.atan(bulge);
|
|
166
|
-
const radius = Math.abs(chord / (2 * Math.sin(sweep / 2)));
|
|
167
|
-
const m = mid(a, b);
|
|
168
|
-
const dir = scale(sub(b, a), 1 / chord);
|
|
169
|
-
const h = chord / 2 / Math.tan(sweep / 2);
|
|
170
|
-
const center = add(m, scale(perp(dir), h));
|
|
171
|
-
const angA = angle(sub(a, center));
|
|
172
|
-
const angB = angle(sub(b, center));
|
|
173
|
-
return bulge > 0 ? { center, radius, startAngle: angA, endAngle: angB } : { center, radius, startAngle: angB, endAngle: angA };
|
|
174
|
-
};
|
|
175
|
-
var bulgeFrom3Points = (a, m, b) => {
|
|
176
|
-
let turn = angle(sub(b, m)) - angle(sub(m, a));
|
|
177
|
-
while (turn > Math.PI) turn -= 2 * Math.PI;
|
|
178
|
-
while (turn < -Math.PI) turn += 2 * Math.PI;
|
|
179
|
-
return Math.tan(turn / 2);
|
|
180
|
-
};
|
|
181
|
-
var circleFrom3Points = (p1, p2, p3) => {
|
|
182
|
-
const ax = p1.x;
|
|
183
|
-
const ay = p1.y;
|
|
184
|
-
const bx = p2.x;
|
|
185
|
-
const by = p2.y;
|
|
186
|
-
const cx = p3.x;
|
|
187
|
-
const cy = p3.y;
|
|
188
|
-
const d = 2 * (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by));
|
|
189
|
-
if (Math.abs(d) < 1e-12) return null;
|
|
190
|
-
const a2 = ax * ax + ay * ay;
|
|
191
|
-
const b2 = bx * bx + by * by;
|
|
192
|
-
const c2 = cx * cx + cy * cy;
|
|
193
|
-
const center = {
|
|
194
|
-
x: (a2 * (by - cy) + b2 * (cy - ay) + c2 * (ay - by)) / d,
|
|
195
|
-
y: (a2 * (cx - bx) + b2 * (ax - cx) + c2 * (bx - ax)) / d
|
|
196
|
-
};
|
|
197
|
-
return { center, radius: dist(center, p1) };
|
|
198
|
-
};
|
|
199
|
-
var arcFrom3Points = (start, on, end) => {
|
|
200
|
-
const c = circleFrom3Points(start, on, end);
|
|
201
|
-
if (!c) return null;
|
|
202
|
-
const angS = angle(sub(start, c.center));
|
|
203
|
-
const angO = angle(sub(on, c.center));
|
|
204
|
-
const angE = angle(sub(end, c.center));
|
|
205
|
-
const ccw = {
|
|
206
|
-
center: c.center,
|
|
207
|
-
radius: c.radius,
|
|
208
|
-
startAngle: angS,
|
|
209
|
-
endAngle: angE
|
|
210
|
-
};
|
|
211
|
-
if (angleInArc(ccw, angO)) return ccw;
|
|
212
|
-
return {
|
|
213
|
-
center: c.center,
|
|
214
|
-
radius: c.radius,
|
|
215
|
-
startAngle: angE,
|
|
216
|
-
endAngle: angS
|
|
217
|
-
};
|
|
218
|
-
};
|
|
219
|
-
var closestPointOnArc = (a, p) => {
|
|
220
|
-
const v = sub(p, a.center);
|
|
221
|
-
const ang = angle(v);
|
|
222
|
-
if (angleInArc(a, ang)) return pointOnArc(a, ang);
|
|
223
|
-
const s = arcStartPoint(a);
|
|
224
|
-
const e = arcEndPoint(a);
|
|
225
|
-
return dist(p, s) <= dist(p, e) ? s : e;
|
|
226
|
-
};
|
|
227
|
-
var distToArc = (a, p) => dist(p, closestPointOnArc(a, p));
|
|
228
|
-
var tessellateArc = (a, chordTolerance = 0.1) => {
|
|
229
|
-
const sweep = arcSweep(a);
|
|
230
|
-
const maxStep = a.radius <= chordTolerance ? sweep : 2 * Math.acos(Math.max(-1, 1 - chordTolerance / a.radius));
|
|
231
|
-
const n2 = Math.max(2, Math.ceil(sweep / Math.max(maxStep, 1e-3)));
|
|
232
|
-
const pts = [];
|
|
233
|
-
for (let i = 0; i <= n2; i++) {
|
|
234
|
-
pts.push(pointOnArc(a, a.startAngle + sweep * i / n2));
|
|
235
|
-
}
|
|
236
|
-
return pts;
|
|
237
|
-
};
|
|
238
|
-
|
|
239
179
|
// ../core/src/geometry/ellipse.ts
|
|
240
180
|
var ellipseSweep = (e) => {
|
|
241
181
|
const s = normAngle(e.endAngle - e.startAngle);
|
|
@@ -353,12 +293,6 @@ var chainLength = (points, closed) => {
|
|
|
353
293
|
return sum;
|
|
354
294
|
};
|
|
355
295
|
var polylineArea = (points) => polygonArea(verticesToPolygon(points));
|
|
356
|
-
var hatchArea = (loops) => {
|
|
357
|
-
const areas = loops.map((l) => polygonArea(verticesToPolygon(l.points)));
|
|
358
|
-
if (areas.length === 0) return 0;
|
|
359
|
-
const holes = areas.slice(1).reduce((a, b) => a + b, 0);
|
|
360
|
-
return Math.max(areas[0] - holes, 0);
|
|
361
|
-
};
|
|
362
296
|
|
|
363
297
|
// ../core/src/model/document.ts
|
|
364
298
|
import { z as z2 } from "zod";
|
|
@@ -366,11 +300,13 @@ import { z as z2 } from "zod";
|
|
|
366
300
|
// ../core/src/model/paperLayout.ts
|
|
367
301
|
import { z } from "zod";
|
|
368
302
|
var SHEET_PRESETS = {
|
|
303
|
+
A5: [148, 210],
|
|
369
304
|
A4: [210, 297],
|
|
370
305
|
A3: [297, 420],
|
|
371
306
|
A2: [420, 594],
|
|
372
307
|
A1: [594, 841],
|
|
373
|
-
A0: [841, 1189]
|
|
308
|
+
A0: [841, 1189],
|
|
309
|
+
Letter: [215.9, 279.4]
|
|
374
310
|
};
|
|
375
311
|
var resolveSheetSize = (sheet = "A3", defaultOrientation = "landscape") => {
|
|
376
312
|
if (typeof sheet !== "string" && "width" in sheet)
|
|
@@ -421,7 +357,8 @@ var LayerSchema = z2.object({
|
|
|
421
357
|
});
|
|
422
358
|
var DEFAULT_DOCUMENT_NAME = "Untitled project";
|
|
423
359
|
var DocumentSettingsSchema = z2.object({
|
|
424
|
-
units: z2.enum(["mm", "in"]).default("mm")
|
|
360
|
+
units: z2.enum(["mm", "in"]).default("mm"),
|
|
361
|
+
modelScale: z2.number().positive().default(1)
|
|
425
362
|
});
|
|
426
363
|
var LineaDocumentSchema = z2.preprocess(
|
|
427
364
|
migrateDocument,
|
|
@@ -438,7 +375,7 @@ var LineaDocumentSchema = z2.preprocess(
|
|
|
438
375
|
/** Document-wide settings (`DocumentSettingsSchema`). `units` is
|
|
439
376
|
* declarative for now: geometry is always stored in mm and nothing
|
|
440
377
|
* renders in inches yet. */
|
|
441
|
-
settings: DocumentSettingsSchema.default({ units: "mm" }),
|
|
378
|
+
settings: DocumentSettingsSchema.default({ units: "mm", modelScale: 1 }),
|
|
442
379
|
layers: z2.array(LayerSchema).min(1),
|
|
443
380
|
currentLayerId: z2.string(),
|
|
444
381
|
/** Array order is draw order (bottom to top).
|
|
@@ -672,10 +609,10 @@ var SvgSink = class {
|
|
|
672
609
|
transforms.push(
|
|
673
610
|
`translate(${n(tp.x)} ${n(-tp.y)}) scale(${n(w)} 1) translate(${n(-tp.x)} ${n(tp.y)})`
|
|
674
611
|
);
|
|
675
|
-
const
|
|
612
|
+
const rot = transforms.length > 0 ? ` transform="${transforms.join(" ")}"` : "";
|
|
676
613
|
const alpha = t.opacity !== void 0 && t.opacity < 1 ? ` fill-opacity="${n(t.opacity)}"` : "";
|
|
677
614
|
this.els.push(
|
|
678
|
-
`<text x="${n(tp.x)}" y="${n(-tp.y)}" font-size="${n(t.heightMm / def.capHeight * scale2)}" font-family="${def.cssStack}"${face} fill="${t.color}"${alpha} text-anchor="${anchor}"${
|
|
615
|
+
`<text x="${n(tp.x)}" y="${n(-tp.y)}" font-size="${n(t.heightMm / def.capHeight * scale2)}" font-family="${def.cssStack}"${face} fill="${t.color}"${alpha} text-anchor="${anchor}"${rot}>${escapeXml(t.text)}</text>`
|
|
679
616
|
);
|
|
680
617
|
}
|
|
681
618
|
measureText(text, heightMm, font, widthFactor) {
|
|
@@ -690,10 +627,10 @@ var SvgSink = class {
|
|
|
690
627
|
});
|
|
691
628
|
const scale2 = Math.hypot(this.m[0], this.m[1]) || 1;
|
|
692
629
|
const deg = -i.rotation * 180 / Math.PI;
|
|
693
|
-
const
|
|
630
|
+
const rot = deg !== 0 ? ` transform="rotate(${n(deg)} ${n(topLeft.x)} ${n(-topLeft.y)})"` : "";
|
|
694
631
|
const opacity = i.opacity < 1 ? ` opacity="${n(i.opacity)}"` : "";
|
|
695
632
|
this.els.push(
|
|
696
|
-
`<image x="${n(topLeft.x)}" y="${n(-topLeft.y)}" width="${n(i.widthMm * scale2)}" height="${n(i.heightMm * scale2)}" preserveAspectRatio="none"${opacity}${
|
|
633
|
+
`<image x="${n(topLeft.x)}" y="${n(-topLeft.y)}" width="${n(i.widthMm * scale2)}" height="${n(i.heightMm * scale2)}" preserveAspectRatio="none"${opacity}${rot} href="${i.data}"/>`
|
|
697
634
|
);
|
|
698
635
|
}
|
|
699
636
|
pushTransform(m) {
|
|
@@ -826,6 +763,22 @@ var paintEllipse = (obj, sink, env) => {
|
|
|
826
763
|
sink.stroke(env.style);
|
|
827
764
|
};
|
|
828
765
|
|
|
766
|
+
// ../core/src/paint/painters/spline.ts
|
|
767
|
+
var paintSpline = (obj, sink, env) => {
|
|
768
|
+
sink.beginPath();
|
|
769
|
+
const pieces = nurbsToBeziers(obj);
|
|
770
|
+
if (pieces && pieces.length > 0) {
|
|
771
|
+
sink.moveTo(pieces[0].start);
|
|
772
|
+
for (const b of pieces) sink.bezierTo(b.c1, b.c2, b.end);
|
|
773
|
+
} else {
|
|
774
|
+
const pts = sampleNurbs(obj, curveTolerance(obj));
|
|
775
|
+
if (pts.length < 2) return;
|
|
776
|
+
sink.moveTo(pts[0]);
|
|
777
|
+
for (let i = 1; i < pts.length; i++) sink.lineTo(pts[i]);
|
|
778
|
+
}
|
|
779
|
+
sink.stroke(env.style);
|
|
780
|
+
};
|
|
781
|
+
|
|
829
782
|
// ../core/src/paint/painters/hatch.ts
|
|
830
783
|
var SINGLE_FAMILY = {
|
|
831
784
|
name: "",
|
|
@@ -833,7 +786,7 @@ var SINGLE_FAMILY = {
|
|
|
833
786
|
};
|
|
834
787
|
var paintSolid = (obj, sink, env) => {
|
|
835
788
|
sink.beginPath();
|
|
836
|
-
for (const loop of obj.loops)
|
|
789
|
+
for (const loop of obj.loops) emitLoopPath(sink, loop);
|
|
837
790
|
sink.fill({ color: env.style.color, opacity: env.style.opacity });
|
|
838
791
|
};
|
|
839
792
|
var paintGradient = (obj, fill, sink, env) => {
|
|
@@ -842,7 +795,7 @@ var paintGradient = (obj, fill, sink, env) => {
|
|
|
842
795
|
let maxX = -Infinity;
|
|
843
796
|
let maxY = -Infinity;
|
|
844
797
|
for (const loop of obj.loops)
|
|
845
|
-
for (const p of loop
|
|
798
|
+
for (const p of loopPolygon(loop)) {
|
|
846
799
|
if (p.x < minX) minX = p.x;
|
|
847
800
|
if (p.y < minY) minY = p.y;
|
|
848
801
|
if (p.x > maxX) maxX = p.x;
|
|
@@ -865,7 +818,7 @@ var paintGradient = (obj, fill, sink, env) => {
|
|
|
865
818
|
to = { x: c.x + dir.x * r, y: c.y + dir.y * r };
|
|
866
819
|
}
|
|
867
820
|
sink.beginPath();
|
|
868
|
-
for (const loop of obj.loops)
|
|
821
|
+
for (const loop of obj.loops) emitLoopPath(sink, loop);
|
|
869
822
|
sink.fill({
|
|
870
823
|
color: fill.color1,
|
|
871
824
|
opacity: env.style.opacity,
|
|
@@ -883,7 +836,7 @@ var paintHatch = (obj, sink, env) => {
|
|
|
883
836
|
}
|
|
884
837
|
let lines = env.cache?.hatchLines.get(obj);
|
|
885
838
|
if (!lines) {
|
|
886
|
-
const rings = obj.loops.map((loop) =>
|
|
839
|
+
const rings = obj.loops.map((loop) => loopPolygon(loop));
|
|
887
840
|
const s = obj.fill.kind === "pattern" ? obj.fill.scale * obj.scale : obj.scale;
|
|
888
841
|
const pat = obj.fill.kind === "pattern" ? resolveHatchPattern(obj.fill.name, env.hatchPatterns) : void 0;
|
|
889
842
|
const estimate = pat ? estimatePatternSegments(rings, pat, s) : estimatePatternSegments(
|
|
@@ -925,50 +878,6 @@ var paintHatch = (obj, sink, env) => {
|
|
|
925
878
|
});
|
|
926
879
|
};
|
|
927
880
|
|
|
928
|
-
// ../core/src/paint/painters/arrows.ts
|
|
929
|
-
var paintArrowhead = (sink, tip, toward, size, color, type = "filled", opacity) => {
|
|
930
|
-
if (type === "none") return;
|
|
931
|
-
const dir = norm(sub(toward, tip));
|
|
932
|
-
if (dir.x === 0 && dir.y === 0) return;
|
|
933
|
-
switch (type) {
|
|
934
|
-
case "filled": {
|
|
935
|
-
const base = add(tip, scale(dir, size));
|
|
936
|
-
const half = scale(perp(dir), size / 3);
|
|
937
|
-
sink.beginPath();
|
|
938
|
-
sink.moveTo(tip);
|
|
939
|
-
sink.lineTo(add(base, half));
|
|
940
|
-
sink.lineTo(sub(base, half));
|
|
941
|
-
sink.closePath();
|
|
942
|
-
sink.fill({ color, opacity });
|
|
943
|
-
break;
|
|
944
|
-
}
|
|
945
|
-
case "open": {
|
|
946
|
-
const base = add(tip, scale(dir, size));
|
|
947
|
-
const half = scale(perp(dir), size / 3);
|
|
948
|
-
sink.beginPath();
|
|
949
|
-
sink.moveTo(add(base, half));
|
|
950
|
-
sink.lineTo(tip);
|
|
951
|
-
sink.lineTo(sub(base, half));
|
|
952
|
-
sink.stroke({ color, widthMm: Math.min(size / 10, 0.25), opacity });
|
|
953
|
-
break;
|
|
954
|
-
}
|
|
955
|
-
case "tick": {
|
|
956
|
-
const diag = scale(norm(add(dir, perp(dir))), size / 2);
|
|
957
|
-
sink.beginPath();
|
|
958
|
-
sink.moveTo(sub(tip, diag));
|
|
959
|
-
sink.lineTo(add(tip, diag));
|
|
960
|
-
sink.stroke({ color, widthMm: Math.min(size / 8, 0.35), opacity });
|
|
961
|
-
break;
|
|
962
|
-
}
|
|
963
|
-
case "dot": {
|
|
964
|
-
sink.beginPath();
|
|
965
|
-
sink.arc(tip, size / 4, 0, Math.PI * 2, true);
|
|
966
|
-
sink.fill({ color, opacity });
|
|
967
|
-
break;
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
};
|
|
971
|
-
|
|
972
881
|
// ../core/src/paint/painters/text.ts
|
|
973
882
|
var paintText = (obj, sink, env) => {
|
|
974
883
|
const { font, widthFactor } = effectiveTextFont(obj, env.textStyles);
|
|
@@ -984,18 +893,20 @@ var paintText = (obj, sink, env) => {
|
|
|
984
893
|
)
|
|
985
894
|
};
|
|
986
895
|
const { color, widthMm, opacity } = env.style;
|
|
896
|
+
const arrowSize = textArrowSize(obj, env.textStyles);
|
|
897
|
+
const arrowType = textArrowType(obj, env.textStyles);
|
|
987
898
|
for (const line of obj.leaderLines) {
|
|
988
899
|
sink.beginPath();
|
|
989
|
-
sink.moveTo(line[0]);
|
|
900
|
+
sink.moveTo(arrowLineStart(line[0], line[1], arrowSize, arrowType));
|
|
990
901
|
for (let i = 1; i < line.length; i++) sink.lineTo(line[i]);
|
|
991
902
|
sink.stroke({ color, widthMm, opacity });
|
|
992
903
|
paintArrowhead(
|
|
993
904
|
sink,
|
|
994
905
|
line[0],
|
|
995
906
|
line[1],
|
|
996
|
-
|
|
907
|
+
arrowSize,
|
|
997
908
|
color,
|
|
998
|
-
|
|
909
|
+
arrowType,
|
|
999
910
|
opacity
|
|
1000
911
|
);
|
|
1001
912
|
}
|
|
@@ -1123,15 +1034,21 @@ var paintDimension = (obj, sink, env) => {
|
|
|
1123
1034
|
dashMm: env.style.dashMm,
|
|
1124
1035
|
opacity: env.style.opacity
|
|
1125
1036
|
};
|
|
1037
|
+
const trim = (p, other) => {
|
|
1038
|
+
const arrow = geom.arrows.find(
|
|
1039
|
+
(ar) => dist(ar.tip, p) < 1e-9 && dot(sub(ar.toward, ar.tip), sub(other, p)) > 0
|
|
1040
|
+
);
|
|
1041
|
+
return arrow ? arrowLineStart(p, other, arrow.size, geom.arrowType) : p;
|
|
1042
|
+
};
|
|
1126
1043
|
sink.beginPath();
|
|
1127
|
-
for (const seg of
|
|
1128
|
-
...geom.extensionLines,
|
|
1129
|
-
...geom.dimLines,
|
|
1130
|
-
...geom.leaders
|
|
1131
|
-
]) {
|
|
1044
|
+
for (const seg of geom.extensionLines) {
|
|
1132
1045
|
sink.moveTo(seg.a);
|
|
1133
1046
|
sink.lineTo(seg.b);
|
|
1134
1047
|
}
|
|
1048
|
+
for (const seg of [...geom.dimLines, ...geom.leaders]) {
|
|
1049
|
+
sink.moveTo(trim(seg.a, seg.b));
|
|
1050
|
+
sink.lineTo(trim(seg.b, seg.a));
|
|
1051
|
+
}
|
|
1135
1052
|
if (geom.dimArc) {
|
|
1136
1053
|
const arc = geom.dimArc;
|
|
1137
1054
|
sink.moveTo(add(arc.center, scale(fromAngle(arc.startAngle), arc.radius)));
|
|
@@ -1246,7 +1163,7 @@ var paintChildren = (children, sink, env, parentLayerId) => {
|
|
|
1246
1163
|
// Same width-proportional dash rule as resolveStyle.
|
|
1247
1164
|
dashMm: scaleDash(
|
|
1248
1165
|
dashForLineType(child.lineType, env.lineTypes),
|
|
1249
|
-
(child.lineWidth ?? env.style.widthMm) * (child.lineTypeScale ?? 1)
|
|
1166
|
+
(child.lineWidth ?? env.style.widthMm) * (child.lineTypeScale ?? 1) * (env.lineTypeScale ?? 1)
|
|
1250
1167
|
) ?? env.style.dashMm,
|
|
1251
1168
|
opacity: child.opacity ?? env.style.opacity
|
|
1252
1169
|
},
|
|
@@ -1256,6 +1173,7 @@ var paintChildren = (children, sink, env, parentLayerId) => {
|
|
|
1256
1173
|
lineTypes: env.lineTypes,
|
|
1257
1174
|
hatchPatterns: env.hatchPatterns,
|
|
1258
1175
|
blockDefinitions: env.blockDefinitions,
|
|
1176
|
+
lineTypeScale: env.lineTypeScale,
|
|
1259
1177
|
resolveObject: env.resolveObject,
|
|
1260
1178
|
assets: env.assets,
|
|
1261
1179
|
// A reference child (linked / embedded file) loads like any other.
|
|
@@ -1464,6 +1382,17 @@ var buildEllipse = (obj) => {
|
|
|
1464
1382
|
]
|
|
1465
1383
|
};
|
|
1466
1384
|
};
|
|
1385
|
+
var buildSpline = (obj) => {
|
|
1386
|
+
const pts = sampleNurbs(obj, curveTolerance(obj) / 10);
|
|
1387
|
+
const segments = [];
|
|
1388
|
+
for (let i = 1; i < pts.length; i++)
|
|
1389
|
+
segments.push({ a: pts[i - 1], b: pts[i], facet: true });
|
|
1390
|
+
const points = obj.closed || pts.length < 2 ? [] : [
|
|
1391
|
+
{ p: pts[0], type: "endpoint" },
|
|
1392
|
+
{ p: pts[pts.length - 1], type: "endpoint" }
|
|
1393
|
+
];
|
|
1394
|
+
return { bounds: boundsOfPoints(pts), points, segments, arcs: [] };
|
|
1395
|
+
};
|
|
1467
1396
|
var buildHatch = (obj) => {
|
|
1468
1397
|
let bounds = emptyBounds();
|
|
1469
1398
|
const points = [];
|
|
@@ -1471,12 +1400,11 @@ var buildHatch = (obj) => {
|
|
|
1471
1400
|
const arcs = [];
|
|
1472
1401
|
const rings = [];
|
|
1473
1402
|
for (const loop of obj.loops) {
|
|
1474
|
-
const curves =
|
|
1403
|
+
const curves = loopCurves(loop);
|
|
1475
1404
|
segments.push(...curves.segments);
|
|
1476
1405
|
arcs.push(...curves.arcs);
|
|
1477
|
-
for (const
|
|
1478
|
-
|
|
1479
|
-
rings.push(verticesToPolygon(loop.points));
|
|
1406
|
+
for (const p of loopCorners(loop)) points.push({ p, type: "endpoint" });
|
|
1407
|
+
rings.push(loopPolygon(loop));
|
|
1480
1408
|
bounds = unionBounds(bounds, curveBounds(curves.segments, curves.arcs));
|
|
1481
1409
|
}
|
|
1482
1410
|
return { bounds, points, segments, arcs, rings };
|
|
@@ -1662,6 +1590,8 @@ var buildEntry = (obj, ctx) => {
|
|
|
1662
1590
|
}
|
|
1663
1591
|
case "ellipse":
|
|
1664
1592
|
return buildEllipse(obj);
|
|
1593
|
+
case "spline":
|
|
1594
|
+
return buildSpline(obj);
|
|
1665
1595
|
case "hatch":
|
|
1666
1596
|
return buildHatch(obj);
|
|
1667
1597
|
case "text":
|
|
@@ -1825,7 +1755,8 @@ var referenceEntry = (obj, ctx) => {
|
|
|
1825
1755
|
segments.push({
|
|
1826
1756
|
a: applyMat(m, kept[0]),
|
|
1827
1757
|
b: applyMat(m, kept[1]),
|
|
1828
|
-
chord: seg.chord
|
|
1758
|
+
chord: seg.chord,
|
|
1759
|
+
facet: seg.facet
|
|
1829
1760
|
});
|
|
1830
1761
|
}
|
|
1831
1762
|
for (const a of e.arcs) {
|
|
@@ -2061,174 +1992,6 @@ var mergeStyles = (existing, incoming, same, opts) => {
|
|
|
2061
1992
|
return { styles, idByName, created };
|
|
2062
1993
|
};
|
|
2063
1994
|
|
|
2064
|
-
// ../core/src/geometry/nurbs.ts
|
|
2065
|
-
var nurbsDomain = (c) => {
|
|
2066
|
-
const n2 = c.controlPoints.length;
|
|
2067
|
-
return [c.knots[c.degree], c.knots[n2]];
|
|
2068
|
-
};
|
|
2069
|
-
var findSpan = (c, u) => {
|
|
2070
|
-
const n2 = c.controlPoints.length;
|
|
2071
|
-
const p = c.degree;
|
|
2072
|
-
if (u >= c.knots[n2]) return n2 - 1;
|
|
2073
|
-
if (u <= c.knots[p]) return p;
|
|
2074
|
-
let lo = p;
|
|
2075
|
-
let hi = n2;
|
|
2076
|
-
let mid2 = lo + hi >> 1;
|
|
2077
|
-
while (u < c.knots[mid2] || u >= c.knots[mid2 + 1]) {
|
|
2078
|
-
if (u < c.knots[mid2]) hi = mid2;
|
|
2079
|
-
else lo = mid2;
|
|
2080
|
-
mid2 = lo + hi >> 1;
|
|
2081
|
-
}
|
|
2082
|
-
return mid2;
|
|
2083
|
-
};
|
|
2084
|
-
var evaluateNurbs = (c, u) => {
|
|
2085
|
-
const p = c.degree;
|
|
2086
|
-
const k = findSpan(c, u);
|
|
2087
|
-
const d = [];
|
|
2088
|
-
for (let j = 0; j <= p; j++) {
|
|
2089
|
-
const i = k - p + j;
|
|
2090
|
-
const cp = c.controlPoints[i];
|
|
2091
|
-
const w2 = c.weights?.[i] ?? 1;
|
|
2092
|
-
d.push([cp.x * w2, cp.y * w2, w2]);
|
|
2093
|
-
}
|
|
2094
|
-
for (let r = 1; r <= p; r++)
|
|
2095
|
-
for (let j = p; j >= r; j--) {
|
|
2096
|
-
const i = k - p + j;
|
|
2097
|
-
const den = c.knots[i + p - r + 1] - c.knots[i];
|
|
2098
|
-
const a = den === 0 ? 0 : (u - c.knots[i]) / den;
|
|
2099
|
-
d[j] = [
|
|
2100
|
-
(1 - a) * d[j - 1][0] + a * d[j][0],
|
|
2101
|
-
(1 - a) * d[j - 1][1] + a * d[j][1],
|
|
2102
|
-
(1 - a) * d[j - 1][2] + a * d[j][2]
|
|
2103
|
-
];
|
|
2104
|
-
}
|
|
2105
|
-
const [x, y, w] = d[p];
|
|
2106
|
-
return w === 0 ? { x, y } : { x: x / w, y: y / w };
|
|
2107
|
-
};
|
|
2108
|
-
var isValidNurbs = (c) => c.degree >= 1 && c.controlPoints.length > c.degree && c.knots.length === c.controlPoints.length + c.degree + 1 && (c.weights === void 0 || c.weights.length === c.controlPoints.length) && c.knots.every((v, i) => i === 0 || v >= c.knots[i - 1]);
|
|
2109
|
-
var sampleNurbs = (c, tolerance, maxDepth = 10) => {
|
|
2110
|
-
const [u0, u1] = nurbsDomain(c);
|
|
2111
|
-
const out = [evaluateNurbs(c, u0)];
|
|
2112
|
-
const push = (q) => {
|
|
2113
|
-
const last = out[out.length - 1];
|
|
2114
|
-
if (Math.hypot(q.x - last.x, q.y - last.y) > 1e-9) out.push(q);
|
|
2115
|
-
};
|
|
2116
|
-
const refine = (a, pa, b, pb, depth) => {
|
|
2117
|
-
const m = (a + b) / 2;
|
|
2118
|
-
const pm = evaluateNurbs(c, m);
|
|
2119
|
-
const chord = { x: (pa.x + pb.x) / 2, y: (pa.y + pb.y) / 2 };
|
|
2120
|
-
const dev = Math.hypot(pm.x - chord.x, pm.y - chord.y);
|
|
2121
|
-
if (depth >= maxDepth || dev <= tolerance) {
|
|
2122
|
-
if (dev > tolerance / 4) push(pm);
|
|
2123
|
-
push(pb);
|
|
2124
|
-
return;
|
|
2125
|
-
}
|
|
2126
|
-
refine(a, pa, m, pm, depth + 1);
|
|
2127
|
-
refine(m, pm, b, pb, depth + 1);
|
|
2128
|
-
};
|
|
2129
|
-
const spans = [];
|
|
2130
|
-
for (let i = c.degree; i < c.controlPoints.length; i++) {
|
|
2131
|
-
const a = Math.max(c.knots[i], u0);
|
|
2132
|
-
const b = Math.min(c.knots[i + 1], u1);
|
|
2133
|
-
if (b > a) spans.push(a, b);
|
|
2134
|
-
}
|
|
2135
|
-
for (let i = 0; i < spans.length; i += 2) {
|
|
2136
|
-
const a = spans[i];
|
|
2137
|
-
const b = spans[i + 1];
|
|
2138
|
-
const pa = evaluateNurbs(c, a);
|
|
2139
|
-
const pb = evaluateNurbs(c, b);
|
|
2140
|
-
const m = (a + b) / 2;
|
|
2141
|
-
const pm = evaluateNurbs(c, m);
|
|
2142
|
-
refine(a, pa, m, pm, 1);
|
|
2143
|
-
refine(m, pm, b, pb, 1);
|
|
2144
|
-
}
|
|
2145
|
-
return dropCollinear(out, tolerance / 10);
|
|
2146
|
-
};
|
|
2147
|
-
var dropCollinear = (pts, eps) => {
|
|
2148
|
-
if (pts.length < 3) return pts;
|
|
2149
|
-
const out = [pts[0]];
|
|
2150
|
-
for (let i = 1; i < pts.length - 1; i++) {
|
|
2151
|
-
const a = out[out.length - 1];
|
|
2152
|
-
const b = pts[i + 1];
|
|
2153
|
-
const q = pts[i];
|
|
2154
|
-
const abx = b.x - a.x;
|
|
2155
|
-
const aby = b.y - a.y;
|
|
2156
|
-
const len2 = abx * abx + aby * aby;
|
|
2157
|
-
const t = len2 === 0 ? 0 : Math.max(
|
|
2158
|
-
0,
|
|
2159
|
-
Math.min(1, ((q.x - a.x) * abx + (q.y - a.y) * aby) / len2)
|
|
2160
|
-
);
|
|
2161
|
-
const dist2 = Math.hypot(q.x - (a.x + t * abx), q.y - (a.y + t * aby));
|
|
2162
|
-
if (dist2 > eps) out.push(q);
|
|
2163
|
-
}
|
|
2164
|
-
out.push(pts[pts.length - 1]);
|
|
2165
|
-
return out;
|
|
2166
|
-
};
|
|
2167
|
-
var interpolateFitPoints = (points, degree = 3) => {
|
|
2168
|
-
const n2 = points.length;
|
|
2169
|
-
if (n2 < 2) return null;
|
|
2170
|
-
const p = Math.min(degree, n2 - 1);
|
|
2171
|
-
const u = [0];
|
|
2172
|
-
let total2 = 0;
|
|
2173
|
-
for (let i = 1; i < n2; i++) {
|
|
2174
|
-
total2 += Math.hypot(
|
|
2175
|
-
points[i].x - points[i - 1].x,
|
|
2176
|
-
points[i].y - points[i - 1].y
|
|
2177
|
-
);
|
|
2178
|
-
u.push(total2);
|
|
2179
|
-
}
|
|
2180
|
-
if (total2 === 0) return null;
|
|
2181
|
-
for (let i = 0; i < n2; i++) u[i] /= total2;
|
|
2182
|
-
const knots = new Array(p + 1).fill(0);
|
|
2183
|
-
for (let j = 1; j <= n2 - p - 1; j++) {
|
|
2184
|
-
let s = 0;
|
|
2185
|
-
for (let i = j; i <= j + p - 1; i++) s += u[i];
|
|
2186
|
-
knots.push(s / p);
|
|
2187
|
-
}
|
|
2188
|
-
knots.push(...new Array(p + 1).fill(1));
|
|
2189
|
-
const basisRow = (ui) => {
|
|
2190
|
-
const row = new Array(n2).fill(0);
|
|
2191
|
-
const probe = {
|
|
2192
|
-
degree: p,
|
|
2193
|
-
controlPoints: points.map(() => ({ x: 0, y: 0 })),
|
|
2194
|
-
knots
|
|
2195
|
-
};
|
|
2196
|
-
for (let j = 0; j < n2; j++) {
|
|
2197
|
-
probe.controlPoints = points.map((_, k) => ({
|
|
2198
|
-
x: k === j ? 1 : 0,
|
|
2199
|
-
y: 0
|
|
2200
|
-
}));
|
|
2201
|
-
row[j] = evaluateNurbs(probe, ui).x;
|
|
2202
|
-
}
|
|
2203
|
-
return row;
|
|
2204
|
-
};
|
|
2205
|
-
const A = u.map((ui) => basisRow(ui));
|
|
2206
|
-
const bx = points.map((q) => q.x);
|
|
2207
|
-
const by = points.map((q) => q.y);
|
|
2208
|
-
for (let col = 0; col < n2; col++) {
|
|
2209
|
-
let pivot = col;
|
|
2210
|
-
for (let r = col + 1; r < n2; r++)
|
|
2211
|
-
if (Math.abs(A[r][col]) > Math.abs(A[pivot][col])) pivot = r;
|
|
2212
|
-
if (Math.abs(A[pivot][col]) < 1e-12) return null;
|
|
2213
|
-
[A[col], A[pivot]] = [A[pivot], A[col]];
|
|
2214
|
-
[bx[col], bx[pivot]] = [bx[pivot], bx[col]];
|
|
2215
|
-
[by[col], by[pivot]] = [by[pivot], by[col]];
|
|
2216
|
-
for (let r = 0; r < n2; r++) {
|
|
2217
|
-
if (r === col) continue;
|
|
2218
|
-
const k = A[r][col] / A[col][col];
|
|
2219
|
-
if (k === 0) continue;
|
|
2220
|
-
for (let c = col; c < n2; c++) A[r][c] -= k * A[col][c];
|
|
2221
|
-
bx[r] -= k * bx[col];
|
|
2222
|
-
by[r] -= k * by[col];
|
|
2223
|
-
}
|
|
2224
|
-
}
|
|
2225
|
-
const controlPoints = points.map((_, i) => ({
|
|
2226
|
-
x: bx[i] / A[i][i],
|
|
2227
|
-
y: by[i] / A[i][i]
|
|
2228
|
-
}));
|
|
2229
|
-
return { degree: p, controlPoints, knots };
|
|
2230
|
-
};
|
|
2231
|
-
|
|
2232
1995
|
// ../core/src/geometry/band.ts
|
|
2233
1996
|
var left = (d) => ({ x: -d.y, y: d.x });
|
|
2234
1997
|
var unit = (a, b) => {
|
|
@@ -3202,7 +2965,6 @@ var unitFactor = (insunits) => {
|
|
|
3202
2965
|
}
|
|
3203
2966
|
};
|
|
3204
2967
|
var IMPORT_LINE_WIDTH_MM = 0.25;
|
|
3205
|
-
var SPLINE_TOLERANCE_MM = 0.02;
|
|
3206
2968
|
var TEXT_TYPES = /* @__PURE__ */ new Set(["TEXT", "MTEXT", "ATTRIB", "ATTDEF"]);
|
|
3207
2969
|
var DIM_TYPES = /* @__PURE__ */ new Set(["DIMENSION", "LEADER"]);
|
|
3208
2970
|
var scanTags = (lines) => {
|
|
@@ -3412,48 +3174,55 @@ var baseFor = (e, ctx) => {
|
|
|
3412
3174
|
hidden: false
|
|
3413
3175
|
};
|
|
3414
3176
|
};
|
|
3415
|
-
var
|
|
3416
|
-
const
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
}
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3177
|
+
var hatchLoopEdges = (path, f, mirrored) => {
|
|
3178
|
+
const edges = hatchLoopEdgesOcs(path, f);
|
|
3179
|
+
if (!mirrored || edges.length === 0) return edges;
|
|
3180
|
+
const reflected = mirrorObject(
|
|
3181
|
+
{
|
|
3182
|
+
type: "hatch",
|
|
3183
|
+
id: "",
|
|
3184
|
+
layerId: "",
|
|
3185
|
+
loops: [{ edges }],
|
|
3186
|
+
fill: { kind: "solid" },
|
|
3187
|
+
scale: 1
|
|
3188
|
+
},
|
|
3189
|
+
{ x: 0, y: 0 },
|
|
3190
|
+
{ x: 0, y: 1 }
|
|
3191
|
+
);
|
|
3192
|
+
return reflected.loops[0].edges;
|
|
3193
|
+
};
|
|
3194
|
+
var hatchLoopEdgesOcs = (path, f) => {
|
|
3195
|
+
const pt2 = (p) => ({ x: p.x * f, y: p.y * f });
|
|
3196
|
+
if (path.isPolyline)
|
|
3197
|
+
return verticesToLoop(
|
|
3198
|
+
(path.vertices ?? []).map((v) => ({
|
|
3199
|
+
...pt2(v),
|
|
3200
|
+
bulge: v.bulge ?? 0
|
|
3201
|
+
}))
|
|
3202
|
+
).edges;
|
|
3203
|
+
const edges = [];
|
|
3430
3204
|
for (const edge of path.edges ?? []) {
|
|
3431
3205
|
switch (edge.kind) {
|
|
3432
3206
|
case 1: {
|
|
3433
|
-
const
|
|
3434
|
-
|
|
3207
|
+
const a = edge.points[0];
|
|
3208
|
+
const b = edge.end;
|
|
3209
|
+
if (a && b) edges.push({ kind: "line", a: pt2(a), b: pt2(b) });
|
|
3435
3210
|
break;
|
|
3436
3211
|
}
|
|
3437
3212
|
case 2: {
|
|
3438
3213
|
const c = edge.points[0];
|
|
3439
3214
|
if (!c || !(edge.r40 > 0)) break;
|
|
3440
|
-
const ccw = edge.ccw !== false;
|
|
3441
3215
|
const a0 = (edge.startAngle ?? 0) * DEG2RAD;
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
const
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
c.x + edge.r40 * Math.cos(ang),
|
|
3453
|
-
c.y + edge.r40 * Math.sin(ang),
|
|
3454
|
-
bulge
|
|
3455
|
-
);
|
|
3456
|
-
}
|
|
3216
|
+
const a1 = (edge.endAngle ?? 360) * DEG2RAD;
|
|
3217
|
+
const ccw = edge.ccw !== false;
|
|
3218
|
+
const full = Math.abs(a1 - a0) >= Math.PI * 2 - 1e-9;
|
|
3219
|
+
edges.push({
|
|
3220
|
+
kind: "arc",
|
|
3221
|
+
center: pt2(c),
|
|
3222
|
+
radius: edge.r40 * f,
|
|
3223
|
+
startAngle: ccw ? a0 : -a1,
|
|
3224
|
+
endAngle: full ? ccw ? a0 : -a1 : ccw ? a1 : -a0
|
|
3225
|
+
});
|
|
3457
3226
|
break;
|
|
3458
3227
|
}
|
|
3459
3228
|
case 3: {
|
|
@@ -3463,29 +3232,21 @@ var hatchLoopPointsOcs = (path, f) => {
|
|
|
3463
3232
|
const ratio = edge.r40 > 0 ? edge.r40 : 1;
|
|
3464
3233
|
const ccw = edge.ccw !== false;
|
|
3465
3234
|
const a0 = (edge.startAngle ?? 0) * DEG2RAD;
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
const
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
push(
|
|
3478
|
-
c.x + major.x * Math.cos(t) - major.y * ratio * Math.sin(t),
|
|
3479
|
-
c.y + major.y * Math.cos(t) + major.x * ratio * Math.sin(t)
|
|
3480
|
-
);
|
|
3481
|
-
}
|
|
3235
|
+
const a1 = (edge.endAngle ?? 360) * DEG2RAD;
|
|
3236
|
+
const full = Math.abs(a1 - a0) >= Math.PI * 2 - 1e-9;
|
|
3237
|
+
const param = (theta) => Math.atan2(Math.sin(theta) / ratio, Math.cos(theta));
|
|
3238
|
+
edges.push({
|
|
3239
|
+
kind: "ellipse",
|
|
3240
|
+
center: pt2(c),
|
|
3241
|
+
majorAxis: pt2(major),
|
|
3242
|
+
ratio: Math.min(1, ratio),
|
|
3243
|
+
startAngle: full ? 0 : param(ccw ? a0 : -a1),
|
|
3244
|
+
endAngle: full ? Math.PI * 2 : param(ccw ? a1 : -a0)
|
|
3245
|
+
});
|
|
3482
3246
|
break;
|
|
3483
3247
|
}
|
|
3484
3248
|
case 4: {
|
|
3485
|
-
const control = (edge.points ?? []).map(
|
|
3486
|
-
x: p.x,
|
|
3487
|
-
y: p.y
|
|
3488
|
-
}));
|
|
3249
|
+
const control = (edge.points ?? []).map(pt2);
|
|
3489
3250
|
const weights = edge.weights ?? [];
|
|
3490
3251
|
const curve = {
|
|
3491
3252
|
degree: edge.degree ?? 3,
|
|
@@ -3493,36 +3254,24 @@ var hatchLoopPointsOcs = (path, f) => {
|
|
|
3493
3254
|
knots: edge.knots ?? [],
|
|
3494
3255
|
...edge.rational && weights.length === control.length ? { weights } : {}
|
|
3495
3256
|
};
|
|
3496
|
-
const fit = (edge.fitPoints ?? []).map(
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3257
|
+
const fit = (edge.fitPoints ?? []).map(pt2);
|
|
3258
|
+
const exact = isValidNurbs(curve) ? curve : interpolateFitPoints(fit);
|
|
3259
|
+
if (exact) {
|
|
3260
|
+
edges.push({
|
|
3261
|
+
kind: "spline",
|
|
3262
|
+
...exact,
|
|
3263
|
+
...fit.length >= 2 ? { fitPoints: fit } : {}
|
|
3264
|
+
});
|
|
3265
|
+
break;
|
|
3266
|
+
}
|
|
3267
|
+
const poly = fit.length >= 2 ? fit : control;
|
|
3268
|
+
for (let i = 1; i < poly.length; i++)
|
|
3269
|
+
edges.push({ kind: "line", a: poly[i - 1], b: poly[i] });
|
|
3503
3270
|
break;
|
|
3504
3271
|
}
|
|
3505
3272
|
}
|
|
3506
3273
|
}
|
|
3507
|
-
return
|
|
3508
|
-
(p, i) => i === 0 || Math.abs(p.x - points[i - 1].x) > 1e-9 || Math.abs(p.y - points[i - 1].y) > 1e-9 || points[i - 1].bulge !== 0
|
|
3509
|
-
);
|
|
3510
|
-
};
|
|
3511
|
-
var atLeastThreeVertices = (points) => {
|
|
3512
|
-
if (points.length !== 2 || points.every((p) => p.bulge === 0)) return points;
|
|
3513
|
-
const out = [];
|
|
3514
|
-
for (let i = 0; i < 2; i++) {
|
|
3515
|
-
const a = points[i];
|
|
3516
|
-
const b = points[1 - i];
|
|
3517
|
-
out.push(a);
|
|
3518
|
-
const arc = a.bulge === 0 ? null : bulgeToArc(a, b, a.bulge);
|
|
3519
|
-
if (!arc) continue;
|
|
3520
|
-
const half = Math.tan(Math.atan(a.bulge) / 2);
|
|
3521
|
-
const mid2 = arcMidPoint(arc);
|
|
3522
|
-
out[out.length - 1] = { ...a, bulge: half };
|
|
3523
|
-
out.push({ x: mid2.x, y: mid2.y, bulge: half });
|
|
3524
|
-
}
|
|
3525
|
-
return out;
|
|
3274
|
+
return edges;
|
|
3526
3275
|
};
|
|
3527
3276
|
var convertHatch = (e, ctx) => {
|
|
3528
3277
|
const anyE = e;
|
|
@@ -3530,8 +3279,8 @@ var convertHatch = (e, ctx) => {
|
|
|
3530
3279
|
const mirrored = ctx.tags.mirroredHandles.has(String(anyE.handle));
|
|
3531
3280
|
const flip = mirrored ? -1 : 1;
|
|
3532
3281
|
const loops = (anyE.boundaryPaths ?? []).map((path) => ({
|
|
3533
|
-
|
|
3534
|
-
})).filter((loop) => loop.
|
|
3282
|
+
edges: hatchLoopEdges(path, ctx.f, mirrored)
|
|
3283
|
+
})).filter((loop) => loop.edges.length > 0);
|
|
3535
3284
|
if (loops.length === 0) return [];
|
|
3536
3285
|
let fill;
|
|
3537
3286
|
const patternMatch = typeof anyE.patternName === "string" ? getHatchPattern(anyE.patternName) : void 0;
|
|
@@ -3995,9 +3744,9 @@ var convertEntityInner = (e, dxf, ctx) => {
|
|
|
3995
3744
|
return [
|
|
3996
3745
|
{
|
|
3997
3746
|
type: "hatch",
|
|
3998
|
-
loops: loops.map(
|
|
3999
|
-
|
|
4000
|
-
|
|
3747
|
+
loops: loops.map(
|
|
3748
|
+
(l) => verticesToLoop(l.map((p) => ({ ...p, bulge: 0 })))
|
|
3749
|
+
),
|
|
4001
3750
|
fill: { kind: "solid" },
|
|
4002
3751
|
scale: 1,
|
|
4003
3752
|
...base
|
|
@@ -4127,32 +3876,46 @@ var convertEntityInner = (e, dxf, ctx) => {
|
|
|
4127
3876
|
case "SPLINE": {
|
|
4128
3877
|
const control = anyE.controlPoints ?? [];
|
|
4129
3878
|
const weights = ctx.tags.splineWeightsByHandle.get(String(anyE.handle));
|
|
3879
|
+
const fit = (anyE.fitPoints ?? []).map((p) => ({
|
|
3880
|
+
x: p.x * f,
|
|
3881
|
+
y: p.y * f
|
|
3882
|
+
}));
|
|
4130
3883
|
const curve = {
|
|
4131
3884
|
degree: anyE.degreeOfSplineCurve ?? 3,
|
|
4132
|
-
controlPoints: control.map((p) => ({ x: p.x, y: p.y })),
|
|
3885
|
+
controlPoints: control.map((p) => ({ x: p.x * f, y: p.y * f })),
|
|
4133
3886
|
knots: anyE.knotValues ?? [],
|
|
4134
3887
|
...weights && weights.length === control.length ? { weights } : {}
|
|
4135
3888
|
};
|
|
4136
|
-
const
|
|
4137
|
-
const
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
3889
|
+
const tangent = (t) => t && Math.hypot(t.x, t.y) > 1e-12 ? { x: t.x, y: t.y } : void 0;
|
|
3890
|
+
const startTangent = tangent(anyE.startTangent);
|
|
3891
|
+
const endTangent = tangent(anyE.endTangent);
|
|
3892
|
+
const closed = anyE.closed === true;
|
|
3893
|
+
const fitted = isValidNurbs(curve) ? curve : closed ? interpolateClosed(fit) : interpolateFitPoints(fit, 3, {
|
|
3894
|
+
start: startTangent,
|
|
3895
|
+
end: endTangent
|
|
3896
|
+
});
|
|
3897
|
+
if (fitted && isValidNurbs(fitted))
|
|
3898
|
+
return [
|
|
3899
|
+
{
|
|
3900
|
+
type: "spline",
|
|
3901
|
+
degree: fitted.degree,
|
|
3902
|
+
controlPoints: fitted.controlPoints,
|
|
3903
|
+
knots: fitted.knots,
|
|
3904
|
+
...fitted.weights ? { weights: fitted.weights } : {},
|
|
3905
|
+
...fit.length >= 2 ? { fitPoints: fit } : {},
|
|
3906
|
+
...fit.length >= 2 && !closed && startTangent ? { startTangent } : {},
|
|
3907
|
+
...fit.length >= 2 && !closed && endTangent ? { endTangent } : {},
|
|
3908
|
+
closed,
|
|
3909
|
+
...base
|
|
3910
|
+
}
|
|
3911
|
+
];
|
|
3912
|
+
const raw = fit.length >= 2 ? fit : control.map((p) => ({ x: p.x * f, y: p.y * f }));
|
|
3913
|
+
if (raw.length < 2) return [];
|
|
3914
|
+
bump(ctx.degraded, "SPLINE\u2192polyline (control points)");
|
|
4152
3915
|
return [
|
|
4153
3916
|
{
|
|
4154
3917
|
type: "polyline",
|
|
4155
|
-
points:
|
|
3918
|
+
points: raw.map((p) => ({ x: p.x, y: p.y, bulge: 0 })),
|
|
4156
3919
|
closed: anyE.closed === true,
|
|
4157
3920
|
...base
|
|
4158
3921
|
}
|
|
@@ -4167,7 +3930,9 @@ var convertEntityInner = (e, dxf, ctx) => {
|
|
|
4167
3930
|
return [
|
|
4168
3931
|
{
|
|
4169
3932
|
type: "hatch",
|
|
4170
|
-
loops: [
|
|
3933
|
+
loops: [
|
|
3934
|
+
verticesToLoop(points.map((p) => ({ ...pt(p, f), bulge: 0 })))
|
|
3935
|
+
],
|
|
4171
3936
|
fill: { kind: "solid" },
|
|
4172
3937
|
scale: 1,
|
|
4173
3938
|
...base
|
|
@@ -4183,9 +3948,7 @@ var convertEntityInner = (e, dxf, ctx) => {
|
|
|
4183
3948
|
{
|
|
4184
3949
|
type: "hatch",
|
|
4185
3950
|
loops: [
|
|
4186
|
-
{
|
|
4187
|
-
points: ordered.map((p) => ({ ...ocs(p), bulge: 0 }))
|
|
4188
|
-
}
|
|
3951
|
+
verticesToLoop(ordered.map((p) => ({ ...ocs(p), bulge: 0 })))
|
|
4189
3952
|
],
|
|
4190
3953
|
fill: { kind: "solid" },
|
|
4191
3954
|
scale: 1,
|
|
@@ -4397,7 +4160,7 @@ var convertInsertInner = (e, dxf, ctx, depth, inheritedColor) => {
|
|
|
4397
4160
|
const sx = anyE.xScale ?? 1;
|
|
4398
4161
|
const sy = (anyE.yScale ?? 1) * (mirrored ? -1 : 1);
|
|
4399
4162
|
const rot0 = (anyE.rotation ?? 0) * DEG2RAD;
|
|
4400
|
-
const
|
|
4163
|
+
const rot = mirrored ? Math.PI - rot0 : rot0;
|
|
4401
4164
|
const pos = anyE.position ?? { x: 0, y: 0 };
|
|
4402
4165
|
const insert = mirrored ? { x: -pos.x * ctx.f, y: pos.y * ctx.f } : pt(pos, ctx.f);
|
|
4403
4166
|
if (e.type === "INSERT" && depth === 0 && !mirrored && sx > 0 && sy > 0 && Math.abs(sx - sy) < 1e-9) {
|
|
@@ -4408,7 +4171,7 @@ var convertInsertInner = (e, dxf, ctx, depth, inheritedColor) => {
|
|
|
4408
4171
|
type: "block",
|
|
4409
4172
|
definitionId: def.id,
|
|
4410
4173
|
inputs: [insert],
|
|
4411
|
-
rotation:
|
|
4174
|
+
rotation: rot,
|
|
4412
4175
|
scale: sx,
|
|
4413
4176
|
params: {},
|
|
4414
4177
|
...baseFor(e, ctx)
|
|
@@ -4417,8 +4180,8 @@ var convertInsertInner = (e, dxf, ctx, depth, inheritedColor) => {
|
|
|
4417
4180
|
}
|
|
4418
4181
|
if (e.type === "INSERT" && depth === 0) bump(ctx.degraded, "INSERT\u2192exploded");
|
|
4419
4182
|
const base = pt(block.position ?? { x: 0, y: 0 }, ctx.f);
|
|
4420
|
-
const cos = Math.cos(
|
|
4421
|
-
const sin = Math.sin(
|
|
4183
|
+
const cos = Math.cos(rot);
|
|
4184
|
+
const sin = Math.sin(rot);
|
|
4422
4185
|
const reflect = sx * sy < 0;
|
|
4423
4186
|
const meanScale = Math.sqrt(Math.abs(sx * sy)) || 1e-6;
|
|
4424
4187
|
const lin = (v) => ({
|
|
@@ -4471,7 +4234,7 @@ var convertInsertInner = (e, dxf, ctx, depth, inheritedColor) => {
|
|
|
4471
4234
|
return t;
|
|
4472
4235
|
}
|
|
4473
4236
|
const majorLen = Math.max(ax, ay);
|
|
4474
|
-
const ang =
|
|
4237
|
+
const ang = rot + (ax >= ay ? 0 : Math.PI / 2);
|
|
4475
4238
|
return {
|
|
4476
4239
|
type: "ellipse",
|
|
4477
4240
|
center,
|
|
@@ -4519,7 +4282,18 @@ var convertInsertInner = (e, dxf, ctx, depth, inheritedColor) => {
|
|
|
4519
4282
|
return t;
|
|
4520
4283
|
case "hatch": {
|
|
4521
4284
|
t.loops = t.loops.map((loop) => ({
|
|
4522
|
-
|
|
4285
|
+
edges: loop.edges.flatMap((edge) => {
|
|
4286
|
+
const { kind, ...geometry } = edge;
|
|
4287
|
+
const moved = transform({
|
|
4288
|
+
...geometry,
|
|
4289
|
+
type: kind,
|
|
4290
|
+
layerId: t.layerId
|
|
4291
|
+
});
|
|
4292
|
+
if (!moved || moved.type !== kind) return [];
|
|
4293
|
+
const out = { kind };
|
|
4294
|
+
for (const key of Object.keys(geometry)) out[key] = moved[key];
|
|
4295
|
+
return [out];
|
|
4296
|
+
})
|
|
4523
4297
|
}));
|
|
4524
4298
|
if (t.fill.kind === "pattern" || t.fill.kind === "lines") {
|
|
4525
4299
|
const d = lin({
|
|
@@ -4536,9 +4310,15 @@ var convertInsertInner = (e, dxf, ctx, depth, inheritedColor) => {
|
|
|
4536
4310
|
}
|
|
4537
4311
|
return t;
|
|
4538
4312
|
}
|
|
4313
|
+
case "spline":
|
|
4314
|
+
t.controlPoints = t.controlPoints.map(map);
|
|
4315
|
+
if (t.fitPoints) t.fitPoints = t.fitPoints.map(map);
|
|
4316
|
+
if (t.startTangent) t.startTangent = lin(t.startTangent);
|
|
4317
|
+
if (t.endTangent) t.endTangent = lin(t.endTangent);
|
|
4318
|
+
return t;
|
|
4539
4319
|
case "text":
|
|
4540
4320
|
t.position = map(t.position);
|
|
4541
|
-
t.rotation +=
|
|
4321
|
+
t.rotation += rot;
|
|
4542
4322
|
if (meanScale !== 1) {
|
|
4543
4323
|
const style = t.styleId && ctx.textStyleById.get(t.styleId) || ctx.defaultTextStyle;
|
|
4544
4324
|
const o = t.styleOverride ?? {};
|
|
@@ -5148,7 +4928,7 @@ var FALLBACK_STYLE = {
|
|
|
5148
4928
|
color: "#e8e8e8",
|
|
5149
4929
|
widthMm: 0.25
|
|
5150
4930
|
};
|
|
5151
|
-
var resolveStyle = (obj, layers, lineTypes) => {
|
|
4931
|
+
var resolveStyle = (obj, layers, lineTypes, lineTypeScale = 1) => {
|
|
5152
4932
|
const layer = layers.find((l) => l.id === obj.layerId);
|
|
5153
4933
|
const widthMm = obj.lineWidth ?? layer?.lineWidth ?? FALLBACK_STYLE.widthMm;
|
|
5154
4934
|
return {
|
|
@@ -5156,10 +4936,11 @@ var resolveStyle = (obj, layers, lineTypes) => {
|
|
|
5156
4936
|
widthMm,
|
|
5157
4937
|
// Dash patterns are defined per 1 mm of line width (ISO 128 style —
|
|
5158
4938
|
// pattern legibility tracks stroke weight), so the resolved lineweight
|
|
5159
|
-
// scales them; lineTypeScale (CELTSCALE)
|
|
4939
|
+
// scales them; lineTypeScale (CELTSCALE) and the model scale multiply
|
|
4940
|
+
// on top.
|
|
5160
4941
|
dashMm: scaleDash(
|
|
5161
4942
|
dashForLineType(obj.lineType ?? layer?.lineType, lineTypes),
|
|
5162
|
-
widthMm * (obj.lineTypeScale ?? 1)
|
|
4943
|
+
widthMm * (obj.lineTypeScale ?? 1) * lineTypeScale
|
|
5163
4944
|
),
|
|
5164
4945
|
opacity: obj.opacity ?? layer?.opacity
|
|
5165
4946
|
};
|
|
@@ -5176,7 +4957,7 @@ var rebaseSink = (sink, origin) => {
|
|
|
5176
4957
|
lineTo: (p) => sink.lineTo(at(p)),
|
|
5177
4958
|
bezierTo: (c1, c2, end) => sink.bezierTo(at(c1), at(c2), at(end)),
|
|
5178
4959
|
arc: (center, r, a0, a1, ccw) => sink.arc(at(center), r, a0, a1, ccw),
|
|
5179
|
-
ellipse: (center, rx, ry,
|
|
4960
|
+
ellipse: (center, rx, ry, rot, a0, a1) => sink.ellipse(at(center), rx, ry, rot, a0, a1),
|
|
5180
4961
|
closePath: () => sink.closePath(),
|
|
5181
4962
|
stroke: (s) => sink.stroke(s),
|
|
5182
4963
|
fill: (f) => sink.fill(
|
|
@@ -5264,7 +5045,8 @@ var paintReference = (obj, sink, env) => {
|
|
|
5264
5045
|
const own = resolveStyle(
|
|
5265
5046
|
child,
|
|
5266
5047
|
content.layers,
|
|
5267
|
-
content.lineTypes
|
|
5048
|
+
content.lineTypes,
|
|
5049
|
+
env.lineTypeScale
|
|
5268
5050
|
);
|
|
5269
5051
|
paintObject(child, out, {
|
|
5270
5052
|
// A highlight paints the whole reference in one style.
|
|
@@ -5333,6 +5115,7 @@ var painters = {
|
|
|
5333
5115
|
circle: paintCircle,
|
|
5334
5116
|
arc: paintArc,
|
|
5335
5117
|
ellipse: paintEllipse,
|
|
5118
|
+
spline: paintSpline,
|
|
5336
5119
|
hatch: paintHatch,
|
|
5337
5120
|
text: paintText,
|
|
5338
5121
|
dimension: paintDimension,
|
|
@@ -5580,6 +5363,7 @@ var extractCommandMeta = (mod) => {
|
|
|
5580
5363
|
};
|
|
5581
5364
|
};
|
|
5582
5365
|
var compileCache = /* @__PURE__ */ new Map();
|
|
5366
|
+
onSandboxReset(() => compileCache.clear());
|
|
5583
5367
|
var COMPILE_CACHE_MAX = 100;
|
|
5584
5368
|
var compileCommand = (script) => {
|
|
5585
5369
|
const cached = compileCache.get(script);
|
|
@@ -5588,16 +5372,24 @@ var compileCommand = (script) => {
|
|
|
5588
5372
|
compileCache.set(script, cached);
|
|
5589
5373
|
return cached;
|
|
5590
5374
|
}
|
|
5591
|
-
const mod = executeScriptModule(script);
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5375
|
+
const mod = executeScriptModule(script, "command");
|
|
5376
|
+
let meta;
|
|
5377
|
+
try {
|
|
5378
|
+
meta = extractCommandMeta(mod);
|
|
5379
|
+
if (typeof mod.run !== "function")
|
|
5380
|
+
throw new Error("Command script must export a `run` function");
|
|
5381
|
+
} catch (e) {
|
|
5382
|
+
releaseScriptModule(mod);
|
|
5383
|
+
throw e;
|
|
5384
|
+
}
|
|
5596
5385
|
if (compileCache.size >= COMPILE_CACHE_MAX) {
|
|
5597
5386
|
const oldest = compileCache.keys().next().value;
|
|
5598
|
-
if (oldest !== void 0)
|
|
5387
|
+
if (oldest !== void 0) {
|
|
5388
|
+
releaseScriptModule(compileCache.get(oldest).mod);
|
|
5389
|
+
compileCache.delete(oldest);
|
|
5390
|
+
}
|
|
5599
5391
|
}
|
|
5600
|
-
const compiled = { meta, run };
|
|
5392
|
+
const compiled = { mod, meta, run: mod.run };
|
|
5601
5393
|
compileCache.set(script, compiled);
|
|
5602
5394
|
return compiled;
|
|
5603
5395
|
};
|
|
@@ -6789,12 +6581,19 @@ var renderModelToSvg = (model, opts = {}) => {
|
|
|
6789
6581
|
const origin = far ? { x: bbox.minX, y: bbox.minY } : { x: 0, y: 0 };
|
|
6790
6582
|
const out = rebaseSink(sink, origin);
|
|
6791
6583
|
for (const obj of toPaint) {
|
|
6792
|
-
const
|
|
6584
|
+
const lineTypeScale = opts.lineTypeScale ?? 1;
|
|
6585
|
+
const style = resolveStyle(
|
|
6586
|
+
obj,
|
|
6587
|
+
model.layers,
|
|
6588
|
+
model.lineTypes,
|
|
6589
|
+
lineTypeScale
|
|
6590
|
+
);
|
|
6793
6591
|
sink.beginObject(obj.id, layerName.get(obj.layerId));
|
|
6794
6592
|
paintObject(obj, out, {
|
|
6795
6593
|
style: { ...style, color: mapColor(style.color) },
|
|
6796
6594
|
...model,
|
|
6797
|
-
mapColor
|
|
6595
|
+
mapColor,
|
|
6596
|
+
lineTypeScale
|
|
6798
6597
|
});
|
|
6799
6598
|
sink.endObject();
|
|
6800
6599
|
}
|
|
@@ -6805,7 +6604,12 @@ var renderModelToSvg = (model, opts = {}) => {
|
|
|
6805
6604
|
maxX: bbox.maxX - origin.x,
|
|
6806
6605
|
maxY: bbox.maxY - origin.y
|
|
6807
6606
|
},
|
|
6808
|
-
|
|
6607
|
+
// Default: 2% of the frame (at least 5 mm), so strokes and arrowheads
|
|
6608
|
+
// at the extents aren't cut by the image edge.
|
|
6609
|
+
opts.padding ?? Math.max(
|
|
6610
|
+
5,
|
|
6611
|
+
0.02 * Math.max(bbox.maxX - bbox.minX, bbox.maxY - bbox.minY)
|
|
6612
|
+
)
|
|
6809
6613
|
);
|
|
6810
6614
|
};
|
|
6811
6615
|
var FAR_MM = 1e7;
|
|
@@ -8379,17 +8183,188 @@ var DocumentKernel = class {
|
|
|
8379
8183
|
|
|
8380
8184
|
// ../core/src/drawing/localDrawing.ts
|
|
8381
8185
|
import { z as z6 } from "zod";
|
|
8186
|
+
|
|
8187
|
+
// ../core/src/drawing/inputChecks.ts
|
|
8188
|
+
var DrawingError = class extends Error {
|
|
8189
|
+
code;
|
|
8190
|
+
issues;
|
|
8191
|
+
constructor(code, message, issues) {
|
|
8192
|
+
super(message);
|
|
8193
|
+
this.code = code;
|
|
8194
|
+
if (issues) this.issues = issues;
|
|
8195
|
+
}
|
|
8196
|
+
};
|
|
8197
|
+
var MAX_COORDINATE_MM = 1e9;
|
|
8198
|
+
var STYLE_OVERRIDE_KEYS = {
|
|
8199
|
+
text: TextStyleOverrideSchema.shape,
|
|
8200
|
+
table: TextStyleOverrideSchema.shape,
|
|
8201
|
+
dimension: DimStyleOverrideSchema.shape
|
|
8202
|
+
};
|
|
8203
|
+
var hintFor = (type, key) => {
|
|
8204
|
+
if (type && key in (STYLE_OVERRIDE_KEYS[type] ?? {}))
|
|
8205
|
+
return ` \u2014 style keys go in styleOverride: { ${key}: \u2026 }`;
|
|
8206
|
+
if (type === "layer" && key === "hidden") return " \u2014 use visible: false";
|
|
8207
|
+
if (type === "dimension" && (key === "upVector" || key === "linePoint"))
|
|
8208
|
+
return " \u2014 `offset` is the signed distance of the dimension line";
|
|
8209
|
+
if (type === "dimension" && key === "textOverride")
|
|
8210
|
+
return " \u2014 use labels[i].content (with {value} for the measurement)";
|
|
8211
|
+
return "";
|
|
8212
|
+
};
|
|
8213
|
+
var assertNoUnknownKeys = (sent, parsed, context, type) => {
|
|
8214
|
+
const unknown = Object.keys(sent).filter(
|
|
8215
|
+
(k) => sent[k] !== void 0 && !(k in parsed)
|
|
8216
|
+
);
|
|
8217
|
+
if (unknown.length > 0)
|
|
8218
|
+
throw new DrawingError(
|
|
8219
|
+
"unknownField",
|
|
8220
|
+
`${context}: unknown field(s) ${unknown.map((k) => `"${k}"${hintFor(type, k)}`).join(", ")}`
|
|
8221
|
+
);
|
|
8222
|
+
};
|
|
8223
|
+
var assertSaneNumbers = (value, context) => {
|
|
8224
|
+
const walk = (v, path) => {
|
|
8225
|
+
if (typeof v === "number") {
|
|
8226
|
+
if (Math.abs(v) > MAX_COORDINATE_MM)
|
|
8227
|
+
throw new DrawingError(
|
|
8228
|
+
"outOfRange",
|
|
8229
|
+
`${context}: ${path || "value"} = ${v} is out of range (|value| \u2264 ${MAX_COORDINATE_MM} mm)`
|
|
8230
|
+
);
|
|
8231
|
+
} else if (Array.isArray(v)) v.forEach((x, i) => walk(x, `${path}[${i}]`));
|
|
8232
|
+
else if (v !== null && typeof v === "object")
|
|
8233
|
+
for (const [k, x] of Object.entries(v))
|
|
8234
|
+
walk(x, path ? `${path}.${k}` : k);
|
|
8235
|
+
};
|
|
8236
|
+
walk(value, "");
|
|
8237
|
+
};
|
|
8238
|
+
var knownLineType = (name, sources) => resolveLineType(name, sources.lineTypes) !== void 0 || getLineType(name) !== void 0;
|
|
8239
|
+
var knownFont = (font) => (font.includes(";") ? font.slice(0, font.indexOf(";")) : font) in FONTS;
|
|
8240
|
+
var fontList = Object.keys(FONTS).join(", ");
|
|
8241
|
+
var assertLineType = (name, sources, context) => {
|
|
8242
|
+
if (name !== void 0 && !knownLineType(name, sources))
|
|
8243
|
+
throw new DrawingError(
|
|
8244
|
+
"unknownLineType",
|
|
8245
|
+
`${context}: unknown line type "${name}" (the built-in catalogue or linea_list_line_types)`
|
|
8246
|
+
);
|
|
8247
|
+
};
|
|
8248
|
+
var assertFont = (font, context) => {
|
|
8249
|
+
if (typeof font === "string" && !knownFont(font))
|
|
8250
|
+
throw new DrawingError(
|
|
8251
|
+
"unknownFont",
|
|
8252
|
+
`${context}: unknown font "${font}" (one of ${fontList})`
|
|
8253
|
+
);
|
|
8254
|
+
};
|
|
8255
|
+
var assertObjectFields = (obj, fields, sources, context) => {
|
|
8256
|
+
const o = obj;
|
|
8257
|
+
if (fields.has("lineType"))
|
|
8258
|
+
assertLineType(o.lineType, sources, context);
|
|
8259
|
+
if (fields.has("font")) assertFont(o.font, context);
|
|
8260
|
+
if (fields.has("styleOverride"))
|
|
8261
|
+
assertFont(
|
|
8262
|
+
o.styleOverride?.font,
|
|
8263
|
+
context
|
|
8264
|
+
);
|
|
8265
|
+
if (obj.type === "hatch" && fields.has("fill") && obj.fill.kind === "pattern") {
|
|
8266
|
+
if (!resolveHatchPattern(obj.fill.name, sources.hatchPatterns))
|
|
8267
|
+
throw new DrawingError(
|
|
8268
|
+
"unknownHatchPattern",
|
|
8269
|
+
`${context}: unknown hatch pattern "${obj.fill.name}" (the built-in catalogue or linea_list_hatch_patterns)`
|
|
8270
|
+
);
|
|
8271
|
+
}
|
|
8272
|
+
if (obj.type === "text" && (fields.has("spans") || fields.has("content")))
|
|
8273
|
+
for (const [i, s] of (obj.spans ?? []).entries()) {
|
|
8274
|
+
if (s.end > obj.content.length || s.start >= s.end)
|
|
8275
|
+
throw new DrawingError(
|
|
8276
|
+
"invalidSpan",
|
|
8277
|
+
`${context}: spans[${i}] ${s.start}\u2013${s.end} must satisfy start < end \u2264 ${obj.content.length} (the content's length)`
|
|
8278
|
+
);
|
|
8279
|
+
assertFont(s.font, `${context}: spans[${i}]`);
|
|
8280
|
+
}
|
|
8281
|
+
if (obj.type === "block" && fields.has("params"))
|
|
8282
|
+
assertBlockParams(obj, sources, context);
|
|
8283
|
+
};
|
|
8284
|
+
var assertBlockParams = (obj, sources, context) => {
|
|
8285
|
+
let script;
|
|
8286
|
+
try {
|
|
8287
|
+
script = findBlockScript(sources.blockDefinitions, obj.definitionId);
|
|
8288
|
+
} catch {
|
|
8289
|
+
return;
|
|
8290
|
+
}
|
|
8291
|
+
if (!script) return;
|
|
8292
|
+
const meta = getBlockMetaResult(script);
|
|
8293
|
+
if (!meta.ok) return;
|
|
8294
|
+
const defs = valueParams(meta.meta.params);
|
|
8295
|
+
for (const [name, value] of Object.entries(obj.params ?? {})) {
|
|
8296
|
+
const def = defs.find((d) => d.name === name);
|
|
8297
|
+
if (!def)
|
|
8298
|
+
throw new DrawingError(
|
|
8299
|
+
"invalidParam",
|
|
8300
|
+
`${context}: block "${obj.definitionId}" has no parameter "${name}"${defs.length ? ` (declares ${defs.map((d) => d.name).join(", ")})` : ""}`
|
|
8301
|
+
);
|
|
8302
|
+
const mismatch = paramMismatch(def, value);
|
|
8303
|
+
if (mismatch)
|
|
8304
|
+
throw new DrawingError(
|
|
8305
|
+
"invalidParam",
|
|
8306
|
+
`${context}: parameter "${name}" \u2014 ${mismatch}`
|
|
8307
|
+
);
|
|
8308
|
+
}
|
|
8309
|
+
};
|
|
8310
|
+
|
|
8311
|
+
// ../core/src/drawing/localDrawing.ts
|
|
8382
8312
|
var toVec = (p) => Vec2Schema.parse(p);
|
|
8313
|
+
var refuseRejected = (report, kind) => {
|
|
8314
|
+
if (report.rejected.length === 0) return;
|
|
8315
|
+
const lines = report.rejected.map(
|
|
8316
|
+
(r, i) => `${i + 1}) ${scanScriptId(r.script, /define(Block|Command)\(|export\s+default\s*\{/) ?? "(no id)"}: ${r.error}`
|
|
8317
|
+
);
|
|
8318
|
+
throw Object.assign(
|
|
8319
|
+
new Error(
|
|
8320
|
+
`${report.rejected.length} ${kind} source(s) rejected, so none were added:
|
|
8321
|
+
${lines.join("\n")}`
|
|
8322
|
+
),
|
|
8323
|
+
{ code: "moduleRejected" }
|
|
8324
|
+
);
|
|
8325
|
+
};
|
|
8326
|
+
var checkedStyle = (schema, full, sent, context) => {
|
|
8327
|
+
let style;
|
|
8328
|
+
try {
|
|
8329
|
+
style = schema.parse(full);
|
|
8330
|
+
} catch (e) {
|
|
8331
|
+
throw wrapZod(e, context);
|
|
8332
|
+
}
|
|
8333
|
+
assertNoUnknownKeys(sent, style, context);
|
|
8334
|
+
if ("font" in sent) assertFont(sent.font, context);
|
|
8335
|
+
return style;
|
|
8336
|
+
};
|
|
8337
|
+
var assertDataUrl = (dataUrl) => {
|
|
8338
|
+
const m = /^data:([\w.+-]+\/[\w.+-]+)(;[^,]*)?;base64,([A-Za-z0-9+/]*={0,2})$/.exec(
|
|
8339
|
+
dataUrl
|
|
8340
|
+
);
|
|
8341
|
+
if (!m)
|
|
8342
|
+
throw new DrawingError(
|
|
8343
|
+
"invalidAsset",
|
|
8344
|
+
"An asset must be a base64 data URL (data:<type>;base64,...)"
|
|
8345
|
+
);
|
|
8346
|
+
const bytes = Math.floor(m[3].length * 3 / 4) - (m[3].match(/=/g)?.length ?? 0);
|
|
8347
|
+
if (bytes < 16)
|
|
8348
|
+
throw new DrawingError(
|
|
8349
|
+
"invalidAsset",
|
|
8350
|
+
`The ${m[1]} data URL holds only ${bytes} bytes, not a real file`
|
|
8351
|
+
);
|
|
8352
|
+
};
|
|
8353
|
+
var MAX_COPIES = 1e4;
|
|
8383
8354
|
var wrapZod = (e, context) => {
|
|
8384
8355
|
if (!(e instanceof z6.ZodError))
|
|
8385
8356
|
return e instanceof Error ? e : new Error(String(e));
|
|
8386
|
-
return new
|
|
8357
|
+
return new DrawingError(
|
|
8358
|
+
"validation",
|
|
8359
|
+
`${context}: ${z6.prettifyError(e)}`,
|
|
8360
|
+
e.issues
|
|
8361
|
+
);
|
|
8387
8362
|
};
|
|
8388
8363
|
var PDF_PAGE_GAP_MM = 50;
|
|
8389
8364
|
var selectPdfLayouts = (layouts, opts, fallback) => {
|
|
8390
8365
|
const byRef = (ref) => {
|
|
8391
8366
|
const l = layouts.find((x) => x.name === ref || x.id === ref);
|
|
8392
|
-
if (!l) throw new
|
|
8367
|
+
if (!l) throw new DrawingError("unknownLayout", `Unknown layout "${ref}"`);
|
|
8393
8368
|
return l;
|
|
8394
8369
|
};
|
|
8395
8370
|
let selected = opts.layouts !== void 0 ? opts.layouts.map(byRef) : layouts.length > 0 ? [...layouts] : [fallback()];
|
|
@@ -8496,11 +8471,6 @@ var kernelHooks = (doc) => {
|
|
|
8496
8471
|
revision: () => rev
|
|
8497
8472
|
};
|
|
8498
8473
|
};
|
|
8499
|
-
var withVisible = (layer) => {
|
|
8500
|
-
const { hidden, ...rest } = layer;
|
|
8501
|
-
if (hidden === void 0) return layer;
|
|
8502
|
-
return { ...rest, visible: !hidden };
|
|
8503
|
-
};
|
|
8504
8474
|
var LocalDrawing = class {
|
|
8505
8475
|
hooks;
|
|
8506
8476
|
/** Schema-version migration applied on open; null when none was needed. */
|
|
@@ -8556,7 +8526,7 @@ var LocalDrawing = class {
|
|
|
8556
8526
|
findObject(id) {
|
|
8557
8527
|
const doc = this.state;
|
|
8558
8528
|
const obj = resolveDocumentObject(doc, id);
|
|
8559
|
-
if (!obj) throw new
|
|
8529
|
+
if (!obj) throw new DrawingError("unknownObject", `Unknown object "${id}"`);
|
|
8560
8530
|
const layout = doc.layouts.find((l) => l.objects.includes(obj));
|
|
8561
8531
|
return { obj, space: layout ? { layoutId: layout.id } : "model" };
|
|
8562
8532
|
}
|
|
@@ -8638,8 +8608,11 @@ var LocalDrawing = class {
|
|
|
8638
8608
|
(l) => l.name.toLowerCase() === layer.name.toLowerCase()
|
|
8639
8609
|
);
|
|
8640
8610
|
if (clash)
|
|
8641
|
-
throw new
|
|
8642
|
-
|
|
8611
|
+
throw new DrawingError(
|
|
8612
|
+
"duplicateName",
|
|
8613
|
+
`Layer "${clash.name}" already exists`
|
|
8614
|
+
);
|
|
8615
|
+
const full = this.checkedLayer(layer, layer, "add layer");
|
|
8643
8616
|
this.applyForward({ type: "add-layer", layer: full });
|
|
8644
8617
|
return full.id;
|
|
8645
8618
|
}
|
|
@@ -8647,7 +8620,8 @@ var LocalDrawing = class {
|
|
|
8647
8620
|
const l = this.state.layers.find(
|
|
8648
8621
|
(x) => x.id === nameOrId || x.name === nameOrId
|
|
8649
8622
|
);
|
|
8650
|
-
if (!l)
|
|
8623
|
+
if (!l)
|
|
8624
|
+
throw new DrawingError("unknownLayer", `Unknown layer "${nameOrId}"`);
|
|
8651
8625
|
return l;
|
|
8652
8626
|
}
|
|
8653
8627
|
/** Patch a layer (rename, color, lineWidth, visible, locked) by name or id. */
|
|
@@ -8658,13 +8632,36 @@ var LocalDrawing = class {
|
|
|
8658
8632
|
(l) => l.name.toLowerCase() === patch.name.toLowerCase()
|
|
8659
8633
|
);
|
|
8660
8634
|
if (clash)
|
|
8661
|
-
throw new
|
|
8635
|
+
throw new DrawingError(
|
|
8636
|
+
"duplicateName",
|
|
8637
|
+
`Layer "${clash.name}" already exists`
|
|
8638
|
+
);
|
|
8662
8639
|
}
|
|
8663
8640
|
this.applyForward({
|
|
8664
8641
|
type: "update-layer",
|
|
8665
|
-
layer:
|
|
8642
|
+
layer: this.checkedLayer(
|
|
8643
|
+
{ ...cur, ...patch, id: cur.id },
|
|
8644
|
+
patch,
|
|
8645
|
+
`update layer "${cur.name}"`
|
|
8646
|
+
)
|
|
8666
8647
|
});
|
|
8667
8648
|
}
|
|
8649
|
+
/** A layer parsed from `full`, refusing an empty name, unknown fields
|
|
8650
|
+
* and an unknown line type among what the caller `sent`. */
|
|
8651
|
+
checkedLayer(full, sent, context) {
|
|
8652
|
+
if (typeof sent.name === "string" && sent.name.trim() === "")
|
|
8653
|
+
throw new DrawingError("validation", `${context}: the name is empty`);
|
|
8654
|
+
let layer;
|
|
8655
|
+
try {
|
|
8656
|
+
layer = LayerSchema.parse(full);
|
|
8657
|
+
} catch (e) {
|
|
8658
|
+
throw wrapZod(e, context);
|
|
8659
|
+
}
|
|
8660
|
+
assertNoUnknownKeys(sent, layer, context, "layer");
|
|
8661
|
+
if ("lineType" in sent)
|
|
8662
|
+
assertLineType(layer.lineType, this.nameSources, context);
|
|
8663
|
+
return layer;
|
|
8664
|
+
}
|
|
8668
8665
|
/** Remove an EMPTY, non-current layer (the kernel refuses otherwise). */
|
|
8669
8666
|
removeLayer(nameOrId) {
|
|
8670
8667
|
this.applyForward({
|
|
@@ -8699,6 +8696,7 @@ var LocalDrawing = class {
|
|
|
8699
8696
|
* Content-keyed: the same data reuses one entry.
|
|
8700
8697
|
*/
|
|
8701
8698
|
addAsset(dataUrl) {
|
|
8699
|
+
assertDataUrl(dataUrl);
|
|
8702
8700
|
const id = hashAsset(dataUrl);
|
|
8703
8701
|
if (this.state.assets[id] !== dataUrl)
|
|
8704
8702
|
this.applyForward({ type: "set-asset", id, dataUrl });
|
|
@@ -8806,25 +8804,32 @@ var LocalDrawing = class {
|
|
|
8806
8804
|
// (case-insensitive) on add and rename.
|
|
8807
8805
|
resolveStyle(styles, nameOrId, what) {
|
|
8808
8806
|
const s = styles.find((x) => x.id === nameOrId || x.name === nameOrId);
|
|
8809
|
-
if (!s)
|
|
8807
|
+
if (!s)
|
|
8808
|
+
throw new DrawingError("unknownStyle", `Unknown ${what} "${nameOrId}"`);
|
|
8810
8809
|
return s;
|
|
8811
8810
|
}
|
|
8812
|
-
assertStyleName(styles, name,
|
|
8811
|
+
assertStyleName(styles, name, except) {
|
|
8813
8812
|
const clash = styles.find(
|
|
8814
8813
|
(s) => s.id !== except && s.name.toLowerCase() === name.toLowerCase()
|
|
8815
8814
|
);
|
|
8816
8815
|
if (clash)
|
|
8817
|
-
throw new
|
|
8816
|
+
throw new DrawingError(
|
|
8817
|
+
"duplicateName",
|
|
8818
|
+
`Style "${clash.name}" already exists`
|
|
8819
|
+
);
|
|
8818
8820
|
}
|
|
8819
8821
|
/** Layouts are addressed by name everywhere (`layout` on the object
|
|
8820
8822
|
* tools, remove, reorder, render) — a duplicate would silently resolve to
|
|
8821
8823
|
* the first match. */
|
|
8822
|
-
assertLayoutName(name,
|
|
8824
|
+
assertLayoutName(name, except) {
|
|
8823
8825
|
const clash = this.state.layouts.find(
|
|
8824
8826
|
(l) => l.id !== except && l.name.toLowerCase() === name.toLowerCase()
|
|
8825
8827
|
);
|
|
8826
8828
|
if (clash)
|
|
8827
|
-
throw new
|
|
8829
|
+
throw new DrawingError(
|
|
8830
|
+
"duplicateName",
|
|
8831
|
+
`Layout "${clash.name}" already exists`
|
|
8832
|
+
);
|
|
8828
8833
|
}
|
|
8829
8834
|
/** Objects reference styles by id, but callers often pass the NAME:
|
|
8830
8835
|
* resolve it (text/table → text styles, dimension → dim styles). An
|
|
@@ -8836,7 +8841,8 @@ var LocalDrawing = class {
|
|
|
8836
8841
|
if (!styles) return {};
|
|
8837
8842
|
const s = styles.find((x) => x.id === obj.styleId) ?? styles.find((x) => x.name === obj.styleId);
|
|
8838
8843
|
if (!s)
|
|
8839
|
-
throw new
|
|
8844
|
+
throw new DrawingError(
|
|
8845
|
+
"unknownStyle",
|
|
8840
8846
|
`${context}: unknown ${obj.type === "dimension" ? "dim" : "text"} style "${obj.styleId}"`
|
|
8841
8847
|
);
|
|
8842
8848
|
return { styleId: s.id };
|
|
@@ -8850,8 +8856,8 @@ var LocalDrawing = class {
|
|
|
8850
8856
|
/** Create a text style (unique name; unset fields take the defaults);
|
|
8851
8857
|
* returns its id. */
|
|
8852
8858
|
addTextStyle(props) {
|
|
8853
|
-
this.assertStyleName(this.state.textStyles, props.name
|
|
8854
|
-
const style = TextStyleSchema
|
|
8859
|
+
this.assertStyleName(this.state.textStyles, props.name);
|
|
8860
|
+
const style = checkedStyle(TextStyleSchema, props, props, "add text style");
|
|
8855
8861
|
this.applyForward({ type: "add-text-style", style });
|
|
8856
8862
|
return style.id;
|
|
8857
8863
|
}
|
|
@@ -8862,15 +8868,15 @@ var LocalDrawing = class {
|
|
|
8862
8868
|
"text style"
|
|
8863
8869
|
);
|
|
8864
8870
|
if (patch.name !== void 0)
|
|
8865
|
-
this.assertStyleName(
|
|
8866
|
-
this.state.textStyles,
|
|
8867
|
-
patch.name,
|
|
8868
|
-
"updateTextStyle()",
|
|
8869
|
-
cur.id
|
|
8870
|
-
);
|
|
8871
|
+
this.assertStyleName(this.state.textStyles, patch.name, cur.id);
|
|
8871
8872
|
this.applyForward({
|
|
8872
8873
|
type: "update-text-style",
|
|
8873
|
-
style:
|
|
8874
|
+
style: checkedStyle(
|
|
8875
|
+
TextStyleSchema,
|
|
8876
|
+
{ ...cur, ...patch, id: cur.id },
|
|
8877
|
+
patch,
|
|
8878
|
+
`update text style "${cur.name}"`
|
|
8879
|
+
)
|
|
8874
8880
|
});
|
|
8875
8881
|
}
|
|
8876
8882
|
// --- line types / hatch patterns (name-keyed definitions) -----------------
|
|
@@ -8889,7 +8895,8 @@ var LocalDrawing = class {
|
|
|
8889
8895
|
const cur = this.state.lineTypes.find(
|
|
8890
8896
|
(t) => lineTypeKey(t.name) === lineTypeKey(name)
|
|
8891
8897
|
);
|
|
8892
|
-
if (!cur)
|
|
8898
|
+
if (!cur)
|
|
8899
|
+
throw new DrawingError("unknownLineType", `Unknown line type "${name}"`);
|
|
8893
8900
|
const next = LineTypeSchema.parse({ ...cur, ...patch });
|
|
8894
8901
|
if (lineTypeKey(next.name) !== lineTypeKey(cur.name)) {
|
|
8895
8902
|
this.transaction(() => {
|
|
@@ -8916,7 +8923,11 @@ var LocalDrawing = class {
|
|
|
8916
8923
|
const cur = this.state.hatchPatterns.find(
|
|
8917
8924
|
(p) => hatchPatternKey(p.name) === hatchPatternKey(name)
|
|
8918
8925
|
);
|
|
8919
|
-
if (!cur)
|
|
8926
|
+
if (!cur)
|
|
8927
|
+
throw new DrawingError(
|
|
8928
|
+
"unknownHatchPattern",
|
|
8929
|
+
`Unknown hatch pattern "${name}"`
|
|
8930
|
+
);
|
|
8920
8931
|
const next = HatchPatternSchema.parse({ ...cur, ...patch });
|
|
8921
8932
|
if (hatchPatternKey(next.name) !== hatchPatternKey(cur.name)) {
|
|
8922
8933
|
this.transaction(() => {
|
|
@@ -8939,23 +8950,23 @@ var LocalDrawing = class {
|
|
|
8939
8950
|
/** Create a dimension style (unique name; unset fields take the
|
|
8940
8951
|
* defaults); returns its id. */
|
|
8941
8952
|
addDimStyle(props) {
|
|
8942
|
-
this.assertStyleName(this.state.dimStyles, props.name
|
|
8943
|
-
const style = DimStyleSchema
|
|
8953
|
+
this.assertStyleName(this.state.dimStyles, props.name);
|
|
8954
|
+
const style = checkedStyle(DimStyleSchema, props, props, "add dim style");
|
|
8944
8955
|
this.applyForward({ type: "add-dim-style", style });
|
|
8945
8956
|
return style.id;
|
|
8946
8957
|
}
|
|
8947
8958
|
updateDimStyle(nameOrId, patch) {
|
|
8948
8959
|
const cur = this.resolveStyle(this.state.dimStyles, nameOrId, "dim style");
|
|
8949
8960
|
if (patch.name !== void 0)
|
|
8950
|
-
this.assertStyleName(
|
|
8951
|
-
this.state.dimStyles,
|
|
8952
|
-
patch.name,
|
|
8953
|
-
"updateDimStyle()",
|
|
8954
|
-
cur.id
|
|
8955
|
-
);
|
|
8961
|
+
this.assertStyleName(this.state.dimStyles, patch.name, cur.id);
|
|
8956
8962
|
this.applyForward({
|
|
8957
8963
|
type: "update-dim-style",
|
|
8958
|
-
style:
|
|
8964
|
+
style: checkedStyle(
|
|
8965
|
+
DimStyleSchema,
|
|
8966
|
+
{ ...cur, ...patch, id: cur.id },
|
|
8967
|
+
patch,
|
|
8968
|
+
`update dim style "${cur.name}"`
|
|
8969
|
+
)
|
|
8959
8970
|
});
|
|
8960
8971
|
}
|
|
8961
8972
|
/** Remove a dimension style no dimension uses (the kernel refuses
|
|
@@ -9031,6 +9042,7 @@ var LocalDrawing = class {
|
|
|
9031
9042
|
async addBlockDefinitions(sources) {
|
|
9032
9043
|
await ensureScriptTranspiler();
|
|
9033
9044
|
const report = mergeBlockModules(this.state.blockDefinitions, sources);
|
|
9045
|
+
refuseRejected(report, "block definition");
|
|
9034
9046
|
this.applyForwardAll(
|
|
9035
9047
|
diffModuleOps(
|
|
9036
9048
|
this.state.blockDefinitions,
|
|
@@ -9043,6 +9055,7 @@ var LocalDrawing = class {
|
|
|
9043
9055
|
async addUserCommands(sources) {
|
|
9044
9056
|
await ensureScriptTranspiler();
|
|
9045
9057
|
const report = mergeCommandModules(this.state.commands, sources);
|
|
9058
|
+
refuseRejected(report, "user command");
|
|
9046
9059
|
this.applyForwardAll(
|
|
9047
9060
|
diffModuleOps(this.state.commands, report.merged, "commands")
|
|
9048
9061
|
);
|
|
@@ -9132,7 +9145,6 @@ var LocalDrawing = class {
|
|
|
9132
9145
|
};
|
|
9133
9146
|
for (const plan of plans) {
|
|
9134
9147
|
const r = plan.kind === "block" ? await this.addBlockDefinitions(plan.sources) : await this.addUserCommands(plan.sources);
|
|
9135
|
-
if (r.rejected.length > 0) throw new Error(r.rejected[0].error);
|
|
9136
9148
|
report.merged = r.merged;
|
|
9137
9149
|
report.added.push(...r.added);
|
|
9138
9150
|
report.replaced.push(...r.replaced);
|
|
@@ -9146,7 +9158,8 @@ var LocalDrawing = class {
|
|
|
9146
9158
|
const source = this.state.blockDefinitions.find(
|
|
9147
9159
|
(s) => listBlockMeta([s]).some((r) => r.ok && r.meta.id === id)
|
|
9148
9160
|
);
|
|
9149
|
-
if (source === void 0)
|
|
9161
|
+
if (source === void 0)
|
|
9162
|
+
throw new DrawingError("unknownBlock", `Unknown block "${id}"`);
|
|
9150
9163
|
this.applyForward({ type: "remove-block-definition", source });
|
|
9151
9164
|
}
|
|
9152
9165
|
/** Remove a command module by its exported id (unknown id → error). */
|
|
@@ -9154,7 +9167,8 @@ var LocalDrawing = class {
|
|
|
9154
9167
|
const source = this.state.commands.find(
|
|
9155
9168
|
(s) => listCommandMeta([s]).some((r) => r.ok && r.meta.id === id)
|
|
9156
9169
|
);
|
|
9157
|
-
if (source === void 0)
|
|
9170
|
+
if (source === void 0)
|
|
9171
|
+
throw new DrawingError("unknownCommand", `Unknown command "${id}"`);
|
|
9158
9172
|
this.applyForward({ type: "remove-document-command", source });
|
|
9159
9173
|
}
|
|
9160
9174
|
/**
|
|
@@ -9230,7 +9244,7 @@ var LocalDrawing = class {
|
|
|
9230
9244
|
* to the model extents. Returns the layout id.
|
|
9231
9245
|
*/
|
|
9232
9246
|
addLayout(name, opts = {}) {
|
|
9233
|
-
this.assertLayoutName(name
|
|
9247
|
+
this.assertLayoutName(name);
|
|
9234
9248
|
const layout = this.makeLayout(name, opts);
|
|
9235
9249
|
this.applyForward({ type: "add-layout", layout, index: opts.index });
|
|
9236
9250
|
return layout.id;
|
|
@@ -9253,8 +9267,7 @@ var LocalDrawing = class {
|
|
|
9253
9267
|
/** Patch a layout's name / sheet (preset or mm) / print palette. */
|
|
9254
9268
|
updateLayout(nameOrId, patch) {
|
|
9255
9269
|
const layout = this.resolveLayout(nameOrId);
|
|
9256
|
-
if (patch.name !== void 0)
|
|
9257
|
-
this.assertLayoutName(patch.name, "updateLayout()", layout.id);
|
|
9270
|
+
if (patch.name !== void 0) this.assertLayoutName(patch.name, layout.id);
|
|
9258
9271
|
const { sheet, ...rest } = patch;
|
|
9259
9272
|
this.applyForward({
|
|
9260
9273
|
type: "update-layout-meta",
|
|
@@ -9264,6 +9277,14 @@ var LocalDrawing = class {
|
|
|
9264
9277
|
});
|
|
9265
9278
|
}
|
|
9266
9279
|
// --- object mutations ----------------------------------------------------
|
|
9280
|
+
/** What names in a new or changed object must resolve against. */
|
|
9281
|
+
get nameSources() {
|
|
9282
|
+
return {
|
|
9283
|
+
lineTypes: this.state.lineTypes,
|
|
9284
|
+
hatchPatterns: this.state.hatchPatterns,
|
|
9285
|
+
blockDefinitions: this.state.blockDefinitions
|
|
9286
|
+
};
|
|
9287
|
+
}
|
|
9267
9288
|
normalize(input, index) {
|
|
9268
9289
|
const { layer, layerId, id, ...rest } = input;
|
|
9269
9290
|
const context = `add(): objects[${index ?? 0}] (${String(input.type ?? "?")})`;
|
|
@@ -9276,9 +9297,16 @@ var LocalDrawing = class {
|
|
|
9276
9297
|
layerId: this.resolveLayerId(layer, layerId),
|
|
9277
9298
|
id: id ?? crypto.randomUUID()
|
|
9278
9299
|
};
|
|
9279
|
-
|
|
9280
|
-
|
|
9300
|
+
const obj = ModelObjectSchema.parse(raw);
|
|
9301
|
+
assertNoUnknownKeys(raw, obj, context, obj.type);
|
|
9302
|
+
assertSaneNumbers(obj, context);
|
|
9303
|
+
assertObjectFields(
|
|
9304
|
+
obj,
|
|
9305
|
+
new Set(Object.keys(rest)),
|
|
9306
|
+
this.nameSources,
|
|
9307
|
+
context
|
|
9281
9308
|
);
|
|
9309
|
+
return obj;
|
|
9282
9310
|
} catch (e) {
|
|
9283
9311
|
throw wrapZod(
|
|
9284
9312
|
e,
|
|
@@ -9310,18 +9338,25 @@ var LocalDrawing = class {
|
|
|
9310
9338
|
`update(): "${id}" (${cur.type})`
|
|
9311
9339
|
) : {};
|
|
9312
9340
|
const staleSpans = cur.type === "text" && "content" in rest && !("spans" in rest) ? { spans: void 0 } : {};
|
|
9341
|
+
const context = `update(): "${id}" (${cur.type})`;
|
|
9313
9342
|
try {
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9343
|
+
const obj = ModelObjectSchema.parse({
|
|
9344
|
+
...cur,
|
|
9345
|
+
...rest,
|
|
9346
|
+
...staleSpans,
|
|
9347
|
+
...styleRef,
|
|
9348
|
+
...resolvedLayerId ? { layerId: resolvedLayerId } : {},
|
|
9349
|
+
id
|
|
9350
|
+
});
|
|
9351
|
+
assertNoUnknownKeys(rest, obj, context, cur.type);
|
|
9352
|
+
assertSaneNumbers(rest, context);
|
|
9353
|
+
assertObjectFields(
|
|
9354
|
+
obj,
|
|
9355
|
+
new Set(Object.keys(rest)),
|
|
9356
|
+
this.nameSources,
|
|
9357
|
+
context
|
|
9358
|
+
);
|
|
9359
|
+
return { space, obj };
|
|
9325
9360
|
} catch (e) {
|
|
9326
9361
|
throw wrapZod(e, `update(): "${id}" (${cur.type})`);
|
|
9327
9362
|
}
|
|
@@ -9430,22 +9465,50 @@ var LocalDrawing = class {
|
|
|
9430
9465
|
mirror(ids, a, b) {
|
|
9431
9466
|
const pa = toVec(a);
|
|
9432
9467
|
const pb = toVec(b);
|
|
9468
|
+
if (pa.x === pb.x && pa.y === pb.y)
|
|
9469
|
+
throw new DrawingError(
|
|
9470
|
+
"validation",
|
|
9471
|
+
"Mirror needs two different points for its axis"
|
|
9472
|
+
);
|
|
9433
9473
|
this.transformEach(ids, (o) => mirrorObject(o, pa, pb));
|
|
9434
9474
|
}
|
|
9435
9475
|
/** Duplicate objects (into their own space) displaced by `delta`. */
|
|
9436
9476
|
copy(ids, delta) {
|
|
9437
|
-
|
|
9477
|
+
return this.copySteps(ids, [toVec(delta)]);
|
|
9478
|
+
}
|
|
9479
|
+
/**
|
|
9480
|
+
* Linear array: `count` TOTAL instances (including the originals) stepped
|
|
9481
|
+
* by `delta`. Returns the new ids, one batch per step, in one undo step.
|
|
9482
|
+
*/
|
|
9483
|
+
array(ids, count, delta) {
|
|
9484
|
+
if (!Number.isInteger(count) || count < 1)
|
|
9485
|
+
throw new Error(`Invalid array count ${count}`);
|
|
9438
9486
|
const d = toVec(delta);
|
|
9439
|
-
const
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9487
|
+
const steps = Array.from({ length: count - 1 }, (_, i) => ({
|
|
9488
|
+
x: d.x * (i + 1),
|
|
9489
|
+
y: d.y * (i + 1)
|
|
9490
|
+
}));
|
|
9491
|
+
return this.copySteps(ids, steps);
|
|
9492
|
+
}
|
|
9493
|
+
/** One displaced copy of `ids` per step, applied as ONE add op per space
|
|
9494
|
+
* (an op per step re-copied the whole space each time: quadratic). */
|
|
9495
|
+
copySteps(ids, steps) {
|
|
9496
|
+
if (ids.length === 0 || steps.length === 0) return [];
|
|
9497
|
+
const total2 = ids.length * steps.length;
|
|
9498
|
+
if (total2 > MAX_COPIES)
|
|
9499
|
+
throw new Error(
|
|
9500
|
+
`That would create ${total2} objects; one copy or array makes at most ${MAX_COPIES}.`
|
|
9501
|
+
);
|
|
9502
|
+
const sources = ids.map((id) => this.findObject(id));
|
|
9503
|
+
const clones = steps.flatMap((d) => {
|
|
9504
|
+
const idMap = new Map(ids.map((id) => [id, crypto.randomUUID()]));
|
|
9505
|
+
return sources.map(({ obj, space }) => ({
|
|
9443
9506
|
space,
|
|
9444
9507
|
obj: ModelObjectSchema.parse({
|
|
9445
9508
|
...remapBlockInputRefs(translateObject(obj, d), idMap),
|
|
9446
|
-
id: idMap.get(id)
|
|
9509
|
+
id: idMap.get(obj.id)
|
|
9447
9510
|
})
|
|
9448
|
-
};
|
|
9511
|
+
}));
|
|
9449
9512
|
});
|
|
9450
9513
|
this.applyBySpace(clones, (space, objects) => ({
|
|
9451
9514
|
type: "add-objects",
|
|
@@ -9454,21 +9517,6 @@ var LocalDrawing = class {
|
|
|
9454
9517
|
}));
|
|
9455
9518
|
return clones.map((c) => c.obj.id);
|
|
9456
9519
|
}
|
|
9457
|
-
/**
|
|
9458
|
-
* Linear array: `count` TOTAL instances (including the originals) stepped
|
|
9459
|
-
* by `delta`. Returns the new ids, one batch per step, in one undo step.
|
|
9460
|
-
*/
|
|
9461
|
-
array(ids, count, delta) {
|
|
9462
|
-
if (!Number.isInteger(count) || count < 1)
|
|
9463
|
-
throw new Error(`Invalid array count ${count}`);
|
|
9464
|
-
const d = toVec(delta);
|
|
9465
|
-
return this.transaction(() => {
|
|
9466
|
-
const created = [];
|
|
9467
|
-
for (let i = 1; i < count; i++)
|
|
9468
|
-
created.push(...this.copy(ids, { x: d.x * i, y: d.y * i }));
|
|
9469
|
-
return created;
|
|
9470
|
-
});
|
|
9471
|
-
}
|
|
9472
9520
|
// --- reads ---------------------------------------------------------------
|
|
9473
9521
|
get measurer() {
|
|
9474
9522
|
return this.hooks.measure ?? approximateTextMeasurer;
|
|
@@ -9632,7 +9680,8 @@ var LocalDrawing = class {
|
|
|
9632
9680
|
const layout = this.state.layouts.find(
|
|
9633
9681
|
(l) => l.name === nameOrId || l.id === nameOrId
|
|
9634
9682
|
);
|
|
9635
|
-
if (!layout)
|
|
9683
|
+
if (!layout)
|
|
9684
|
+
throw new DrawingError("unknownLayout", `Unknown layout "${nameOrId}"`);
|
|
9636
9685
|
return layout;
|
|
9637
9686
|
}
|
|
9638
9687
|
/** Render model space (or a paper layout via `layout`) to an SVG string. */
|
|
@@ -9643,11 +9692,18 @@ var LocalDrawing = class {
|
|
|
9643
9692
|
this.paintContext(),
|
|
9644
9693
|
opts
|
|
9645
9694
|
);
|
|
9646
|
-
return renderModelToSvg(this.paintContext(),
|
|
9695
|
+
return renderModelToSvg(this.paintContext(), {
|
|
9696
|
+
lineTypeScale: this.document.settings.modelScale,
|
|
9697
|
+
// Model lineweights are true mm: on a building-sized drawing they
|
|
9698
|
+
// rasterize sub-pixel and read as a blank sheet. Keep every stroke
|
|
9699
|
+
// ≥ ~1.5 px at the output width (PNG) or a 1024 px view (SVG).
|
|
9700
|
+
minStrokeFrac: 1.5 / (opts.width ?? 1024),
|
|
9701
|
+
...opts
|
|
9702
|
+
});
|
|
9647
9703
|
}
|
|
9648
9704
|
/** Export the document to a DXF string. */
|
|
9649
9705
|
async toDxf() {
|
|
9650
|
-
const { buildDxf } = await import("./exportDxf-
|
|
9706
|
+
const { buildDxf } = await import("./exportDxf-6XTXQ4XN.js");
|
|
9651
9707
|
return buildDxf(this.state, this.measurer).content;
|
|
9652
9708
|
}
|
|
9653
9709
|
/** Export the document to DWG bytes (the DXF content, wasm-transcoded).
|
|
@@ -9656,7 +9712,7 @@ var LocalDrawing = class {
|
|
|
9656
9712
|
* exploded to plain geometry (DWG_DXF_OPTIONS — the transcoder's DWG
|
|
9657
9713
|
* output for them is not accepted by AutoCAD). */
|
|
9658
9714
|
async toDwg(opts) {
|
|
9659
|
-
const { buildDxf, DWG_DXF_OPTIONS } = await import("./exportDxf-
|
|
9715
|
+
const { buildDxf, DWG_DXF_OPTIONS } = await import("./exportDxf-6XTXQ4XN.js");
|
|
9660
9716
|
const dxf = buildDxf(this.state, this.measurer, DWG_DXF_OPTIONS).content;
|
|
9661
9717
|
return dxfToDwg(dxf, opts?.version ?? "AC1027");
|
|
9662
9718
|
}
|
|
@@ -9790,7 +9846,7 @@ var runCommandModule = async (source, opts) => {
|
|
|
9790
9846
|
}
|
|
9791
9847
|
};
|
|
9792
9848
|
var namedEditorError = (name, e) => {
|
|
9793
|
-
const m = e instanceof TypeError ? /reading '(pickPoint|pickPoints|pickObject|pickObjects|prompt|ask|toast|state|setSelection|setActiveSpace|zoom|listCommands|runCommand)'/.exec(
|
|
9849
|
+
const m = e instanceof TypeError ? /(?:reading|property) '(pickPoint|pickPoints|pickObject|pickObjects|prompt|ask|toast|state|setSelection|setActiveSpace|zoom|listCommands|runCommand)'/.exec(
|
|
9794
9850
|
e.message
|
|
9795
9851
|
) : null;
|
|
9796
9852
|
if (!m) return e;
|
|
@@ -9982,7 +10038,10 @@ var Drawing = class extends LocalDrawing {
|
|
|
9982
10038
|
this.paintContext(),
|
|
9983
10039
|
opts
|
|
9984
10040
|
);
|
|
9985
|
-
return renderModelToPng(this.paintContext(),
|
|
10041
|
+
return renderModelToPng(this.paintContext(), {
|
|
10042
|
+
lineTypeScale: this.document.settings.modelScale,
|
|
10043
|
+
...opts
|
|
10044
|
+
});
|
|
9986
10045
|
}
|
|
9987
10046
|
/** Multi-page PDF of the layouts (default: all) with the embedded fonts. */
|
|
9988
10047
|
async renderPdf(opts = {}) {
|
|
@@ -10094,10 +10153,12 @@ export {
|
|
|
10094
10153
|
ensureScriptTranspiler,
|
|
10095
10154
|
getBlockMetaResult,
|
|
10096
10155
|
getCommandMetaResult,
|
|
10156
|
+
hatchLoop,
|
|
10097
10157
|
newDrawing,
|
|
10098
10158
|
openDrawing,
|
|
10099
10159
|
parseScale,
|
|
10100
10160
|
renderBlockThumbnailSvg,
|
|
10161
|
+
splineThrough,
|
|
10101
10162
|
testBlockDefinition
|
|
10102
10163
|
};
|
|
10103
10164
|
//# sourceMappingURL=sdk.js.map
|