forgecad 0.9.4 → 0.9.5
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/dist/assets/{AdminPage-jwoEgwE_.js → AdminPage-uTtcSXtn.js} +1 -1
- package/dist/assets/{BlogPage-Ck7g3ue2.js → BlogPage-DYJMjWx3.js} +1 -1
- package/dist/assets/{DocsPage-9WaRC14b.js → DocsPage-C58f0K5v.js} +1 -6
- package/dist/assets/{EditorApp-Dja2jMmW.js → EditorApp-DNH1TEz1.js} +282 -62
- package/dist/assets/{EmbedViewer-37_PfMwv.js → EmbedViewer-CMXWA2LX.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-CO8WL0CY.js → LandingPageProofDriven-CAu2OZFn.js} +1 -1
- package/dist/assets/{PricingPage-DADKGuOa.js → PricingPage-BIgW7m3X.js} +1 -1
- package/dist/assets/{SettingsPage-DKKI4W49.js → SettingsPage-N1l1tMXO.js} +1 -1
- package/dist/assets/{app-CwI02pTA.js → app-CFy7g5WP.js} +74 -12
- package/dist/assets/cli/{render-Kw5hLEcL.js → render-BrVVdj_T.js} +453 -41
- package/dist/assets/{evalWorker-D6ub3kfS.js → evalWorker-c_SB9gg3.js} +2057 -446
- package/dist/assets/{manifold-lru0jwVw.js → manifold-CRoBhJKH.js} +2 -2
- package/dist/assets/{manifold-CwDdMKyc.js → manifold-Cjk7WhRs.js} +1 -1
- package/dist/assets/{manifold-DTvmxSDf.js → manifold-Dp6pvFr6.js} +1 -1
- package/dist/assets/{renderSceneState-tvtNKNRi.js → renderSceneState-3DfsSASX.js} +1 -1
- package/dist/assets/{reportWorker-DeqktDGt.js → reportWorker-BLkuIoS8.js} +2052 -443
- package/dist/assets/{sectionPlaneMath-C8N0w8o3.js → sectionPlaneMath-CykEnkvQ.js} +2258 -518
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +2 -2
- package/dist/docs-raw/AI/usage.md +0 -1
- package/dist/docs-raw/API/core/concepts.md +11 -1
- package/dist/docs-raw/CLI.md +64 -13
- package/dist/docs-raw/generated/assembly.md +8 -3
- package/dist/docs-raw/generated/concepts.md +44 -41
- package/dist/docs-raw/generated/core.md +97 -47
- package/dist/docs-raw/generated/curves.md +6 -580
- package/dist/docs-raw/generated/lib.md +40 -3
- package/dist/docs-raw/generated/output.md +6 -1
- package/dist/docs-raw/generated/sdf.md +50 -4
- package/dist/docs-raw/generated/viewport.md +1 -9
- package/dist/docs-raw/guides/inspection-bundles.md +31 -6
- package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -0
- package/dist/docs-raw/skills/forgecad-image-replicator.md +3 -1
- package/dist/docs-raw/skills/forgecad-make-a-model.md +48 -4
- package/dist/docs-raw/skills/forgecad-render-inspect.md +3 -1
- package/dist/docs-raw/skills/forgecad-visual-spec.md +2 -0
- package/dist/docs-raw/skills/forgecad.md +2 -1
- package/dist/docs-raw/skills/index.md +0 -1
- package/dist/index.html +1 -1
- package/dist/sitemap.xml +6 -6
- package/dist-cli/blender/render.py +43 -8
- package/dist-cli/forgecad.js +4941 -1758
- package/dist-cli/forgecad.js.map +1 -1
- package/dist-skill/CONTEXT.md +255 -656
- package/dist-skill/SKILL-dev.md +2 -1
- package/dist-skill/SKILL.md +2 -1
- package/dist-skill/docs/API/core/concepts.md +11 -1
- package/dist-skill/docs/CLI.md +64 -13
- package/dist-skill/docs/generated/assembly.md +8 -3
- package/dist-skill/docs/generated/core.md +97 -47
- package/dist-skill/docs/generated/curves.md +6 -580
- package/dist-skill/docs/generated/lib.md +40 -3
- package/dist-skill/docs/generated/output.md +6 -1
- package/dist-skill/docs/generated/sdf.md +50 -4
- package/dist-skill/docs/generated/viewport.md +1 -9
- package/dist-skill/docs/guides/inspection-bundles.md +31 -6
- package/dist-skill/docs-dev/API/core/concepts.md +11 -1
- package/dist-skill/docs-dev/CLI.md +64 -13
- package/dist-skill/docs-dev/generated/assembly.md +8 -3
- package/dist-skill/docs-dev/generated/core.md +97 -47
- package/dist-skill/docs-dev/generated/curves.md +6 -580
- package/dist-skill/docs-dev/generated/lib.md +40 -3
- package/dist-skill/docs-dev/generated/output.md +6 -1
- package/dist-skill/docs-dev/generated/sdf.md +50 -4
- package/dist-skill/docs-dev/generated/viewport.md +1 -9
- package/dist-skill/docs-dev/guides/inspection-bundles.md +31 -6
- package/dist-skill/library/README.md +0 -1
- package/dist-skill/library/forgecad-blockout-model/SKILL.md +1 -0
- package/dist-skill/library/forgecad-image-replicator/SKILL.md +3 -1
- package/dist-skill/library/forgecad-make-a-model/SKILL.md +48 -4
- package/dist-skill/library/forgecad-render-inspect/SKILL.md +3 -1
- package/dist-skill/library/forgecad-visual-spec/SKILL.md +2 -0
- package/examples/api/drive-wheel-regions.forge.js +43 -0
- package/examples/api/sdf-circular-array-knurling.forge.js +19 -0
- package/examples/api/sdf-pattern2d-ceramic-ripple-set.forge.js +83 -0
- package/examples/api/sdf-pattern2d-grip-tread.forge.js +72 -0
- package/examples/api/sdf-pattern2d-orbital-jewelry.forge.js +62 -0
- package/examples/api/sdf-surface-basket-weave.forge.js +67 -0
- package/examples/api/sector-gear-body.forge.js +34 -0
- package/package.json +1 -1
- package/dist/docs-raw/skills/forgecad-api-dogfood.md +0 -130
- package/dist-skill/library/forgecad-api-dogfood/SKILL.md +0 -125
|
@@ -620,6 +620,47 @@ function cloneSdfFunctionConstants(constants) {
|
|
|
620
620
|
if (!constants) return void 0;
|
|
621
621
|
return Object.fromEntries(Object.entries(constants).map(([key, value]) => [key, cloneSdfFunctionConstant(value)]));
|
|
622
622
|
}
|
|
623
|
+
function cloneSdfSurfacePatternNode(pattern) {
|
|
624
|
+
switch (pattern.kind) {
|
|
625
|
+
case "surfacePattern:constant":
|
|
626
|
+
return { kind: "surfacePattern:constant", value: pattern.value };
|
|
627
|
+
case "surfacePattern:sineWave":
|
|
628
|
+
return {
|
|
629
|
+
kind: "surfacePattern:sineWave",
|
|
630
|
+
direction: [...pattern.direction],
|
|
631
|
+
wavelength: pattern.wavelength,
|
|
632
|
+
amplitude: pattern.amplitude,
|
|
633
|
+
phase: pattern.phase,
|
|
634
|
+
bias: pattern.bias
|
|
635
|
+
};
|
|
636
|
+
case "surfacePattern:stripes":
|
|
637
|
+
return {
|
|
638
|
+
kind: "surfacePattern:stripes",
|
|
639
|
+
direction: [...pattern.direction],
|
|
640
|
+
spacing: pattern.spacing,
|
|
641
|
+
width: pattern.width,
|
|
642
|
+
depth: pattern.depth
|
|
643
|
+
};
|
|
644
|
+
case "surfacePattern:overUnderWeave":
|
|
645
|
+
return {
|
|
646
|
+
kind: "surfacePattern:overUnderWeave",
|
|
647
|
+
spacing: [...pattern.spacing],
|
|
648
|
+
threadWidth: [...pattern.threadWidth],
|
|
649
|
+
depth: pattern.depth,
|
|
650
|
+
underScale: pattern.underScale
|
|
651
|
+
};
|
|
652
|
+
case "surfacePattern:abs":
|
|
653
|
+
case "surfacePattern:negate":
|
|
654
|
+
return { kind: pattern.kind, child: cloneSdfSurfacePatternNode(pattern.child) };
|
|
655
|
+
case "surfacePattern:add":
|
|
656
|
+
case "surfacePattern:multiply":
|
|
657
|
+
case "surfacePattern:min":
|
|
658
|
+
case "surfacePattern:max":
|
|
659
|
+
return { kind: pattern.kind, children: pattern.children.map(cloneSdfSurfacePatternNode) };
|
|
660
|
+
case "surfacePattern:clamp":
|
|
661
|
+
return { kind: "surfacePattern:clamp", child: cloneSdfSurfacePatternNode(pattern.child), min: pattern.min, max: pattern.max };
|
|
662
|
+
}
|
|
663
|
+
}
|
|
623
664
|
function cloneSdfNode(node) {
|
|
624
665
|
switch (node.kind) {
|
|
625
666
|
// Primitives — plain value types
|
|
@@ -670,6 +711,8 @@ function cloneSdfNode(node) {
|
|
|
670
711
|
return { kind: "sdf:bend", child: cloneSdfNode(node.child), radius: node.radius };
|
|
671
712
|
case "sdf:repeat":
|
|
672
713
|
return { kind: "sdf:repeat", child: cloneSdfNode(node.child), spacing: [...node.spacing], count: [...node.count] };
|
|
714
|
+
case "sdf:circularArray":
|
|
715
|
+
return { kind: "sdf:circularArray", child: cloneSdfNode(node.child), count: node.count, offset: node.offset };
|
|
673
716
|
case "sdf:shell":
|
|
674
717
|
return { kind: "sdf:shell", child: cloneSdfNode(node.child), thickness: node.thickness };
|
|
675
718
|
case "sdf:displace":
|
|
@@ -683,6 +726,7 @@ function cloneSdfNode(node) {
|
|
|
683
726
|
return {
|
|
684
727
|
kind: "sdf:surfaceDisplace",
|
|
685
728
|
child: cloneSdfNode(node.child),
|
|
729
|
+
...node.pattern ? { pattern: cloneSdfSurfacePatternNode(node.pattern) } : {},
|
|
686
730
|
patternBody: node.patternBody,
|
|
687
731
|
...node.constants ? { constants: cloneSdfFunctionConstants(node.constants) } : {},
|
|
688
732
|
...node.uvMode ? { uvMode: node.uvMode } : {},
|
|
@@ -4724,7 +4768,7 @@ for (var i = 0; i < 32; ++i)
|
|
|
4724
4768
|
fdt[i] = 5;
|
|
4725
4769
|
var flm = /* @__PURE__ */ hMap(flt, 9, 0), flrm = /* @__PURE__ */ hMap(flt, 9, 1);
|
|
4726
4770
|
var fdm = /* @__PURE__ */ hMap(fdt, 5, 0), fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);
|
|
4727
|
-
var max$
|
|
4771
|
+
var max$2 = function(a2) {
|
|
4728
4772
|
var m2 = a2[0];
|
|
4729
4773
|
for (var i = 1; i < a2.length; ++i) {
|
|
4730
4774
|
if (a2[i] > m2)
|
|
@@ -4824,7 +4868,7 @@ var inflt = function(dat, st, buf, dict) {
|
|
|
4824
4868
|
clt[clim[i]] = bits(dat, pos + i * 3, 7);
|
|
4825
4869
|
}
|
|
4826
4870
|
pos += hcLen * 3;
|
|
4827
|
-
var clb = max$
|
|
4871
|
+
var clb = max$2(clt), clbmsk = (1 << clb) - 1;
|
|
4828
4872
|
var clm = hMap(clt, clb, 1);
|
|
4829
4873
|
for (var i = 0; i < tl; ) {
|
|
4830
4874
|
var r = clm[bits(dat, pos, clbmsk)];
|
|
@@ -4845,8 +4889,8 @@ var inflt = function(dat, st, buf, dict) {
|
|
|
4845
4889
|
}
|
|
4846
4890
|
}
|
|
4847
4891
|
var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
|
|
4848
|
-
lbt = max$
|
|
4849
|
-
dbt = max$
|
|
4892
|
+
lbt = max$2(lt);
|
|
4893
|
+
dbt = max$2(dt);
|
|
4850
4894
|
lm = hMap(lt, lbt, 1);
|
|
4851
4895
|
dm = hMap(dt, dbt, 1);
|
|
4852
4896
|
} else
|
|
@@ -5698,9 +5742,9 @@ function parse3mf(data) {
|
|
|
5698
5742
|
let tMatch;
|
|
5699
5743
|
while ((tMatch = trianglePattern.exec(meshXml)) !== null) {
|
|
5700
5744
|
const v1 = parseInt(tMatch[1], 10) + vertexOffset;
|
|
5701
|
-
const
|
|
5745
|
+
const v22 = parseInt(tMatch[2], 10) + vertexOffset;
|
|
5702
5746
|
const v32 = parseInt(tMatch[3], 10) + vertexOffset;
|
|
5703
|
-
allTriIndices.push(v1,
|
|
5747
|
+
allTriIndices.push(v1, v22, v32);
|
|
5704
5748
|
}
|
|
5705
5749
|
for (let i = 0; i < meshVerts.length; i++) {
|
|
5706
5750
|
allPositions.push(meshVerts[i]);
|
|
@@ -6083,6 +6127,287 @@ function lowerShellShapeCompilePlanToConcretePlan(plan) {
|
|
|
6083
6127
|
}
|
|
6084
6128
|
return lowerBaseShellPlanToConcretePlan(plan.base, plan.thickness, normalizeShellOpenFaces(plan.openFaces));
|
|
6085
6129
|
}
|
|
6130
|
+
const DEFAULT_MAX_GRID_POINTS = 8e6;
|
|
6131
|
+
const DEFAULT_MIN_EDGE_LENGTH = 0.15;
|
|
6132
|
+
function resolveSdfMeshingSettings(tree, bounds, options = {}) {
|
|
6133
|
+
const quality = options.quality ?? "preview";
|
|
6134
|
+
const minEdgeLength = positiveOrDefault(options.minEdgeLength, DEFAULT_MIN_EDGE_LENGTH);
|
|
6135
|
+
const maxGridPoints = positiveOrDefault(options.maxGridPoints, DEFAULT_MAX_GRID_POINTS);
|
|
6136
|
+
const tolerance = options.tolerance !== void 0 ? requirePositiveFinite$3(options.tolerance, "SDF tolerance") : void 0;
|
|
6137
|
+
const minFeatureSize = options.minFeatureSize !== void 0 ? requirePositiveFinite$3(options.minFeatureSize, "SDF minFeatureSize") : void 0;
|
|
6138
|
+
const maxTriangles = options.maxTriangles !== void 0 ? Math.floor(requirePositiveFinite$3(options.maxTriangles, "SDF maxTriangles")) : void 0;
|
|
6139
|
+
const analysis = analyzeSdfTree(tree);
|
|
6140
|
+
const warnings = [];
|
|
6141
|
+
let edgeLength2;
|
|
6142
|
+
if (options.edgeLength !== void 0) {
|
|
6143
|
+
edgeLength2 = requirePositiveFinite$3(options.edgeLength, "SDF edgeLength");
|
|
6144
|
+
if (edgeLength2 < minEdgeLength) {
|
|
6145
|
+
warnings.push(`edgeLength ${formatMm(edgeLength2)} was clamped to minimum ${formatMm(minEdgeLength)}.`);
|
|
6146
|
+
edgeLength2 = minEdgeLength;
|
|
6147
|
+
}
|
|
6148
|
+
} else {
|
|
6149
|
+
edgeLength2 = resolveDefaultEdgeLength(bounds, quality, minEdgeLength, analysis, options);
|
|
6150
|
+
}
|
|
6151
|
+
if (analysis.minWallThickness < Infinity && analysis.minWallThickness < edgeLength2 * 2) {
|
|
6152
|
+
analysis.riskFlags.add("thin-shell");
|
|
6153
|
+
warnings.push(
|
|
6154
|
+
`shell/wall thickness ${formatMm(analysis.minWallThickness)} is below 2 x edgeLength ${formatMm(edgeLength2)}; thin features may be under-sampled.`
|
|
6155
|
+
);
|
|
6156
|
+
}
|
|
6157
|
+
if (!options.bounds && analysis.hasInfiniteRepeat) {
|
|
6158
|
+
warnings.push("infinite repeat bounds are heuristic; pass .toShape({ bounds }) for predictable clipping.");
|
|
6159
|
+
}
|
|
6160
|
+
if (!options.bounds && analysis.riskFlags.has("noise")) {
|
|
6161
|
+
warnings.push("noise field bounds are heuristic; pass .toShape({ bounds }) for predictable clipping.");
|
|
6162
|
+
}
|
|
6163
|
+
if (!options.bounds && (analysis.riskFlags.has("tpms") || analysis.riskFlags.has("voronoi"))) {
|
|
6164
|
+
warnings.push("TPMS/Voronoi bounds are heuristic unless clipped or passed explicitly.");
|
|
6165
|
+
}
|
|
6166
|
+
if (analysis.hasLegacyTpmsThreshold) {
|
|
6167
|
+
warnings.push("TPMS thickness is using legacy field-threshold units; use wallThickness for approximate millimeters.");
|
|
6168
|
+
}
|
|
6169
|
+
return {
|
|
6170
|
+
quality,
|
|
6171
|
+
edgeLength: edgeLength2,
|
|
6172
|
+
tolerance,
|
|
6173
|
+
minFeatureSize,
|
|
6174
|
+
minEdgeLength,
|
|
6175
|
+
simplify: resolveSimplificationMode(options.simplify, quality, analysis.riskFlags),
|
|
6176
|
+
maxTriangles,
|
|
6177
|
+
maxGridPoints,
|
|
6178
|
+
diagnostics: options.diagnostics === true,
|
|
6179
|
+
treeRiskFlags: [...analysis.riskFlags].sort(),
|
|
6180
|
+
warnings
|
|
6181
|
+
};
|
|
6182
|
+
}
|
|
6183
|
+
function withScaledSdfEdgeLength(settings, edgeLength2) {
|
|
6184
|
+
return { ...settings, edgeLength: Math.max(settings.minEdgeLength, edgeLength2) };
|
|
6185
|
+
}
|
|
6186
|
+
function createSdfMeshingDiagnostics(settings, bounds, paddedBounds) {
|
|
6187
|
+
const grid = estimateSdfGridDimensions(paddedBounds, settings.edgeLength);
|
|
6188
|
+
const estimatedSamples = grid[0] * grid[1] * grid[2];
|
|
6189
|
+
return {
|
|
6190
|
+
bounds: cloneBounds$2(bounds),
|
|
6191
|
+
paddedBounds: cloneBounds$2(paddedBounds),
|
|
6192
|
+
edgeLength: settings.edgeLength,
|
|
6193
|
+
grid,
|
|
6194
|
+
estimatedSamples,
|
|
6195
|
+
estimatedMemoryBytes: estimatedSamples * 8,
|
|
6196
|
+
treeRiskFlags: [...settings.treeRiskFlags],
|
|
6197
|
+
simplification: settings.simplify,
|
|
6198
|
+
capMode: "box",
|
|
6199
|
+
capInset: settings.edgeLength,
|
|
6200
|
+
warnings: [...settings.warnings]
|
|
6201
|
+
};
|
|
6202
|
+
}
|
|
6203
|
+
function assertSdfMeshingBudget(diagnostics, maxGridPoints) {
|
|
6204
|
+
if (diagnostics.estimatedSamples <= maxGridPoints) return;
|
|
6205
|
+
const suggestedEdge = suggestEdgeLengthForSampleBudget(diagnostics.paddedBounds, maxGridPoints);
|
|
6206
|
+
throw new Error(
|
|
6207
|
+
`SDF meshing would sample ${formatCount(diagnostics.estimatedSamples)} grid points (~${formatBytes(
|
|
6208
|
+
diagnostics.estimatedMemoryBytes
|
|
6209
|
+
)}). Reduce bounds or use edgeLength >= ${formatMm(suggestedEdge)}.`
|
|
6210
|
+
);
|
|
6211
|
+
}
|
|
6212
|
+
function estimateSdfGridDimensions(bounds, edgeLength2) {
|
|
6213
|
+
const dx = bounds.max[0] - bounds.min[0];
|
|
6214
|
+
const dy = bounds.max[1] - bounds.min[1];
|
|
6215
|
+
const dz = bounds.max[2] - bounds.min[2];
|
|
6216
|
+
return [
|
|
6217
|
+
Math.max(2, Math.ceil(dx / edgeLength2) + 1),
|
|
6218
|
+
Math.max(2, Math.ceil(dy / edgeLength2) + 1),
|
|
6219
|
+
Math.max(2, Math.ceil(dz / edgeLength2) + 1)
|
|
6220
|
+
];
|
|
6221
|
+
}
|
|
6222
|
+
function logSdfMeshingDiagnostics(prefix, diagnostics) {
|
|
6223
|
+
const warnings = diagnostics.warnings.length > 0 ? `, warnings=${diagnostics.warnings.join(" | ")}` : "";
|
|
6224
|
+
const evaluator = diagnostics.evaluator ? `, evaluator=${diagnostics.evaluator}${diagnostics.evaluatorUnsupportedReason ? ` (${diagnostics.evaluatorUnsupportedReason})` : ""}` : "";
|
|
6225
|
+
console.info(
|
|
6226
|
+
`${prefix}: bounds=${formatBounds(diagnostics.bounds)}, paddedBounds=${formatBounds(diagnostics.paddedBounds)}, edgeLength=${formatMm(diagnostics.edgeLength)}, grid=${diagnostics.grid.join("x")}, estimatedSamples=${formatCount(diagnostics.estimatedSamples)}, treeRisk=${diagnostics.treeRiskFlags.join("+") || "none"}, simplify=${diagnostics.simplification}${evaluator}, capMode=${diagnostics.capMode}, capInset=${formatMm(diagnostics.capInset)}${warnings}`
|
|
6227
|
+
);
|
|
6228
|
+
}
|
|
6229
|
+
function resolveDefaultEdgeLength(bounds, quality, minEdgeLength, analysis, options) {
|
|
6230
|
+
const dx = bounds.max[0] - bounds.min[0];
|
|
6231
|
+
const dy = bounds.max[1] - bounds.min[1];
|
|
6232
|
+
const dz = bounds.max[2] - bounds.min[2];
|
|
6233
|
+
const maxDim = Math.max(dx, dy, dz, minEdgeLength);
|
|
6234
|
+
const divisor = quality === "draft" ? 60 : quality === "export" ? 160 : 100;
|
|
6235
|
+
const candidates = [maxDim / divisor];
|
|
6236
|
+
if (options.tolerance !== void 0) candidates.push(requirePositiveFinite$3(options.tolerance, "SDF tolerance") * 2);
|
|
6237
|
+
if (options.minFeatureSize !== void 0) candidates.push(requirePositiveFinite$3(options.minFeatureSize, "SDF minFeatureSize") / 2.5);
|
|
6238
|
+
if (analysis.minMetricTpmsThickness < Infinity) candidates.push(analysis.minMetricTpmsThickness / 2);
|
|
6239
|
+
if (analysis.minTpmsCellSize < Infinity) candidates.push(analysis.minTpmsCellSize / 10);
|
|
6240
|
+
if (analysis.minRepeatSpacing < Infinity) candidates.push(analysis.minRepeatSpacing / 8);
|
|
6241
|
+
if (analysis.minWallThickness < Infinity) candidates.push(analysis.minWallThickness / 2.5);
|
|
6242
|
+
return Math.max(minEdgeLength, Math.min(...candidates.filter((v) => Number.isFinite(v) && v > 0)));
|
|
6243
|
+
}
|
|
6244
|
+
function resolveSimplificationMode(simplify, quality, riskFlags) {
|
|
6245
|
+
if (simplify === false) return "off";
|
|
6246
|
+
if (simplify === true || simplify === "safe") return "safe";
|
|
6247
|
+
if (quality === "export" && riskFlags.size > 0) return "off";
|
|
6248
|
+
return "safe";
|
|
6249
|
+
}
|
|
6250
|
+
function analyzeSdfTree(tree) {
|
|
6251
|
+
const analysis = {
|
|
6252
|
+
riskFlags: /* @__PURE__ */ new Set(),
|
|
6253
|
+
minTpmsCellSize: Infinity,
|
|
6254
|
+
minMetricTpmsThickness: Infinity,
|
|
6255
|
+
minRepeatSpacing: Infinity,
|
|
6256
|
+
minWallThickness: Infinity,
|
|
6257
|
+
hasInfiniteRepeat: false,
|
|
6258
|
+
hasLegacyTpmsThreshold: false
|
|
6259
|
+
};
|
|
6260
|
+
visitSdfNode(tree, analysis);
|
|
6261
|
+
return analysis;
|
|
6262
|
+
}
|
|
6263
|
+
function minPositive$1(...values) {
|
|
6264
|
+
let result = Infinity;
|
|
6265
|
+
for (const value of values) {
|
|
6266
|
+
if (value !== null && value !== void 0 && Number.isFinite(value) && value > 0) {
|
|
6267
|
+
result = Math.min(result, value);
|
|
6268
|
+
}
|
|
6269
|
+
}
|
|
6270
|
+
return result === Infinity ? null : result;
|
|
6271
|
+
}
|
|
6272
|
+
function estimateSurfacePatternSpacing(pattern) {
|
|
6273
|
+
switch (pattern.kind) {
|
|
6274
|
+
case "surfacePattern:constant":
|
|
6275
|
+
return null;
|
|
6276
|
+
case "surfacePattern:sineWave":
|
|
6277
|
+
return pattern.wavelength;
|
|
6278
|
+
case "surfacePattern:stripes":
|
|
6279
|
+
return Math.min(pattern.spacing, pattern.width);
|
|
6280
|
+
case "surfacePattern:overUnderWeave":
|
|
6281
|
+
return Math.min(...pattern.spacing, ...pattern.threadWidth);
|
|
6282
|
+
case "surfacePattern:abs":
|
|
6283
|
+
case "surfacePattern:negate":
|
|
6284
|
+
return estimateSurfacePatternSpacing(pattern.child);
|
|
6285
|
+
case "surfacePattern:add":
|
|
6286
|
+
case "surfacePattern:multiply":
|
|
6287
|
+
case "surfacePattern:min":
|
|
6288
|
+
case "surfacePattern:max":
|
|
6289
|
+
return minPositive$1(...pattern.children.map(estimateSurfacePatternSpacing));
|
|
6290
|
+
case "surfacePattern:clamp":
|
|
6291
|
+
return estimateSurfacePatternSpacing(pattern.child);
|
|
6292
|
+
}
|
|
6293
|
+
}
|
|
6294
|
+
function visitSdfNode(node, analysis) {
|
|
6295
|
+
switch (node.kind) {
|
|
6296
|
+
case "sdf:union":
|
|
6297
|
+
case "sdf:difference":
|
|
6298
|
+
case "sdf:intersection":
|
|
6299
|
+
case "sdf:smoothUnion":
|
|
6300
|
+
case "sdf:smoothDifference":
|
|
6301
|
+
case "sdf:smoothIntersection":
|
|
6302
|
+
for (const child of node.children) visitSdfNode(child, analysis);
|
|
6303
|
+
break;
|
|
6304
|
+
case "sdf:morph":
|
|
6305
|
+
case "sdf:spatialBlend":
|
|
6306
|
+
visitSdfNode(node.a, analysis);
|
|
6307
|
+
visitSdfNode(node.b, analysis);
|
|
6308
|
+
break;
|
|
6309
|
+
case "sdf:translate":
|
|
6310
|
+
case "sdf:rotate":
|
|
6311
|
+
case "sdf:scale":
|
|
6312
|
+
case "sdf:twist":
|
|
6313
|
+
case "sdf:bend":
|
|
6314
|
+
case "sdf:onion":
|
|
6315
|
+
visitSdfNode(node.child, analysis);
|
|
6316
|
+
break;
|
|
6317
|
+
case "sdf:repeat":
|
|
6318
|
+
analysis.riskFlags.add("repeat");
|
|
6319
|
+
for (let i = 0; i < 3; i++) {
|
|
6320
|
+
const spacing = node.spacing[i];
|
|
6321
|
+
if (spacing > 0) {
|
|
6322
|
+
analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, spacing);
|
|
6323
|
+
if (node.count[i] <= 0) analysis.hasInfiniteRepeat = true;
|
|
6324
|
+
}
|
|
6325
|
+
}
|
|
6326
|
+
visitSdfNode(node.child, analysis);
|
|
6327
|
+
break;
|
|
6328
|
+
case "sdf:circularArray": {
|
|
6329
|
+
analysis.riskFlags.add("repeat");
|
|
6330
|
+
if (node.offset > 0) {
|
|
6331
|
+
analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, 2 * Math.PI * node.offset / node.count);
|
|
6332
|
+
}
|
|
6333
|
+
visitSdfNode(node.child, analysis);
|
|
6334
|
+
break;
|
|
6335
|
+
}
|
|
6336
|
+
case "sdf:shell":
|
|
6337
|
+
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.thickness);
|
|
6338
|
+
visitSdfNode(node.child, analysis);
|
|
6339
|
+
break;
|
|
6340
|
+
case "sdf:displace":
|
|
6341
|
+
case "sdf:surfaceDisplace":
|
|
6342
|
+
analysis.riskFlags.add("displacement");
|
|
6343
|
+
if (node.kind === "sdf:surfaceDisplace" && node.pattern) {
|
|
6344
|
+
const spacing = estimateSurfacePatternSpacing(node.pattern);
|
|
6345
|
+
if (spacing !== null) analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, spacing);
|
|
6346
|
+
}
|
|
6347
|
+
visitSdfNode(node.child, analysis);
|
|
6348
|
+
break;
|
|
6349
|
+
case "sdf:gyroid":
|
|
6350
|
+
case "sdf:schwarzP":
|
|
6351
|
+
case "sdf:diamond":
|
|
6352
|
+
case "sdf:lidinoid":
|
|
6353
|
+
analysis.riskFlags.add("tpms");
|
|
6354
|
+
analysis.minTpmsCellSize = Math.min(analysis.minTpmsCellSize, node.cellSize);
|
|
6355
|
+
if (node.thicknessMode === "metric-approx") {
|
|
6356
|
+
analysis.minMetricTpmsThickness = Math.min(analysis.minMetricTpmsThickness, node.thickness);
|
|
6357
|
+
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.thickness);
|
|
6358
|
+
} else {
|
|
6359
|
+
analysis.hasLegacyTpmsThreshold = true;
|
|
6360
|
+
}
|
|
6361
|
+
break;
|
|
6362
|
+
case "sdf:noise":
|
|
6363
|
+
analysis.riskFlags.add("noise");
|
|
6364
|
+
break;
|
|
6365
|
+
case "sdf:voronoi":
|
|
6366
|
+
analysis.riskFlags.add("voronoi");
|
|
6367
|
+
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.wallThickness);
|
|
6368
|
+
if (node.surfaceChild) visitSdfNode(node.surfaceChild, analysis);
|
|
6369
|
+
break;
|
|
6370
|
+
case "sdf:custom":
|
|
6371
|
+
analysis.riskFlags.add("custom");
|
|
6372
|
+
break;
|
|
6373
|
+
}
|
|
6374
|
+
}
|
|
6375
|
+
function positiveOrDefault(value, fallback) {
|
|
6376
|
+
if (value === void 0) return fallback;
|
|
6377
|
+
return requirePositiveFinite$3(value, "SDF meshing option");
|
|
6378
|
+
}
|
|
6379
|
+
function requirePositiveFinite$3(value, name) {
|
|
6380
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
6381
|
+
throw new Error(`${name} must be a positive finite number.`);
|
|
6382
|
+
}
|
|
6383
|
+
return value;
|
|
6384
|
+
}
|
|
6385
|
+
function cloneBounds$2(bounds) {
|
|
6386
|
+
return { min: [...bounds.min], max: [...bounds.max] };
|
|
6387
|
+
}
|
|
6388
|
+
function suggestEdgeLengthForSampleBudget(bounds, maxGridPoints) {
|
|
6389
|
+
const dx = bounds.max[0] - bounds.min[0];
|
|
6390
|
+
const dy = bounds.max[1] - bounds.min[1];
|
|
6391
|
+
const dz = bounds.max[2] - bounds.min[2];
|
|
6392
|
+
const volume = Math.max(dx * dy * dz, 1);
|
|
6393
|
+
return Math.cbrt(volume / Math.max(maxGridPoints, 8));
|
|
6394
|
+
}
|
|
6395
|
+
function formatBounds(bounds) {
|
|
6396
|
+
return `[${bounds.min.map(formatNumber$1).join(",")}]-[${bounds.max.map(formatNumber$1).join(",")}]`;
|
|
6397
|
+
}
|
|
6398
|
+
function formatMm(value) {
|
|
6399
|
+
return `${formatNumber$1(value)}mm`;
|
|
6400
|
+
}
|
|
6401
|
+
function formatNumber$1(value) {
|
|
6402
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(3).replace(/0+$/, "").replace(/\.$/, "");
|
|
6403
|
+
}
|
|
6404
|
+
function formatCount(value) {
|
|
6405
|
+
return Math.round(value).toLocaleString("en-US");
|
|
6406
|
+
}
|
|
6407
|
+
function formatBytes(bytes) {
|
|
6408
|
+
if (bytes < 1024 * 1024) return `${Math.ceil(bytes / 1024)} KB`;
|
|
6409
|
+
return `${Math.ceil(bytes / (1024 * 1024))} MB`;
|
|
6410
|
+
}
|
|
6086
6411
|
const grad3 = new Float64Array([
|
|
6087
6412
|
1,
|
|
6088
6413
|
1,
|
|
@@ -6543,8 +6868,8 @@ function triplanarWeights(nx, ny, nz, sharpness) {
|
|
|
6543
6868
|
const inv = 1 / sum2;
|
|
6544
6869
|
return { wx: wx * inv, wy: wy * inv, wz: wz * inv };
|
|
6545
6870
|
}
|
|
6546
|
-
const { atan2, acos, cos: cos$
|
|
6547
|
-
const DEG$
|
|
6871
|
+
const { atan2, acos, cos: cos$3, sin: sin$3, sqrt: sqrt$3, PI: PI$3 } = Math;
|
|
6872
|
+
const DEG$3 = PI$3 / 180;
|
|
6548
6873
|
const IDENTITY = (p2) => p2;
|
|
6549
6874
|
function analyzeUV(node, override) {
|
|
6550
6875
|
if (override) {
|
|
@@ -6571,10 +6896,10 @@ function analyzeNodeUV(node, toLocal) {
|
|
|
6571
6896
|
return analyzeNodeUV(node.child, next);
|
|
6572
6897
|
}
|
|
6573
6898
|
case "sdf:rotate": {
|
|
6574
|
-
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$
|
|
6575
|
-
const cx = cos$
|
|
6576
|
-
const cy = cos$
|
|
6577
|
-
const cz = cos$
|
|
6899
|
+
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$3);
|
|
6900
|
+
const cx = cos$3(rx), sx = sin$3(rx);
|
|
6901
|
+
const cy = cos$3(ry), sy = sin$3(ry);
|
|
6902
|
+
const cz = cos$3(rz), sz = sin$3(rz);
|
|
6578
6903
|
const prev = toLocal;
|
|
6579
6904
|
const next = (p2) => {
|
|
6580
6905
|
const pp = prev(p2);
|
|
@@ -6631,7 +6956,7 @@ function compileUVFunction(analysis) {
|
|
|
6631
6956
|
return (p2) => {
|
|
6632
6957
|
const lp = toLocal(p2);
|
|
6633
6958
|
const u2 = atan2(lp[1], lp[0]) * R;
|
|
6634
|
-
const len2 = sqrt$
|
|
6959
|
+
const len2 = sqrt$3(lp[0] * lp[0] + lp[1] * lp[1] + lp[2] * lp[2]);
|
|
6635
6960
|
const v = acos(clampUnit(lp[2] / (len2 || 1))) * R;
|
|
6636
6961
|
return [u2, v];
|
|
6637
6962
|
};
|
|
@@ -6651,23 +6976,23 @@ function compileUVFunction(analysis) {
|
|
|
6651
6976
|
return (p2) => {
|
|
6652
6977
|
const lp = toLocal(p2);
|
|
6653
6978
|
const u2 = atan2(lp[1], lp[0]) * R;
|
|
6654
|
-
const xyDist = sqrt$
|
|
6979
|
+
const xyDist = sqrt$3(lp[0] * lp[0] + lp[1] * lp[1]) - R;
|
|
6655
6980
|
const v = atan2(lp[2], xyDist) * r;
|
|
6656
6981
|
return [u2, v];
|
|
6657
6982
|
};
|
|
6658
6983
|
}
|
|
6659
6984
|
}
|
|
6660
6985
|
}
|
|
6661
|
-
const { abs: abs$1, cos: cos$
|
|
6662
|
-
const TAU = 2 * PI$
|
|
6663
|
-
const GRAD_EPS = 1e-9;
|
|
6986
|
+
const { abs: abs$1, cos: cos$2, sin: sin$2, sqrt: sqrt$2, PI: PI$2 } = Math;
|
|
6987
|
+
const TAU$1 = 2 * PI$2;
|
|
6988
|
+
const GRAD_EPS$1 = 1e-9;
|
|
6664
6989
|
function gyroidValueAndGradient(x2, y2, z2, cellSize) {
|
|
6665
|
-
const s = TAU / cellSize;
|
|
6990
|
+
const s = TAU$1 / cellSize;
|
|
6666
6991
|
const xs = x2 * s;
|
|
6667
6992
|
const ys = y2 * s;
|
|
6668
6993
|
const zs = z2 * s;
|
|
6669
|
-
const sx = sin$
|
|
6670
|
-
const cx = cos$
|
|
6994
|
+
const sx = sin$2(xs), sy = sin$2(ys), sz = sin$2(zs);
|
|
6995
|
+
const cx = cos$2(xs), cy = cos$2(ys), cz = cos$2(zs);
|
|
6671
6996
|
return {
|
|
6672
6997
|
value: sx * cy + sy * cz + sz * cx,
|
|
6673
6998
|
gx: s * (cx * cy - sz * sx),
|
|
@@ -6676,24 +7001,24 @@ function gyroidValueAndGradient(x2, y2, z2, cellSize) {
|
|
|
6676
7001
|
};
|
|
6677
7002
|
}
|
|
6678
7003
|
function schwarzPValueAndGradient(x2, y2, z2, cellSize) {
|
|
6679
|
-
const s = TAU / cellSize;
|
|
7004
|
+
const s = TAU$1 / cellSize;
|
|
6680
7005
|
const xs = x2 * s;
|
|
6681
7006
|
const ys = y2 * s;
|
|
6682
7007
|
const zs = z2 * s;
|
|
6683
7008
|
return {
|
|
6684
|
-
value: cos$
|
|
6685
|
-
gx: -s * sin$
|
|
6686
|
-
gy: -s * sin$
|
|
6687
|
-
gz: -s * sin$
|
|
7009
|
+
value: cos$2(xs) + cos$2(ys) + cos$2(zs),
|
|
7010
|
+
gx: -s * sin$2(xs),
|
|
7011
|
+
gy: -s * sin$2(ys),
|
|
7012
|
+
gz: -s * sin$2(zs)
|
|
6688
7013
|
};
|
|
6689
7014
|
}
|
|
6690
7015
|
function diamondValueAndGradient(x2, y2, z2, cellSize) {
|
|
6691
|
-
const s = TAU / cellSize;
|
|
7016
|
+
const s = TAU$1 / cellSize;
|
|
6692
7017
|
const xs = x2 * s;
|
|
6693
7018
|
const ys = y2 * s;
|
|
6694
7019
|
const zs = z2 * s;
|
|
6695
|
-
const sx = sin$
|
|
6696
|
-
const cx = cos$
|
|
7020
|
+
const sx = sin$2(xs), sy = sin$2(ys), sz = sin$2(zs);
|
|
7021
|
+
const cx = cos$2(xs), cy = cos$2(ys), cz = cos$2(zs);
|
|
6697
7022
|
return {
|
|
6698
7023
|
value: sx * sy * sz + sx * cy * cz + cx * sy * cz + cx * cy * sz,
|
|
6699
7024
|
gx: s * (cx * sy * sz + cx * cy * cz - sx * sy * cz - sx * cy * sz),
|
|
@@ -6702,12 +7027,12 @@ function diamondValueAndGradient(x2, y2, z2, cellSize) {
|
|
|
6702
7027
|
};
|
|
6703
7028
|
}
|
|
6704
7029
|
function lidinoidValueAndGradient(x2, y2, z2, cellSize) {
|
|
6705
|
-
const s = TAU / cellSize;
|
|
7030
|
+
const s = TAU$1 / cellSize;
|
|
6706
7031
|
const sx2 = x2 * s, sy2 = y2 * s, sz2 = z2 * s;
|
|
6707
|
-
const sx = sin$
|
|
6708
|
-
const cx = cos$
|
|
6709
|
-
const s2x = sin$
|
|
6710
|
-
const c2x = cos$
|
|
7032
|
+
const sx = sin$2(sx2), sy = sin$2(sy2), sz = sin$2(sz2);
|
|
7033
|
+
const cx = cos$2(sx2), cy = cos$2(sy2), cz = cos$2(sz2);
|
|
7034
|
+
const s2x = sin$2(2 * sx2), s2y = sin$2(2 * sy2), s2z = sin$2(2 * sz2);
|
|
7035
|
+
const c2x = cos$2(2 * sx2), c2y = cos$2(2 * sy2), c2z = cos$2(2 * sz2);
|
|
6711
7036
|
const val = s2x * cy * sz + s2y * cz * sx + s2z * cx * sy - c2x * c2y - c2y * c2z - c2z * c2x + 0.3;
|
|
6712
7037
|
return {
|
|
6713
7038
|
value: val,
|
|
@@ -6730,8 +7055,8 @@ function lidinoid$1(x2, y2, z2, cellSize, thickness, thicknessMode) {
|
|
|
6730
7055
|
}
|
|
6731
7056
|
function tpmsDistance({ value, gx, gy, gz }, thickness, thicknessMode) {
|
|
6732
7057
|
if (thicknessMode !== "metric-approx") return abs$1(value) - thickness;
|
|
6733
|
-
const grad = sqrt$
|
|
6734
|
-
return abs$1(value) / Math.max(grad, GRAD_EPS) - thickness * 0.5;
|
|
7058
|
+
const grad = sqrt$2(gx * gx + gy * gy + gz * gz);
|
|
7059
|
+
return abs$1(value) / Math.max(grad, GRAD_EPS$1) - thickness * 0.5;
|
|
6735
7060
|
}
|
|
6736
7061
|
function mix(h) {
|
|
6737
7062
|
h = (h ^ h >>> 16) * 2246822507 | 0;
|
|
@@ -6827,76 +7152,76 @@ function seededWorley3Surface(seed) {
|
|
|
6827
7152
|
const s = seed | 0;
|
|
6828
7153
|
return (x2, y2, z2, nx, ny, nz, threshold) => worleySurface(x2, y2, z2, s, nx, ny, nz, threshold);
|
|
6829
7154
|
}
|
|
6830
|
-
const { abs, cos, max, min, sin, sqrt, PI } = Math;
|
|
6831
|
-
const DEG$
|
|
7155
|
+
const { abs, cos: cos$1, max: max$1, min, sin: sin$1, sqrt: sqrt$1, PI: PI$1 } = Math;
|
|
7156
|
+
const DEG$2 = PI$1 / 180;
|
|
6832
7157
|
function clamp$a(v, lo, hi) {
|
|
6833
7158
|
return v < lo ? lo : v > hi ? hi : v;
|
|
6834
7159
|
}
|
|
6835
|
-
function length2(x2, y2) {
|
|
6836
|
-
return sqrt(x2 * x2 + y2 * y2);
|
|
7160
|
+
function length2$1(x2, y2) {
|
|
7161
|
+
return sqrt$1(x2 * x2 + y2 * y2);
|
|
6837
7162
|
}
|
|
6838
|
-
function length3(x2, y2, z2) {
|
|
6839
|
-
return sqrt(x2 * x2 + y2 * y2 + z2 * z2);
|
|
7163
|
+
function length3$1(x2, y2, z2) {
|
|
7164
|
+
return sqrt$1(x2 * x2 + y2 * y2 + z2 * z2);
|
|
6840
7165
|
}
|
|
6841
|
-
function sdSphere(px2, py2, pz2, r) {
|
|
6842
|
-
return length3(px2, py2, pz2) - r;
|
|
7166
|
+
function sdSphere$1(px2, py2, pz2, r) {
|
|
7167
|
+
return length3$1(px2, py2, pz2) - r;
|
|
6843
7168
|
}
|
|
6844
|
-
function sdBox(px2, py2, pz2, hx, hy, hz) {
|
|
7169
|
+
function sdBox$1(px2, py2, pz2, hx, hy, hz) {
|
|
6845
7170
|
const dx = abs(px2) - hx;
|
|
6846
7171
|
const dy = abs(py2) - hy;
|
|
6847
7172
|
const dz = abs(pz2) - hz;
|
|
6848
|
-
return length3(max(dx, 0), max(dy, 0), max(dz, 0)) + min(max(dx, dy, dz), 0);
|
|
7173
|
+
return length3$1(max$1(dx, 0), max$1(dy, 0), max$1(dz, 0)) + min(max$1(dx, dy, dz), 0);
|
|
6849
7174
|
}
|
|
6850
|
-
function sdCylinder(px2, py2, pz2, h, r) {
|
|
6851
|
-
const dx = length2(px2, py2) - r;
|
|
7175
|
+
function sdCylinder$1(px2, py2, pz2, h, r) {
|
|
7176
|
+
const dx = length2$1(px2, py2) - r;
|
|
6852
7177
|
const dz = abs(pz2) - h * 0.5;
|
|
6853
|
-
return length2(max(dx, 0), max(dz, 0)) + min(max(dx, dz), 0);
|
|
7178
|
+
return length2$1(max$1(dx, 0), max$1(dz, 0)) + min(max$1(dx, dz), 0);
|
|
6854
7179
|
}
|
|
6855
|
-
function sdTorus(px2, py2, pz2, R, r) {
|
|
6856
|
-
const qx = length2(px2, py2) - R;
|
|
6857
|
-
return length2(qx, pz2) - r;
|
|
7180
|
+
function sdTorus$1(px2, py2, pz2, R, r) {
|
|
7181
|
+
const qx = length2$1(px2, py2) - R;
|
|
7182
|
+
return length2$1(qx, pz2) - r;
|
|
6858
7183
|
}
|
|
6859
|
-
function sdCapsule(px2, py2, pz2, h, r) {
|
|
7184
|
+
function sdCapsule$1(px2, py2, pz2, h, r) {
|
|
6860
7185
|
const halfH = h * 0.5;
|
|
6861
7186
|
const cz = clamp$a(pz2, -halfH, halfH);
|
|
6862
|
-
return length3(px2, py2, pz2 - cz) - r;
|
|
7187
|
+
return length3$1(px2, py2, pz2 - cz) - r;
|
|
6863
7188
|
}
|
|
6864
|
-
function sdCone(px2, py2, pz2, h, r) {
|
|
6865
|
-
const q = length2(px2, py2);
|
|
6866
|
-
const cLen = length2(h, r);
|
|
7189
|
+
function sdCone$1(px2, py2, pz2, h, r) {
|
|
7190
|
+
const q = length2$1(px2, py2);
|
|
7191
|
+
const cLen = length2$1(h, r);
|
|
6867
7192
|
const nx = h / cLen;
|
|
6868
7193
|
const nz = -r / cLen;
|
|
6869
|
-
const d2 = max(nx * q + nz * (pz2 - h), -pz2, pz2 - h);
|
|
7194
|
+
const d2 = max$1(nx * q + nz * (pz2 - h), -pz2, pz2 - h);
|
|
6870
7195
|
return d2;
|
|
6871
7196
|
}
|
|
6872
|
-
function sdTaperedSegment(px2, py2, pz2, ax, ay, az, bx, by, bz, ra, rb) {
|
|
7197
|
+
function sdTaperedSegment$1(px2, py2, pz2, ax, ay, az, bx, by, bz, ra, rb) {
|
|
6873
7198
|
const vx = bx - ax;
|
|
6874
7199
|
const vy = by - ay;
|
|
6875
7200
|
const vz = bz - az;
|
|
6876
7201
|
const len2 = vx * vx + vy * vy + vz * vz;
|
|
6877
|
-
if (len2 <= 1e-12) return sdSphere(px2 - ax, py2 - ay, pz2 - az, max(ra, rb));
|
|
7202
|
+
if (len2 <= 1e-12) return sdSphere$1(px2 - ax, py2 - ay, pz2 - az, max$1(ra, rb));
|
|
6878
7203
|
const h = clamp$a(((px2 - ax) * vx + (py2 - ay) * vy + (pz2 - az) * vz) / len2, 0, 1);
|
|
6879
|
-
return length3(px2 - (ax + vx * h), py2 - (ay + vy * h), pz2 - (az + vz * h)) - (ra + (rb - ra) * h);
|
|
7204
|
+
return length3$1(px2 - (ax + vx * h), py2 - (ay + vy * h), pz2 - (az + vz * h)) - (ra + (rb - ra) * h);
|
|
6880
7205
|
}
|
|
6881
7206
|
function sdPolylineSweep3(node, x2, y2, z2) {
|
|
6882
7207
|
let d2 = 1e20;
|
|
6883
7208
|
for (let i = 0; i < node.points.length - 1; i++) {
|
|
6884
7209
|
const a2 = node.points[i];
|
|
6885
7210
|
const b = node.points[i + 1];
|
|
6886
|
-
const segment = sdTaperedSegment(x2, y2, z2, a2[0], a2[1], a2[2], b[0], b[1], b[2], node.radii[i], node.radii[i + 1]);
|
|
6887
|
-
d2 = i === 0 ? segment : smin(d2, segment, node.blend);
|
|
7211
|
+
const segment = sdTaperedSegment$1(x2, y2, z2, a2[0], a2[1], a2[2], b[0], b[1], b[2], node.radii[i], node.radii[i + 1]);
|
|
7212
|
+
d2 = i === 0 ? segment : smin$1(d2, segment, node.blend);
|
|
6888
7213
|
}
|
|
6889
7214
|
return d2;
|
|
6890
7215
|
}
|
|
6891
|
-
function smin(a2, b, k2) {
|
|
7216
|
+
function smin$1(a2, b, k2) {
|
|
6892
7217
|
if (k2 <= 0) return min(a2, b);
|
|
6893
|
-
const h = max(k2 - abs(a2 - b), 0) / k2;
|
|
7218
|
+
const h = max$1(k2 - abs(a2 - b), 0) / k2;
|
|
6894
7219
|
return min(a2, b) - h * h * h * k2 * (1 / 6);
|
|
6895
7220
|
}
|
|
6896
|
-
function smax(a2, b, k2) {
|
|
6897
|
-
return -smin(-a2, -b, k2);
|
|
7221
|
+
function smax$1(a2, b, k2) {
|
|
7222
|
+
return -smin$1(-a2, -b, k2);
|
|
6898
7223
|
}
|
|
6899
|
-
function repeatCoord(v, spacing, count) {
|
|
7224
|
+
function repeatCoord$1(v, spacing, count) {
|
|
6900
7225
|
if (spacing <= 0) return v;
|
|
6901
7226
|
if (count > 0) {
|
|
6902
7227
|
const center = (count - 1) * 0.5;
|
|
@@ -6905,31 +7230,138 @@ function repeatCoord(v, spacing, count) {
|
|
|
6905
7230
|
}
|
|
6906
7231
|
return v - spacing * Math.round(v / spacing);
|
|
6907
7232
|
}
|
|
7233
|
+
function positiveMod(v, period) {
|
|
7234
|
+
return (v % period + period) % period;
|
|
7235
|
+
}
|
|
7236
|
+
function evalStripesPattern(u2, v, directionX, directionY, spacing, width, depth) {
|
|
7237
|
+
const coord = u2 * directionX + v * directionY;
|
|
7238
|
+
const d2 = abs(coord - Math.round(coord / spacing) * spacing);
|
|
7239
|
+
const profile = max$1(0, 1 - d2 / (width * 0.5));
|
|
7240
|
+
return -(profile * profile) * depth;
|
|
7241
|
+
}
|
|
7242
|
+
function evalOverUnderWeavePattern(u2, v, spacingX, spacingY, widthX, widthY, depth, underScale) {
|
|
7243
|
+
const su = u2 / spacingX;
|
|
7244
|
+
const sv = v / spacingY;
|
|
7245
|
+
let pU = max$1(0, 1 - abs(su - Math.round(su)) * spacingX / (widthX * 0.5));
|
|
7246
|
+
let pV = max$1(0, 1 - abs(sv - Math.round(sv)) * spacingY / (widthY * 0.5));
|
|
7247
|
+
pU *= pU;
|
|
7248
|
+
pV *= pV;
|
|
7249
|
+
const checker = (Math.round(su) & 65535) + (Math.round(sv) & 65535) & 1;
|
|
7250
|
+
const top = checker ? pV : pU;
|
|
7251
|
+
const bot = checker ? pU : pV;
|
|
7252
|
+
return -max$1(top, bot * underScale) * depth;
|
|
7253
|
+
}
|
|
7254
|
+
function compileTypedSurfacePattern(pattern) {
|
|
7255
|
+
switch (pattern.kind) {
|
|
7256
|
+
case "surfacePattern:constant":
|
|
7257
|
+
return () => pattern.value;
|
|
7258
|
+
case "surfacePattern:sineWave": {
|
|
7259
|
+
const { direction: direction2, wavelength, amplitude, phase, bias } = pattern;
|
|
7260
|
+
const frequency = 2 * PI$1 / wavelength;
|
|
7261
|
+
return (u2, v) => bias + sin$1((u2 * direction2[0] + v * direction2[1]) * frequency + phase) * amplitude;
|
|
7262
|
+
}
|
|
7263
|
+
case "surfacePattern:stripes": {
|
|
7264
|
+
const { direction: direction2, spacing, width, depth } = pattern;
|
|
7265
|
+
return (u2, v) => evalStripesPattern(u2, v, direction2[0], direction2[1], spacing, width, depth);
|
|
7266
|
+
}
|
|
7267
|
+
case "surfacePattern:overUnderWeave": {
|
|
7268
|
+
const { spacing, threadWidth, depth, underScale } = pattern;
|
|
7269
|
+
return (u2, v) => evalOverUnderWeavePattern(u2, v, spacing[0], spacing[1], threadWidth[0], threadWidth[1], depth, underScale);
|
|
7270
|
+
}
|
|
7271
|
+
case "surfacePattern:abs": {
|
|
7272
|
+
const child = compileTypedSurfacePattern(pattern.child);
|
|
7273
|
+
return (u2, v) => abs(child(u2, v));
|
|
7274
|
+
}
|
|
7275
|
+
case "surfacePattern:negate": {
|
|
7276
|
+
const child = compileTypedSurfacePattern(pattern.child);
|
|
7277
|
+
return (u2, v) => -child(u2, v);
|
|
7278
|
+
}
|
|
7279
|
+
case "surfacePattern:add": {
|
|
7280
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
7281
|
+
return (u2, v) => children.reduce((sum2, child) => sum2 + child(u2, v), 0);
|
|
7282
|
+
}
|
|
7283
|
+
case "surfacePattern:multiply": {
|
|
7284
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
7285
|
+
return (u2, v) => children.reduce((product, child) => product * child(u2, v), 1);
|
|
7286
|
+
}
|
|
7287
|
+
case "surfacePattern:min": {
|
|
7288
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
7289
|
+
if (children.length === 0) return () => 0;
|
|
7290
|
+
return (u2, v) => children.reduce((value, child) => min(value, child(u2, v)), Infinity);
|
|
7291
|
+
}
|
|
7292
|
+
case "surfacePattern:max": {
|
|
7293
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
7294
|
+
if (children.length === 0) return () => 0;
|
|
7295
|
+
return (u2, v) => children.reduce((value, child) => max$1(value, child(u2, v)), -Infinity);
|
|
7296
|
+
}
|
|
7297
|
+
case "surfacePattern:clamp": {
|
|
7298
|
+
const child = compileTypedSurfacePattern(pattern.child);
|
|
7299
|
+
return (u2, v) => clamp$a(child(u2, v), pattern.min, pattern.max);
|
|
7300
|
+
}
|
|
7301
|
+
}
|
|
7302
|
+
}
|
|
7303
|
+
function estimateSurfacePatternAmplitude(pattern) {
|
|
7304
|
+
switch (pattern.kind) {
|
|
7305
|
+
case "surfacePattern:constant":
|
|
7306
|
+
return abs(pattern.value);
|
|
7307
|
+
case "surfacePattern:sineWave":
|
|
7308
|
+
return abs(pattern.bias) + abs(pattern.amplitude);
|
|
7309
|
+
case "surfacePattern:stripes":
|
|
7310
|
+
case "surfacePattern:overUnderWeave":
|
|
7311
|
+
return pattern.depth;
|
|
7312
|
+
case "surfacePattern:abs":
|
|
7313
|
+
case "surfacePattern:negate":
|
|
7314
|
+
return estimateSurfacePatternAmplitude(pattern.child);
|
|
7315
|
+
case "surfacePattern:add": {
|
|
7316
|
+
const amplitudes = pattern.children.map(estimateSurfacePatternAmplitude);
|
|
7317
|
+
return amplitudes.every((value) => value !== null) ? amplitudes.reduce((sum2, value) => sum2 + value, 0) : null;
|
|
7318
|
+
}
|
|
7319
|
+
case "surfacePattern:multiply": {
|
|
7320
|
+
const amplitudes = pattern.children.map(estimateSurfacePatternAmplitude);
|
|
7321
|
+
return amplitudes.every((value) => value !== null) ? amplitudes.reduce((product, value) => product * value, 1) : null;
|
|
7322
|
+
}
|
|
7323
|
+
case "surfacePattern:min":
|
|
7324
|
+
case "surfacePattern:max": {
|
|
7325
|
+
const amplitudes = pattern.children.map(estimateSurfacePatternAmplitude);
|
|
7326
|
+
return amplitudes.every((value) => value !== null) ? max$1(...amplitudes) : null;
|
|
7327
|
+
}
|
|
7328
|
+
case "surfacePattern:clamp":
|
|
7329
|
+
return max$1(abs(pattern.min), abs(pattern.max));
|
|
7330
|
+
}
|
|
7331
|
+
}
|
|
7332
|
+
function compileSurfacePattern(node) {
|
|
7333
|
+
if (node.pattern) return compileTypedSurfacePattern(node.pattern);
|
|
7334
|
+
const constEntries = Object.entries(node.constants ?? {});
|
|
7335
|
+
const constNames = constEntries.map(([k2]) => k2);
|
|
7336
|
+
const constValues = constEntries.map(([, v]) => v);
|
|
7337
|
+
const patternFn = new Function("u", "v", ...constNames, `return (${node.patternBody});`);
|
|
7338
|
+
return (u2, v) => patternFn(u2, v, ...constValues);
|
|
7339
|
+
}
|
|
6908
7340
|
function compileSdfNode3(node) {
|
|
6909
7341
|
switch (node.kind) {
|
|
6910
7342
|
case "sdf:sphere": {
|
|
6911
7343
|
const r = node.radius;
|
|
6912
|
-
return (x2, y2, z2) => sdSphere(x2, y2, z2, r);
|
|
7344
|
+
return (x2, y2, z2) => sdSphere$1(x2, y2, z2, r);
|
|
6913
7345
|
}
|
|
6914
7346
|
case "sdf:box": {
|
|
6915
7347
|
const [hx, hy, hz] = node.halfExtents;
|
|
6916
|
-
return (x2, y2, z2) => sdBox(x2, y2, z2, hx, hy, hz);
|
|
7348
|
+
return (x2, y2, z2) => sdBox$1(x2, y2, z2, hx, hy, hz);
|
|
6917
7349
|
}
|
|
6918
7350
|
case "sdf:cylinder": {
|
|
6919
7351
|
const { height: h, radius: r } = node;
|
|
6920
|
-
return (x2, y2, z2) => sdCylinder(x2, y2, z2, h, r);
|
|
7352
|
+
return (x2, y2, z2) => sdCylinder$1(x2, y2, z2, h, r);
|
|
6921
7353
|
}
|
|
6922
7354
|
case "sdf:torus": {
|
|
6923
7355
|
const { majorRadius: R, minorRadius: r } = node;
|
|
6924
|
-
return (x2, y2, z2) => sdTorus(x2, y2, z2, R, r);
|
|
7356
|
+
return (x2, y2, z2) => sdTorus$1(x2, y2, z2, R, r);
|
|
6925
7357
|
}
|
|
6926
7358
|
case "sdf:capsule": {
|
|
6927
7359
|
const { height: h, radius: r } = node;
|
|
6928
|
-
return (x2, y2, z2) => sdCapsule(x2, y2, z2, h, r);
|
|
7360
|
+
return (x2, y2, z2) => sdCapsule$1(x2, y2, z2, h, r);
|
|
6929
7361
|
}
|
|
6930
7362
|
case "sdf:cone": {
|
|
6931
7363
|
const { height: h, radius: r } = node;
|
|
6932
|
-
return (x2, y2, z2) => sdCone(x2, y2, z2, h, r);
|
|
7364
|
+
return (x2, y2, z2) => sdCone$1(x2, y2, z2, h, r);
|
|
6933
7365
|
}
|
|
6934
7366
|
case "sdf:polylineSweep": {
|
|
6935
7367
|
return (x2, y2, z2) => sdPolylineSweep3(node, x2, y2, z2);
|
|
@@ -6946,7 +7378,7 @@ function compileSdfNode3(node) {
|
|
|
6946
7378
|
const fns = node.children.map(compileSdfNode3);
|
|
6947
7379
|
return (x2, y2, z2) => {
|
|
6948
7380
|
let d2 = fns[0](x2, y2, z2);
|
|
6949
|
-
for (let i = 1; i < fns.length; i++) d2 = max(d2, -fns[i](x2, y2, z2));
|
|
7381
|
+
for (let i = 1; i < fns.length; i++) d2 = max$1(d2, -fns[i](x2, y2, z2));
|
|
6950
7382
|
return d2;
|
|
6951
7383
|
};
|
|
6952
7384
|
}
|
|
@@ -6954,7 +7386,7 @@ function compileSdfNode3(node) {
|
|
|
6954
7386
|
const fns = node.children.map(compileSdfNode3);
|
|
6955
7387
|
return (x2, y2, z2) => {
|
|
6956
7388
|
let d2 = fns[0](x2, y2, z2);
|
|
6957
|
-
for (let i = 1; i < fns.length; i++) d2 = max(d2, fns[i](x2, y2, z2));
|
|
7389
|
+
for (let i = 1; i < fns.length; i++) d2 = max$1(d2, fns[i](x2, y2, z2));
|
|
6958
7390
|
return d2;
|
|
6959
7391
|
};
|
|
6960
7392
|
}
|
|
@@ -6963,7 +7395,7 @@ function compileSdfNode3(node) {
|
|
|
6963
7395
|
const k2 = node.radius;
|
|
6964
7396
|
return (x2, y2, z2) => {
|
|
6965
7397
|
let d2 = fns[0](x2, y2, z2);
|
|
6966
|
-
for (let i = 1; i < fns.length; i++) d2 = smin(d2, fns[i](x2, y2, z2), k2);
|
|
7398
|
+
for (let i = 1; i < fns.length; i++) d2 = smin$1(d2, fns[i](x2, y2, z2), k2);
|
|
6967
7399
|
return d2;
|
|
6968
7400
|
};
|
|
6969
7401
|
}
|
|
@@ -6972,7 +7404,7 @@ function compileSdfNode3(node) {
|
|
|
6972
7404
|
const k2 = node.radius;
|
|
6973
7405
|
return (x2, y2, z2) => {
|
|
6974
7406
|
let d2 = fns[0](x2, y2, z2);
|
|
6975
|
-
for (let i = 1; i < fns.length; i++) d2 = smax(d2, -fns[i](x2, y2, z2), k2);
|
|
7407
|
+
for (let i = 1; i < fns.length; i++) d2 = smax$1(d2, -fns[i](x2, y2, z2), k2);
|
|
6976
7408
|
return d2;
|
|
6977
7409
|
};
|
|
6978
7410
|
}
|
|
@@ -6981,7 +7413,7 @@ function compileSdfNode3(node) {
|
|
|
6981
7413
|
const k2 = node.radius;
|
|
6982
7414
|
return (x2, y2, z2) => {
|
|
6983
7415
|
let d2 = fns[0](x2, y2, z2);
|
|
6984
|
-
for (let i = 1; i < fns.length; i++) d2 = smax(d2, fns[i](x2, y2, z2), k2);
|
|
7416
|
+
for (let i = 1; i < fns.length; i++) d2 = smax$1(d2, fns[i](x2, y2, z2), k2);
|
|
6985
7417
|
return d2;
|
|
6986
7418
|
};
|
|
6987
7419
|
}
|
|
@@ -6999,10 +7431,10 @@ function compileSdfNode3(node) {
|
|
|
6999
7431
|
}
|
|
7000
7432
|
case "sdf:rotate": {
|
|
7001
7433
|
const fn = compileSdfNode3(node.child);
|
|
7002
|
-
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$
|
|
7003
|
-
const cx = cos(rx), sx = sin(rx);
|
|
7004
|
-
const cy = cos(ry), sy = sin(ry);
|
|
7005
|
-
const cz = cos(rz), sz = sin(rz);
|
|
7434
|
+
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$2);
|
|
7435
|
+
const cx = cos$1(rx), sx = sin$1(rx);
|
|
7436
|
+
const cy = cos$1(ry), sy = sin$1(ry);
|
|
7437
|
+
const cz = cos$1(rz), sz = sin$1(rz);
|
|
7006
7438
|
return (x2, y2, z2) => {
|
|
7007
7439
|
const x1 = cz * x2 + sz * y2;
|
|
7008
7440
|
const y1 = -sz * x2 + cz * y2;
|
|
@@ -7021,10 +7453,10 @@ function compileSdfNode3(node) {
|
|
|
7021
7453
|
}
|
|
7022
7454
|
case "sdf:twist": {
|
|
7023
7455
|
const fn = compileSdfNode3(node.child);
|
|
7024
|
-
const k2 = node.degreesPerUnit * DEG$
|
|
7456
|
+
const k2 = node.degreesPerUnit * DEG$2;
|
|
7025
7457
|
return (x2, y2, z2) => {
|
|
7026
7458
|
const angle = k2 * z2;
|
|
7027
|
-
const c2 = cos(angle), s = sin(angle);
|
|
7459
|
+
const c2 = cos$1(angle), s = sin$1(angle);
|
|
7028
7460
|
return fn(c2 * x2 - s * y2, s * x2 + c2 * y2, z2);
|
|
7029
7461
|
};
|
|
7030
7462
|
}
|
|
@@ -7033,7 +7465,7 @@ function compileSdfNode3(node) {
|
|
|
7033
7465
|
const r = node.radius;
|
|
7034
7466
|
return (x2, y2, z2) => {
|
|
7035
7467
|
const angle = x2 / r;
|
|
7036
|
-
const c2 = cos(angle), s = sin(angle);
|
|
7468
|
+
const c2 = cos$1(angle), s = sin$1(angle);
|
|
7037
7469
|
return fn((r + y2) * s, (r + y2) * c2 - r, z2);
|
|
7038
7470
|
};
|
|
7039
7471
|
}
|
|
@@ -7041,7 +7473,19 @@ function compileSdfNode3(node) {
|
|
|
7041
7473
|
const fn = compileSdfNode3(node.child);
|
|
7042
7474
|
const [sx, sy, sz] = node.spacing;
|
|
7043
7475
|
const [cx, cy, cz] = node.count;
|
|
7044
|
-
return (x2, y2, z2) => fn(repeatCoord(x2, sx, cx), repeatCoord(y2, sy, cy), repeatCoord(z2, sz, cz));
|
|
7476
|
+
return (x2, y2, z2) => fn(repeatCoord$1(x2, sx, cx), repeatCoord$1(y2, sy, cy), repeatCoord$1(z2, sz, cz));
|
|
7477
|
+
}
|
|
7478
|
+
case "sdf:circularArray": {
|
|
7479
|
+
const fn = compileSdfNode3(node.child);
|
|
7480
|
+
const da = 2 * PI$1 / node.count;
|
|
7481
|
+
const offset2 = node.offset;
|
|
7482
|
+
return (x2, y2, z2) => {
|
|
7483
|
+
const r = length2$1(x2, y2);
|
|
7484
|
+
const a2 = positiveMod(Math.atan2(y2, x2), da);
|
|
7485
|
+
const d1 = fn(cos$1(a2 - da) * r - offset2, sin$1(a2 - da) * r, z2);
|
|
7486
|
+
const d2 = fn(cos$1(a2) * r - offset2, sin$1(a2) * r, z2);
|
|
7487
|
+
return min(d1, d2);
|
|
7488
|
+
};
|
|
7045
7489
|
}
|
|
7046
7490
|
case "sdf:shell": {
|
|
7047
7491
|
const fn = compileSdfNode3(node.child);
|
|
@@ -7058,10 +7502,7 @@ function compileSdfNode3(node) {
|
|
|
7058
7502
|
}
|
|
7059
7503
|
case "sdf:surfaceDisplace": {
|
|
7060
7504
|
const childFn = compileSdfNode3(node.child);
|
|
7061
|
-
const
|
|
7062
|
-
const constNames = constEntries.map(([k2]) => k2);
|
|
7063
|
-
const constValues = constEntries.map(([, v]) => v);
|
|
7064
|
-
const patternFn = new Function("u", "v", ...constNames, `return (${node.patternBody});`);
|
|
7505
|
+
const patternFn = compileSurfacePattern(node);
|
|
7065
7506
|
const uvMode = node.uvMode && node.uvMode !== "auto" ? node.uvMode : void 0;
|
|
7066
7507
|
const analysis = analyzeUV(node.child, uvMode);
|
|
7067
7508
|
const uvFn = compileUVFunction(analysis);
|
|
@@ -7073,7 +7514,7 @@ function compileSdfNode3(node) {
|
|
|
7073
7514
|
p2[1] = y2;
|
|
7074
7515
|
p2[2] = z2;
|
|
7075
7516
|
const [u2, v] = uvFn(p2);
|
|
7076
|
-
return d2 + patternFn(u2, v
|
|
7517
|
+
return d2 + patternFn(u2, v);
|
|
7077
7518
|
};
|
|
7078
7519
|
}
|
|
7079
7520
|
const sharpness = node.triplanarSharpness ?? 4;
|
|
@@ -7084,9 +7525,9 @@ function compileSdfNode3(node) {
|
|
|
7084
7525
|
const gy = childFn(x2, y2 + eps, z2) - childFn(x2, y2 - eps, z2);
|
|
7085
7526
|
const gz = childFn(x2, y2, z2 + eps) - childFn(x2, y2, z2 - eps);
|
|
7086
7527
|
const { wx, wy, wz } = triplanarWeights(gx, gy, gz, sharpness);
|
|
7087
|
-
const hX = patternFn(y2, z2
|
|
7088
|
-
const hY = patternFn(x2, z2
|
|
7089
|
-
const hZ = patternFn(x2, y2
|
|
7528
|
+
const hX = patternFn(y2, z2);
|
|
7529
|
+
const hY = patternFn(x2, z2);
|
|
7530
|
+
const hZ = patternFn(x2, y2);
|
|
7090
7531
|
return d2 + wx * hX + wy * hY + wz * hZ;
|
|
7091
7532
|
};
|
|
7092
7533
|
}
|
|
@@ -7156,7 +7597,7 @@ function compileSdfNode3(node) {
|
|
|
7156
7597
|
const gx = gradFn(x2 + eps, y2, z2) - gradFn(x2 - eps, y2, z2);
|
|
7157
7598
|
const gy = gradFn(x2, y2 + eps, z2) - gradFn(x2, y2 - eps, z2);
|
|
7158
7599
|
const gz = gradFn(x2, y2, z2 + eps) - gradFn(x2, y2, z2 - eps);
|
|
7159
|
-
const glen = sqrt(gx * gx + gy * gy + gz * gz);
|
|
7600
|
+
const glen = sqrt$1(gx * gx + gy * gy + gz * gz);
|
|
7160
7601
|
let nx = 0, ny = 0, nz = 0;
|
|
7161
7602
|
if (glen > 1e-10) {
|
|
7162
7603
|
const invG = 1 / glen;
|
|
@@ -7218,7 +7659,7 @@ function estimateSdfBounds(node) {
|
|
|
7218
7659
|
for (const point2 of node.points) {
|
|
7219
7660
|
for (let i = 0; i < 3; i++) {
|
|
7220
7661
|
minPoint[i] = min(minPoint[i], point2[i]);
|
|
7221
|
-
maxPoint[i] = max(maxPoint[i], point2[i]);
|
|
7662
|
+
maxPoint[i] = max$1(maxPoint[i], point2[i]);
|
|
7222
7663
|
}
|
|
7223
7664
|
}
|
|
7224
7665
|
return padBounds({ min: minPoint, max: maxPoint }, pad);
|
|
@@ -7249,7 +7690,7 @@ function estimateSdfBounds(node) {
|
|
|
7249
7690
|
}
|
|
7250
7691
|
case "sdf:rotate": {
|
|
7251
7692
|
const b = estimateSdfBounds(node.child);
|
|
7252
|
-
const r = length3(max(abs(b.min[0]), abs(b.max[0])), max(abs(b.min[1]), abs(b.max[1])), max(abs(b.min[2]), abs(b.max[2])));
|
|
7693
|
+
const r = length3$1(max$1(abs(b.min[0]), abs(b.max[0])), max$1(abs(b.min[1]), abs(b.max[1])), max$1(abs(b.min[2]), abs(b.max[2])));
|
|
7253
7694
|
return { min: [-r, -r, -r], max: [r, r, r] };
|
|
7254
7695
|
}
|
|
7255
7696
|
case "sdf:scale": {
|
|
@@ -7263,7 +7704,7 @@ function estimateSdfBounds(node) {
|
|
|
7263
7704
|
case "sdf:twist":
|
|
7264
7705
|
case "sdf:bend": {
|
|
7265
7706
|
const b = estimateSdfBounds(node.child);
|
|
7266
|
-
const r = length3(max(abs(b.min[0]), abs(b.max[0])), max(abs(b.min[1]), abs(b.max[1])), max(abs(b.min[2]), abs(b.max[2]))) * 1.5;
|
|
7707
|
+
const r = length3$1(max$1(abs(b.min[0]), abs(b.max[0])), max$1(abs(b.min[1]), abs(b.max[1])), max$1(abs(b.min[2]), abs(b.max[2]))) * 1.5;
|
|
7267
7708
|
return { min: [-r, -r, -r], max: [r, r, r] };
|
|
7268
7709
|
}
|
|
7269
7710
|
case "sdf:repeat": {
|
|
@@ -7284,16 +7725,29 @@ function estimateSdfBounds(node) {
|
|
|
7284
7725
|
const [zMin, zMax] = expand(sz, cz, b.min[2], b.max[2]);
|
|
7285
7726
|
return { min: [xMin, yMin, zMin], max: [xMax, yMax, zMax] };
|
|
7286
7727
|
}
|
|
7728
|
+
case "sdf:circularArray": {
|
|
7729
|
+
const b = estimateSdfBounds(node.child);
|
|
7730
|
+
const x0 = b.min[0] + node.offset;
|
|
7731
|
+
const x1 = b.max[0] + node.offset;
|
|
7732
|
+
const y0 = b.min[1];
|
|
7733
|
+
const y1 = b.max[1];
|
|
7734
|
+
const r = max$1(length2$1(x0, y0), length2$1(x0, y1), length2$1(x1, y0), length2$1(x1, y1));
|
|
7735
|
+
return { min: [-r, -r, b.min[2]], max: [r, r, b.max[2]] };
|
|
7736
|
+
}
|
|
7287
7737
|
case "sdf:shell": {
|
|
7288
7738
|
const b = estimateSdfBounds(node.child);
|
|
7289
7739
|
const t = node.thickness * 0.5;
|
|
7290
7740
|
return padBounds(b, t);
|
|
7291
7741
|
}
|
|
7292
|
-
case "sdf:displace":
|
|
7293
|
-
case "sdf:surfaceDisplace": {
|
|
7742
|
+
case "sdf:displace": {
|
|
7294
7743
|
const b = estimateSdfBounds(node.child);
|
|
7295
7744
|
return padBounds(b, 5);
|
|
7296
7745
|
}
|
|
7746
|
+
case "sdf:surfaceDisplace": {
|
|
7747
|
+
const b = estimateSdfBounds(node.child);
|
|
7748
|
+
if (!node.pattern) return padBounds(b, 5);
|
|
7749
|
+
return padBounds(b, estimateSurfacePatternAmplitude(node.pattern) ?? 5);
|
|
7750
|
+
}
|
|
7297
7751
|
case "sdf:onion": {
|
|
7298
7752
|
const b = estimateSdfBounds(node.child);
|
|
7299
7753
|
return padBounds(b, node.layers * node.thickness);
|
|
@@ -7330,7 +7784,7 @@ function unionBounds(bounds, pad) {
|
|
|
7330
7784
|
for (const b of bounds) {
|
|
7331
7785
|
for (let i = 0; i < 3; i++) {
|
|
7332
7786
|
result.min[i] = min(result.min[i], b.min[i]);
|
|
7333
|
-
result.max[i] = max(result.max[i], b.max[i]);
|
|
7787
|
+
result.max[i] = max$1(result.max[i], b.max[i]);
|
|
7334
7788
|
}
|
|
7335
7789
|
}
|
|
7336
7790
|
if (pad > 0) return padBounds(result, pad);
|
|
@@ -7343,7 +7797,7 @@ function intersectBounds(bounds, pad) {
|
|
|
7343
7797
|
};
|
|
7344
7798
|
for (const b of bounds) {
|
|
7345
7799
|
for (let i = 0; i < 3; i++) {
|
|
7346
|
-
result.min[i] = max(result.min[i], b.min[i]);
|
|
7800
|
+
result.min[i] = max$1(result.min[i], b.min[i]);
|
|
7347
7801
|
result.max[i] = min(result.max[i], b.max[i]);
|
|
7348
7802
|
}
|
|
7349
7803
|
}
|
|
@@ -7359,242 +7813,544 @@ function padBounds(b, pad) {
|
|
|
7359
7813
|
max: [b.max[0] + pad, b.max[1] + pad, b.max[2] + pad]
|
|
7360
7814
|
};
|
|
7361
7815
|
}
|
|
7362
|
-
const
|
|
7363
|
-
const
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
7816
|
+
const { PI } = Math;
|
|
7817
|
+
const DEG$1 = PI / 180;
|
|
7818
|
+
const TAU = 2 * PI;
|
|
7819
|
+
const GRAD_EPS = 1e-9;
|
|
7820
|
+
const Op = {
|
|
7821
|
+
Const: 0,
|
|
7822
|
+
Neg: 1,
|
|
7823
|
+
Abs: 2,
|
|
7824
|
+
Sqrt: 3,
|
|
7825
|
+
Sin: 4,
|
|
7826
|
+
Cos: 5,
|
|
7827
|
+
Round: 6,
|
|
7828
|
+
Add: 7,
|
|
7829
|
+
Sub: 8,
|
|
7830
|
+
Mul: 9,
|
|
7831
|
+
Div: 10,
|
|
7832
|
+
Min: 11,
|
|
7833
|
+
Max: 12
|
|
7834
|
+
};
|
|
7835
|
+
class UnsupportedSdfProgramNodeError extends Error {
|
|
7836
|
+
constructor(message) {
|
|
7837
|
+
super(message);
|
|
7838
|
+
this.name = "UnsupportedSdfProgramNodeError";
|
|
7382
7839
|
}
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
);
|
|
7840
|
+
}
|
|
7841
|
+
class SdfProgramBuilder {
|
|
7842
|
+
constructor() {
|
|
7843
|
+
__publicField(this, "opcodes", []);
|
|
7844
|
+
__publicField(this, "argA", []);
|
|
7845
|
+
__publicField(this, "argB", []);
|
|
7846
|
+
__publicField(this, "argC", []);
|
|
7847
|
+
__publicField(this, "constants", []);
|
|
7848
|
+
__publicField(this, "x", 0);
|
|
7849
|
+
__publicField(this, "y", 1);
|
|
7850
|
+
__publicField(this, "z", 2);
|
|
7388
7851
|
}
|
|
7389
|
-
|
|
7390
|
-
|
|
7852
|
+
constant(value) {
|
|
7853
|
+
const index2 = this.constants.length;
|
|
7854
|
+
this.constants.push(value);
|
|
7855
|
+
return this.push(Op.Const, 0, 0, index2);
|
|
7391
7856
|
}
|
|
7392
|
-
|
|
7393
|
-
|
|
7857
|
+
neg(a2) {
|
|
7858
|
+
return this.push(Op.Neg, a2);
|
|
7394
7859
|
}
|
|
7395
|
-
|
|
7396
|
-
|
|
7860
|
+
abs(a2) {
|
|
7861
|
+
return this.push(Op.Abs, a2);
|
|
7397
7862
|
}
|
|
7398
|
-
|
|
7399
|
-
|
|
7863
|
+
sqrt(a2) {
|
|
7864
|
+
return this.push(Op.Sqrt, a2);
|
|
7865
|
+
}
|
|
7866
|
+
sin(a2) {
|
|
7867
|
+
return this.push(Op.Sin, a2);
|
|
7868
|
+
}
|
|
7869
|
+
cos(a2) {
|
|
7870
|
+
return this.push(Op.Cos, a2);
|
|
7871
|
+
}
|
|
7872
|
+
round(a2) {
|
|
7873
|
+
return this.push(Op.Round, a2);
|
|
7874
|
+
}
|
|
7875
|
+
add(a2, b) {
|
|
7876
|
+
return this.push(Op.Add, a2, b);
|
|
7877
|
+
}
|
|
7878
|
+
sub(a2, b) {
|
|
7879
|
+
return this.push(Op.Sub, a2, b);
|
|
7880
|
+
}
|
|
7881
|
+
mul(a2, b) {
|
|
7882
|
+
return this.push(Op.Mul, a2, b);
|
|
7883
|
+
}
|
|
7884
|
+
div(a2, b) {
|
|
7885
|
+
return this.push(Op.Div, a2, b);
|
|
7886
|
+
}
|
|
7887
|
+
min(a2, b) {
|
|
7888
|
+
return this.push(Op.Min, a2, b);
|
|
7889
|
+
}
|
|
7890
|
+
max(a2, b) {
|
|
7891
|
+
return this.push(Op.Max, a2, b);
|
|
7892
|
+
}
|
|
7893
|
+
finalize(output) {
|
|
7894
|
+
return {
|
|
7895
|
+
opcodes: Uint8Array.from(this.opcodes),
|
|
7896
|
+
argA: Int32Array.from(this.argA),
|
|
7897
|
+
argB: Int32Array.from(this.argB),
|
|
7898
|
+
argC: Int32Array.from(this.argC),
|
|
7899
|
+
constants: Float64Array.from(this.constants),
|
|
7900
|
+
output,
|
|
7901
|
+
slotCount: this.opcodes.length + 3
|
|
7902
|
+
};
|
|
7903
|
+
}
|
|
7904
|
+
push(op, a2 = 0, b = 0, c2 = 0) {
|
|
7905
|
+
const slot2 = this.opcodes.length + 3;
|
|
7906
|
+
this.opcodes.push(op);
|
|
7907
|
+
this.argA.push(a2);
|
|
7908
|
+
this.argB.push(b);
|
|
7909
|
+
this.argC.push(c2);
|
|
7910
|
+
return slot2;
|
|
7911
|
+
}
|
|
7912
|
+
}
|
|
7913
|
+
function compileSdfProgramEvaluator3(program) {
|
|
7914
|
+
const lines = ["const { abs, sqrt, sin, cos, round, min, max } = Math;", "let v0 = x;", "let v1 = y;", "let v2 = z;"];
|
|
7915
|
+
const { opcodes, argA, argB, argC, constants, output } = program;
|
|
7916
|
+
for (let i = 0; i < opcodes.length; i++) {
|
|
7917
|
+
const slot2 = `v${i + 3}`;
|
|
7918
|
+
const a2 = `v${argA[i]}`;
|
|
7919
|
+
const b = `v${argB[i]}`;
|
|
7920
|
+
switch (opcodes[i]) {
|
|
7921
|
+
case Op.Const:
|
|
7922
|
+
lines.push(`let ${slot2} = ${numberLiteral(constants[argC[i]])};`);
|
|
7923
|
+
break;
|
|
7924
|
+
case Op.Neg:
|
|
7925
|
+
lines.push(`let ${slot2} = -${a2};`);
|
|
7926
|
+
break;
|
|
7927
|
+
case Op.Abs:
|
|
7928
|
+
lines.push(`let ${slot2} = abs(${a2});`);
|
|
7929
|
+
break;
|
|
7930
|
+
case Op.Sqrt:
|
|
7931
|
+
lines.push(`let ${slot2} = sqrt(${a2});`);
|
|
7932
|
+
break;
|
|
7933
|
+
case Op.Sin:
|
|
7934
|
+
lines.push(`let ${slot2} = sin(${a2});`);
|
|
7935
|
+
break;
|
|
7936
|
+
case Op.Cos:
|
|
7937
|
+
lines.push(`let ${slot2} = cos(${a2});`);
|
|
7938
|
+
break;
|
|
7939
|
+
case Op.Round:
|
|
7940
|
+
lines.push(`let ${slot2} = round(${a2});`);
|
|
7941
|
+
break;
|
|
7942
|
+
case Op.Add:
|
|
7943
|
+
lines.push(`let ${slot2} = ${a2} + ${b};`);
|
|
7944
|
+
break;
|
|
7945
|
+
case Op.Sub:
|
|
7946
|
+
lines.push(`let ${slot2} = ${a2} - ${b};`);
|
|
7947
|
+
break;
|
|
7948
|
+
case Op.Mul:
|
|
7949
|
+
lines.push(`let ${slot2} = ${a2} * ${b};`);
|
|
7950
|
+
break;
|
|
7951
|
+
case Op.Div:
|
|
7952
|
+
lines.push(`let ${slot2} = ${a2} / ${b};`);
|
|
7953
|
+
break;
|
|
7954
|
+
case Op.Min:
|
|
7955
|
+
lines.push(`let ${slot2} = min(${a2}, ${b});`);
|
|
7956
|
+
break;
|
|
7957
|
+
case Op.Max:
|
|
7958
|
+
lines.push(`let ${slot2} = max(${a2}, ${b});`);
|
|
7959
|
+
break;
|
|
7960
|
+
default:
|
|
7961
|
+
throw new Error(`Unknown SdfProgram opcode ${opcodes[i]} at instruction ${i}.`);
|
|
7962
|
+
}
|
|
7400
7963
|
}
|
|
7964
|
+
lines.push(`return v${output};`);
|
|
7965
|
+
return new Function("Math", `return function sdfProgramEval(x, y, z) {
|
|
7966
|
+
${lines.join("\n")}
|
|
7967
|
+
};`)(Math);
|
|
7968
|
+
}
|
|
7969
|
+
function numberLiteral(value) {
|
|
7970
|
+
if (Number.isNaN(value)) return "NaN";
|
|
7971
|
+
if (value === Number.POSITIVE_INFINITY) return "Infinity";
|
|
7972
|
+
if (value === Number.NEGATIVE_INFINITY) return "-Infinity";
|
|
7973
|
+
return String(value);
|
|
7974
|
+
}
|
|
7975
|
+
function clampSlot(b, v, lo, hi) {
|
|
7976
|
+
return b.min(b.max(v, b.constant(lo)), b.constant(hi));
|
|
7977
|
+
}
|
|
7978
|
+
function length2(b, x2, y2) {
|
|
7979
|
+
return b.sqrt(b.add(b.mul(x2, x2), b.mul(y2, y2)));
|
|
7980
|
+
}
|
|
7981
|
+
function length3(b, x2, y2, z2) {
|
|
7982
|
+
return b.sqrt(b.add(b.add(b.mul(x2, x2), b.mul(y2, y2)), b.mul(z2, z2)));
|
|
7983
|
+
}
|
|
7984
|
+
function smin(b, a2, child, k2) {
|
|
7985
|
+
if (k2 <= 0) return b.min(a2, child);
|
|
7986
|
+
const h = b.div(b.max(b.sub(b.constant(k2), b.abs(b.sub(a2, child))), b.constant(0)), b.constant(k2));
|
|
7987
|
+
return b.sub(b.min(a2, child), b.mul(b.mul(b.mul(h, h), h), b.constant(k2 / 6)));
|
|
7988
|
+
}
|
|
7989
|
+
function smax(b, a2, child, k2) {
|
|
7990
|
+
return b.neg(smin(b, b.neg(a2), b.neg(child), k2));
|
|
7991
|
+
}
|
|
7992
|
+
function emitScaledTrig(b, x2, y2, z2, cellSize) {
|
|
7993
|
+
const s = b.constant(TAU / cellSize);
|
|
7994
|
+
const xs = b.mul(x2, s);
|
|
7995
|
+
const ys = b.mul(y2, s);
|
|
7996
|
+
const zs = b.mul(z2, s);
|
|
7401
7997
|
return {
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7998
|
+
scale: s,
|
|
7999
|
+
sx: b.sin(xs),
|
|
8000
|
+
sy: b.sin(ys),
|
|
8001
|
+
sz: b.sin(zs),
|
|
8002
|
+
cx: b.cos(xs),
|
|
8003
|
+
cy: b.cos(ys),
|
|
8004
|
+
cz: b.cos(zs),
|
|
8005
|
+
sx2: b.sin(b.mul(b.constant(2), xs)),
|
|
8006
|
+
sy2: b.sin(b.mul(b.constant(2), ys)),
|
|
8007
|
+
sz2: b.sin(b.mul(b.constant(2), zs)),
|
|
8008
|
+
cx2: b.cos(b.mul(b.constant(2), xs)),
|
|
8009
|
+
cy2: b.cos(b.mul(b.constant(2), ys)),
|
|
8010
|
+
cz2: b.cos(b.mul(b.constant(2), zs))
|
|
7413
8011
|
};
|
|
7414
8012
|
}
|
|
7415
|
-
function
|
|
7416
|
-
|
|
8013
|
+
function emitGyroidValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
8014
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
8015
|
+
return {
|
|
8016
|
+
value: b.add(b.add(b.mul(t.sx, t.cy), b.mul(t.sy, t.cz)), b.mul(t.sz, t.cx)),
|
|
8017
|
+
gx: b.mul(t.scale, b.sub(b.mul(t.cx, t.cy), b.mul(t.sz, t.sx))),
|
|
8018
|
+
gy: b.mul(t.scale, b.add(b.neg(b.mul(t.sx, t.sy)), b.mul(t.cy, t.cz))),
|
|
8019
|
+
gz: b.mul(t.scale, b.add(b.neg(b.mul(t.sy, t.sz)), b.mul(t.cz, t.cx)))
|
|
8020
|
+
};
|
|
7417
8021
|
}
|
|
7418
|
-
function
|
|
7419
|
-
const
|
|
7420
|
-
const estimatedSamples = grid[0] * grid[1] * grid[2];
|
|
8022
|
+
function emitSchwarzPValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
8023
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
7421
8024
|
return {
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
estimatedSamples,
|
|
7427
|
-
estimatedMemoryBytes: estimatedSamples * 8,
|
|
7428
|
-
treeRiskFlags: [...settings.treeRiskFlags],
|
|
7429
|
-
simplification: settings.simplify,
|
|
7430
|
-
capMode: "box",
|
|
7431
|
-
capInset: settings.edgeLength,
|
|
7432
|
-
warnings: [...settings.warnings]
|
|
8025
|
+
value: b.add(b.add(t.cx, t.cy), t.cz),
|
|
8026
|
+
gx: b.neg(b.mul(t.scale, t.sx)),
|
|
8027
|
+
gy: b.neg(b.mul(t.scale, t.sy)),
|
|
8028
|
+
gz: b.neg(b.mul(t.scale, t.sz))
|
|
7433
8029
|
};
|
|
7434
8030
|
}
|
|
7435
|
-
function
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
)
|
|
8031
|
+
function emitDiamondValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
8032
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
8033
|
+
return {
|
|
8034
|
+
value: b.add(
|
|
8035
|
+
b.add(b.mul(b.mul(t.sx, t.sy), t.sz), b.mul(b.mul(t.sx, t.cy), t.cz)),
|
|
8036
|
+
b.add(b.mul(b.mul(t.cx, t.sy), t.cz), b.mul(b.mul(t.cx, t.cy), t.sz))
|
|
8037
|
+
),
|
|
8038
|
+
gx: b.mul(
|
|
8039
|
+
t.scale,
|
|
8040
|
+
b.add(
|
|
8041
|
+
b.add(b.mul(b.mul(t.cx, t.sy), t.sz), b.mul(b.mul(t.cx, t.cy), t.cz)),
|
|
8042
|
+
b.add(b.neg(b.mul(b.mul(t.sx, t.sy), t.cz)), b.neg(b.mul(b.mul(t.sx, t.cy), t.sz)))
|
|
8043
|
+
)
|
|
8044
|
+
),
|
|
8045
|
+
gy: b.mul(
|
|
8046
|
+
t.scale,
|
|
8047
|
+
b.add(
|
|
8048
|
+
b.add(b.mul(b.mul(t.sx, t.cy), t.sz), b.neg(b.mul(b.mul(t.sx, t.sy), t.cz))),
|
|
8049
|
+
b.add(b.mul(b.mul(t.cx, t.cy), t.cz), b.neg(b.mul(b.mul(t.cx, t.sy), t.sz)))
|
|
8050
|
+
)
|
|
8051
|
+
),
|
|
8052
|
+
gz: b.mul(
|
|
8053
|
+
t.scale,
|
|
8054
|
+
b.add(
|
|
8055
|
+
b.add(b.mul(b.mul(t.sx, t.sy), t.cz), b.neg(b.mul(b.mul(t.sx, t.cy), t.sz))),
|
|
8056
|
+
b.add(b.neg(b.mul(b.mul(t.cx, t.sy), t.sz)), b.mul(b.mul(t.cx, t.cy), t.cz))
|
|
8057
|
+
)
|
|
8058
|
+
)
|
|
8059
|
+
};
|
|
8060
|
+
}
|
|
8061
|
+
function emitLidinoidValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
8062
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
8063
|
+
const value = b.add(
|
|
8064
|
+
b.sub(
|
|
8065
|
+
b.add(b.add(b.mul(b.mul(t.sx2, t.cy), t.sz), b.mul(b.mul(t.sy2, t.cz), t.sx)), b.mul(b.mul(t.sz2, t.cx), t.sy)),
|
|
8066
|
+
b.add(b.add(b.mul(t.cx2, t.cy2), b.mul(t.cy2, t.cz2)), b.mul(t.cz2, t.cx2))
|
|
8067
|
+
),
|
|
8068
|
+
b.constant(0.3)
|
|
7442
8069
|
);
|
|
8070
|
+
return {
|
|
8071
|
+
value,
|
|
8072
|
+
gx: b.mul(
|
|
8073
|
+
t.scale,
|
|
8074
|
+
b.add(
|
|
8075
|
+
b.add(
|
|
8076
|
+
b.add(b.mul(b.mul(b.constant(2), t.cx2), b.mul(t.cy, t.sz)), b.mul(b.mul(t.sy2, t.cz), t.cx)),
|
|
8077
|
+
b.neg(b.mul(b.mul(t.sz2, t.sx), t.sy))
|
|
8078
|
+
),
|
|
8079
|
+
b.add(b.mul(b.mul(b.constant(2), t.sx2), t.cy2), b.mul(b.mul(b.constant(2), t.cz2), t.sx2))
|
|
8080
|
+
)
|
|
8081
|
+
),
|
|
8082
|
+
gy: b.mul(
|
|
8083
|
+
t.scale,
|
|
8084
|
+
b.add(
|
|
8085
|
+
b.add(
|
|
8086
|
+
b.add(b.neg(b.mul(b.mul(t.sx2, t.sy), t.sz)), b.mul(b.mul(b.constant(2), t.cy2), b.mul(t.cz, t.sx))),
|
|
8087
|
+
b.mul(b.mul(t.sz2, t.cx), t.cy)
|
|
8088
|
+
),
|
|
8089
|
+
b.add(b.mul(b.mul(b.constant(2), t.cx2), t.sy2), b.mul(b.mul(b.constant(2), t.sy2), t.cz2))
|
|
8090
|
+
)
|
|
8091
|
+
),
|
|
8092
|
+
gz: b.mul(
|
|
8093
|
+
t.scale,
|
|
8094
|
+
b.add(
|
|
8095
|
+
b.add(
|
|
8096
|
+
b.add(b.mul(b.mul(t.sx2, t.cy), t.cz), b.neg(b.mul(b.mul(t.sy2, t.sz), t.sx))),
|
|
8097
|
+
b.mul(b.mul(b.constant(2), t.cz2), b.mul(t.cx, t.sy))
|
|
8098
|
+
),
|
|
8099
|
+
b.add(b.mul(b.mul(b.constant(2), t.cy2), t.sz2), b.mul(b.mul(b.constant(2), t.sz2), t.cx2))
|
|
8100
|
+
)
|
|
8101
|
+
)
|
|
8102
|
+
};
|
|
7443
8103
|
}
|
|
7444
|
-
function
|
|
7445
|
-
|
|
7446
|
-
const
|
|
7447
|
-
|
|
7448
|
-
return [
|
|
7449
|
-
Math.max(2, Math.ceil(dx / edgeLength2) + 1),
|
|
7450
|
-
Math.max(2, Math.ceil(dy / edgeLength2) + 1),
|
|
7451
|
-
Math.max(2, Math.ceil(dz / edgeLength2) + 1)
|
|
7452
|
-
];
|
|
8104
|
+
function emitTpmsDistance(b, { value, gx, gy, gz }, thickness, thicknessMode) {
|
|
8105
|
+
if (thicknessMode !== "metric-approx") return b.sub(b.abs(value), b.constant(thickness));
|
|
8106
|
+
const grad = length3(b, gx, gy, gz);
|
|
8107
|
+
return b.sub(b.div(b.abs(value), b.max(grad, b.constant(GRAD_EPS))), b.constant(thickness * 0.5));
|
|
7453
8108
|
}
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
8109
|
+
const { cos, max, sin, sqrt } = Math;
|
|
8110
|
+
function emitSdfProgramNode(b, node, x2, y2, z2) {
|
|
8111
|
+
switch (node.kind) {
|
|
8112
|
+
case "sdf:sphere":
|
|
8113
|
+
return sdSphere(b, x2, y2, z2, node.radius);
|
|
8114
|
+
case "sdf:box": {
|
|
8115
|
+
const [hx, hy, hz] = node.halfExtents;
|
|
8116
|
+
return sdBox(b, x2, y2, z2, hx, hy, hz);
|
|
8117
|
+
}
|
|
8118
|
+
case "sdf:cylinder":
|
|
8119
|
+
return sdCylinder(b, x2, y2, z2, node.height, node.radius);
|
|
8120
|
+
case "sdf:torus":
|
|
8121
|
+
return sdTorus(b, x2, y2, z2, node.majorRadius, node.minorRadius);
|
|
8122
|
+
case "sdf:capsule":
|
|
8123
|
+
return sdCapsule(b, x2, y2, z2, node.height, node.radius);
|
|
8124
|
+
case "sdf:cone":
|
|
8125
|
+
return sdCone(b, x2, y2, z2, node.height, node.radius);
|
|
8126
|
+
case "sdf:polylineSweep":
|
|
8127
|
+
return sdPolylineSweep(b, node, x2, y2, z2);
|
|
8128
|
+
case "sdf:union":
|
|
8129
|
+
return foldChildren$1(b, node.children, x2, y2, z2, (a2, child) => b.min(a2, child));
|
|
8130
|
+
case "sdf:difference":
|
|
8131
|
+
return foldChildren$1(b, node.children, x2, y2, z2, (a2, child) => b.max(a2, b.neg(child)));
|
|
8132
|
+
case "sdf:intersection":
|
|
8133
|
+
return foldChildren$1(b, node.children, x2, y2, z2, (a2, child) => b.max(a2, child));
|
|
8134
|
+
case "sdf:smoothUnion":
|
|
8135
|
+
return foldChildren$1(b, node.children, x2, y2, z2, (a2, child) => smin(b, a2, child, node.radius));
|
|
8136
|
+
case "sdf:smoothDifference":
|
|
8137
|
+
return foldChildren$1(b, node.children, x2, y2, z2, (a2, child) => smax(b, a2, b.neg(child), node.radius));
|
|
8138
|
+
case "sdf:smoothIntersection":
|
|
8139
|
+
return foldChildren$1(b, node.children, x2, y2, z2, (a2, child) => smax(b, a2, child, node.radius));
|
|
8140
|
+
case "sdf:morph": {
|
|
8141
|
+
const a2 = emitSdfProgramNode(b, node.a, x2, y2, z2);
|
|
8142
|
+
const childB = emitSdfProgramNode(b, node.b, x2, y2, z2);
|
|
8143
|
+
return b.add(b.mul(a2, b.constant(1 - node.t)), b.mul(childB, b.constant(node.t)));
|
|
8144
|
+
}
|
|
8145
|
+
case "sdf:translate": {
|
|
8146
|
+
const [ox, oy, oz] = node.offset;
|
|
8147
|
+
return emitSdfProgramNode(b, node.child, b.sub(x2, b.constant(ox)), b.sub(y2, b.constant(oy)), b.sub(z2, b.constant(oz)));
|
|
8148
|
+
}
|
|
8149
|
+
case "sdf:rotate":
|
|
8150
|
+
return emitRotated(b, node, x2, y2, z2);
|
|
8151
|
+
case "sdf:scale": {
|
|
8152
|
+
const inv = 1 / node.factor;
|
|
8153
|
+
const child = emitSdfProgramNode(b, node.child, b.mul(x2, b.constant(inv)), b.mul(y2, b.constant(inv)), b.mul(z2, b.constant(inv)));
|
|
8154
|
+
return b.mul(child, b.constant(node.factor));
|
|
8155
|
+
}
|
|
8156
|
+
case "sdf:twist": {
|
|
8157
|
+
const angle = b.mul(b.constant(node.degreesPerUnit * DEG$1), z2);
|
|
8158
|
+
const c2 = b.cos(angle);
|
|
8159
|
+
const s = b.sin(angle);
|
|
8160
|
+
return emitSdfProgramNode(b, node.child, b.sub(b.mul(c2, x2), b.mul(s, y2)), b.add(b.mul(s, x2), b.mul(c2, y2)), z2);
|
|
8161
|
+
}
|
|
8162
|
+
case "sdf:bend": {
|
|
8163
|
+
const angle = b.div(x2, b.constant(node.radius));
|
|
8164
|
+
const c2 = b.cos(angle);
|
|
8165
|
+
const s = b.sin(angle);
|
|
8166
|
+
const radiusPlusY = b.add(b.constant(node.radius), y2);
|
|
8167
|
+
return emitSdfProgramNode(b, node.child, b.mul(radiusPlusY, s), b.sub(b.mul(radiusPlusY, c2), b.constant(node.radius)), z2);
|
|
8168
|
+
}
|
|
8169
|
+
case "sdf:repeat": {
|
|
8170
|
+
const [sx, sy, sz] = node.spacing;
|
|
8171
|
+
const [cx, cy, cz] = node.count;
|
|
8172
|
+
return emitSdfProgramNode(b, node.child, repeatCoord(b, x2, sx, cx), repeatCoord(b, y2, sy, cy), repeatCoord(b, z2, sz, cz));
|
|
8173
|
+
}
|
|
8174
|
+
case "sdf:shell": {
|
|
8175
|
+
const child = emitSdfProgramNode(b, node.child, x2, y2, z2);
|
|
8176
|
+
return b.sub(b.abs(child), b.constant(node.thickness * 0.5));
|
|
8177
|
+
}
|
|
8178
|
+
case "sdf:onion": {
|
|
8179
|
+
let d2 = emitSdfProgramNode(b, node.child, x2, y2, z2);
|
|
8180
|
+
for (let i = 0; i < node.layers; i++) d2 = b.sub(b.abs(d2), b.constant(node.thickness));
|
|
8181
|
+
return d2;
|
|
8182
|
+
}
|
|
8183
|
+
case "sdf:gyroid":
|
|
8184
|
+
return emitTpmsDistance(b, emitGyroidValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
8185
|
+
case "sdf:schwarzP":
|
|
8186
|
+
return emitTpmsDistance(b, emitSchwarzPValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
8187
|
+
case "sdf:diamond":
|
|
8188
|
+
return emitTpmsDistance(b, emitDiamondValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
8189
|
+
case "sdf:lidinoid":
|
|
8190
|
+
return emitTpmsDistance(b, emitLidinoidValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
8191
|
+
default:
|
|
8192
|
+
throw new UnsupportedSdfProgramNodeError(`SdfProgram does not support node kind ${node.kind} yet.`);
|
|
8193
|
+
}
|
|
7459
8194
|
}
|
|
7460
|
-
function
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
const maxDim = Math.max(dx, dy, dz, minEdgeLength);
|
|
7465
|
-
const divisor = quality === "draft" ? 60 : quality === "export" ? 160 : 100;
|
|
7466
|
-
const candidates = [maxDim / divisor];
|
|
7467
|
-
if (options.tolerance !== void 0) candidates.push(requirePositiveFinite$2(options.tolerance, "SDF tolerance") * 2);
|
|
7468
|
-
if (options.minFeatureSize !== void 0) candidates.push(requirePositiveFinite$2(options.minFeatureSize, "SDF minFeatureSize") / 2.5);
|
|
7469
|
-
if (analysis.minMetricTpmsThickness < Infinity) candidates.push(analysis.minMetricTpmsThickness / 2);
|
|
7470
|
-
if (analysis.minTpmsCellSize < Infinity) candidates.push(analysis.minTpmsCellSize / 10);
|
|
7471
|
-
if (analysis.minRepeatSpacing < Infinity) candidates.push(analysis.minRepeatSpacing / 8);
|
|
7472
|
-
if (analysis.minWallThickness < Infinity) candidates.push(analysis.minWallThickness / 2.5);
|
|
7473
|
-
return Math.max(minEdgeLength, Math.min(...candidates.filter((v) => Number.isFinite(v) && v > 0)));
|
|
8195
|
+
function foldChildren$1(b, children, x2, y2, z2, combine2) {
|
|
8196
|
+
let d2 = emitSdfProgramNode(b, children[0], x2, y2, z2);
|
|
8197
|
+
for (let i = 1; i < children.length; i++) d2 = combine2(d2, emitSdfProgramNode(b, children[i], x2, y2, z2));
|
|
8198
|
+
return d2;
|
|
7474
8199
|
}
|
|
7475
|
-
function
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
8200
|
+
function emitRotated(b, node, x2, y2, z2) {
|
|
8201
|
+
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$1);
|
|
8202
|
+
const cx = cos(rx);
|
|
8203
|
+
const sx = sin(rx);
|
|
8204
|
+
const cy = cos(ry);
|
|
8205
|
+
const sy = sin(ry);
|
|
8206
|
+
const cz = cos(rz);
|
|
8207
|
+
const sz = sin(rz);
|
|
8208
|
+
const x1 = b.add(b.mul(b.constant(cz), x2), b.mul(b.constant(sz), y2));
|
|
8209
|
+
const y1 = b.sub(b.mul(b.constant(cz), y2), b.mul(b.constant(sz), x2));
|
|
8210
|
+
const x22 = b.sub(b.mul(b.constant(cy), x1), b.mul(b.constant(sy), z2));
|
|
8211
|
+
const z22 = b.add(b.mul(b.constant(sy), x1), b.mul(b.constant(cy), z2));
|
|
8212
|
+
const y22 = b.add(b.mul(b.constant(cx), y1), b.mul(b.constant(sx), z22));
|
|
8213
|
+
const z3 = b.sub(b.mul(b.constant(cx), z22), b.mul(b.constant(sx), y1));
|
|
8214
|
+
return emitSdfProgramNode(b, node.child, x22, y22, z3);
|
|
8215
|
+
}
|
|
8216
|
+
function sdSphere(b, x2, y2, z2, r) {
|
|
8217
|
+
return b.sub(length3(b, x2, y2, z2), b.constant(r));
|
|
8218
|
+
}
|
|
8219
|
+
function sdBox(b, x2, y2, z2, hx, hy, hz) {
|
|
8220
|
+
const dx = b.sub(b.abs(x2), b.constant(hx));
|
|
8221
|
+
const dy = b.sub(b.abs(y2), b.constant(hy));
|
|
8222
|
+
const dz = b.sub(b.abs(z2), b.constant(hz));
|
|
8223
|
+
const outside = length3(b, b.max(dx, b.constant(0)), b.max(dy, b.constant(0)), b.max(dz, b.constant(0)));
|
|
8224
|
+
const inside = b.min(b.max(b.max(dx, dy), dz), b.constant(0));
|
|
8225
|
+
return b.add(outside, inside);
|
|
8226
|
+
}
|
|
8227
|
+
function sdCylinder(b, x2, y2, z2, h, r) {
|
|
8228
|
+
const dx = b.sub(length2(b, x2, y2), b.constant(r));
|
|
8229
|
+
const dz = b.sub(b.abs(z2), b.constant(h * 0.5));
|
|
8230
|
+
return b.add(length2(b, b.max(dx, b.constant(0)), b.max(dz, b.constant(0))), b.min(b.max(dx, dz), b.constant(0)));
|
|
8231
|
+
}
|
|
8232
|
+
function sdTorus(b, x2, y2, z2, majorRadius, minorRadius) {
|
|
8233
|
+
return b.sub(length2(b, b.sub(length2(b, x2, y2), b.constant(majorRadius)), z2), b.constant(minorRadius));
|
|
8234
|
+
}
|
|
8235
|
+
function sdCapsule(b, x2, y2, z2, h, r) {
|
|
8236
|
+
const cz = clampSlot(b, z2, -h * 0.5, h * 0.5);
|
|
8237
|
+
return b.sub(length3(b, x2, y2, b.sub(z2, cz)), b.constant(r));
|
|
8238
|
+
}
|
|
8239
|
+
function sdCone(b, x2, y2, z2, h, r) {
|
|
8240
|
+
const q = length2(b, x2, y2);
|
|
8241
|
+
const cLen = sqrt(h * h + r * r);
|
|
8242
|
+
const side = b.add(b.mul(b.constant(h / cLen), q), b.mul(b.constant(-r / cLen), b.sub(z2, b.constant(h))));
|
|
8243
|
+
return b.max(b.max(side, b.neg(z2)), b.sub(z2, b.constant(h)));
|
|
8244
|
+
}
|
|
8245
|
+
function sdPolylineSweep(b, node, x2, y2, z2) {
|
|
8246
|
+
let d2 = sdTaperedSegment(b, x2, y2, z2, node.points[0], node.points[1], node.radii[0], node.radii[1]);
|
|
8247
|
+
for (let i = 1; i < node.points.length - 1; i++) {
|
|
8248
|
+
const segment = sdTaperedSegment(b, x2, y2, z2, node.points[i], node.points[i + 1], node.radii[i], node.radii[i + 1]);
|
|
8249
|
+
d2 = smin(b, d2, segment, node.blend);
|
|
8250
|
+
}
|
|
8251
|
+
return d2;
|
|
7480
8252
|
}
|
|
7481
|
-
function
|
|
7482
|
-
const
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
8253
|
+
function sdTaperedSegment(b, x2, y2, z2, a2, end, ra, rb) {
|
|
8254
|
+
const vx = end[0] - a2[0];
|
|
8255
|
+
const vy = end[1] - a2[1];
|
|
8256
|
+
const vz = end[2] - a2[2];
|
|
8257
|
+
const len2 = vx * vx + vy * vy + vz * vz;
|
|
8258
|
+
if (len2 <= 1e-12) return sdSphere(b, b.sub(x2, b.constant(a2[0])), b.sub(y2, b.constant(a2[1])), b.sub(z2, b.constant(a2[2])), max(ra, rb));
|
|
8259
|
+
const h = clampSlot(
|
|
8260
|
+
b,
|
|
8261
|
+
b.div(
|
|
8262
|
+
b.add(
|
|
8263
|
+
b.add(b.mul(b.sub(x2, b.constant(a2[0])), b.constant(vx)), b.mul(b.sub(y2, b.constant(a2[1])), b.constant(vy))),
|
|
8264
|
+
b.mul(b.sub(z2, b.constant(a2[2])), b.constant(vz))
|
|
8265
|
+
),
|
|
8266
|
+
b.constant(len2)
|
|
8267
|
+
),
|
|
8268
|
+
0,
|
|
8269
|
+
1
|
|
8270
|
+
);
|
|
8271
|
+
const sx = b.sub(x2, b.add(b.constant(a2[0]), b.mul(b.constant(vx), h)));
|
|
8272
|
+
const sy = b.sub(y2, b.add(b.constant(a2[1]), b.mul(b.constant(vy), h)));
|
|
8273
|
+
const sz = b.sub(z2, b.add(b.constant(a2[2]), b.mul(b.constant(vz), h)));
|
|
8274
|
+
const radius = b.add(b.constant(ra), b.mul(b.constant(rb - ra), h));
|
|
8275
|
+
return b.sub(length3(b, sx, sy, sz), radius);
|
|
7493
8276
|
}
|
|
7494
|
-
function
|
|
8277
|
+
function repeatCoord(b, v, spacing, count) {
|
|
8278
|
+
if (spacing <= 0) return v;
|
|
8279
|
+
if (count > 0) {
|
|
8280
|
+
const center = (count - 1) * 0.5;
|
|
8281
|
+
const index2 = clampSlot(b, b.round(b.add(b.div(v, b.constant(spacing)), b.constant(center))), 0, count - 1);
|
|
8282
|
+
return b.sub(v, b.mul(b.sub(index2, b.constant(center)), b.constant(spacing)));
|
|
8283
|
+
}
|
|
8284
|
+
return b.sub(v, b.mul(b.constant(spacing), b.round(b.div(v, b.constant(spacing)))));
|
|
8285
|
+
}
|
|
8286
|
+
function getUnsupportedSdfProgramReason(node) {
|
|
7495
8287
|
switch (node.kind) {
|
|
8288
|
+
case "sdf:displace":
|
|
8289
|
+
return "displace uses a dynamic JavaScript function body";
|
|
8290
|
+
case "sdf:surfaceDisplace":
|
|
8291
|
+
return "surfaceDisplace uses dynamic UV/pattern evaluation";
|
|
8292
|
+
case "sdf:spatialBlend":
|
|
8293
|
+
return "spatialBlend uses a dynamic JavaScript blend function";
|
|
8294
|
+
case "sdf:noise":
|
|
8295
|
+
return "noise depends on table-based simplex evaluation";
|
|
8296
|
+
case "sdf:voronoi":
|
|
8297
|
+
return "voronoi depends on table-based Worley evaluation";
|
|
8298
|
+
case "sdf:custom":
|
|
8299
|
+
return "custom uses a dynamic JavaScript function body";
|
|
8300
|
+
case "sdf:polylineSweep":
|
|
8301
|
+
if (node.points.length < 2) return "polylineSweep needs at least two points";
|
|
8302
|
+
if (node.points.length !== node.radii.length) return "polylineSweep point/radius counts differ";
|
|
8303
|
+
return void 0;
|
|
7496
8304
|
case "sdf:union":
|
|
7497
8305
|
case "sdf:difference":
|
|
7498
8306
|
case "sdf:intersection":
|
|
7499
8307
|
case "sdf:smoothUnion":
|
|
7500
8308
|
case "sdf:smoothDifference":
|
|
7501
8309
|
case "sdf:smoothIntersection":
|
|
7502
|
-
for (const child of node.children)
|
|
7503
|
-
|
|
8310
|
+
for (const child of node.children) {
|
|
8311
|
+
const reason = getUnsupportedSdfProgramReason(child);
|
|
8312
|
+
if (reason) return reason;
|
|
8313
|
+
}
|
|
8314
|
+
return void 0;
|
|
7504
8315
|
case "sdf:morph":
|
|
7505
|
-
|
|
7506
|
-
visitSdfNode(node.a, analysis);
|
|
7507
|
-
visitSdfNode(node.b, analysis);
|
|
7508
|
-
break;
|
|
8316
|
+
return getUnsupportedSdfProgramReason(node.a) ?? getUnsupportedSdfProgramReason(node.b);
|
|
7509
8317
|
case "sdf:translate":
|
|
7510
8318
|
case "sdf:rotate":
|
|
7511
8319
|
case "sdf:scale":
|
|
7512
8320
|
case "sdf:twist":
|
|
7513
8321
|
case "sdf:bend":
|
|
7514
|
-
case "sdf:onion":
|
|
7515
|
-
visitSdfNode(node.child, analysis);
|
|
7516
|
-
break;
|
|
7517
8322
|
case "sdf:repeat":
|
|
7518
|
-
analysis.riskFlags.add("repeat");
|
|
7519
|
-
for (let i = 0; i < 3; i++) {
|
|
7520
|
-
const spacing = node.spacing[i];
|
|
7521
|
-
if (spacing > 0) {
|
|
7522
|
-
analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, spacing);
|
|
7523
|
-
if (node.count[i] <= 0) analysis.hasInfiniteRepeat = true;
|
|
7524
|
-
}
|
|
7525
|
-
}
|
|
7526
|
-
visitSdfNode(node.child, analysis);
|
|
7527
|
-
break;
|
|
7528
8323
|
case "sdf:shell":
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
case "sdf:surfaceDisplace":
|
|
7534
|
-
analysis.riskFlags.add("displacement");
|
|
7535
|
-
visitSdfNode(node.child, analysis);
|
|
7536
|
-
break;
|
|
7537
|
-
case "sdf:gyroid":
|
|
7538
|
-
case "sdf:schwarzP":
|
|
7539
|
-
case "sdf:diamond":
|
|
7540
|
-
case "sdf:lidinoid":
|
|
7541
|
-
analysis.riskFlags.add("tpms");
|
|
7542
|
-
analysis.minTpmsCellSize = Math.min(analysis.minTpmsCellSize, node.cellSize);
|
|
7543
|
-
if (node.thicknessMode === "metric-approx") {
|
|
7544
|
-
analysis.minMetricTpmsThickness = Math.min(analysis.minMetricTpmsThickness, node.thickness);
|
|
7545
|
-
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.thickness);
|
|
7546
|
-
} else {
|
|
7547
|
-
analysis.hasLegacyTpmsThreshold = true;
|
|
7548
|
-
}
|
|
7549
|
-
break;
|
|
7550
|
-
case "sdf:noise":
|
|
7551
|
-
analysis.riskFlags.add("noise");
|
|
7552
|
-
break;
|
|
7553
|
-
case "sdf:voronoi":
|
|
7554
|
-
analysis.riskFlags.add("voronoi");
|
|
7555
|
-
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.wallThickness);
|
|
7556
|
-
if (node.surfaceChild) visitSdfNode(node.surfaceChild, analysis);
|
|
7557
|
-
break;
|
|
7558
|
-
case "sdf:custom":
|
|
7559
|
-
analysis.riskFlags.add("custom");
|
|
7560
|
-
break;
|
|
8324
|
+
case "sdf:onion":
|
|
8325
|
+
return getUnsupportedSdfProgramReason(node.child);
|
|
8326
|
+
default:
|
|
8327
|
+
return void 0;
|
|
7561
8328
|
}
|
|
7562
8329
|
}
|
|
7563
|
-
function
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
}
|
|
7567
|
-
function requirePositiveFinite$2(value, name) {
|
|
7568
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
7569
|
-
throw new Error(`${name} must be a positive finite number.`);
|
|
8330
|
+
function compileSdfProgram(node) {
|
|
8331
|
+
const unsupportedReason = getUnsupportedSdfProgramReason(node);
|
|
8332
|
+
if (unsupportedReason) {
|
|
8333
|
+
throw new UnsupportedSdfProgramNodeError(`SdfProgram does not support this tree yet: ${unsupportedReason}.`);
|
|
7570
8334
|
}
|
|
7571
|
-
|
|
7572
|
-
|
|
7573
|
-
function cloneBounds$2(bounds) {
|
|
7574
|
-
return { min: [...bounds.min], max: [...bounds.max] };
|
|
7575
|
-
}
|
|
7576
|
-
function suggestEdgeLengthForSampleBudget(bounds, maxGridPoints) {
|
|
7577
|
-
const dx = bounds.max[0] - bounds.min[0];
|
|
7578
|
-
const dy = bounds.max[1] - bounds.min[1];
|
|
7579
|
-
const dz = bounds.max[2] - bounds.min[2];
|
|
7580
|
-
const volume = Math.max(dx * dy * dz, 1);
|
|
7581
|
-
return Math.cbrt(volume / Math.max(maxGridPoints, 8));
|
|
7582
|
-
}
|
|
7583
|
-
function formatBounds(bounds) {
|
|
7584
|
-
return `[${bounds.min.map(formatNumber$1).join(",")}]-[${bounds.max.map(formatNumber$1).join(",")}]`;
|
|
7585
|
-
}
|
|
7586
|
-
function formatMm(value) {
|
|
7587
|
-
return `${formatNumber$1(value)}mm`;
|
|
8335
|
+
const builder = new SdfProgramBuilder();
|
|
8336
|
+
return builder.finalize(emitSdfProgramNode(builder, node, builder.x, builder.y, builder.z));
|
|
7588
8337
|
}
|
|
7589
|
-
function
|
|
7590
|
-
return
|
|
8338
|
+
function compileSdfProgram3(node) {
|
|
8339
|
+
return compileSdfProgramEvaluator3(compileSdfProgram(node));
|
|
7591
8340
|
}
|
|
7592
|
-
function
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
8341
|
+
function compileSdfMaterializationEvaluator3(node) {
|
|
8342
|
+
const unsupportedReason = getUnsupportedSdfProgramReason(node);
|
|
8343
|
+
if (unsupportedReason) {
|
|
8344
|
+
return {
|
|
8345
|
+
fn: compileSdfNode3(node),
|
|
8346
|
+
engine: "closure",
|
|
8347
|
+
unsupportedReason
|
|
8348
|
+
};
|
|
8349
|
+
}
|
|
8350
|
+
return {
|
|
8351
|
+
fn: compileSdfProgram3(node),
|
|
8352
|
+
engine: "program"
|
|
8353
|
+
};
|
|
7598
8354
|
}
|
|
7599
8355
|
function midpoint$3(a2, b) {
|
|
7600
8356
|
return [(a2[0] + b[0]) / 2, (a2[1] + b[1]) / 2, (a2[2] + b[2]) / 2];
|
|
@@ -8060,7 +8816,7 @@ function buildCircleExtrusionTopology(circ, height, center = false) {
|
|
|
8060
8816
|
);
|
|
8061
8817
|
return { faces, edges };
|
|
8062
8818
|
}
|
|
8063
|
-
function requireFinite$
|
|
8819
|
+
function requireFinite$9(v, label) {
|
|
8064
8820
|
if (!Number.isFinite(v)) throw new Error(`nurbsSurface: ${label} must be finite, got ${v}`);
|
|
8065
8821
|
}
|
|
8066
8822
|
function normalizeSurfaceTessellation(tessellation) {
|
|
@@ -8070,11 +8826,11 @@ function normalizeSurfaceTessellation(tessellation) {
|
|
|
8070
8826
|
throw new Error(`nurbsSurface: tessellation.mode must be "uniform" or "adaptive", got ${mode}`);
|
|
8071
8827
|
}
|
|
8072
8828
|
if (tessellation.tolerance !== void 0) {
|
|
8073
|
-
requireFinite$
|
|
8829
|
+
requireFinite$9(tessellation.tolerance, "tessellation.tolerance");
|
|
8074
8830
|
if (tessellation.tolerance <= 0) throw new Error("nurbsSurface: tessellation.tolerance must be > 0");
|
|
8075
8831
|
}
|
|
8076
|
-
if (tessellation.minResolution !== void 0) requireFinite$
|
|
8077
|
-
if (tessellation.maxResolution !== void 0) requireFinite$
|
|
8832
|
+
if (tessellation.minResolution !== void 0) requireFinite$9(tessellation.minResolution, "tessellation.minResolution");
|
|
8833
|
+
if (tessellation.maxResolution !== void 0) requireFinite$9(tessellation.maxResolution, "tessellation.maxResolution");
|
|
8078
8834
|
const minResolution = tessellation.minResolution === void 0 ? void 0 : Math.max(2, Math.round(tessellation.minResolution));
|
|
8079
8835
|
const maxResolution = tessellation.maxResolution === void 0 ? void 0 : Math.max(2, Math.round(tessellation.maxResolution));
|
|
8080
8836
|
if (minResolution !== void 0 && maxResolution !== void 0 && minResolution > maxResolution) {
|
|
@@ -8093,10 +8849,10 @@ function normalizeSurfaceDomain(domain) {
|
|
|
8093
8849
|
const uMax = domain.uMax ?? 1;
|
|
8094
8850
|
const vMin = domain.vMin ?? 0;
|
|
8095
8851
|
const vMax = domain.vMax ?? 1;
|
|
8096
|
-
requireFinite$
|
|
8097
|
-
requireFinite$
|
|
8098
|
-
requireFinite$
|
|
8099
|
-
requireFinite$
|
|
8852
|
+
requireFinite$9(uMin, "domain.uMin");
|
|
8853
|
+
requireFinite$9(uMax, "domain.uMax");
|
|
8854
|
+
requireFinite$9(vMin, "domain.vMin");
|
|
8855
|
+
requireFinite$9(vMax, "domain.vMax");
|
|
8100
8856
|
if (uMin < 0 || uMax > 1 || vMin < 0 || vMax > 1) {
|
|
8101
8857
|
throw new Error("nurbsSurface: domain bounds must stay within [0, 1]");
|
|
8102
8858
|
}
|
|
@@ -8108,8 +8864,8 @@ function normalizeSurfaceDomain(domain) {
|
|
|
8108
8864
|
function normalizeTrimLoop(loop, label) {
|
|
8109
8865
|
if (loop.length < 3) throw new Error(`nurbsSurface: ${label} requires at least 3 points`);
|
|
8110
8866
|
const normalized = loop.map(([u2, v], idx) => {
|
|
8111
|
-
requireFinite$
|
|
8112
|
-
requireFinite$
|
|
8867
|
+
requireFinite$9(u2, `${label}[${idx}][0]`);
|
|
8868
|
+
requireFinite$9(v, `${label}[${idx}][1]`);
|
|
8113
8869
|
if (u2 < 0 || u2 > 1 || v < 0 || v > 1) throw new Error(`nurbsSurface: ${label}[${idx}] must stay within [0, 1]`);
|
|
8114
8870
|
return [u2, v];
|
|
8115
8871
|
});
|
|
@@ -8132,8 +8888,8 @@ function normalizeTrimCurve(curve, label) {
|
|
|
8132
8888
|
throw new Error(`nurbsSurface: ${label} needs at least ${degree + 1} control points for degree=${degree}`);
|
|
8133
8889
|
}
|
|
8134
8890
|
const normalizedControlPoints = controlPoints.map(([u2, v], idx) => {
|
|
8135
|
-
requireFinite$
|
|
8136
|
-
requireFinite$
|
|
8891
|
+
requireFinite$9(u2, `${label}.controlPoints[${idx}][0]`);
|
|
8892
|
+
requireFinite$9(v, `${label}.controlPoints[${idx}][1]`);
|
|
8137
8893
|
if (u2 < 0 || u2 > 1 || v < 0 || v > 1) {
|
|
8138
8894
|
throw new Error(`nurbsSurface: ${label}.controlPoints[${idx}] must stay within [0, 1]`);
|
|
8139
8895
|
}
|
|
@@ -8144,7 +8900,7 @@ function normalizeTrimCurve(curve, label) {
|
|
|
8144
8900
|
throw new Error(`nurbsSurface: ${label}.weights length must match controlPoints length`);
|
|
8145
8901
|
}
|
|
8146
8902
|
for (let idx = 0; idx < weights.length; idx += 1) {
|
|
8147
|
-
requireFinite$
|
|
8903
|
+
requireFinite$9(weights[idx], `${label}.weights[${idx}]`);
|
|
8148
8904
|
if (weights[idx] <= 0) throw new Error(`nurbsSurface: ${label}.weights[${idx}] must be > 0`);
|
|
8149
8905
|
}
|
|
8150
8906
|
const knots = curve.knots ?? generateClampedKnots(controlPoints.length, degree);
|
|
@@ -8152,7 +8908,7 @@ function normalizeTrimCurve(curve, label) {
|
|
|
8152
8908
|
throw new Error(`nurbsSurface: ${label}.knots.length should be ${controlPoints.length + degree + 1}, got ${knots.length}`);
|
|
8153
8909
|
}
|
|
8154
8910
|
for (let idx = 0; idx < knots.length; idx += 1) {
|
|
8155
|
-
requireFinite$
|
|
8911
|
+
requireFinite$9(knots[idx], `${label}.knots[${idx}]`);
|
|
8156
8912
|
if (idx > 0 && knots[idx] < knots[idx - 1]) throw new Error(`nurbsSurface: ${label}.knots must be non-decreasing`);
|
|
8157
8913
|
}
|
|
8158
8914
|
if (knots[degree] >= knots[controlPoints.length]) {
|
|
@@ -8332,16 +9088,16 @@ class NurbsSurface {
|
|
|
8332
9088
|
for (let i = 0; i < nU; i++) {
|
|
8333
9089
|
if (controlGrid[i].length !== nV) throw new Error(`nurbsSurface: row ${i} has ${controlGrid[i].length} points, expected ${nV}`);
|
|
8334
9090
|
for (let j = 0; j < nV; j++) {
|
|
8335
|
-
requireFinite$
|
|
8336
|
-
requireFinite$
|
|
8337
|
-
requireFinite$
|
|
9091
|
+
requireFinite$9(controlGrid[i][j][0], `controlGrid[${i}][${j}][0]`);
|
|
9092
|
+
requireFinite$9(controlGrid[i][j][1], `controlGrid[${i}][${j}][1]`);
|
|
9093
|
+
requireFinite$9(controlGrid[i][j][2], `controlGrid[${i}][${j}][2]`);
|
|
8338
9094
|
}
|
|
8339
9095
|
}
|
|
8340
9096
|
const weightsGrid = options.weights ?? controlGrid.map((row) => row.map(() => 1));
|
|
8341
9097
|
for (let i = 0; i < nU; i++) {
|
|
8342
9098
|
if (weightsGrid[i].length !== nV) throw new Error(`nurbsSurface: weights row ${i} length mismatch`);
|
|
8343
9099
|
for (let j = 0; j < nV; j++) {
|
|
8344
|
-
requireFinite$
|
|
9100
|
+
requireFinite$9(weightsGrid[i][j], `weights[${i}][${j}]`);
|
|
8345
9101
|
if (weightsGrid[i][j] <= 0) throw new Error(`nurbsSurface: weights[${i}][${j}] must be > 0`);
|
|
8346
9102
|
}
|
|
8347
9103
|
}
|
|
@@ -9730,24 +10486,24 @@ function stitchSingleLoopLoft(loops, heights, wasm) {
|
|
|
9730
10486
|
const j1 = (j + 1) % N;
|
|
9731
10487
|
const v0 = baseIdx + j;
|
|
9732
10488
|
const v1 = nextIdx + j;
|
|
9733
|
-
const
|
|
10489
|
+
const v22 = nextIdx + j1;
|
|
9734
10490
|
const v32 = baseIdx + j1;
|
|
9735
|
-
triangles.push(v0, v32,
|
|
9736
|
-
triangles.push(v0,
|
|
10491
|
+
triangles.push(v0, v32, v22);
|
|
10492
|
+
triangles.push(v0, v22, v1);
|
|
9737
10493
|
}
|
|
9738
10494
|
}
|
|
9739
10495
|
const bottomResampled2D = resampled[0].map(([x2, y2]) => [x2, y2]);
|
|
9740
10496
|
const bottomTrisResampled = wasm.triangulate([bottomResampled2D]);
|
|
9741
10497
|
for (const tri of bottomTrisResampled) {
|
|
9742
|
-
const [v0, v1,
|
|
9743
|
-
triangles.push(v0,
|
|
10498
|
+
const [v0, v1, v22] = Array.isArray(tri) ? tri : [tri[0], tri[1], tri[2]];
|
|
10499
|
+
triangles.push(v0, v22, v1);
|
|
9744
10500
|
}
|
|
9745
10501
|
const topResampled2D = resampled[resampled.length - 1].map(([x2, y2]) => [x2, y2]);
|
|
9746
10502
|
const topTrisResampled = wasm.triangulate([topResampled2D]);
|
|
9747
10503
|
const topStartIdx = (resampled.length - 1) * N;
|
|
9748
10504
|
for (const tri of topTrisResampled) {
|
|
9749
|
-
const [v0, v1,
|
|
9750
|
-
triangles.push(topStartIdx + v0, topStartIdx + v1, topStartIdx +
|
|
10505
|
+
const [v0, v1, v22] = Array.isArray(tri) ? tri : [tri[0], tri[1], tri[2]];
|
|
10506
|
+
triangles.push(topStartIdx + v0, topStartIdx + v1, topStartIdx + v22);
|
|
9751
10507
|
}
|
|
9752
10508
|
const mesh = new wasm.Mesh({
|
|
9753
10509
|
numProp: 3,
|
|
@@ -9774,7 +10530,7 @@ async function initManifoldWasm() {
|
|
|
9774
10530
|
if (_wasm$1) return _wasm$1;
|
|
9775
10531
|
performance.mark("manifold:start");
|
|
9776
10532
|
const Module = (await __vitePreload(async () => {
|
|
9777
|
-
const { default: __vite_default__ } = await import("./manifold-
|
|
10533
|
+
const { default: __vite_default__ } = await import("./manifold-CRoBhJKH.js");
|
|
9778
10534
|
return { default: __vite_default__ };
|
|
9779
10535
|
}, true ? [] : void 0)).default;
|
|
9780
10536
|
performance.mark("manifold:imported");
|
|
@@ -10057,10 +10813,10 @@ function stitchLoopAlongPath(loop, _path, frames, wasm) {
|
|
|
10057
10813
|
const j1 = (j + 1) % N;
|
|
10058
10814
|
const v0 = baseIdx + j;
|
|
10059
10815
|
const v1 = nextIdx + j;
|
|
10060
|
-
const
|
|
10816
|
+
const v22 = nextIdx + j1;
|
|
10061
10817
|
const v32 = baseIdx + j1;
|
|
10062
|
-
triangles.push(v0, v32,
|
|
10063
|
-
triangles.push(v0,
|
|
10818
|
+
triangles.push(v0, v32, v22);
|
|
10819
|
+
triangles.push(v0, v22, v1);
|
|
10064
10820
|
}
|
|
10065
10821
|
}
|
|
10066
10822
|
const bottomPts = resampled.map(([u2, v]) => [u2, v]);
|
|
@@ -11405,8 +12161,16 @@ function lowerShapeCompilePlanToManifold(plan, wasm) {
|
|
|
11405
12161
|
case "importedMesh":
|
|
11406
12162
|
return lowerImportedMeshToManifold(plan.fileData, plan.format, plan.filePath, wasm);
|
|
11407
12163
|
case "sdf": {
|
|
11408
|
-
const
|
|
11409
|
-
return lowerSdfToManifold(
|
|
12164
|
+
const evaluator = compileSdfMaterializationEvaluator3(plan.tree);
|
|
12165
|
+
return lowerSdfToManifold(
|
|
12166
|
+
evaluator.fn,
|
|
12167
|
+
plan.bounds,
|
|
12168
|
+
plan.edgeLength,
|
|
12169
|
+
wasm,
|
|
12170
|
+
plan.meshing,
|
|
12171
|
+
evaluator.engine,
|
|
12172
|
+
evaluator.unsupportedReason
|
|
12173
|
+
);
|
|
11410
12174
|
}
|
|
11411
12175
|
case "fromSlices":
|
|
11412
12176
|
return lowerFromSlicesToManifold(plan, wasm);
|
|
@@ -11424,8 +12188,12 @@ function lowerShapeCompilePlanToManifold(plan, wasm) {
|
|
|
11424
12188
|
assertExhaustive(plan);
|
|
11425
12189
|
}
|
|
11426
12190
|
}
|
|
11427
|
-
function lowerSdfToManifold(evalFn, bounds, edgeLength2, wasm, meshing) {
|
|
12191
|
+
function lowerSdfToManifold(evalFn, bounds, edgeLength2, wasm, meshing, evaluatorEngine, evaluatorUnsupportedReason) {
|
|
11428
12192
|
const diagnostics = (meshing == null ? void 0 : meshing.diagnostics) ? { ...meshing.diagnostics } : void 0;
|
|
12193
|
+
if (diagnostics && evaluatorEngine) {
|
|
12194
|
+
diagnostics.evaluator = evaluatorEngine;
|
|
12195
|
+
if (evaluatorUnsupportedReason) diagnostics.evaluatorUnsupportedReason = evaluatorUnsupportedReason;
|
|
12196
|
+
}
|
|
11429
12197
|
const inset = edgeLength2;
|
|
11430
12198
|
const cappedEvalFn = (x2, y2, z2) => {
|
|
11431
12199
|
const bx = Math.max(bounds.min[0] + inset - x2, x2 - bounds.max[0] + inset);
|
|
@@ -16846,9 +17614,9 @@ function requireClipper() {
|
|
|
16846
17614
|
if (ClipperLib2.use_xyz) j.OffPt.Z = OffPt.Z;
|
|
16847
17615
|
this.m_Joins.push(j);
|
|
16848
17616
|
};
|
|
16849
|
-
ClipperLib2.Clipper.prototype.AddGhostJoin = function(
|
|
17617
|
+
ClipperLib2.Clipper.prototype.AddGhostJoin = function(Op2, OffPt) {
|
|
16850
17618
|
var j = new ClipperLib2.Join();
|
|
16851
|
-
j.OutPt1 =
|
|
17619
|
+
j.OutPt1 = Op2;
|
|
16852
17620
|
j.OffPt.X = OffPt.X;
|
|
16853
17621
|
j.OffPt.Y = OffPt.Y;
|
|
16854
17622
|
if (ClipperLib2.use_xyz) j.OffPt.Z = OffPt.Z;
|
|
@@ -19750,7 +20518,7 @@ function requireClipper() {
|
|
|
19750
20518
|
}
|
|
19751
20519
|
var clipperExports = requireClipper();
|
|
19752
20520
|
const ClipperLib = /* @__PURE__ */ getDefaultExportFromCjs(clipperExports);
|
|
19753
|
-
let f$
|
|
20521
|
+
let f$3 = class f {
|
|
19754
20522
|
constructor(t, e) {
|
|
19755
20523
|
this.next = null, this.key = t, this.data = e, this.left = null, this.right = null;
|
|
19756
20524
|
}
|
|
@@ -19759,7 +20527,7 @@ function d(n, t) {
|
|
|
19759
20527
|
return n > t ? 1 : n < t ? -1 : 0;
|
|
19760
20528
|
}
|
|
19761
20529
|
function u$1(n, t, e) {
|
|
19762
|
-
const r = new f$
|
|
20530
|
+
const r = new f$3(null, null);
|
|
19763
20531
|
let l = r, i = r;
|
|
19764
20532
|
for (; ; ) {
|
|
19765
20533
|
const o = e(n, t.key);
|
|
@@ -19782,7 +20550,7 @@ function u$1(n, t, e) {
|
|
|
19782
20550
|
return l.right = t.left, i.left = t.right, t.left = r.right, t.right = r.left, t;
|
|
19783
20551
|
}
|
|
19784
20552
|
function c(n, t, e, r) {
|
|
19785
|
-
const l = new f$
|
|
20553
|
+
const l = new f$3(n, t);
|
|
19786
20554
|
if (e === null)
|
|
19787
20555
|
return l.left = l.right = null, l;
|
|
19788
20556
|
e = u$1(n, e, r);
|
|
@@ -19823,7 +20591,7 @@ class z {
|
|
|
19823
20591
|
* Adds a key, if it is not present in the tree
|
|
19824
20592
|
*/
|
|
19825
20593
|
add(t, e) {
|
|
19826
|
-
const r = new f$
|
|
20594
|
+
const r = new f$3(t, e);
|
|
19827
20595
|
this._root === null && (r.left = r.right = null, this._size++, this._root = r);
|
|
19828
20596
|
const l = this._comparator, i = u$1(t, this._root, l), o = l(t, i.key);
|
|
19829
20597
|
return o === 0 ? this._root = i : (o < 0 ? (r.left = i.left, r.right = i, i.left = null) : o > 0 && (r.right = i.right, r.left = i, i.right = null), this._size++, this._root = r), this._root;
|
|
@@ -20036,23 +20804,23 @@ class z {
|
|
|
20036
20804
|
function a(n, t, e, r) {
|
|
20037
20805
|
const l = r - e;
|
|
20038
20806
|
if (l > 0) {
|
|
20039
|
-
const i = e + Math.floor(l / 2), o = n[i], s = t[i], h = new f$
|
|
20807
|
+
const i = e + Math.floor(l / 2), o = n[i], s = t[i], h = new f$3(o, s);
|
|
20040
20808
|
return h.left = a(n, t, e, i), h.right = a(n, t, i + 1, r), h;
|
|
20041
20809
|
}
|
|
20042
20810
|
return null;
|
|
20043
20811
|
}
|
|
20044
20812
|
function x(n, t) {
|
|
20045
|
-
const e = new f$
|
|
20813
|
+
const e = new f$3(null, null);
|
|
20046
20814
|
let r = e;
|
|
20047
20815
|
for (let l = 0; l < n.length; l++)
|
|
20048
|
-
r = r.next = new f$
|
|
20816
|
+
r = r.next = new f$3(n[l], t[l]);
|
|
20049
20817
|
return r.next = null, e.next;
|
|
20050
20818
|
}
|
|
20051
20819
|
function k(n) {
|
|
20052
20820
|
let t = n;
|
|
20053
20821
|
const e = [];
|
|
20054
20822
|
let r = false;
|
|
20055
|
-
const l = new f$
|
|
20823
|
+
const l = new f$3(null, null);
|
|
20056
20824
|
let i = l;
|
|
20057
20825
|
for (; !r; )
|
|
20058
20826
|
t ? (e.push(t), t = t.left) : e.length > 0 ? (t = i = i.next = e.pop(), t = t.right) : r = true;
|
|
@@ -20067,7 +20835,7 @@ function p(n, t, e) {
|
|
|
20067
20835
|
return null;
|
|
20068
20836
|
}
|
|
20069
20837
|
function y(n, t, e) {
|
|
20070
|
-
const r = new f$
|
|
20838
|
+
const r = new f$3(null, null);
|
|
20071
20839
|
let l = r, i = n, o = t;
|
|
20072
20840
|
for (; i !== null && o !== null; )
|
|
20073
20841
|
e(i.key, o.key) < 0 ? (l.next = i, i = i.next) : (l.next = o, o = o.next), l = l.next;
|
|
@@ -20459,21 +21227,21 @@ const verticalIntersection = (pt, v, x2) => {
|
|
|
20459
21227
|
y: pt.y + v.y / v.x * (x2 - pt.x)
|
|
20460
21228
|
};
|
|
20461
21229
|
};
|
|
20462
|
-
const intersection$1 = (pt1, v1, pt2,
|
|
20463
|
-
if (v1.x === 0) return verticalIntersection(pt2,
|
|
20464
|
-
if (
|
|
20465
|
-
if (v1.y === 0) return horizontalIntersection(pt2,
|
|
20466
|
-
if (
|
|
20467
|
-
const kross = crossProduct(v1,
|
|
21230
|
+
const intersection$1 = (pt1, v1, pt2, v22) => {
|
|
21231
|
+
if (v1.x === 0) return verticalIntersection(pt2, v22, pt1.x);
|
|
21232
|
+
if (v22.x === 0) return verticalIntersection(pt1, v1, pt2.x);
|
|
21233
|
+
if (v1.y === 0) return horizontalIntersection(pt2, v22, pt1.y);
|
|
21234
|
+
if (v22.y === 0) return horizontalIntersection(pt1, v1, pt2.y);
|
|
21235
|
+
const kross = crossProduct(v1, v22);
|
|
20468
21236
|
if (kross == 0) return null;
|
|
20469
21237
|
const ve = {
|
|
20470
21238
|
x: pt2.x - pt1.x,
|
|
20471
21239
|
y: pt2.y - pt1.y
|
|
20472
21240
|
};
|
|
20473
21241
|
const d1 = crossProduct(ve, v1) / kross;
|
|
20474
|
-
const d2 = crossProduct(ve,
|
|
20475
|
-
const x1 = pt1.x + d2 * v1.x, x2 = pt2.x + d1 *
|
|
20476
|
-
const y1 = pt1.y + d2 * v1.y, y2 = pt2.y + d1 *
|
|
21242
|
+
const d2 = crossProduct(ve, v22) / kross;
|
|
21243
|
+
const x1 = pt1.x + d2 * v1.x, x2 = pt2.x + d1 * v22.x;
|
|
21244
|
+
const y1 = pt1.y + d2 * v1.y, y2 = pt2.y + d1 * v22.y;
|
|
20477
21245
|
const x3 = (x1 + x2) / 2;
|
|
20478
21246
|
const y3 = (y1 + y2) / 2;
|
|
20479
21247
|
return {
|
|
@@ -25055,7 +25823,13 @@ function normalizeTruckShapeForBooleanInput(shape) {
|
|
|
25055
25823
|
return normalized;
|
|
25056
25824
|
}
|
|
25057
25825
|
function lowerSdfPlan(plan) {
|
|
25058
|
-
|
|
25826
|
+
var _a3, _b3, _c2;
|
|
25827
|
+
const evaluator = compileSdfMaterializationEvaluator3(plan.tree);
|
|
25828
|
+
if ((_a3 = plan.meshing) == null ? void 0 : _a3.diagnostics) {
|
|
25829
|
+
plan.meshing.diagnostics.evaluator = evaluator.engine;
|
|
25830
|
+
if (evaluator.unsupportedReason) plan.meshing.diagnostics.evaluatorUnsupportedReason = evaluator.unsupportedReason;
|
|
25831
|
+
}
|
|
25832
|
+
const evalFn = evaluator.fn;
|
|
25059
25833
|
const inset = plan.edgeLength;
|
|
25060
25834
|
const cappedEvalFn = (x2, y2, z2) => {
|
|
25061
25835
|
const bx = Math.max(plan.bounds.min[0] + inset - x2, x2 - plan.bounds.max[0] + inset);
|
|
@@ -25067,14 +25841,18 @@ function lowerSdfPlan(plan) {
|
|
|
25067
25841
|
assertSdfMeshBudget(mesh, plan);
|
|
25068
25842
|
let surfaceNetsError;
|
|
25069
25843
|
try {
|
|
25070
|
-
|
|
25844
|
+
const shape = lowerExtractedSdfMesh(mesh, cappedEvalFn, true);
|
|
25845
|
+
if ((_b3 = plan.meshing) == null ? void 0 : _b3.diagnostics) logSdfMeshingDiagnostics("SDF meshing result", plan.meshing.diagnostics);
|
|
25846
|
+
return shape;
|
|
25071
25847
|
} catch (error) {
|
|
25072
25848
|
surfaceNetsError = error;
|
|
25073
25849
|
}
|
|
25074
25850
|
const tetraMesh = marchingTetrahedra(cappedEvalFn, plan.bounds, plan.edgeLength);
|
|
25075
25851
|
assertSdfMeshBudget(tetraMesh, plan);
|
|
25076
25852
|
try {
|
|
25077
|
-
|
|
25853
|
+
const shape = lowerExtractedSdfMesh(tetraMesh, cappedEvalFn, false);
|
|
25854
|
+
if ((_c2 = plan.meshing) == null ? void 0 : _c2.diagnostics) logSdfMeshingDiagnostics("SDF meshing result", plan.meshing.diagnostics);
|
|
25855
|
+
return shape;
|
|
25078
25856
|
} catch (error) {
|
|
25079
25857
|
throw new Error(
|
|
25080
25858
|
`Truck backend does not support compile plan "sdf" for this materialized field yet: Surface Nets failed with ${surfaceNetsError instanceof Error ? surfaceNetsError.message : String(surfaceNetsError)}; marching tetrahedra failed with ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -25438,7 +26216,9 @@ function lowerOffsetSolidPlan(plan) {
|
|
|
25438
26216
|
if (base.kind === "transform") {
|
|
25439
26217
|
return lowerTransformedOffsetSolidPlan(base, plan.thickness);
|
|
25440
26218
|
}
|
|
25441
|
-
return truckUnsupported(
|
|
26219
|
+
return truckUnsupported(
|
|
26220
|
+
`compile plan "${plan.kind}" for non-vertical-prism/non-revolved/non-loft/non-straight-sweep/non-straight-variable-sweep solids`
|
|
26221
|
+
);
|
|
25442
26222
|
}
|
|
25443
26223
|
function lowerLoftPlan(plan) {
|
|
25444
26224
|
return wrapTruckShapeBackend(
|
|
@@ -29668,16 +30448,16 @@ function clusterMeshFaces(shape) {
|
|
|
29668
30448
|
const i2 = triVerts[i * 3 + 2];
|
|
29669
30449
|
const v0 = [vertProperties[i0 * numProp], vertProperties[i0 * numProp + 1], vertProperties[i0 * numProp + 2]];
|
|
29670
30450
|
const v1 = [vertProperties[i1 * numProp], vertProperties[i1 * numProp + 1], vertProperties[i1 * numProp + 2]];
|
|
29671
|
-
const
|
|
30451
|
+
const v22 = [vertProperties[i2 * numProp], vertProperties[i2 * numProp + 1], vertProperties[i2 * numProp + 2]];
|
|
29672
30452
|
const e1 = [v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2]];
|
|
29673
|
-
const e2 = [
|
|
30453
|
+
const e2 = [v22[0] - v0[0], v22[1] - v0[1], v22[2] - v0[2]];
|
|
29674
30454
|
const rawCross = cross$4(e1, e2);
|
|
29675
30455
|
const normal = normVec3(rawCross);
|
|
29676
30456
|
if (!normal) continue;
|
|
29677
30457
|
const crossLen = Math.sqrt(rawCross[0] * rawCross[0] + rawCross[1] * rawCross[1] + rawCross[2] * rawCross[2]);
|
|
29678
30458
|
const triArea = crossLen / 2;
|
|
29679
30459
|
const planeOffset = dot$5(normal, v0);
|
|
29680
|
-
const triCentroid = [(v0[0] + v1[0] +
|
|
30460
|
+
const triCentroid = [(v0[0] + v1[0] + v22[0]) / 3, (v0[1] + v1[1] + v22[1]) / 3, (v0[2] + v1[2] + v22[2]) / 3];
|
|
29681
30461
|
let merged = false;
|
|
29682
30462
|
for (const c2 of clusters) {
|
|
29683
30463
|
if (dot$5(c2.normal, normal) > NORMAL_COS_EPS$1 && Math.abs(c2.planeOffset - planeOffset) < PLANE_OFFSET_EPS$1) {
|
|
@@ -32740,6 +33520,37 @@ function mergeSketchPlacementModel(sketches) {
|
|
|
32740
33520
|
}
|
|
32741
33521
|
return first;
|
|
32742
33522
|
}
|
|
33523
|
+
function normalizeSceneTags(value, label = "tags") {
|
|
33524
|
+
if (value == null) return [];
|
|
33525
|
+
const rawTags = typeof value === "string" ? [value] : value;
|
|
33526
|
+
if (!Array.isArray(rawTags)) {
|
|
33527
|
+
throw new Error(`${label} must be a string or array of strings`);
|
|
33528
|
+
}
|
|
33529
|
+
const out = [];
|
|
33530
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
33531
|
+
rawTags.forEach((tag, index2) => {
|
|
33532
|
+
if (typeof tag !== "string") {
|
|
33533
|
+
throw new Error(`${label}[${index2}] must be a string`);
|
|
33534
|
+
}
|
|
33535
|
+
const trimmed = tag.trim();
|
|
33536
|
+
if (!trimmed || seen2.has(trimmed)) return;
|
|
33537
|
+
seen2.add(trimmed);
|
|
33538
|
+
out.push(trimmed);
|
|
33539
|
+
});
|
|
33540
|
+
return out;
|
|
33541
|
+
}
|
|
33542
|
+
function mergeSceneTags(...values) {
|
|
33543
|
+
const out = [];
|
|
33544
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
33545
|
+
values.forEach((value) => {
|
|
33546
|
+
normalizeSceneTags(value).forEach((tag) => {
|
|
33547
|
+
if (seen2.has(tag)) return;
|
|
33548
|
+
seen2.add(tag);
|
|
33549
|
+
out.push(tag);
|
|
33550
|
+
});
|
|
33551
|
+
});
|
|
33552
|
+
return out;
|
|
33553
|
+
}
|
|
32743
33554
|
const _groupPlacementRefs = /* @__PURE__ */ new WeakMap();
|
|
32744
33555
|
const _groupExplodeHint = /* @__PURE__ */ new WeakMap();
|
|
32745
33556
|
function getGroupRefs(g2) {
|
|
@@ -32763,7 +33574,7 @@ function transformGroupRefs(source, dest, matrix) {
|
|
|
32763
33574
|
}
|
|
32764
33575
|
return dest;
|
|
32765
33576
|
}
|
|
32766
|
-
function requireFiniteAngle(v, method) {
|
|
33577
|
+
function requireFiniteAngle$1(v, method) {
|
|
32767
33578
|
if (typeof v !== "number" || !Number.isFinite(v))
|
|
32768
33579
|
throw new Error(`${method} angleDeg must be a finite number, got ${typeof v === "number" ? v : typeof v}`);
|
|
32769
33580
|
}
|
|
@@ -32824,31 +33635,46 @@ function resolveNamedGroupChild(item) {
|
|
|
32824
33635
|
function normalizeGroupInputs(items) {
|
|
32825
33636
|
const children = [];
|
|
32826
33637
|
const childNames = [];
|
|
33638
|
+
const childTags = [];
|
|
32827
33639
|
items.forEach((item) => {
|
|
32828
33640
|
if (isNamedGroupChild(item)) {
|
|
32829
33641
|
children.push(resolveNamedGroupChild(item));
|
|
32830
33642
|
childNames.push(normalizeChildName(item.name));
|
|
33643
|
+
childTags.push(normalizeSceneTags(item.tags, `group(...) named item "${item.name}" tags`));
|
|
32831
33644
|
return;
|
|
32832
33645
|
}
|
|
32833
33646
|
children.push(item);
|
|
32834
33647
|
childNames.push(void 0);
|
|
33648
|
+
childTags.push([]);
|
|
32835
33649
|
});
|
|
32836
|
-
return { children, childNames };
|
|
33650
|
+
return { children, childNames, childTags };
|
|
32837
33651
|
}
|
|
32838
33652
|
class ShapeGroup {
|
|
32839
|
-
constructor(children, childNames) {
|
|
33653
|
+
constructor(children, childNames, childTags) {
|
|
32840
33654
|
__publicField(this, "children");
|
|
32841
33655
|
__publicField(this, "childNames");
|
|
33656
|
+
__publicField(this, "childTags");
|
|
32842
33657
|
if (childNames && childNames.length !== children.length) {
|
|
32843
33658
|
throw new Error("ShapeGroup childNames must match children length");
|
|
32844
33659
|
}
|
|
33660
|
+
if (childTags && childTags.length !== children.length) {
|
|
33661
|
+
throw new Error("ShapeGroup childTags must match children length");
|
|
33662
|
+
}
|
|
32845
33663
|
this.children = [...children];
|
|
32846
33664
|
this.childNames = this.children.map((_2, index2) => normalizeChildName(childNames == null ? void 0 : childNames[index2]));
|
|
33665
|
+
this.childTags = this.children.map((_2, index2) => normalizeSceneTags(childTags == null ? void 0 : childTags[index2], "ShapeGroup childTags"));
|
|
32847
33666
|
}
|
|
32848
33667
|
/** Return the optional name of the child at `index`. */
|
|
32849
33668
|
childName(index2) {
|
|
32850
33669
|
return this.childNames[index2];
|
|
32851
33670
|
}
|
|
33671
|
+
/**
|
|
33672
|
+
* Return tags attached to the child at `index`.
|
|
33673
|
+
* @internal
|
|
33674
|
+
*/
|
|
33675
|
+
tagsForChild(index2) {
|
|
33676
|
+
return [...this.childTags[index2] ?? []];
|
|
33677
|
+
}
|
|
32852
33678
|
/**
|
|
32853
33679
|
* Return the named child by name. Throws if not found.
|
|
32854
33680
|
* Useful when importing a multipart group and working on components individually.
|
|
@@ -32863,13 +33689,13 @@ class ShapeGroup {
|
|
|
32863
33689
|
}
|
|
32864
33690
|
/** Apply fn to all children, producing a new ShapeGroup that also copies placement refs. */
|
|
32865
33691
|
mapChildren(fn) {
|
|
32866
|
-
const next = new ShapeGroup(this.children.map(fn), this.childNames);
|
|
33692
|
+
const next = new ShapeGroup(this.children.map(fn), this.childNames, this.childTags);
|
|
32867
33693
|
copyGroupPorts(this, next);
|
|
32868
33694
|
return copyGroupRefs(this, next);
|
|
32869
33695
|
}
|
|
32870
33696
|
/** Apply fn to all children and also transform placement refs by the given matrix. */
|
|
32871
33697
|
mapChildrenTransform(fn, matrix) {
|
|
32872
|
-
const next = new ShapeGroup(this.children.map(fn), this.childNames);
|
|
33698
|
+
const next = new ShapeGroup(this.children.map(fn), this.childNames, this.childTags);
|
|
32873
33699
|
transformGroupPortsHelper(this, next, matrix);
|
|
32874
33700
|
return transformGroupRefs(this, next, matrix);
|
|
32875
33701
|
}
|
|
@@ -32984,37 +33810,37 @@ class ShapeGroup {
|
|
|
32984
33810
|
const u2 = opts.u ?? 0, v = opts.v ?? 0, p2 = opts.protrude ?? 0;
|
|
32985
33811
|
const opp = { front: "back", back: "front", left: "right", right: "left", top: "bottom", bottom: "top" };
|
|
32986
33812
|
const uvMap = {
|
|
32987
|
-
front: (u22,
|
|
32988
|
-
back: (u22,
|
|
32989
|
-
left: (u22,
|
|
32990
|
-
right: (u22,
|
|
32991
|
-
top: (u22,
|
|
32992
|
-
bottom: (u22,
|
|
33813
|
+
front: (u22, v22, p22) => [u22, -p22, v22],
|
|
33814
|
+
back: (u22, v22, p22) => [u22, p22, v22],
|
|
33815
|
+
left: (u22, v22, p22) => [-p22, u22, v22],
|
|
33816
|
+
right: (u22, v22, p22) => [p22, u22, v22],
|
|
33817
|
+
top: (u22, v22, p22) => [u22, v22, p22],
|
|
33818
|
+
bottom: (u22, v22, p22) => [u22, v22, -p22]
|
|
32993
33819
|
};
|
|
32994
33820
|
return this.attachTo(parent, face, opp[face], uvMap[face](u2, v, p2));
|
|
32995
33821
|
}
|
|
32996
33822
|
/** Rotate the group around an arbitrary axis through the origin. */
|
|
32997
33823
|
rotate(axis, angleDeg, options) {
|
|
32998
33824
|
requireRotateAxis(axis, "ShapeGroup.rotate()");
|
|
32999
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotate()");
|
|
33825
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotate()");
|
|
33000
33826
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotate()");
|
|
33001
33827
|
return this.rotateAroundAxis(axis, angleDeg, options == null ? void 0 : options.pivot);
|
|
33002
33828
|
}
|
|
33003
33829
|
/** Rotate the group around the X axis. */
|
|
33004
33830
|
rotateX(angleDeg, options) {
|
|
33005
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotateX()");
|
|
33831
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotateX()");
|
|
33006
33832
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotateX()");
|
|
33007
33833
|
return this.rotateAroundAxis([1, 0, 0], angleDeg, options == null ? void 0 : options.pivot);
|
|
33008
33834
|
}
|
|
33009
33835
|
/** Rotate the group around the Y axis. */
|
|
33010
33836
|
rotateY(angleDeg, options) {
|
|
33011
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotateY()");
|
|
33837
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotateY()");
|
|
33012
33838
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotateY()");
|
|
33013
33839
|
return this.rotateAroundAxis([0, 1, 0], angleDeg, options == null ? void 0 : options.pivot);
|
|
33014
33840
|
}
|
|
33015
33841
|
/** Rotate the group around the Z axis. */
|
|
33016
33842
|
rotateZ(angleDeg, options) {
|
|
33017
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotateZ()");
|
|
33843
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotateZ()");
|
|
33018
33844
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotateZ()");
|
|
33019
33845
|
return this.rotateAroundAxis([0, 0, 1], angleDeg, options == null ? void 0 : options.pivot);
|
|
33020
33846
|
}
|
|
@@ -33057,7 +33883,8 @@ class ShapeGroup {
|
|
|
33057
33883
|
"ShapeGroup.transform only supports 3D children (Shape/ShapeGroup). For Sketch children, use 2D transforms (translate/rotate/scale/mirror)."
|
|
33058
33884
|
);
|
|
33059
33885
|
}),
|
|
33060
|
-
this.childNames
|
|
33886
|
+
this.childNames,
|
|
33887
|
+
this.childTags
|
|
33061
33888
|
);
|
|
33062
33889
|
transformGroupPortsHelper(this, next, matrix);
|
|
33063
33890
|
return transformGroupRefs(this, next, matrix);
|
|
@@ -33125,7 +33952,7 @@ class ShapeGroup {
|
|
|
33125
33952
|
* ```
|
|
33126
33953
|
*/
|
|
33127
33954
|
withReferences(refs) {
|
|
33128
|
-
const next = new ShapeGroup(this.children, this.childNames);
|
|
33955
|
+
const next = new ShapeGroup(this.children, this.childNames, this.childTags);
|
|
33129
33956
|
const merged = applyPlacementReferenceInput(getGroupRefs(this), refs);
|
|
33130
33957
|
return setGroupRefs(next, merged);
|
|
33131
33958
|
}
|
|
@@ -33193,7 +34020,7 @@ class ShapeGroup {
|
|
|
33193
34020
|
/** Attach named connectors — attachment points that survive transforms.
|
|
33194
34021
|
* Connectors can be bare (position + orientation) or typed (with connectorType/gender for compatibility matching). */
|
|
33195
34022
|
withConnectors(connectors) {
|
|
33196
|
-
const next = new ShapeGroup(this.children, this.childNames);
|
|
34023
|
+
const next = new ShapeGroup(this.children, this.childNames, this.childTags);
|
|
33197
34024
|
copyGroupRefs(this, next);
|
|
33198
34025
|
const existing = getGroupPorts(this);
|
|
33199
34026
|
const incoming = normalizeConnectorMapInput(connectors);
|
|
@@ -33243,7 +34070,7 @@ class ShapeGroup {
|
|
|
33243
34070
|
}
|
|
33244
34071
|
function group(...items) {
|
|
33245
34072
|
const normalized = normalizeGroupInputs(items);
|
|
33246
|
-
return new ShapeGroup(normalized.children, normalized.childNames);
|
|
34073
|
+
return new ShapeGroup(normalized.children, normalized.childNames, normalized.childTags);
|
|
33247
34074
|
}
|
|
33248
34075
|
function getTargetPortsForGroup(target) {
|
|
33249
34076
|
if (target instanceof Shape$1) {
|
|
@@ -35418,7 +36245,7 @@ function buildSdfFunctionDefinition(source, options) {
|
|
|
35418
36245
|
jsExpression: expression,
|
|
35419
36246
|
...shader.ok ? { shaderExpression: shader.expression } : { shaderUnsupportedReason: shader.reason },
|
|
35420
36247
|
raymarchStepLimit: resolveRaymarchStepLimit(options.bounds, options.maxStep),
|
|
35421
|
-
...options.lipschitz !== void 0 ? { raymarchLipschitz: requirePositiveFinite$
|
|
36248
|
+
...options.lipschitz !== void 0 ? { raymarchLipschitz: requirePositiveFinite$2(options.lipschitz, "sdf.fromFunction() lipschitz") } : {}
|
|
35422
36249
|
};
|
|
35423
36250
|
}
|
|
35424
36251
|
function extractSdfExpression(source) {
|
|
@@ -35586,7 +36413,7 @@ function formatNumericLiteralsForGlsl(source) {
|
|
|
35586
36413
|
return result;
|
|
35587
36414
|
}
|
|
35588
36415
|
function resolveRaymarchStepLimit(bounds, maxStep) {
|
|
35589
|
-
if (maxStep !== void 0) return requirePositiveFinite$
|
|
36416
|
+
if (maxStep !== void 0) return requirePositiveFinite$2(maxStep, "sdf.fromFunction() maxStep");
|
|
35590
36417
|
const dx = bounds.max[0] - bounds.min[0];
|
|
35591
36418
|
const dy = bounds.max[1] - bounds.min[1];
|
|
35592
36419
|
const dz = bounds.max[2] - bounds.min[2];
|
|
@@ -35594,7 +36421,7 @@ function resolveRaymarchStepLimit(bounds, maxStep) {
|
|
|
35594
36421
|
if (!Number.isFinite(diagonal) || diagonal <= 0) return 0.1;
|
|
35595
36422
|
return Math.max(0.025, Math.min(0.5, diagonal / 240));
|
|
35596
36423
|
}
|
|
35597
|
-
function requirePositiveFinite$
|
|
36424
|
+
function requirePositiveFinite$2(value, label) {
|
|
35598
36425
|
if (!Number.isFinite(value) || value <= 0) throw new Error(`${label} must be a positive finite number.`);
|
|
35599
36426
|
return value;
|
|
35600
36427
|
}
|
|
@@ -35621,6 +36448,199 @@ class SurfacePattern {
|
|
|
35621
36448
|
this.constants = constants;
|
|
35622
36449
|
}
|
|
35623
36450
|
}
|
|
36451
|
+
const typedSurfacePatterns = /* @__PURE__ */ new WeakMap();
|
|
36452
|
+
function getTypedSurfacePattern(pattern) {
|
|
36453
|
+
return typedSurfacePatterns.get(pattern);
|
|
36454
|
+
}
|
|
36455
|
+
class Pattern2D extends SurfacePattern {
|
|
36456
|
+
constructor(body) {
|
|
36457
|
+
super(body);
|
|
36458
|
+
}
|
|
36459
|
+
/** Add this pattern to one or more patterns or constant height offsets. */
|
|
36460
|
+
add(...patterns) {
|
|
36461
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36462
|
+
}
|
|
36463
|
+
/** Subtract another pattern or constant height offset from this pattern. */
|
|
36464
|
+
subtract(pattern) {
|
|
36465
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36466
|
+
}
|
|
36467
|
+
/** Multiply this pattern by one or more patterns or numeric scale factors. */
|
|
36468
|
+
multiply(...patterns) {
|
|
36469
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36470
|
+
}
|
|
36471
|
+
/** Keep the lower height between this pattern and one or more other patterns. */
|
|
36472
|
+
min(...patterns) {
|
|
36473
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36474
|
+
}
|
|
36475
|
+
/** Keep the higher height between this pattern and one or more other patterns. */
|
|
36476
|
+
max(...patterns) {
|
|
36477
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36478
|
+
}
|
|
36479
|
+
/** Limit pattern height to the inclusive `[min, max]` range in millimeters. */
|
|
36480
|
+
clamp(min2, max2) {
|
|
36481
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36482
|
+
}
|
|
36483
|
+
/** Convert negative heights to positive heights. */
|
|
36484
|
+
abs() {
|
|
36485
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36486
|
+
}
|
|
36487
|
+
/** Flip the pattern height sign. */
|
|
36488
|
+
negate() {
|
|
36489
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36490
|
+
}
|
|
36491
|
+
}
|
|
36492
|
+
class Pattern2DImpl extends Pattern2D {
|
|
36493
|
+
constructor(node) {
|
|
36494
|
+
super(emitSurfacePatternJsExpression(node));
|
|
36495
|
+
__publicField(this, "node");
|
|
36496
|
+
this.node = node;
|
|
36497
|
+
typedSurfacePatterns.set(this, node);
|
|
36498
|
+
}
|
|
36499
|
+
add(...patterns) {
|
|
36500
|
+
return new Pattern2DImpl({ kind: "surfacePattern:add", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
36501
|
+
}
|
|
36502
|
+
subtract(pattern) {
|
|
36503
|
+
return this.add(new Pattern2DImpl({ kind: "surfacePattern:negate", child: patternNodeFromInput(pattern) }));
|
|
36504
|
+
}
|
|
36505
|
+
multiply(...patterns) {
|
|
36506
|
+
return new Pattern2DImpl({ kind: "surfacePattern:multiply", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
36507
|
+
}
|
|
36508
|
+
min(...patterns) {
|
|
36509
|
+
return new Pattern2DImpl({ kind: "surfacePattern:min", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
36510
|
+
}
|
|
36511
|
+
max(...patterns) {
|
|
36512
|
+
return new Pattern2DImpl({ kind: "surfacePattern:max", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
36513
|
+
}
|
|
36514
|
+
clamp(min2, max2) {
|
|
36515
|
+
const lo = requireFinite$8(min2, "Pattern2D.clamp() min");
|
|
36516
|
+
const hi = requireFinite$8(max2, "Pattern2D.clamp() max");
|
|
36517
|
+
if (lo > hi) throw new Error(`Pattern2D.clamp() min must be <= max. Received: ${lo} > ${hi}`);
|
|
36518
|
+
return new Pattern2DImpl({ kind: "surfacePattern:clamp", child: this.node, min: lo, max: hi });
|
|
36519
|
+
}
|
|
36520
|
+
abs() {
|
|
36521
|
+
return new Pattern2DImpl({ kind: "surfacePattern:abs", child: this.node });
|
|
36522
|
+
}
|
|
36523
|
+
negate() {
|
|
36524
|
+
return new Pattern2DImpl({ kind: "surfacePattern:negate", child: this.node });
|
|
36525
|
+
}
|
|
36526
|
+
}
|
|
36527
|
+
class Pattern2DBuilder {
|
|
36528
|
+
/** Create a constant-height pattern in millimeters. */
|
|
36529
|
+
constant(value = 0) {
|
|
36530
|
+
return new Pattern2DImpl({ kind: "surfacePattern:constant", value: requireFinite$8(value, "sdf.pattern2d().constant() value") });
|
|
36531
|
+
}
|
|
36532
|
+
/** Create a sinusoidal wave pattern in UV space. */
|
|
36533
|
+
sineWave(options) {
|
|
36534
|
+
return new Pattern2DImpl({
|
|
36535
|
+
kind: "surfacePattern:sineWave",
|
|
36536
|
+
direction: normalizeDirection$1(options.direction ?? [1, 0], "sdf.pattern2d().sineWave() direction"),
|
|
36537
|
+
wavelength: requirePositiveFinite$1(options.wavelength, "sdf.pattern2d().sineWave() wavelength"),
|
|
36538
|
+
amplitude: requireFinite$8(options.amplitude ?? 1, "sdf.pattern2d().sineWave() amplitude"),
|
|
36539
|
+
phase: requireFinite$8(options.phase ?? 0, "sdf.pattern2d().sineWave() phase"),
|
|
36540
|
+
bias: requireFinite$8(options.bias ?? 0, "sdf.pattern2d().sineWave() bias")
|
|
36541
|
+
});
|
|
36542
|
+
}
|
|
36543
|
+
/** Create recessed stripe bands in UV space. */
|
|
36544
|
+
stripes(options) {
|
|
36545
|
+
return new Pattern2DImpl({
|
|
36546
|
+
kind: "surfacePattern:stripes",
|
|
36547
|
+
direction: normalizeDirection$1(options.direction ?? [1, 0], "sdf.pattern2d().stripes() direction"),
|
|
36548
|
+
spacing: requirePositiveFinite$1(options.spacing, "sdf.pattern2d().stripes() spacing"),
|
|
36549
|
+
width: requirePositiveFinite$1(options.width, "sdf.pattern2d().stripes() width"),
|
|
36550
|
+
depth: requireNonNegativeFinite$1(options.depth ?? 1, "sdf.pattern2d().stripes() depth")
|
|
36551
|
+
});
|
|
36552
|
+
}
|
|
36553
|
+
/** Create an over-under woven relief pattern in UV space. */
|
|
36554
|
+
overUnderWeave(options) {
|
|
36555
|
+
return new Pattern2DImpl({
|
|
36556
|
+
kind: "surfacePattern:overUnderWeave",
|
|
36557
|
+
spacing: normalizeVec2(options.spacing, "sdf.pattern2d().overUnderWeave() spacing", requirePositiveFinite$1),
|
|
36558
|
+
threadWidth: normalizeVec2(options.threadWidth, "sdf.pattern2d().overUnderWeave() threadWidth", requirePositiveFinite$1),
|
|
36559
|
+
depth: requireNonNegativeFinite$1(options.depth ?? 0.8, "sdf.pattern2d().overUnderWeave() depth"),
|
|
36560
|
+
underScale: requireNonNegativeFinite$1(options.underScale ?? 0.15, "sdf.pattern2d().overUnderWeave() underScale")
|
|
36561
|
+
});
|
|
36562
|
+
}
|
|
36563
|
+
}
|
|
36564
|
+
function pattern2d() {
|
|
36565
|
+
return new Pattern2DBuilder();
|
|
36566
|
+
}
|
|
36567
|
+
function patternNodeFromInput(input) {
|
|
36568
|
+
if (input instanceof SurfacePattern) {
|
|
36569
|
+
const node = getTypedSurfacePattern(input);
|
|
36570
|
+
if (node) return node;
|
|
36571
|
+
}
|
|
36572
|
+
if (typeof input === "number") {
|
|
36573
|
+
return { kind: "surfacePattern:constant", value: requireFinite$8(input, "Pattern2D numeric input") };
|
|
36574
|
+
}
|
|
36575
|
+
throw new Error("Pattern2D composition expects another typed Pattern2D or a number.");
|
|
36576
|
+
}
|
|
36577
|
+
function requireFinite$8(value, label) {
|
|
36578
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
36579
|
+
throw new Error(`${label} must be a finite number. Received: ${String(value)}`);
|
|
36580
|
+
}
|
|
36581
|
+
return value;
|
|
36582
|
+
}
|
|
36583
|
+
function requirePositiveFinite$1(value, label) {
|
|
36584
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
36585
|
+
throw new Error(`${label} must be a positive finite number. Received: ${String(value)}`);
|
|
36586
|
+
}
|
|
36587
|
+
return value;
|
|
36588
|
+
}
|
|
36589
|
+
function requireNonNegativeFinite$1(value, label) {
|
|
36590
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
36591
|
+
throw new Error(`${label} must be a non-negative finite number. Received: ${String(value)}`);
|
|
36592
|
+
}
|
|
36593
|
+
return value;
|
|
36594
|
+
}
|
|
36595
|
+
function normalizeVec2(value, label, validate) {
|
|
36596
|
+
if (typeof value === "number") {
|
|
36597
|
+
const n = validate(value, label);
|
|
36598
|
+
return [n, n];
|
|
36599
|
+
}
|
|
36600
|
+
return [validate(value[0], `${label}[0]`), validate(value[1], `${label}[1]`)];
|
|
36601
|
+
}
|
|
36602
|
+
function normalizeDirection$1(value, label) {
|
|
36603
|
+
const x2 = requireFinite$8(value[0], `${label}[0]`);
|
|
36604
|
+
const y2 = requireFinite$8(value[1], `${label}[1]`);
|
|
36605
|
+
const length4 = Math.hypot(x2, y2);
|
|
36606
|
+
if (length4 <= 0) throw new Error(`${label} must not be the zero vector.`);
|
|
36607
|
+
return [x2 / length4, y2 / length4];
|
|
36608
|
+
}
|
|
36609
|
+
function f$2(value) {
|
|
36610
|
+
if (!Number.isFinite(value)) return "0";
|
|
36611
|
+
return Number(value.toPrecision(12)).toString();
|
|
36612
|
+
}
|
|
36613
|
+
function emitSurfacePatternJsExpression(node) {
|
|
36614
|
+
switch (node.kind) {
|
|
36615
|
+
case "surfacePattern:constant":
|
|
36616
|
+
return f$2(node.value);
|
|
36617
|
+
case "surfacePattern:sineWave": {
|
|
36618
|
+
const coord = `(u * ${f$2(node.direction[0])} + v * ${f$2(node.direction[1])})`;
|
|
36619
|
+
const phase = `(${coord} * ${f$2(2 * Math.PI / node.wavelength)} + ${f$2(node.phase)})`;
|
|
36620
|
+
return `(${f$2(node.bias)} + Math.sin(${phase}) * ${f$2(node.amplitude)})`;
|
|
36621
|
+
}
|
|
36622
|
+
case "surfacePattern:stripes": {
|
|
36623
|
+
const coord = `(u * ${f$2(node.direction[0])} + v * ${f$2(node.direction[1])})`;
|
|
36624
|
+
return `(function(){var c=${coord};var d=Math.abs(c - Math.round(c / ${f$2(node.spacing)}) * ${f$2(node.spacing)});var p=Math.max(0, 1 - d / ${f$2(node.width * 0.5)});return -(p * p) * ${f$2(node.depth)};})()`;
|
|
36625
|
+
}
|
|
36626
|
+
case "surfacePattern:overUnderWeave":
|
|
36627
|
+
return `(function(){var su=u/${f$2(node.spacing[0])};var sv=v/${f$2(node.spacing[1])};var du=Math.abs(su - Math.round(su))*${f$2(node.spacing[0])};var dv=Math.abs(sv - Math.round(sv))*${f$2(node.spacing[1])};var pU=Math.max(0,1-du/${f$2(node.threadWidth[0] * 0.5)});pU*=pU;var pV=Math.max(0,1-dv/${f$2(node.threadWidth[1] * 0.5)});pV*=pV;var checker=((Math.round(su)&65535)+(Math.round(sv)&65535))&1;var top=checker?pV:pU;var bot=checker?pU:pV;return -Math.max(top,bot*${f$2(node.underScale)})*${f$2(node.depth)};})()`;
|
|
36628
|
+
case "surfacePattern:abs":
|
|
36629
|
+
return `Math.abs(${emitSurfacePatternJsExpression(node.child)})`;
|
|
36630
|
+
case "surfacePattern:negate":
|
|
36631
|
+
return `(-(${emitSurfacePatternJsExpression(node.child)}))`;
|
|
36632
|
+
case "surfacePattern:add":
|
|
36633
|
+
return node.children.length === 0 ? "0" : `(${node.children.map(emitSurfacePatternJsExpression).join(" + ")})`;
|
|
36634
|
+
case "surfacePattern:multiply":
|
|
36635
|
+
return node.children.length === 0 ? "1" : `(${node.children.map(emitSurfacePatternJsExpression).join(" * ")})`;
|
|
36636
|
+
case "surfacePattern:min":
|
|
36637
|
+
return node.children.length === 0 ? "0" : `Math.min(${node.children.map(emitSurfacePatternJsExpression).join(", ")})`;
|
|
36638
|
+
case "surfacePattern:max":
|
|
36639
|
+
return node.children.length === 0 ? "0" : `Math.max(${node.children.map(emitSurfacePatternJsExpression).join(", ")})`;
|
|
36640
|
+
case "surfacePattern:clamp":
|
|
36641
|
+
return `Math.min(${f$2(node.max)}, Math.max(${f$2(node.min)}, ${emitSurfacePatternJsExpression(node.child)}))`;
|
|
36642
|
+
}
|
|
36643
|
+
}
|
|
35624
36644
|
const SCULPT_MATERIAL_PRESETS = {
|
|
35625
36645
|
ceramic: {
|
|
35626
36646
|
color: "#f4f0e6",
|
|
@@ -35690,6 +36710,18 @@ function requirePositiveFinite(value, label) {
|
|
|
35690
36710
|
}
|
|
35691
36711
|
return value;
|
|
35692
36712
|
}
|
|
36713
|
+
function requirePositiveInteger(value, label) {
|
|
36714
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value < 1) {
|
|
36715
|
+
throw new Error(`${label} must be a positive integer. Received: ${String(value)}`);
|
|
36716
|
+
}
|
|
36717
|
+
return value;
|
|
36718
|
+
}
|
|
36719
|
+
function requireNonNegativeFinite(value, label) {
|
|
36720
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
36721
|
+
throw new Error(`${label} must be a non-negative finite number. Received: ${String(value)}`);
|
|
36722
|
+
}
|
|
36723
|
+
return value;
|
|
36724
|
+
}
|
|
35693
36725
|
function resolveBlendRadius(input, label, fallback = 4) {
|
|
35694
36726
|
if (typeof input === "number") return requirePositiveFinite(input, `${label} radius`);
|
|
35695
36727
|
if ((input == null ? void 0 : input.radius) !== void 0) return requirePositiveFinite(input.radius, `${label} radius`);
|
|
@@ -35936,6 +36968,29 @@ class SdfShape {
|
|
|
35936
36968
|
clipBox(x2, y2, z2) {
|
|
35937
36969
|
return this.intersect(box$1(x2, y2, z2));
|
|
35938
36970
|
}
|
|
36971
|
+
/** Keep only the material where this shape overlaps another SDF pattern. */
|
|
36972
|
+
fillWith(pattern) {
|
|
36973
|
+
if (!(pattern instanceof SdfShape)) {
|
|
36974
|
+
throw new Error("SdfShape.fillWith() expects an SdfShape pattern, such as sdf.gyroid({ cellSize, wallThickness }).");
|
|
36975
|
+
}
|
|
36976
|
+
return this.intersect(pattern);
|
|
36977
|
+
}
|
|
36978
|
+
/** Keep only the gyroid lattice inside this shape. */
|
|
36979
|
+
fillWithGyroid(options) {
|
|
36980
|
+
return this.fillWith(gyroid(options));
|
|
36981
|
+
}
|
|
36982
|
+
/** Keep only the Schwarz-P lattice inside this shape. */
|
|
36983
|
+
fillWithSchwarzP(options) {
|
|
36984
|
+
return this.fillWith(schwarzP(options));
|
|
36985
|
+
}
|
|
36986
|
+
/** Keep only the diamond TPMS lattice inside this shape. */
|
|
36987
|
+
fillWithDiamond(options) {
|
|
36988
|
+
return this.fillWith(diamond(options));
|
|
36989
|
+
}
|
|
36990
|
+
/** Keep only the lidinoid TPMS lattice inside this shape. */
|
|
36991
|
+
fillWithLidinoid(options) {
|
|
36992
|
+
return this.fillWith(lidinoid(options));
|
|
36993
|
+
}
|
|
35939
36994
|
/** Smooth union — blends shapes together with a smooth radius. */
|
|
35940
36995
|
smoothUnion(other, radius) {
|
|
35941
36996
|
return this.withNode({ kind: "sdf:smoothUnion", children: [this._node, other._node], radius });
|
|
@@ -35996,6 +37051,21 @@ class SdfShape {
|
|
|
35996
37051
|
repeat(spacing, count) {
|
|
35997
37052
|
return this.withNode({ kind: "sdf:repeat", child: this._node, spacing, count: count ?? [0, 0, 0] });
|
|
35998
37053
|
}
|
|
37054
|
+
/**
|
|
37055
|
+
* Arrange this SDF in a circular array around the Z axis.
|
|
37056
|
+
*
|
|
37057
|
+
* The source shape is translated by `offset` in +X before arraying. This uses
|
|
37058
|
+
* angular domain folding, so evaluation stays O(1): the source SDF is sampled
|
|
37059
|
+
* twice no matter how many copies are requested.
|
|
37060
|
+
*/
|
|
37061
|
+
circularArray(count, offset2 = 0) {
|
|
37062
|
+
return this.withNode({
|
|
37063
|
+
kind: "sdf:circularArray",
|
|
37064
|
+
child: this._node,
|
|
37065
|
+
count: requirePositiveInteger(count, "SdfShape.circularArray() count"),
|
|
37066
|
+
offset: requireNonNegativeFinite(offset2, "SdfShape.circularArray() offset")
|
|
37067
|
+
});
|
|
37068
|
+
}
|
|
35999
37069
|
/** Hollow out, keeping only a shell of given thickness. */
|
|
36000
37070
|
shell(thickness) {
|
|
36001
37071
|
return this.withNode({ kind: "sdf:shell", child: this._node, thickness });
|
|
@@ -36007,8 +37077,8 @@ class SdfShape {
|
|
|
36007
37077
|
* // Function displacement
|
|
36008
37078
|
* shape.displace((x, y, z) => Math.sin(x) * 0.5)
|
|
36009
37079
|
*
|
|
36010
|
-
* // Pattern displacement
|
|
36011
|
-
* shape.displace(sdf.
|
|
37080
|
+
* // Pattern displacement from a 3D SDF field
|
|
37081
|
+
* shape.displace(sdf.knurl({ pitch: 2, depth: 0.3 }))
|
|
36012
37082
|
* ```
|
|
36013
37083
|
*/
|
|
36014
37084
|
displace(fn, constants) {
|
|
@@ -36032,10 +37102,18 @@ class SdfShape {
|
|
|
36032
37102
|
* UV coordinates are in **surface millimeters** — patterns defined with `spacing: 3`
|
|
36033
37103
|
* always produce 3mm spacing, regardless of shape size.
|
|
36034
37104
|
*
|
|
37105
|
+
* Prefer `sdf.pattern2d()` or built-in surface patterns when the relief should
|
|
37106
|
+
* stay on the native shader and meshing path. Callback functions are supported
|
|
37107
|
+
* for experimentation, but they are opaque to the typed pattern optimizer.
|
|
37108
|
+
*
|
|
36035
37109
|
* ```js
|
|
36036
|
-
* //
|
|
37110
|
+
* // Native typed pattern — auto-detects sphere UV
|
|
37111
|
+
* const p = sdf.pattern2d()
|
|
37112
|
+
* const ribs = p.stripes({ spacing: 3, width: 0.8, depth: 0.35 })
|
|
37113
|
+
* .add(p.sineWave({ direction: [0, 1], wavelength: 14, amplitude: 0.08 }))
|
|
37114
|
+
*
|
|
36037
37115
|
* sdf.sphere(27).shell(3)
|
|
36038
|
-
* .surfaceDisplace(
|
|
37116
|
+
* .surfaceDisplace(ribs)
|
|
36039
37117
|
* .toShape()
|
|
36040
37118
|
*
|
|
36041
37119
|
* // Custom 2D pattern via function
|
|
@@ -36045,15 +37123,18 @@ class SdfShape {
|
|
|
36045
37123
|
surfaceDisplace(pattern, options) {
|
|
36046
37124
|
let body;
|
|
36047
37125
|
let constants;
|
|
37126
|
+
let typedPattern;
|
|
36048
37127
|
if (pattern instanceof SurfacePattern) {
|
|
36049
37128
|
body = pattern.body;
|
|
36050
37129
|
constants = pattern.constants;
|
|
37130
|
+
typedPattern = getTypedSurfacePattern(pattern);
|
|
36051
37131
|
} else {
|
|
36052
37132
|
body = extractFunctionBody(pattern);
|
|
36053
37133
|
}
|
|
36054
37134
|
return this.withNode({
|
|
36055
37135
|
kind: "sdf:surfaceDisplace",
|
|
36056
37136
|
child: this._node,
|
|
37137
|
+
...typedPattern ? { pattern: typedPattern } : {},
|
|
36057
37138
|
patternBody: body,
|
|
36058
37139
|
constants,
|
|
36059
37140
|
...(options == null ? void 0 : options.uv) ? { uvMode: options.uv } : {},
|
|
@@ -36272,24 +37353,10 @@ function weave(options) {
|
|
|
36272
37353
|
});
|
|
36273
37354
|
}
|
|
36274
37355
|
function basketWeave(options) {
|
|
36275
|
-
const SP = (options == null ? void 0 : options.spacing) ?? 3;
|
|
36276
|
-
const TW = (options == null ? void 0 : options.threadWidth) ?? 1.5;
|
|
36277
|
-
const D2 = (options == null ? void 0 : options.depth) ?? 0.8;
|
|
36278
|
-
|
|
36279
|
-
const body = `(function() {
|
|
36280
|
-
var su = u / ${SP};
|
|
36281
|
-
var sv = v / ${SP};
|
|
36282
|
-
var du = Math.abs(su - Math.round(su)) * ${SP};
|
|
36283
|
-
var dv = Math.abs(sv - Math.round(sv)) * ${SP};
|
|
36284
|
-
var hw = ${hw};
|
|
36285
|
-
var pU = Math.max(0, 1 - du / hw); pU *= pU;
|
|
36286
|
-
var pV = Math.max(0, 1 - dv / hw); pV *= pV;
|
|
36287
|
-
var checker = ((Math.round(su) & 65535) + (Math.round(sv) & 65535)) & 1;
|
|
36288
|
-
var top = checker ? pV : pU;
|
|
36289
|
-
var bot = checker ? pU : pV;
|
|
36290
|
-
return -(top > bot * 0.15 ? top : bot * 0.15) * ${D2};
|
|
36291
|
-
})()`;
|
|
36292
|
-
return new SurfacePattern(body);
|
|
37356
|
+
const SP = requirePositiveFinite((options == null ? void 0 : options.spacing) ?? 3, "sdf.basketWeave() spacing");
|
|
37357
|
+
const TW = requirePositiveFinite((options == null ? void 0 : options.threadWidth) ?? 1.5, "sdf.basketWeave() threadWidth");
|
|
37358
|
+
const D2 = requireNonNegativeFinite((options == null ? void 0 : options.depth) ?? 0.8, "sdf.basketWeave() depth");
|
|
37359
|
+
return pattern2d().overUnderWeave({ spacing: SP, threadWidth: TW, depth: D2 });
|
|
36293
37360
|
}
|
|
36294
37361
|
function fromFunction(fn, options) {
|
|
36295
37362
|
if (!options || typeof options !== "object") {
|
|
@@ -36322,6 +37389,9 @@ function bend(shape, radius) {
|
|
|
36322
37389
|
function repeat(shape, spacing, count) {
|
|
36323
37390
|
return shape.repeat(spacing, count);
|
|
36324
37391
|
}
|
|
37392
|
+
function circularArray(shape, count, offset2 = 0) {
|
|
37393
|
+
return shape.circularArray(count, offset2);
|
|
37394
|
+
}
|
|
36325
37395
|
function resolveTpmsOptions(options) {
|
|
36326
37396
|
const wallThickness = options.wallThickness;
|
|
36327
37397
|
const thickness = wallThickness ?? options.thickness;
|
|
@@ -36762,12 +37832,16 @@ const sdf = {
|
|
|
36762
37832
|
weave,
|
|
36763
37833
|
/** Basket weave surface pattern — threads with over-under crossings in UV space. Returns a SurfacePattern for use with `.surfaceDisplace()`. */
|
|
36764
37834
|
basketWeave,
|
|
37835
|
+
/** Create typed, composable 2D surface patterns for `.surfaceDisplace()`. */
|
|
37836
|
+
pattern2d,
|
|
36765
37837
|
/** Twist an SDF shape around the Z axis. */
|
|
36766
37838
|
twist,
|
|
36767
37839
|
/** Bend an SDF shape around the Z axis. */
|
|
36768
37840
|
bend,
|
|
36769
37841
|
/** Repeat an SDF shape in space. */
|
|
36770
37842
|
repeat,
|
|
37843
|
+
/** Arrange an SDF shape in a circular array around the Z axis with O(1) folded-domain evaluation. */
|
|
37844
|
+
circularArray,
|
|
36771
37845
|
/** A 2D surface pattern — a heightmap function for use with `.surfaceDisplace()`. */
|
|
36772
37846
|
SurfacePattern,
|
|
36773
37847
|
/** Create a custom SDF from one expression; shader-safe expressions raymarch directly. */
|
|
@@ -39216,17 +40290,17 @@ let Shape$1 = class Shape {
|
|
|
39216
40290
|
bottom: "top"
|
|
39217
40291
|
};
|
|
39218
40292
|
const uvMap = {
|
|
39219
|
-
front: (u22,
|
|
40293
|
+
front: (u22, v22, p22) => [u22, -p22, v22],
|
|
39220
40294
|
// front = −Y face, outward = −Y
|
|
39221
|
-
back: (u22,
|
|
40295
|
+
back: (u22, v22, p22) => [u22, p22, v22],
|
|
39222
40296
|
// back = +Y face, outward = +Y
|
|
39223
|
-
left: (u22,
|
|
40297
|
+
left: (u22, v22, p22) => [-p22, u22, v22],
|
|
39224
40298
|
// left = −X face, outward = −X
|
|
39225
|
-
right: (u22,
|
|
40299
|
+
right: (u22, v22, p22) => [p22, u22, v22],
|
|
39226
40300
|
// right = +X face, outward = +X
|
|
39227
|
-
top: (u22,
|
|
40301
|
+
top: (u22, v22, p22) => [u22, v22, p22],
|
|
39228
40302
|
// top = +Z face, outward = +Z
|
|
39229
|
-
bottom: (u22,
|
|
40303
|
+
bottom: (u22, v22, p22) => [u22, v22, -p22]
|
|
39230
40304
|
// bottom = −Z face, outward = −Z
|
|
39231
40305
|
};
|
|
39232
40306
|
const selfAnchor = opposite[face];
|
|
@@ -41757,13 +42831,16 @@ class SolvedAssembly {
|
|
|
41757
42831
|
* @category Assembly
|
|
41758
42832
|
*/
|
|
41759
42833
|
toGroup() {
|
|
42834
|
+
var _a3;
|
|
41760
42835
|
const children = [];
|
|
41761
42836
|
const childNames = [];
|
|
41762
|
-
|
|
42837
|
+
const childTags = [];
|
|
42838
|
+
for (const [name, rec] of this.parts) {
|
|
41763
42839
|
children.push(this.getPart(name));
|
|
41764
42840
|
childNames.push(name);
|
|
42841
|
+
childTags.push(normalizeSceneTags((_a3 = rec.metadata) == null ? void 0 : _a3.tags, `Assembly part "${name}" metadata.tags`));
|
|
41765
42842
|
}
|
|
41766
|
-
return new ShapeGroup(children, childNames);
|
|
42843
|
+
return new ShapeGroup(children, childNames, childTags);
|
|
41767
42844
|
}
|
|
41768
42845
|
/**
|
|
41769
42846
|
* Return an array of named scene objects for the viewport renderer.
|
|
@@ -41797,17 +42874,18 @@ class SolvedAssembly {
|
|
|
41797
42874
|
const used = usedByPart.get(partName);
|
|
41798
42875
|
if (used && used.length > 0) markShapePortsUsed(shape, used);
|
|
41799
42876
|
};
|
|
41800
|
-
const appendGroupChildren = (grp, prefix, partName, out2) => {
|
|
42877
|
+
const appendGroupChildren = (grp, prefix, partName, out2, inheritedTags = []) => {
|
|
41801
42878
|
grp.children.forEach((child, index2) => {
|
|
41802
42879
|
const childName = grp.childName(index2);
|
|
41803
42880
|
const label = childName ? `${prefix}.${childName}` : `${prefix}.${index2 + 1}`;
|
|
42881
|
+
const tags = mergeSceneTags(inheritedTags, grp.tagsForChild(index2));
|
|
41804
42882
|
if (child instanceof ShapeGroup) {
|
|
41805
|
-
appendGroupChildren(child, label, partName, out2);
|
|
42883
|
+
appendGroupChildren(child, label, partName, out2, tags);
|
|
41806
42884
|
return;
|
|
41807
42885
|
}
|
|
41808
42886
|
if (child instanceof Shape$1) {
|
|
41809
42887
|
markUsedOnShape(child, partName);
|
|
41810
|
-
out2.push({ name: label, shape: child });
|
|
42888
|
+
out2.push({ name: label, shape: child, ...tags.length > 0 ? { tags } : {} });
|
|
41811
42889
|
}
|
|
41812
42890
|
});
|
|
41813
42891
|
};
|
|
@@ -42173,7 +43251,7 @@ class Assembly {
|
|
|
42173
43251
|
*
|
|
42174
43252
|
* @param name - Unique part name (must not already exist)
|
|
42175
43253
|
* @param part - The `Shape` or `ShapeGroup` geometry
|
|
42176
|
-
* @param options - Optional `{ transform, metadata }` (material, process, qty, etc.)
|
|
43254
|
+
* @param options - Optional `{ transform, metadata }` (material, process, qty, tags, etc.)
|
|
42177
43255
|
* @returns `this` for chaining
|
|
42178
43256
|
* @category Assembly
|
|
42179
43257
|
*/
|
|
@@ -43127,15 +44205,18 @@ class ImportedAssembly {
|
|
|
43127
44205
|
* Any stored placement offset and placement references are forwarded to the group.
|
|
43128
44206
|
*/
|
|
43129
44207
|
toGroup(state) {
|
|
44208
|
+
var _a3;
|
|
43130
44209
|
const solved = this._assembly.solve(state);
|
|
43131
44210
|
const def = this._assembly.describe();
|
|
43132
44211
|
const children = [];
|
|
43133
44212
|
const childNames = [];
|
|
44213
|
+
const childTags = [];
|
|
43134
44214
|
for (const p2 of def.parts) {
|
|
43135
44215
|
children.push(solved.getPart(p2.name));
|
|
43136
44216
|
childNames.push(p2.name);
|
|
44217
|
+
childTags.push(normalizeSceneTags((_a3 = p2.metadata) == null ? void 0 : _a3.tags, `Assembly part "${p2.name}" metadata.tags`));
|
|
43137
44218
|
}
|
|
43138
|
-
let result = new ShapeGroup(children, childNames);
|
|
44219
|
+
let result = new ShapeGroup(children, childNames, childTags);
|
|
43139
44220
|
const [dx, dy, dz] = this._offset;
|
|
43140
44221
|
if (dx !== 0 || dy !== 0 || dz !== 0) {
|
|
43141
44222
|
result = result.translate(dx, dy, dz);
|
|
@@ -47504,7 +48585,8 @@ function explode(items, options = {}) {
|
|
|
47504
48585
|
if (child instanceof ShapeGroup) return explodeGroup(child, p2, depth + 1, total, groupCenter, motion.branchDirection);
|
|
47505
48586
|
return explodeLeaf(child, explodeAdd(total, leafMotion(child, p2, depth + 1, groupCenter, motion.branchDirection).offset));
|
|
47506
48587
|
}),
|
|
47507
|
-
grp.childNames
|
|
48588
|
+
grp.childNames,
|
|
48589
|
+
grp.children.map((_2, i) => grp.tagsForChild(i))
|
|
47508
48590
|
);
|
|
47509
48591
|
};
|
|
47510
48592
|
const explodeItemNode = (item, path2, depth, inherited, parentCenter, parentDirection) => {
|
|
@@ -47540,7 +48622,8 @@ function explode(items, options = {}) {
|
|
|
47540
48622
|
if (child instanceof ShapeGroup) return explodeGroup(child, p2, 1, [0, 0, 0], rootCenter, void 0);
|
|
47541
48623
|
return explodeLeaf(child, nodeMotion(child, p2, 1, rootCenter, void 0).offset);
|
|
47542
48624
|
}),
|
|
47543
|
-
items.childNames
|
|
48625
|
+
items.childNames,
|
|
48626
|
+
items.children.map((_2, i) => items.tagsForChild(i))
|
|
47544
48627
|
);
|
|
47545
48628
|
}
|
|
47546
48629
|
return items.map((item, i) => {
|
|
@@ -48309,6 +49392,398 @@ function spurGear(options) {
|
|
|
48309
49392
|
});
|
|
48310
49393
|
return attachGearMeta(shapeWithConnectors, meta2);
|
|
48311
49394
|
}
|
|
49395
|
+
function requirePositive$7(scope, name, value) {
|
|
49396
|
+
if (!isFinitePositive(value)) throw new Error(`${scope}: "${name}" must be > 0`);
|
|
49397
|
+
}
|
|
49398
|
+
function requireOptionalBore(scope, boreDiameter, maxDiameter) {
|
|
49399
|
+
const bore = boreDiameter ?? 0;
|
|
49400
|
+
if (!Number.isFinite(bore) || bore < 0) throw new Error(`${scope}: "boreDiameter" must be >= 0`);
|
|
49401
|
+
if (bore > 0 && bore >= maxDiameter) throw new Error(`${scope}: bore is too large for the body`);
|
|
49402
|
+
return bore;
|
|
49403
|
+
}
|
|
49404
|
+
function resolveSegments(segments) {
|
|
49405
|
+
if (segments === void 0) return void 0;
|
|
49406
|
+
if (!Number.isInteger(segments) || segments < 12) throw new Error('gear body: "segments" must be an integer >= 12');
|
|
49407
|
+
return segments;
|
|
49408
|
+
}
|
|
49409
|
+
function cutBore$1(shape, boreDiameter) {
|
|
49410
|
+
if (boreDiameter <= 0) return shape;
|
|
49411
|
+
const bounds = shape.boundingBox();
|
|
49412
|
+
const height = bounds.max[2] - bounds.min[2] + 2;
|
|
49413
|
+
const cutter = cylinder(height, boreDiameter * 0.5, void 0, 64).translate(0, 0, bounds.min[2] - 1);
|
|
49414
|
+
return shape.subtract(cutter);
|
|
49415
|
+
}
|
|
49416
|
+
function gearBodyDisk(options) {
|
|
49417
|
+
requirePositive$7("gearBodyDisk", "outerRadius", options.outerRadius);
|
|
49418
|
+
requirePositive$7("gearBodyDisk", "faceWidth", options.faceWidth);
|
|
49419
|
+
const bore = requireOptionalBore("gearBodyDisk", options.boreDiameter, options.outerRadius * 2);
|
|
49420
|
+
const segments = resolveSegments(options.segments);
|
|
49421
|
+
const outer = circle2d(options.outerRadius, segments);
|
|
49422
|
+
const profile = bore > 0 ? difference2d(outer, circle2d(bore * 0.5, segments)) : outer;
|
|
49423
|
+
return sketchExtrude(profile, options.faceWidth);
|
|
49424
|
+
}
|
|
49425
|
+
function gearBodyDiskWithHub(options) {
|
|
49426
|
+
requirePositive$7("gearBodyDiskWithHub", "hubDiameter", options.hubDiameter);
|
|
49427
|
+
if (options.hubDiameter >= options.outerRadius * 2) {
|
|
49428
|
+
throw new Error('gearBodyDiskWithHub: "hubDiameter" must be smaller than the outer diameter');
|
|
49429
|
+
}
|
|
49430
|
+
const bore = requireOptionalBore("gearBodyDiskWithHub", options.boreDiameter, options.hubDiameter);
|
|
49431
|
+
const base = gearBodyDisk({ ...options, boreDiameter: 0 });
|
|
49432
|
+
const hubFaceWidth = options.hubFaceWidth ?? options.faceWidth * 1.5;
|
|
49433
|
+
requirePositive$7("gearBodyDiskWithHub", "hubFaceWidth", hubFaceWidth);
|
|
49434
|
+
const hub = cylinder(hubFaceWidth, options.hubDiameter * 0.5, void 0, options.segments).translate(
|
|
49435
|
+
0,
|
|
49436
|
+
0,
|
|
49437
|
+
(options.faceWidth - hubFaceWidth) * 0.5
|
|
49438
|
+
);
|
|
49439
|
+
return cutBore$1(base.add(hub), bore);
|
|
49440
|
+
}
|
|
49441
|
+
function gearBodySpoked(options) {
|
|
49442
|
+
requirePositive$7("gearBodySpoked", "outerRadius", options.outerRadius);
|
|
49443
|
+
requirePositive$7("gearBodySpoked", "faceWidth", options.faceWidth);
|
|
49444
|
+
requirePositive$7("gearBodySpoked", "rimWidth", options.rimWidth);
|
|
49445
|
+
requirePositive$7("gearBodySpoked", "hubDiameter", options.hubDiameter);
|
|
49446
|
+
requirePositive$7("gearBodySpoked", "spokeWidth", options.spokeWidth);
|
|
49447
|
+
if (!Number.isInteger(options.spokeCount) || options.spokeCount < 2) {
|
|
49448
|
+
throw new Error('gearBodySpoked: "spokeCount" must be an integer >= 2');
|
|
49449
|
+
}
|
|
49450
|
+
const hubRadius = options.hubDiameter * 0.5;
|
|
49451
|
+
const rimInnerRadius = options.outerRadius - options.rimWidth;
|
|
49452
|
+
if (rimInnerRadius <= hubRadius) throw new Error("gearBodySpoked: rim overlaps the hub");
|
|
49453
|
+
const bore = requireOptionalBore("gearBodySpoked", options.boreDiameter, options.hubDiameter);
|
|
49454
|
+
const segments = resolveSegments(options.segments);
|
|
49455
|
+
const rim = difference2d(circle2d(options.outerRadius, segments), circle2d(rimInnerRadius, segments));
|
|
49456
|
+
const hub = circle2d(hubRadius, segments);
|
|
49457
|
+
const spokeLength = rimInnerRadius - hubRadius + options.spokeWidth;
|
|
49458
|
+
const spokeCenter = hubRadius + spokeLength * 0.5 - options.spokeWidth * 0.5;
|
|
49459
|
+
const spoke = sketchTranslate(rect(spokeLength, options.spokeWidth), spokeCenter, 0);
|
|
49460
|
+
const spokes = [];
|
|
49461
|
+
for (let i = 0; i < options.spokeCount; i++) {
|
|
49462
|
+
spokes.push(sketchRotateAround(spoke, 360 / options.spokeCount * i, [0, 0]));
|
|
49463
|
+
}
|
|
49464
|
+
const profile = bore > 0 ? difference2d(union2d(rim, hub, ...spokes), circle2d(bore * 0.5, segments)) : union2d(rim, hub, ...spokes);
|
|
49465
|
+
return sketchExtrude(profile, options.faceWidth);
|
|
49466
|
+
}
|
|
49467
|
+
function gearBodyFromProfile(profile, options) {
|
|
49468
|
+
if (!(profile instanceof Sketch)) throw new Error('gearBodyFromProfile: "profile" must be a Sketch');
|
|
49469
|
+
requirePositive$7("gearBodyFromProfile", "faceWidth", options.faceWidth);
|
|
49470
|
+
const bore = options.boreDiameter ?? 0;
|
|
49471
|
+
if (!Number.isFinite(bore) || bore < 0) throw new Error('gearBodyFromProfile: "boreDiameter" must be >= 0');
|
|
49472
|
+
return cutBore$1(sketchExtrude(profile, options.faceWidth), bore);
|
|
49473
|
+
}
|
|
49474
|
+
function requirePositive$6(scope, name, value) {
|
|
49475
|
+
if (!isFinitePositive(value)) throw new Error(`${scope}: "${name}" must be > 0`);
|
|
49476
|
+
}
|
|
49477
|
+
function requireFiniteAngle(scope, name, value) {
|
|
49478
|
+
if (value !== void 0 && !Number.isFinite(value)) throw new Error(`${scope}: "${name}" must be finite`);
|
|
49479
|
+
}
|
|
49480
|
+
function cutBore(shape, boreDiameter) {
|
|
49481
|
+
if (boreDiameter <= 0) return shape;
|
|
49482
|
+
const bounds = shape.boundingBox();
|
|
49483
|
+
const height = bounds.max[2] - bounds.min[2] + 2;
|
|
49484
|
+
const cutter = cylinder(height, boreDiameter * 0.5, void 0, 64).translate(0, 0, bounds.min[2] - 1);
|
|
49485
|
+
return shape.subtract(cutter);
|
|
49486
|
+
}
|
|
49487
|
+
function bodyOuterRadius(shape) {
|
|
49488
|
+
const bounds = shape.boundingBox();
|
|
49489
|
+
return Math.max(Math.abs(bounds.min[0]), Math.abs(bounds.max[0]), Math.abs(bounds.min[1]), Math.abs(bounds.max[1]));
|
|
49490
|
+
}
|
|
49491
|
+
function buildSpurTeethRegion(options, name, faceWidth) {
|
|
49492
|
+
const scope = "driveWheel.addSpurTeethBetween";
|
|
49493
|
+
const teethOnFullCircle = options.teethOnFullCircle;
|
|
49494
|
+
if (!Number.isInteger(teethOnFullCircle) || teethOnFullCircle < 6) {
|
|
49495
|
+
throw new Error(`${scope}: "teethOnFullCircle" must be an integer >= 6`);
|
|
49496
|
+
}
|
|
49497
|
+
const toothCount = options.toothCount;
|
|
49498
|
+
if (!Number.isInteger(toothCount) || toothCount < 1 || toothCount > teethOnFullCircle) {
|
|
49499
|
+
throw new Error(`${scope}: "toothCount" must be an integer in [1, teethOnFullCircle]`);
|
|
49500
|
+
}
|
|
49501
|
+
const firstTooth = options.firstTooth ?? 0;
|
|
49502
|
+
if (!Number.isInteger(firstTooth) || firstTooth < 0 || firstTooth >= teethOnFullCircle) {
|
|
49503
|
+
throw new Error(`${scope}: "firstTooth" must be an integer in [0, teethOnFullCircle)`);
|
|
49504
|
+
}
|
|
49505
|
+
let normalized;
|
|
49506
|
+
try {
|
|
49507
|
+
normalized = normalizeSpurGearOptions({ ...options, teeth: teethOnFullCircle, faceWidth, boreDiameter: 0 });
|
|
49508
|
+
} catch (error) {
|
|
49509
|
+
remapErrorPrefix(error, "spurGear", scope);
|
|
49510
|
+
}
|
|
49511
|
+
const gearMeta = buildSpurGearMeta(normalized);
|
|
49512
|
+
const pitchStepDeg = 360 / teethOnFullCircle;
|
|
49513
|
+
const fromAngleDeg = firstTooth * pitchStepDeg - pitchStepDeg * 0.5;
|
|
49514
|
+
const toAngleDeg = (firstTooth + toothCount - 1) * pitchStepDeg + pitchStepDeg * 0.5;
|
|
49515
|
+
const profile = buildSpurToothRegionProfile(gearMeta, firstTooth, toothCount, normalized.segmentsPerTooth);
|
|
49516
|
+
return {
|
|
49517
|
+
shape: sketchExtrude(profile, faceWidth),
|
|
49518
|
+
gearMeta,
|
|
49519
|
+
meta: {
|
|
49520
|
+
name,
|
|
49521
|
+
kind: "spurTeeth",
|
|
49522
|
+
fromAngleDeg,
|
|
49523
|
+
toAngleDeg,
|
|
49524
|
+
outerRadius: gearMeta.outerRadius,
|
|
49525
|
+
rootRadius: gearMeta.rootRadius,
|
|
49526
|
+
pitchRadius: gearMeta.pitchRadius,
|
|
49527
|
+
module: normalized.module,
|
|
49528
|
+
teethOnFullCircle,
|
|
49529
|
+
toothCount,
|
|
49530
|
+
faceWidth
|
|
49531
|
+
}
|
|
49532
|
+
};
|
|
49533
|
+
}
|
|
49534
|
+
function buildSolidArcRegion(options, name, faceWidth) {
|
|
49535
|
+
const scope = "driveWheel.addSolidArcBetween";
|
|
49536
|
+
requirePositive$6(scope, "outerRadius", options.outerRadius);
|
|
49537
|
+
const innerRadius = options.innerRadius ?? 0;
|
|
49538
|
+
if (!Number.isFinite(innerRadius) || innerRadius < 0) throw new Error(`${scope}: "innerRadius" must be >= 0`);
|
|
49539
|
+
if (innerRadius >= options.outerRadius) throw new Error(`${scope}: "innerRadius" must be smaller than "outerRadius"`);
|
|
49540
|
+
const sweepDeg = normalizedSweep(scope, options.fromAngleDeg, options.toAngleDeg);
|
|
49541
|
+
return {
|
|
49542
|
+
shape: sketchExtrude(buildSolidArcProfile(options, sweepDeg), faceWidth),
|
|
49543
|
+
meta: {
|
|
49544
|
+
name,
|
|
49545
|
+
kind: "solidArc",
|
|
49546
|
+
fromAngleDeg: options.fromAngleDeg,
|
|
49547
|
+
toAngleDeg: options.fromAngleDeg + sweepDeg,
|
|
49548
|
+
innerRadius,
|
|
49549
|
+
outerRadius: options.outerRadius,
|
|
49550
|
+
faceWidth
|
|
49551
|
+
}
|
|
49552
|
+
};
|
|
49553
|
+
}
|
|
49554
|
+
function normalizedSweep(scope, fromAngleDeg, toAngleDeg) {
|
|
49555
|
+
if (!Number.isFinite(fromAngleDeg)) throw new Error(`${scope}: "fromAngleDeg" must be finite`);
|
|
49556
|
+
if (!Number.isFinite(toAngleDeg)) throw new Error(`${scope}: "toAngleDeg" must be finite`);
|
|
49557
|
+
let sweep2 = toAngleDeg - fromAngleDeg;
|
|
49558
|
+
while (sweep2 <= 0) sweep2 += 360;
|
|
49559
|
+
if (sweep2 > 360 + EPSILON$1) throw new Error(`${scope}: angular sweep must be <= 360 degrees`);
|
|
49560
|
+
return Math.min(360, sweep2);
|
|
49561
|
+
}
|
|
49562
|
+
function buildSpurToothRegionProfile(meta2, firstTooth, toothCount, segmentsPerTooth) {
|
|
49563
|
+
const tooth = createSpurToothSketch(meta2, segmentsPerTooth);
|
|
49564
|
+
const teeth = [];
|
|
49565
|
+
for (let i = 0; i < toothCount; i++) {
|
|
49566
|
+
teeth.push(sketchRotateAround(tooth, 360 / meta2.teeth * (firstTooth + i), [0, 0]));
|
|
49567
|
+
}
|
|
49568
|
+
return union2d(...teeth);
|
|
49569
|
+
}
|
|
49570
|
+
function buildSolidArcProfile(options, sweepDeg) {
|
|
49571
|
+
const innerRadius = options.innerRadius ?? 0;
|
|
49572
|
+
const segments = options.segments ?? Math.max(16, Math.ceil(sweepDeg / 6));
|
|
49573
|
+
if (!Number.isInteger(segments) || segments < 4) throw new Error('driveWheel.addSolidArcBetween: "segments" must be an integer >= 4');
|
|
49574
|
+
if (Math.abs(sweepDeg - 360) < EPSILON$1) {
|
|
49575
|
+
const outer = circle2d(options.outerRadius, segments);
|
|
49576
|
+
return innerRadius > 0 ? difference2d(outer, circle2d(innerRadius, segments)) : outer;
|
|
49577
|
+
}
|
|
49578
|
+
const start = options.fromAngleDeg * Math.PI / 180;
|
|
49579
|
+
const end = start + sweepDeg * Math.PI / 180;
|
|
49580
|
+
const pts = [];
|
|
49581
|
+
if (innerRadius <= 0) pts.push([0, 0]);
|
|
49582
|
+
addArcPoints(pts, options.outerRadius, start, end, segments, true, true);
|
|
49583
|
+
if (innerRadius > 0) addArcPoints(pts, innerRadius, end, start, segments, true, true);
|
|
49584
|
+
return polygon(pts);
|
|
49585
|
+
}
|
|
49586
|
+
const DRIVE_WHEEL_META_KEY = Symbol.for("forgecad.library.driveWheelMeta");
|
|
49587
|
+
function attachDriveWheelMeta(shape, meta2) {
|
|
49588
|
+
shape[DRIVE_WHEEL_META_KEY] = meta2;
|
|
49589
|
+
return shape;
|
|
49590
|
+
}
|
|
49591
|
+
function readDriveWheelMeta(shape) {
|
|
49592
|
+
const meta2 = shape[DRIVE_WHEEL_META_KEY];
|
|
49593
|
+
return meta2 ?? null;
|
|
49594
|
+
}
|
|
49595
|
+
class DriveWheelBuilder {
|
|
49596
|
+
constructor(options = {}) {
|
|
49597
|
+
__publicField(this, "body");
|
|
49598
|
+
__publicField(this, "faceWidth");
|
|
49599
|
+
__publicField(this, "boreDiameter");
|
|
49600
|
+
__publicField(this, "regions", []);
|
|
49601
|
+
if (options.body !== void 0 && !(options.body instanceof Shape$1)) throw new Error('driveWheel: "body" must be a Shape');
|
|
49602
|
+
if (options.faceWidth !== void 0) requirePositive$6("driveWheel", "faceWidth", options.faceWidth);
|
|
49603
|
+
const boreDiameter = options.boreDiameter ?? 0;
|
|
49604
|
+
if (!Number.isFinite(boreDiameter) || boreDiameter < 0) throw new Error('driveWheel: "boreDiameter" must be >= 0');
|
|
49605
|
+
this.body = options.body;
|
|
49606
|
+
this.faceWidth = options.faceWidth;
|
|
49607
|
+
this.boreDiameter = boreDiameter;
|
|
49608
|
+
}
|
|
49609
|
+
/**
|
|
49610
|
+
* Add an involute spur-tooth window on part of the pitch circle.
|
|
49611
|
+
*/
|
|
49612
|
+
addSpurTeethBetween(options) {
|
|
49613
|
+
const faceWidth = this.resolveFaceWidth("driveWheel.addSpurTeethBetween", options.faceWidth);
|
|
49614
|
+
this.regions.push(buildSpurTeethRegion(options, this.resolveName("teeth", options.name), faceWidth));
|
|
49615
|
+
return this;
|
|
49616
|
+
}
|
|
49617
|
+
/**
|
|
49618
|
+
* Add a constant-radius solid arc region such as a dwell, stop, or pusher.
|
|
49619
|
+
*/
|
|
49620
|
+
addSolidArcBetween(options) {
|
|
49621
|
+
const faceWidth = this.resolveFaceWidth("driveWheel.addSolidArcBetween", options.faceWidth);
|
|
49622
|
+
this.regions.push(buildSolidArcRegion(options, this.resolveName("arc", options.name), faceWidth));
|
|
49623
|
+
return this;
|
|
49624
|
+
}
|
|
49625
|
+
/**
|
|
49626
|
+
* Add a fully custom region shape while preserving region metadata.
|
|
49627
|
+
*/
|
|
49628
|
+
addShapeRegion(name, shape, options = {}) {
|
|
49629
|
+
const scope = "driveWheel.addShapeRegion";
|
|
49630
|
+
if (typeof name !== "string" || name.trim().length === 0) throw new Error(`${scope}: "name" must be a non-empty string`);
|
|
49631
|
+
if (!(shape instanceof Shape$1)) throw new Error(`${scope}: "shape" must be a Shape`);
|
|
49632
|
+
requireFiniteAngle(scope, "fromAngleDeg", options.fromAngleDeg);
|
|
49633
|
+
requireFiniteAngle(scope, "toAngleDeg", options.toAngleDeg);
|
|
49634
|
+
if (options.innerRadius !== void 0 && (!Number.isFinite(options.innerRadius) || options.innerRadius < 0)) {
|
|
49635
|
+
throw new Error(`${scope}: "innerRadius" must be >= 0`);
|
|
49636
|
+
}
|
|
49637
|
+
if (options.outerRadius !== void 0) requirePositive$6(scope, "outerRadius", options.outerRadius);
|
|
49638
|
+
this.regions.push({
|
|
49639
|
+
shape: shape.clone(),
|
|
49640
|
+
meta: {
|
|
49641
|
+
name: this.resolveName("region", name),
|
|
49642
|
+
kind: "custom",
|
|
49643
|
+
...options
|
|
49644
|
+
}
|
|
49645
|
+
});
|
|
49646
|
+
return this;
|
|
49647
|
+
}
|
|
49648
|
+
/**
|
|
49649
|
+
* Build the final wheel shape with a bore connector and region metadata.
|
|
49650
|
+
*/
|
|
49651
|
+
build() {
|
|
49652
|
+
var _a3, _b3;
|
|
49653
|
+
if (this.regions.length === 0 && this.body === void 0) {
|
|
49654
|
+
throw new Error("driveWheel: add a body or at least one region before build()");
|
|
49655
|
+
}
|
|
49656
|
+
const faceWidth = this.resolveBuildFaceWidth();
|
|
49657
|
+
const firstGearRegion = (_a3 = this.regions.find((region) => region.gearMeta)) == null ? void 0 : _a3.gearMeta;
|
|
49658
|
+
if (firstGearRegion && this.boreDiameter * 0.5 >= firstGearRegion.rootRadius - EPSILON$1) {
|
|
49659
|
+
throw new Error("driveWheel: bore is too large for the first spur-tooth region");
|
|
49660
|
+
}
|
|
49661
|
+
const body = ((_b3 = this.body) == null ? void 0 : _b3.clone()) ?? gearBodyDisk({ outerRadius: (firstGearRegion == null ? void 0 : firstGearRegion.rootRadius) ?? this.defaultBodyRadius(), faceWidth });
|
|
49662
|
+
let combined = body;
|
|
49663
|
+
for (const region of this.regions) combined = combined.add(region.shape);
|
|
49664
|
+
combined = cutBore(combined, this.boreDiameter);
|
|
49665
|
+
const withConnectors = combined.withConnectors({
|
|
49666
|
+
bore: connectorFactory(
|
|
49667
|
+
"drive-wheel-bore",
|
|
49668
|
+
{ origin: [0, 0, faceWidth / 2], axis: [0, 0, 1], kind: "revolute" },
|
|
49669
|
+
this.measurements(faceWidth)
|
|
49670
|
+
)
|
|
49671
|
+
});
|
|
49672
|
+
return attachDriveWheelMeta(withConnectors, {
|
|
49673
|
+
kind: "driveWheel",
|
|
49674
|
+
faceWidth,
|
|
49675
|
+
boreDiameter: this.boreDiameter,
|
|
49676
|
+
regions: this.regionMetadata(body, faceWidth)
|
|
49677
|
+
});
|
|
49678
|
+
}
|
|
49679
|
+
measurements(faceWidth) {
|
|
49680
|
+
var _a3;
|
|
49681
|
+
const firstGearRegion = (_a3 = this.regions.find((region) => region.gearMeta)) == null ? void 0 : _a3.gearMeta;
|
|
49682
|
+
return {
|
|
49683
|
+
faceWidth,
|
|
49684
|
+
boreDiameter: this.boreDiameter,
|
|
49685
|
+
regionCount: this.regions.length,
|
|
49686
|
+
...firstGearRegion ? {
|
|
49687
|
+
module: firstGearRegion.module,
|
|
49688
|
+
teethOnFullCircle: firstGearRegion.teeth,
|
|
49689
|
+
pitchRadius: firstGearRegion.pitchRadius,
|
|
49690
|
+
outerRadius: firstGearRegion.outerRadius
|
|
49691
|
+
} : {}
|
|
49692
|
+
};
|
|
49693
|
+
}
|
|
49694
|
+
regionMetadata(body, faceWidth) {
|
|
49695
|
+
return [
|
|
49696
|
+
{ name: "body", kind: "body", outerRadius: bodyOuterRadius(body), faceWidth },
|
|
49697
|
+
...this.regions.map((region) => ({ ...region.meta }))
|
|
49698
|
+
];
|
|
49699
|
+
}
|
|
49700
|
+
resolveFaceWidth(scope, localFaceWidth) {
|
|
49701
|
+
const faceWidth = localFaceWidth ?? this.faceWidth;
|
|
49702
|
+
if (faceWidth === void 0) throw new Error(`${scope}: "faceWidth" is required unless driveWheel({ faceWidth }) was set`);
|
|
49703
|
+
requirePositive$6(scope, "faceWidth", faceWidth);
|
|
49704
|
+
if (this.faceWidth !== void 0 && localFaceWidth !== void 0 && Math.abs(this.faceWidth - localFaceWidth) > EPSILON$1) {
|
|
49705
|
+
throw new Error(`${scope}: region faceWidth must match driveWheel faceWidth`);
|
|
49706
|
+
}
|
|
49707
|
+
return faceWidth;
|
|
49708
|
+
}
|
|
49709
|
+
resolveBuildFaceWidth() {
|
|
49710
|
+
var _a3;
|
|
49711
|
+
const faceWidth = this.faceWidth ?? ((_a3 = this.regions.find((region) => region.meta.faceWidth !== void 0)) == null ? void 0 : _a3.meta.faceWidth);
|
|
49712
|
+
if (faceWidth === void 0) throw new Error('driveWheel: "faceWidth" is required before build()');
|
|
49713
|
+
return faceWidth;
|
|
49714
|
+
}
|
|
49715
|
+
defaultBodyRadius() {
|
|
49716
|
+
const outerRadius = this.regions.reduce((max2, region) => Math.max(max2, region.meta.outerRadius ?? 0), 0);
|
|
49717
|
+
if (outerRadius <= 0) throw new Error('driveWheel: "body" is required when regions do not define an outer radius');
|
|
49718
|
+
return outerRadius;
|
|
49719
|
+
}
|
|
49720
|
+
resolveName(prefix, requested) {
|
|
49721
|
+
const base = (requested == null ? void 0 : requested.trim()) || prefix;
|
|
49722
|
+
if (this.regions.every((region) => region.meta.name !== base)) return base;
|
|
49723
|
+
for (let i = 2; ; i++) {
|
|
49724
|
+
const candidate = `${base}${i}`;
|
|
49725
|
+
if (this.regions.every((region) => region.meta.name !== candidate)) return candidate;
|
|
49726
|
+
}
|
|
49727
|
+
}
|
|
49728
|
+
}
|
|
49729
|
+
function driveWheel(options = {}) {
|
|
49730
|
+
return new DriveWheelBuilder(options);
|
|
49731
|
+
}
|
|
49732
|
+
function normalizeSectorGearOptions(options) {
|
|
49733
|
+
const teethOnFullCircle = options.teethOnFullCircle;
|
|
49734
|
+
if (!Number.isInteger(teethOnFullCircle) || teethOnFullCircle < 6) {
|
|
49735
|
+
throw new Error('sectorGear: "teethOnFullCircle" must be an integer >= 6');
|
|
49736
|
+
}
|
|
49737
|
+
const toothCount = options.toothCount;
|
|
49738
|
+
if (!Number.isInteger(toothCount) || toothCount < 1 || toothCount > teethOnFullCircle) {
|
|
49739
|
+
throw new Error('sectorGear: "toothCount" must be an integer in [1, teethOnFullCircle]');
|
|
49740
|
+
}
|
|
49741
|
+
const firstTooth = options.firstTooth ?? 0;
|
|
49742
|
+
if (!Number.isInteger(firstTooth) || firstTooth < 0 || firstTooth >= teethOnFullCircle) {
|
|
49743
|
+
throw new Error('sectorGear: "firstTooth" must be an integer in [0, teethOnFullCircle)');
|
|
49744
|
+
}
|
|
49745
|
+
return {
|
|
49746
|
+
...normalizeSpurGearOptions({ ...options, teeth: teethOnFullCircle }),
|
|
49747
|
+
teethOnFullCircle,
|
|
49748
|
+
toothCount,
|
|
49749
|
+
firstTooth,
|
|
49750
|
+
boreDiameter: options.boreDiameter ?? 0
|
|
49751
|
+
};
|
|
49752
|
+
}
|
|
49753
|
+
function sectorGear(options) {
|
|
49754
|
+
const normalized = normalizeSectorGearOptions(options);
|
|
49755
|
+
if (options.body !== void 0 && !(options.body instanceof Shape$1)) {
|
|
49756
|
+
throw new Error('sectorGear: "body" must be a Shape');
|
|
49757
|
+
}
|
|
49758
|
+
const spurMeta = buildSpurGearMeta(normalized);
|
|
49759
|
+
const pitchStepDeg = 360 / normalized.teethOnFullCircle;
|
|
49760
|
+
const activeAngleStartDeg = normalized.firstTooth * pitchStepDeg - pitchStepDeg * 0.5;
|
|
49761
|
+
const activeAngleEndDeg = (normalized.firstTooth + normalized.toothCount - 1) * pitchStepDeg + pitchStepDeg * 0.5;
|
|
49762
|
+
const meta2 = {
|
|
49763
|
+
...spurMeta,
|
|
49764
|
+
kind: "sector",
|
|
49765
|
+
teethOnFullCircle: normalized.teethOnFullCircle,
|
|
49766
|
+
firstTooth: normalized.firstTooth,
|
|
49767
|
+
toothCount: normalized.toothCount,
|
|
49768
|
+
activeAngleStartDeg,
|
|
49769
|
+
activeAngleEndDeg
|
|
49770
|
+
};
|
|
49771
|
+
const wheel = driveWheel({ body: options.body, faceWidth: normalized.faceWidth, boreDiameter: normalized.boreDiameter }).addSpurTeethBetween({
|
|
49772
|
+
name: "teeth",
|
|
49773
|
+
module: normalized.module,
|
|
49774
|
+
teethOnFullCircle: normalized.teethOnFullCircle,
|
|
49775
|
+
toothCount: normalized.toothCount,
|
|
49776
|
+
firstTooth: normalized.firstTooth,
|
|
49777
|
+
pressureAngleDeg: normalized.pressureAngleDeg,
|
|
49778
|
+
faceWidth: normalized.faceWidth,
|
|
49779
|
+
backlash: normalized.backlash,
|
|
49780
|
+
clearance: normalized.clearance,
|
|
49781
|
+
addendum: normalized.addendum,
|
|
49782
|
+
dedendum: normalized.dedendum,
|
|
49783
|
+
segmentsPerTooth: normalized.segmentsPerTooth
|
|
49784
|
+
}).build();
|
|
49785
|
+
return attachGearMeta(wheel, meta2);
|
|
49786
|
+
}
|
|
48312
49787
|
function normalizeSideGearOptions(options) {
|
|
48313
49788
|
let normalizedSpur;
|
|
48314
49789
|
try {
|
|
@@ -49288,6 +50763,12 @@ function boltPattern(options) {
|
|
|
49288
50763
|
}
|
|
49289
50764
|
};
|
|
49290
50765
|
}
|
|
50766
|
+
const gearBodies = {
|
|
50767
|
+
disk: gearBodyDisk,
|
|
50768
|
+
diskWithHub: gearBodyDiskWithHub,
|
|
50769
|
+
spoked: gearBodySpoked,
|
|
50770
|
+
fromProfile: gearBodyFromProfile
|
|
50771
|
+
};
|
|
49291
50772
|
function thread(diameter, pitch, length4, options) {
|
|
49292
50773
|
const r = diameter / 2;
|
|
49293
50774
|
const depth = (options == null ? void 0 : options.depth) ?? pitch * 0.35;
|
|
@@ -49453,7 +50934,23 @@ const partLibrary = {
|
|
|
49453
50934
|
gearRatio,
|
|
49454
50935
|
rackRatio,
|
|
49455
50936
|
planetaryRatio,
|
|
49456
|
-
boltPattern
|
|
50937
|
+
boltPattern,
|
|
50938
|
+
/** Start a composable exceptional gear or drive wheel. */
|
|
50939
|
+
driveWheel,
|
|
50940
|
+
/** Read functional-region metadata from a drive wheel shape. */
|
|
50941
|
+
readDriveWheelMeta,
|
|
50942
|
+
/** Involute sector gear with teeth on only part of the pitch circle. */
|
|
50943
|
+
sectorGear,
|
|
50944
|
+
/** Gear body preset namespace: disk, diskWithHub, spoked, and fromProfile. */
|
|
50945
|
+
gearBodies,
|
|
50946
|
+
/** Solid disk/ring gear body, independent from any tooth geometry. */
|
|
50947
|
+
gearBodyDisk,
|
|
50948
|
+
/** Disk gear body with a raised center hub. */
|
|
50949
|
+
gearBodyDiskWithHub,
|
|
50950
|
+
/** Spoked gear body with an outer rim, center hub, and radial spokes. */
|
|
50951
|
+
gearBodySpoked,
|
|
50952
|
+
/** Extrude a custom 2D profile into a gear body. */
|
|
50953
|
+
gearBodyFromProfile
|
|
49457
50954
|
};
|
|
49458
50955
|
/**
|
|
49459
50956
|
* @license
|
|
@@ -50651,9 +52148,9 @@ class Vector2 {
|
|
|
50651
52148
|
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
|
|
50652
52149
|
* @return {Vector2} A reference to this vector.
|
|
50653
52150
|
*/
|
|
50654
|
-
lerpVectors(v1,
|
|
50655
|
-
this.x = v1.x + (
|
|
50656
|
-
this.y = v1.y + (
|
|
52151
|
+
lerpVectors(v1, v22, alpha) {
|
|
52152
|
+
this.x = v1.x + (v22.x - v1.x) * alpha;
|
|
52153
|
+
this.y = v1.y + (v22.y - v1.y) * alpha;
|
|
50657
52154
|
return this;
|
|
50658
52155
|
}
|
|
50659
52156
|
/**
|
|
@@ -52465,11 +53962,11 @@ class Vector4 {
|
|
|
52465
53962
|
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
|
|
52466
53963
|
* @return {Vector4} A reference to this vector.
|
|
52467
53964
|
*/
|
|
52468
|
-
lerpVectors(v1,
|
|
52469
|
-
this.x = v1.x + (
|
|
52470
|
-
this.y = v1.y + (
|
|
52471
|
-
this.z = v1.z + (
|
|
52472
|
-
this.w = v1.w + (
|
|
53965
|
+
lerpVectors(v1, v22, alpha) {
|
|
53966
|
+
this.x = v1.x + (v22.x - v1.x) * alpha;
|
|
53967
|
+
this.y = v1.y + (v22.y - v1.y) * alpha;
|
|
53968
|
+
this.z = v1.z + (v22.z - v1.z) * alpha;
|
|
53969
|
+
this.w = v1.w + (v22.w - v1.w) * alpha;
|
|
52473
53970
|
return this;
|
|
52474
53971
|
}
|
|
52475
53972
|
/**
|
|
@@ -54049,10 +55546,10 @@ class Vector3 {
|
|
|
54049
55546
|
* @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
|
|
54050
55547
|
* @return {Vector3} A reference to this vector.
|
|
54051
55548
|
*/
|
|
54052
|
-
lerpVectors(v1,
|
|
54053
|
-
this.x = v1.x + (
|
|
54054
|
-
this.y = v1.y + (
|
|
54055
|
-
this.z = v1.z + (
|
|
55549
|
+
lerpVectors(v1, v22, alpha) {
|
|
55550
|
+
this.x = v1.x + (v22.x - v1.x) * alpha;
|
|
55551
|
+
this.y = v1.y + (v22.y - v1.y) * alpha;
|
|
55552
|
+
this.z = v1.z + (v22.z - v1.z) * alpha;
|
|
54056
55553
|
return this;
|
|
54057
55554
|
}
|
|
54058
55555
|
/**
|
|
@@ -54865,13 +56362,13 @@ const _center = /* @__PURE__ */ new Vector3();
|
|
|
54865
56362
|
const _extents = /* @__PURE__ */ new Vector3();
|
|
54866
56363
|
const _triangleNormal = /* @__PURE__ */ new Vector3();
|
|
54867
56364
|
const _testAxis = /* @__PURE__ */ new Vector3();
|
|
54868
|
-
function satForAxes(axes, v0, v1,
|
|
56365
|
+
function satForAxes(axes, v0, v1, v22, extents) {
|
|
54869
56366
|
for (let i = 0, j = axes.length - 3; i <= j; i += 3) {
|
|
54870
56367
|
_testAxis.fromArray(axes, i);
|
|
54871
56368
|
const r = extents.x * Math.abs(_testAxis.x) + extents.y * Math.abs(_testAxis.y) + extents.z * Math.abs(_testAxis.z);
|
|
54872
56369
|
const p0 = v0.dot(_testAxis);
|
|
54873
56370
|
const p1 = v1.dot(_testAxis);
|
|
54874
|
-
const p2 =
|
|
56371
|
+
const p2 = v22.dot(_testAxis);
|
|
54875
56372
|
if (Math.max(-Math.max(p0, p1, p2), Math.min(p0, p1, p2)) > r) {
|
|
54876
56373
|
return false;
|
|
54877
56374
|
}
|
|
@@ -57985,7 +59482,7 @@ class Triangle {
|
|
|
57985
59482
|
* @param {Vector3} target - The target vector that is used to store the method's result.
|
|
57986
59483
|
* @return {?Vector3} The interpolated value.
|
|
57987
59484
|
*/
|
|
57988
|
-
static getInterpolation(point2, p1, p2, p3, v1,
|
|
59485
|
+
static getInterpolation(point2, p1, p2, p3, v1, v22, v32, target) {
|
|
57989
59486
|
if (this.getBarycoord(point2, p1, p2, p3, _v3$2) === null) {
|
|
57990
59487
|
target.x = 0;
|
|
57991
59488
|
target.y = 0;
|
|
@@ -57995,7 +59492,7 @@ class Triangle {
|
|
|
57995
59492
|
}
|
|
57996
59493
|
target.setScalar(0);
|
|
57997
59494
|
target.addScaledVector(v1, _v3$2.x);
|
|
57998
|
-
target.addScaledVector(
|
|
59495
|
+
target.addScaledVector(v22, _v3$2.y);
|
|
57999
59496
|
target.addScaledVector(v32, _v3$2.z);
|
|
58000
59497
|
return target;
|
|
58001
59498
|
}
|
|
@@ -58160,8 +59657,8 @@ class Triangle {
|
|
|
58160
59657
|
* @param {Vector3} target - The target vector that is used to store the method's result.
|
|
58161
59658
|
* @return {?Vector3} The interpolated value.
|
|
58162
59659
|
*/
|
|
58163
|
-
getInterpolation(point2, v1,
|
|
58164
|
-
return Triangle.getInterpolation(point2, this.a, this.b, this.c, v1,
|
|
59660
|
+
getInterpolation(point2, v1, v22, v32, target) {
|
|
59661
|
+
return Triangle.getInterpolation(point2, this.a, this.b, this.c, v1, v22, v32, target);
|
|
58165
59662
|
}
|
|
58166
59663
|
/**
|
|
58167
59664
|
* Returns `true` if the given point, when projected onto the plane of the
|
|
@@ -66438,13 +67935,13 @@ class CubicBezierCurve extends Curve {
|
|
|
66438
67935
|
* @param {Vector2} [v2] - The second control point.
|
|
66439
67936
|
* @param {Vector2} [v3] - The end point.
|
|
66440
67937
|
*/
|
|
66441
|
-
constructor(v0 = new Vector2(), v1 = new Vector2(),
|
|
67938
|
+
constructor(v0 = new Vector2(), v1 = new Vector2(), v22 = new Vector2(), v32 = new Vector2()) {
|
|
66442
67939
|
super();
|
|
66443
67940
|
this.isCubicBezierCurve = true;
|
|
66444
67941
|
this.type = "CubicBezierCurve";
|
|
66445
67942
|
this.v0 = v0;
|
|
66446
67943
|
this.v1 = v1;
|
|
66447
|
-
this.v2 =
|
|
67944
|
+
this.v2 = v22;
|
|
66448
67945
|
this.v3 = v32;
|
|
66449
67946
|
}
|
|
66450
67947
|
/**
|
|
@@ -66456,10 +67953,10 @@ class CubicBezierCurve extends Curve {
|
|
|
66456
67953
|
*/
|
|
66457
67954
|
getPoint(t, optionalTarget = new Vector2()) {
|
|
66458
67955
|
const point2 = optionalTarget;
|
|
66459
|
-
const v0 = this.v0, v1 = this.v1,
|
|
67956
|
+
const v0 = this.v0, v1 = this.v1, v22 = this.v2, v32 = this.v3;
|
|
66460
67957
|
point2.set(
|
|
66461
|
-
CubicBezier(t, v0.x, v1.x,
|
|
66462
|
-
CubicBezier(t, v0.y, v1.y,
|
|
67958
|
+
CubicBezier(t, v0.x, v1.x, v22.x, v32.x),
|
|
67959
|
+
CubicBezier(t, v0.y, v1.y, v22.y, v32.y)
|
|
66463
67960
|
);
|
|
66464
67961
|
return point2;
|
|
66465
67962
|
}
|
|
@@ -66497,13 +67994,13 @@ class CubicBezierCurve3 extends Curve {
|
|
|
66497
67994
|
* @param {Vector3} [v2] - The second control point.
|
|
66498
67995
|
* @param {Vector3} [v3] - The end point.
|
|
66499
67996
|
*/
|
|
66500
|
-
constructor(v0 = new Vector3(), v1 = new Vector3(),
|
|
67997
|
+
constructor(v0 = new Vector3(), v1 = new Vector3(), v22 = new Vector3(), v32 = new Vector3()) {
|
|
66501
67998
|
super();
|
|
66502
67999
|
this.isCubicBezierCurve3 = true;
|
|
66503
68000
|
this.type = "CubicBezierCurve3";
|
|
66504
68001
|
this.v0 = v0;
|
|
66505
68002
|
this.v1 = v1;
|
|
66506
|
-
this.v2 =
|
|
68003
|
+
this.v2 = v22;
|
|
66507
68004
|
this.v3 = v32;
|
|
66508
68005
|
}
|
|
66509
68006
|
/**
|
|
@@ -66515,11 +68012,11 @@ class CubicBezierCurve3 extends Curve {
|
|
|
66515
68012
|
*/
|
|
66516
68013
|
getPoint(t, optionalTarget = new Vector3()) {
|
|
66517
68014
|
const point2 = optionalTarget;
|
|
66518
|
-
const v0 = this.v0, v1 = this.v1,
|
|
68015
|
+
const v0 = this.v0, v1 = this.v1, v22 = this.v2, v32 = this.v3;
|
|
66519
68016
|
point2.set(
|
|
66520
|
-
CubicBezier(t, v0.x, v1.x,
|
|
66521
|
-
CubicBezier(t, v0.y, v1.y,
|
|
66522
|
-
CubicBezier(t, v0.z, v1.z,
|
|
68017
|
+
CubicBezier(t, v0.x, v1.x, v22.x, v32.x),
|
|
68018
|
+
CubicBezier(t, v0.y, v1.y, v22.y, v32.y),
|
|
68019
|
+
CubicBezier(t, v0.z, v1.z, v22.z, v32.z)
|
|
66523
68020
|
);
|
|
66524
68021
|
return point2;
|
|
66525
68022
|
}
|
|
@@ -66555,12 +68052,12 @@ class LineCurve extends Curve {
|
|
|
66555
68052
|
* @param {Vector2} [v1] - The start point.
|
|
66556
68053
|
* @param {Vector2} [v2] - The end point.
|
|
66557
68054
|
*/
|
|
66558
|
-
constructor(v1 = new Vector2(),
|
|
68055
|
+
constructor(v1 = new Vector2(), v22 = new Vector2()) {
|
|
66559
68056
|
super();
|
|
66560
68057
|
this.isLineCurve = true;
|
|
66561
68058
|
this.type = "LineCurve";
|
|
66562
68059
|
this.v1 = v1;
|
|
66563
|
-
this.v2 =
|
|
68060
|
+
this.v2 = v22;
|
|
66564
68061
|
}
|
|
66565
68062
|
/**
|
|
66566
68063
|
* Returns a point on the line.
|
|
@@ -66615,12 +68112,12 @@ class LineCurve3 extends Curve {
|
|
|
66615
68112
|
* @param {Vector3} [v1] - The start point.
|
|
66616
68113
|
* @param {Vector3} [v2] - The end point.
|
|
66617
68114
|
*/
|
|
66618
|
-
constructor(v1 = new Vector3(),
|
|
68115
|
+
constructor(v1 = new Vector3(), v22 = new Vector3()) {
|
|
66619
68116
|
super();
|
|
66620
68117
|
this.isLineCurve3 = true;
|
|
66621
68118
|
this.type = "LineCurve3";
|
|
66622
68119
|
this.v1 = v1;
|
|
66623
|
-
this.v2 =
|
|
68120
|
+
this.v2 = v22;
|
|
66624
68121
|
}
|
|
66625
68122
|
/**
|
|
66626
68123
|
* Returns a point on the line.
|
|
@@ -66676,13 +68173,13 @@ class QuadraticBezierCurve extends Curve {
|
|
|
66676
68173
|
* @param {Vector2} [v1] - The control point.
|
|
66677
68174
|
* @param {Vector2} [v2] - The end point.
|
|
66678
68175
|
*/
|
|
66679
|
-
constructor(v0 = new Vector2(), v1 = new Vector2(),
|
|
68176
|
+
constructor(v0 = new Vector2(), v1 = new Vector2(), v22 = new Vector2()) {
|
|
66680
68177
|
super();
|
|
66681
68178
|
this.isQuadraticBezierCurve = true;
|
|
66682
68179
|
this.type = "QuadraticBezierCurve";
|
|
66683
68180
|
this.v0 = v0;
|
|
66684
68181
|
this.v1 = v1;
|
|
66685
|
-
this.v2 =
|
|
68182
|
+
this.v2 = v22;
|
|
66686
68183
|
}
|
|
66687
68184
|
/**
|
|
66688
68185
|
* Returns a point on the curve.
|
|
@@ -66693,10 +68190,10 @@ class QuadraticBezierCurve extends Curve {
|
|
|
66693
68190
|
*/
|
|
66694
68191
|
getPoint(t, optionalTarget = new Vector2()) {
|
|
66695
68192
|
const point2 = optionalTarget;
|
|
66696
|
-
const v0 = this.v0, v1 = this.v1,
|
|
68193
|
+
const v0 = this.v0, v1 = this.v1, v22 = this.v2;
|
|
66697
68194
|
point2.set(
|
|
66698
|
-
QuadraticBezier(t, v0.x, v1.x,
|
|
66699
|
-
QuadraticBezier(t, v0.y, v1.y,
|
|
68195
|
+
QuadraticBezier(t, v0.x, v1.x, v22.x),
|
|
68196
|
+
QuadraticBezier(t, v0.y, v1.y, v22.y)
|
|
66700
68197
|
);
|
|
66701
68198
|
return point2;
|
|
66702
68199
|
}
|
|
@@ -66730,13 +68227,13 @@ class QuadraticBezierCurve3 extends Curve {
|
|
|
66730
68227
|
* @param {Vector3} [v1] - The control point.
|
|
66731
68228
|
* @param {Vector3} [v2] - The end point.
|
|
66732
68229
|
*/
|
|
66733
|
-
constructor(v0 = new Vector3(), v1 = new Vector3(),
|
|
68230
|
+
constructor(v0 = new Vector3(), v1 = new Vector3(), v22 = new Vector3()) {
|
|
66734
68231
|
super();
|
|
66735
68232
|
this.isQuadraticBezierCurve3 = true;
|
|
66736
68233
|
this.type = "QuadraticBezierCurve3";
|
|
66737
68234
|
this.v0 = v0;
|
|
66738
68235
|
this.v1 = v1;
|
|
66739
|
-
this.v2 =
|
|
68236
|
+
this.v2 = v22;
|
|
66740
68237
|
}
|
|
66741
68238
|
/**
|
|
66742
68239
|
* Returns a point on the curve.
|
|
@@ -66747,11 +68244,11 @@ class QuadraticBezierCurve3 extends Curve {
|
|
|
66747
68244
|
*/
|
|
66748
68245
|
getPoint(t, optionalTarget = new Vector3()) {
|
|
66749
68246
|
const point2 = optionalTarget;
|
|
66750
|
-
const v0 = this.v0, v1 = this.v1,
|
|
68247
|
+
const v0 = this.v0, v1 = this.v1, v22 = this.v2;
|
|
66751
68248
|
point2.set(
|
|
66752
|
-
QuadraticBezier(t, v0.x, v1.x,
|
|
66753
|
-
QuadraticBezier(t, v0.y, v1.y,
|
|
66754
|
-
QuadraticBezier(t, v0.z, v1.z,
|
|
68249
|
+
QuadraticBezier(t, v0.x, v1.x, v22.x),
|
|
68250
|
+
QuadraticBezier(t, v0.y, v1.y, v22.y),
|
|
68251
|
+
QuadraticBezier(t, v0.z, v1.z, v22.z)
|
|
66755
68252
|
);
|
|
66756
68253
|
return point2;
|
|
66757
68254
|
}
|
|
@@ -92099,7 +93596,7 @@ class ProductStationBuilder {
|
|
|
92099
93596
|
this.profileValue = profileFromSketch(sketch, "custom", width, depth);
|
|
92100
93597
|
return this;
|
|
92101
93598
|
}
|
|
92102
|
-
/**
|
|
93599
|
+
/** Set the station crown amount for soft product-section intent. */
|
|
92103
93600
|
crown(amount) {
|
|
92104
93601
|
if (!Number.isFinite(amount)) throw new Error("station.crown(amount) requires a finite number");
|
|
92105
93602
|
this.crownValue = amount;
|
|
@@ -93430,7 +94927,7 @@ class ProductSkinBuilder {
|
|
|
93430
94927
|
this.stationsValue = stations.map(toStationSpec).sort((a2, b) => axisPosition(this.axisValue, a2.center) - axisPosition(this.axisValue, b.center));
|
|
93431
94928
|
return this;
|
|
93432
94929
|
}
|
|
93433
|
-
/** Attach guide rails
|
|
94930
|
+
/** Attach named guide rails for product-skin construction and downstream surface references. */
|
|
93434
94931
|
rails(rails) {
|
|
93435
94932
|
this.railsValue = { ...rails };
|
|
93436
94933
|
return this;
|
|
@@ -93464,7 +94961,7 @@ class ProductSkinBuilder {
|
|
|
93464
94961
|
this.edgeLengthValue = value;
|
|
93465
94962
|
return this;
|
|
93466
94963
|
}
|
|
93467
|
-
/**
|
|
94964
|
+
/** Record intended wall thickness for product design metadata. Use explicit shelling when the model needs real inner-wall geometry. */
|
|
93468
94965
|
wall(thickness) {
|
|
93469
94966
|
if (!Number.isFinite(thickness) || thickness <= 0) throw new Error("Product.skin().wall(thickness) requires a positive finite number");
|
|
93470
94967
|
this.wallValue = thickness;
|
|
@@ -96606,7 +98103,7 @@ class SurfaceMemberBuilder {
|
|
|
96606
98103
|
this.record.features.push({ ...normalizeFeature(name, feature), type: "counterbore" });
|
|
96607
98104
|
return this;
|
|
96608
98105
|
}
|
|
96609
|
-
/** Add a named anchor at a carrier surface coordinate for
|
|
98106
|
+
/** Add a named anchor at a carrier surface coordinate for explicit member joins. */
|
|
96610
98107
|
anchorAt(name, coordinate) {
|
|
96611
98108
|
if (!name.trim()) throw new Error("SurfaceMemberBuilder.anchorAt(name, coordinate) requires a non-empty name");
|
|
96612
98109
|
const explicitAnchors = this.record.spec.explicitAnchors ?? [];
|
|
@@ -106177,8 +107674,8 @@ tinf_build_bits_base(dist_bits, dist_base, 2, 1);
|
|
|
106177
107674
|
length_bits[28] = 0;
|
|
106178
107675
|
length_base[28] = 258;
|
|
106179
107676
|
var tinyInflate = tinf_uncompress;
|
|
106180
|
-
function derive(v0, v1,
|
|
106181
|
-
return Math.pow(1 - t, 3) * v0 + 3 * Math.pow(1 - t, 2) * t * v1 + 3 * (1 - t) * Math.pow(t, 2) *
|
|
107677
|
+
function derive(v0, v1, v22, v32, t) {
|
|
107678
|
+
return Math.pow(1 - t, 3) * v0 + 3 * Math.pow(1 - t, 2) * t * v1 + 3 * (1 - t) * Math.pow(t, 2) * v22 + Math.pow(t, 3) * v32;
|
|
106182
107679
|
}
|
|
106183
107680
|
function BoundingBox() {
|
|
106184
107681
|
this.x1 = Number.NaN;
|
|
@@ -335397,6 +336894,8 @@ function createForgeRuntimeModule(bindings) {
|
|
|
335397
336894
|
runtime.default = runtime;
|
|
335398
336895
|
return runtime;
|
|
335399
336896
|
}
|
|
336897
|
+
const DEFAULT_RAYMARCH_STEPS = 360;
|
|
336898
|
+
const MIN_RAYMARCH_STEP = 0.012;
|
|
335400
336899
|
function classifySdfPreviewNode(node) {
|
|
335401
336900
|
switch (node.kind) {
|
|
335402
336901
|
case "sdf:sphere":
|
|
@@ -335434,6 +336933,7 @@ function classifySdfPreviewNode(node) {
|
|
|
335434
336933
|
case "sdf:twist":
|
|
335435
336934
|
case "sdf:bend":
|
|
335436
336935
|
case "sdf:repeat":
|
|
336936
|
+
case "sdf:circularArray":
|
|
335437
336937
|
case "sdf:shell":
|
|
335438
336938
|
case "sdf:onion":
|
|
335439
336939
|
return classifySdfPreviewNode(node.child);
|
|
@@ -335443,10 +336943,7 @@ function classifySdfPreviewNode(node) {
|
|
|
335443
336943
|
reason: "This SDF uses a custom JavaScript displacement function that cannot be compiled for raymarch preview."
|
|
335444
336944
|
};
|
|
335445
336945
|
case "sdf:surfaceDisplace":
|
|
335446
|
-
return
|
|
335447
|
-
mode: "unsupported",
|
|
335448
|
-
reason: "This SDF uses surface displacement that is not yet available in the raymarch shader."
|
|
335449
|
-
};
|
|
336946
|
+
return classifySurfaceDisplacePreviewNode(node);
|
|
335450
336947
|
case "sdf:spatialBlend":
|
|
335451
336948
|
return {
|
|
335452
336949
|
mode: "unsupported",
|
|
@@ -335472,6 +336969,24 @@ ${node.shaderUnsupportedReason}` : ""}`
|
|
|
335472
336969
|
};
|
|
335473
336970
|
}
|
|
335474
336971
|
}
|
|
336972
|
+
function classifySurfaceDisplacePreviewNode(node) {
|
|
336973
|
+
if (!node.pattern) {
|
|
336974
|
+
return {
|
|
336975
|
+
mode: "unsupported",
|
|
336976
|
+
reason: "This SDF uses a custom JavaScript surface pattern that cannot be compiled for raymarch preview."
|
|
336977
|
+
};
|
|
336978
|
+
}
|
|
336979
|
+
const childResult = classifySdfPreviewNode(node.child);
|
|
336980
|
+
if (childResult.mode !== "raymarch") return childResult;
|
|
336981
|
+
const uv = analyzeShaderSurfaceUv(node.child, "p", node.uvMode);
|
|
336982
|
+
if (uv.mode === "triplanar") {
|
|
336983
|
+
return {
|
|
336984
|
+
mode: "unsupported",
|
|
336985
|
+
reason: "Typed surface displacement raymarch preview currently supports sphere, cylinder, and torus UV mappings."
|
|
336986
|
+
};
|
|
336987
|
+
}
|
|
336988
|
+
return { mode: "raymarch" };
|
|
336989
|
+
}
|
|
335475
336990
|
function f2(value) {
|
|
335476
336991
|
if (!Number.isFinite(value)) return "0.0";
|
|
335477
336992
|
const text = Number(value.toPrecision(9)).toString();
|
|
@@ -335480,6 +336995,9 @@ function f2(value) {
|
|
|
335480
336995
|
function v3(value) {
|
|
335481
336996
|
return `vec3(${f2(value[0])}, ${f2(value[1])}, ${f2(value[2])})`;
|
|
335482
336997
|
}
|
|
336998
|
+
function v2(value) {
|
|
336999
|
+
return `vec2(${f2(value[0])}, ${f2(value[1])})`;
|
|
337000
|
+
}
|
|
335483
337001
|
function metricFlag(mode) {
|
|
335484
337002
|
return mode === "metric-approx" ? "1.0" : "0.0";
|
|
335485
337003
|
}
|
|
@@ -335499,6 +337017,32 @@ function scaleLimit(limit, factor) {
|
|
|
335499
337017
|
const scale2 = positiveFinite(Math.abs(factor));
|
|
335500
337018
|
return limit !== null && scale2 !== null ? limit * scale2 : limit;
|
|
335501
337019
|
}
|
|
337020
|
+
function surfacePatternStepLimit(pattern) {
|
|
337021
|
+
switch (pattern.kind) {
|
|
337022
|
+
case "surfacePattern:constant":
|
|
337023
|
+
return null;
|
|
337024
|
+
case "surfacePattern:sineWave":
|
|
337025
|
+
return minPositive(pattern.wavelength * 0.1, Math.abs(pattern.amplitude) * 0.5);
|
|
337026
|
+
case "surfacePattern:stripes":
|
|
337027
|
+
return minPositive(pattern.spacing * 0.25, pattern.width * 0.25, pattern.depth * 0.5);
|
|
337028
|
+
case "surfacePattern:overUnderWeave":
|
|
337029
|
+
return minPositive(
|
|
337030
|
+
...pattern.spacing.map((value) => value * 0.25),
|
|
337031
|
+
...pattern.threadWidth.map((value) => value * 0.25),
|
|
337032
|
+
pattern.depth * 0.5
|
|
337033
|
+
);
|
|
337034
|
+
case "surfacePattern:abs":
|
|
337035
|
+
case "surfacePattern:negate":
|
|
337036
|
+
return surfacePatternStepLimit(pattern.child);
|
|
337037
|
+
case "surfacePattern:add":
|
|
337038
|
+
case "surfacePattern:multiply":
|
|
337039
|
+
case "surfacePattern:min":
|
|
337040
|
+
case "surfacePattern:max":
|
|
337041
|
+
return minPositive(...pattern.children.map(surfacePatternStepLimit));
|
|
337042
|
+
case "surfacePattern:clamp":
|
|
337043
|
+
return surfacePatternStepLimit(pattern.child);
|
|
337044
|
+
}
|
|
337045
|
+
}
|
|
335502
337046
|
function tpmsStepLimit(node) {
|
|
335503
337047
|
const cellLimit = node.cellSize * 0.08;
|
|
335504
337048
|
const thicknessLimit = node.thicknessMode === "metric-approx" ? node.thickness * 0.35 : cellLimit;
|
|
@@ -335533,6 +337077,10 @@ function estimateNodeStepLimit(node) {
|
|
|
335533
337077
|
return minPositive(estimateNodeStepLimit(node.child), 0.35);
|
|
335534
337078
|
case "sdf:repeat":
|
|
335535
337079
|
return minPositive(estimateNodeStepLimit(node.child), ...node.spacing.map((value) => positiveFinite(value * 0.25)));
|
|
337080
|
+
case "sdf:circularArray": {
|
|
337081
|
+
const arcSpacing = node.offset > 0 ? 2 * Math.PI * node.offset / node.count : null;
|
|
337082
|
+
return minPositive(estimateNodeStepLimit(node.child), arcSpacing !== null ? arcSpacing * 0.25 : null);
|
|
337083
|
+
}
|
|
335536
337084
|
case "sdf:shell":
|
|
335537
337085
|
return minPositive(estimateNodeStepLimit(node.child), Math.max(0.04, node.thickness * 0.25));
|
|
335538
337086
|
case "sdf:onion":
|
|
@@ -335543,11 +337091,12 @@ function estimateNodeStepLimit(node) {
|
|
|
335543
337091
|
case "sdf:lidinoid":
|
|
335544
337092
|
return tpmsStepLimit(node);
|
|
335545
337093
|
case "sdf:displace":
|
|
335546
|
-
case "sdf:surfaceDisplace":
|
|
335547
337094
|
case "sdf:spatialBlend":
|
|
335548
337095
|
case "sdf:noise":
|
|
335549
337096
|
case "sdf:voronoi":
|
|
335550
337097
|
return null;
|
|
337098
|
+
case "sdf:surfaceDisplace":
|
|
337099
|
+
return node.pattern ? minPositive(estimateNodeStepLimit(node.child), surfacePatternStepLimit(node.pattern)) : null;
|
|
335551
337100
|
case "sdf:custom":
|
|
335552
337101
|
return node.shaderBody ? positiveFinite(node.raymarchStepLimit ?? 0.25) ?? 0.25 : null;
|
|
335553
337102
|
}
|
|
@@ -335572,6 +337121,98 @@ function emitPolylineSweepExpr(node, p2) {
|
|
|
335572
337121
|
}
|
|
335573
337122
|
return expr;
|
|
335574
337123
|
}
|
|
337124
|
+
function analyzeShaderSurfaceUv(node, p2, override) {
|
|
337125
|
+
const analysis = analyzeShaderSurfaceUvNode(node, p2);
|
|
337126
|
+
if (!override || override === "auto") return analysis;
|
|
337127
|
+
if (override === "triplanar") return { mode: "triplanar" };
|
|
337128
|
+
if (analysis.mode === "triplanar") return analysis;
|
|
337129
|
+
if (override === analysis.mode) return analysis;
|
|
337130
|
+
if (override === "sphere" || override === "cylinder") {
|
|
337131
|
+
return { mode: override, localPoint: analysis.localPoint, radius: analysis.radius };
|
|
337132
|
+
}
|
|
337133
|
+
return analysis.mode === "torus" ? analysis : { mode: "triplanar" };
|
|
337134
|
+
}
|
|
337135
|
+
function analyzeShaderSurfaceUvNode(node, p2) {
|
|
337136
|
+
switch (node.kind) {
|
|
337137
|
+
case "sdf:sphere":
|
|
337138
|
+
return { mode: "sphere", localPoint: p2, radius: node.radius };
|
|
337139
|
+
case "sdf:cylinder":
|
|
337140
|
+
return { mode: "cylinder", localPoint: p2, radius: node.radius };
|
|
337141
|
+
case "sdf:torus":
|
|
337142
|
+
return { mode: "torus", localPoint: p2, radius: node.minorRadius, majorRadius: node.majorRadius };
|
|
337143
|
+
case "sdf:translate":
|
|
337144
|
+
return analyzeShaderSurfaceUvNode(node.child, `(${p2} - ${v3(node.offset)})`);
|
|
337145
|
+
case "sdf:rotate":
|
|
337146
|
+
return analyzeShaderSurfaceUvNode(node.child, `rotateInvEuler(${p2}, ${v3(node.degrees)})`);
|
|
337147
|
+
case "sdf:scale": {
|
|
337148
|
+
const result = analyzeShaderSurfaceUvNode(node.child, `(${p2} / ${f2(node.factor)})`);
|
|
337149
|
+
if (result.mode === "triplanar") return result;
|
|
337150
|
+
return {
|
|
337151
|
+
...result,
|
|
337152
|
+
radius: result.radius * node.factor,
|
|
337153
|
+
...result.mode === "torus" ? { majorRadius: result.majorRadius * node.factor } : {}
|
|
337154
|
+
};
|
|
337155
|
+
}
|
|
337156
|
+
case "sdf:shell":
|
|
337157
|
+
return analyzeShaderSurfaceUvNode(node.child, p2);
|
|
337158
|
+
case "sdf:union":
|
|
337159
|
+
case "sdf:smoothUnion":
|
|
337160
|
+
case "sdf:intersection":
|
|
337161
|
+
case "sdf:smoothIntersection":
|
|
337162
|
+
case "sdf:difference":
|
|
337163
|
+
case "sdf:smoothDifference":
|
|
337164
|
+
return node.children.length > 0 ? analyzeShaderSurfaceUvNode(node.children[0], p2) : { mode: "triplanar" };
|
|
337165
|
+
case "sdf:morph":
|
|
337166
|
+
return analyzeShaderSurfaceUvNode(node.a, p2);
|
|
337167
|
+
default:
|
|
337168
|
+
return { mode: "triplanar" };
|
|
337169
|
+
}
|
|
337170
|
+
}
|
|
337171
|
+
function emitSurfaceUvExpr(uv) {
|
|
337172
|
+
const p2 = uv.localPoint;
|
|
337173
|
+
switch (uv.mode) {
|
|
337174
|
+
case "sphere":
|
|
337175
|
+
return `surfaceUvSphere(${p2}, ${f2(uv.radius)})`;
|
|
337176
|
+
case "cylinder":
|
|
337177
|
+
return `surfaceUvCylinder(${p2}, ${f2(uv.radius)})`;
|
|
337178
|
+
case "torus":
|
|
337179
|
+
return `surfaceUvTorus(${p2}, ${f2(uv.majorRadius)}, ${f2(uv.radius)})`;
|
|
337180
|
+
}
|
|
337181
|
+
}
|
|
337182
|
+
function emitSurfacePatternExpr(pattern, uvExpr) {
|
|
337183
|
+
switch (pattern.kind) {
|
|
337184
|
+
case "surfacePattern:constant":
|
|
337185
|
+
return f2(pattern.value);
|
|
337186
|
+
case "surfacePattern:sineWave":
|
|
337187
|
+
return `surfacePatternSineWave(${uvExpr}, ${v2(pattern.direction)}, ${f2(pattern.wavelength)}, ${f2(pattern.amplitude)}, ${f2(pattern.phase)}, ${f2(pattern.bias)})`;
|
|
337188
|
+
case "surfacePattern:stripes":
|
|
337189
|
+
return `surfacePatternStripes(${uvExpr}, ${v2(pattern.direction)}, ${f2(pattern.spacing)}, ${f2(pattern.width)}, ${f2(pattern.depth)})`;
|
|
337190
|
+
case "surfacePattern:overUnderWeave":
|
|
337191
|
+
return `surfacePatternOverUnderWeave(${uvExpr}, ${v2(pattern.spacing)}, ${v2(pattern.threadWidth)}, ${f2(pattern.depth)}, ${f2(pattern.underScale)})`;
|
|
337192
|
+
case "surfacePattern:abs":
|
|
337193
|
+
return `abs(${emitSurfacePatternExpr(pattern.child, uvExpr)})`;
|
|
337194
|
+
case "surfacePattern:negate":
|
|
337195
|
+
return `(-(${emitSurfacePatternExpr(pattern.child, uvExpr)}))`;
|
|
337196
|
+
case "surfacePattern:add":
|
|
337197
|
+
return pattern.children.length === 0 ? "0.0" : `(${pattern.children.map((child) => emitSurfacePatternExpr(child, uvExpr)).join(" + ")})`;
|
|
337198
|
+
case "surfacePattern:multiply":
|
|
337199
|
+
return pattern.children.length === 0 ? "1.0" : `(${pattern.children.map((child) => emitSurfacePatternExpr(child, uvExpr)).join(" * ")})`;
|
|
337200
|
+
case "surfacePattern:min":
|
|
337201
|
+
return foldSurfacePatternChildren(pattern, uvExpr, "min", "0.0");
|
|
337202
|
+
case "surfacePattern:max":
|
|
337203
|
+
return foldSurfacePatternChildren(pattern, uvExpr, "max", "0.0");
|
|
337204
|
+
case "surfacePattern:clamp":
|
|
337205
|
+
return `clamp(${emitSurfacePatternExpr(pattern.child, uvExpr)}, ${f2(pattern.min)}, ${f2(pattern.max)})`;
|
|
337206
|
+
}
|
|
337207
|
+
}
|
|
337208
|
+
function foldSurfacePatternChildren(pattern, uvExpr, op, empty) {
|
|
337209
|
+
if (pattern.children.length === 0) return empty;
|
|
337210
|
+
let expr = emitSurfacePatternExpr(pattern.children[0], uvExpr);
|
|
337211
|
+
for (let i = 1; i < pattern.children.length; i++) {
|
|
337212
|
+
expr = `${op}(${expr}, ${emitSurfacePatternExpr(pattern.children[i], uvExpr)})`;
|
|
337213
|
+
}
|
|
337214
|
+
return expr;
|
|
337215
|
+
}
|
|
335575
337216
|
function emitSdfExpr(node, p2) {
|
|
335576
337217
|
switch (node.kind) {
|
|
335577
337218
|
case "sdf:sphere":
|
|
@@ -335614,6 +337255,11 @@ function emitSdfExpr(node, p2) {
|
|
|
335614
337255
|
return emitSdfExpr(node.child, `bendPoint(${p2}, ${f2(node.radius)})`);
|
|
335615
337256
|
case "sdf:repeat":
|
|
335616
337257
|
return emitSdfExpr(node.child, `repeatPoint(${p2}, ${v3(node.spacing)}, ${v3(node.count)})`);
|
|
337258
|
+
case "sdf:circularArray": {
|
|
337259
|
+
const a2 = emitSdfExpr(node.child, `circularArrayPoint(${p2}, ${f2(node.count)}, ${f2(node.offset)}, -1.0)`);
|
|
337260
|
+
const b = emitSdfExpr(node.child, `circularArrayPoint(${p2}, ${f2(node.count)}, ${f2(node.offset)}, 0.0)`);
|
|
337261
|
+
return `min(${a2}, ${b})`;
|
|
337262
|
+
}
|
|
335617
337263
|
case "sdf:shell":
|
|
335618
337264
|
return `(abs(${emitSdfExpr(node.child, p2)}) - ${f2(node.thickness * 0.5)})`;
|
|
335619
337265
|
case "sdf:onion": {
|
|
@@ -335621,6 +337267,12 @@ function emitSdfExpr(node, p2) {
|
|
|
335621
337267
|
for (let i = 0; i < node.layers; i++) expr = `(abs(${expr}) - ${f2(node.thickness)})`;
|
|
335622
337268
|
return expr;
|
|
335623
337269
|
}
|
|
337270
|
+
case "sdf:surfaceDisplace": {
|
|
337271
|
+
if (!node.pattern) return "1e20";
|
|
337272
|
+
const uv = analyzeShaderSurfaceUv(node.child, p2, node.uvMode);
|
|
337273
|
+
if (uv.mode === "triplanar") return "1e20";
|
|
337274
|
+
return `(${emitSdfExpr(node.child, p2)} + ${emitSurfacePatternExpr(node.pattern, emitSurfaceUvExpr(uv))})`;
|
|
337275
|
+
}
|
|
335624
337276
|
case "sdf:gyroid":
|
|
335625
337277
|
return `sdGyroid(${p2}, ${f2(node.cellSize)}, ${f2(node.thickness)}, ${metricFlag(node.thicknessMode)})`;
|
|
335626
337278
|
case "sdf:schwarzP":
|
|
@@ -335636,7 +337288,6 @@ function emitSdfExpr(node, p2) {
|
|
|
335636
337288
|
}
|
|
335637
337289
|
return "1e20";
|
|
335638
337290
|
case "sdf:displace":
|
|
335639
|
-
case "sdf:surfaceDisplace":
|
|
335640
337291
|
case "sdf:spatialBlend":
|
|
335641
337292
|
case "sdf:noise":
|
|
335642
337293
|
case "sdf:voronoi":
|
|
@@ -335710,9 +337361,9 @@ uniform vec3 uHoverColor;
|
|
|
335710
337361
|
uniform float uHoverIntensity;
|
|
335711
337362
|
uniform float uIsOrthographic;
|
|
335712
337363
|
|
|
335713
|
-
const int MAX_STEPS =
|
|
337364
|
+
const int MAX_STEPS = ${DEFAULT_RAYMARCH_STEPS};
|
|
335714
337365
|
const int REFINE_STEPS = 7;
|
|
335715
|
-
const float MIN_STEP =
|
|
337366
|
+
const float MIN_STEP = ${f2(MIN_RAYMARCH_STEP)};
|
|
335716
337367
|
const float HIT_EPS = 0.035;
|
|
335717
337368
|
const float NORMAL_EPS = 0.12;
|
|
335718
337369
|
const float FIELD_STEP_LIMIT = ${stepLimit === null ? "1e20" : f2(stepLimit)};
|
|
@@ -335801,6 +337452,53 @@ vec3 repeatPoint(vec3 p, vec3 spacing, vec3 count) {
|
|
|
335801
337452
|
);
|
|
335802
337453
|
}
|
|
335803
337454
|
|
|
337455
|
+
vec3 circularArrayPoint(vec3 p, float count, float offset, float sectorOffset) {
|
|
337456
|
+
float step = 6.283185307179586 / max(count, 1.0);
|
|
337457
|
+
float radius = length(p.xy);
|
|
337458
|
+
float angle = mod(atan(p.y, p.x), step);
|
|
337459
|
+
if (angle < 0.0) angle += step;
|
|
337460
|
+
angle += sectorOffset * step;
|
|
337461
|
+
return vec3(cos(angle) * radius - offset, sin(angle) * radius, p.z);
|
|
337462
|
+
}
|
|
337463
|
+
|
|
337464
|
+
vec2 surfaceUvSphere(vec3 p, float radius) {
|
|
337465
|
+
return vec2(atan(p.y, p.x) * radius, acos(clamp(p.z / max(length(p), 1e-9), -1.0, 1.0)) * radius);
|
|
337466
|
+
}
|
|
337467
|
+
|
|
337468
|
+
vec2 surfaceUvCylinder(vec3 p, float radius) {
|
|
337469
|
+
return vec2(atan(p.y, p.x) * radius, p.z);
|
|
337470
|
+
}
|
|
337471
|
+
|
|
337472
|
+
vec2 surfaceUvTorus(vec3 p, float majorRadius, float minorRadius) {
|
|
337473
|
+
return vec2(atan(p.y, p.x) * majorRadius, atan(p.z, length(p.xy) - majorRadius) * minorRadius);
|
|
337474
|
+
}
|
|
337475
|
+
|
|
337476
|
+
float surfacePatternSineWave(vec2 uv, vec2 direction, float wavelength, float amplitude, float phase, float bias) {
|
|
337477
|
+
return bias + sin(dot(uv, direction) * (6.283185307179586 / wavelength) + phase) * amplitude;
|
|
337478
|
+
}
|
|
337479
|
+
|
|
337480
|
+
float surfacePatternStripes(vec2 uv, vec2 direction, float spacing, float width, float depth) {
|
|
337481
|
+
float coord = dot(uv, direction);
|
|
337482
|
+
float d = abs(coord - floor(coord / spacing + 0.5) * spacing);
|
|
337483
|
+
float p = max(0.0, 1.0 - d / (width * 0.5));
|
|
337484
|
+
return -(p * p) * depth;
|
|
337485
|
+
}
|
|
337486
|
+
|
|
337487
|
+
float surfacePatternOverUnderWeave(vec2 uv, vec2 spacing, vec2 threadWidth, float depth, float underScale) {
|
|
337488
|
+
float su = uv.x / spacing.x;
|
|
337489
|
+
float sv = uv.y / spacing.y;
|
|
337490
|
+
float du = abs(su - floor(su + 0.5)) * spacing.x;
|
|
337491
|
+
float dv = abs(sv - floor(sv + 0.5)) * spacing.y;
|
|
337492
|
+
float pU = max(0.0, 1.0 - du / (threadWidth.x * 0.5));
|
|
337493
|
+
float pV = max(0.0, 1.0 - dv / (threadWidth.y * 0.5));
|
|
337494
|
+
pU *= pU;
|
|
337495
|
+
pV *= pV;
|
|
337496
|
+
float checker = mod(floor(su + 0.5) + floor(sv + 0.5), 2.0);
|
|
337497
|
+
float top = checker > 0.5 ? pV : pU;
|
|
337498
|
+
float bot = checker > 0.5 ? pU : pV;
|
|
337499
|
+
return -max(top, bot * underScale) * depth;
|
|
337500
|
+
}
|
|
337501
|
+
|
|
335804
337502
|
vec3 rotateInvEuler(vec3 p, vec3 degrees) {
|
|
335805
337503
|
vec3 r = radians(degrees);
|
|
335806
337504
|
float cx = cos(r.x);
|
|
@@ -336001,9 +337699,9 @@ void main() {
|
|
|
336001
337699
|
float bestAbsDist = 1e20;
|
|
336002
337700
|
int bestIndex = -1;
|
|
336003
337701
|
bool conservativeField = FIELD_STEP_LIMIT < 1e19;
|
|
336004
|
-
float
|
|
336005
|
-
|
|
336006
|
-
|
|
337702
|
+
float coarseMaxStep = max(MIN_STEP, sceneDiag / 18.0);
|
|
337703
|
+
float conservativeMaxStep = max(MIN_STEP, min(max(sceneDiag / 260.0, MIN_STEP), FIELD_STEP_LIMIT));
|
|
337704
|
+
float localDetailBand = max(HIT_EPS * 4.0, FIELD_STEP_LIMIT * 4.0);
|
|
336007
337705
|
float stepScale = conservativeField ? CONSERVATIVE_STEP_SCALE : SAFE_STEP_SCALE;
|
|
336008
337706
|
|
|
336009
337707
|
for (int i = 0; i < MAX_STEPS; i++) {
|
|
@@ -336024,6 +337722,7 @@ void main() {
|
|
|
336024
337722
|
hit = true;
|
|
336025
337723
|
break;
|
|
336026
337724
|
}
|
|
337725
|
+
float maxStep = conservativeField && absDist <= localDetailBand ? conservativeMaxStep : coarseMaxStep;
|
|
336027
337726
|
float stepSize = clamp(absDist * stepScale, MIN_STEP, maxStep);
|
|
336028
337727
|
prevT = t;
|
|
336029
337728
|
prevDist = dist;
|
|
@@ -336147,7 +337846,7 @@ function mapScriptResultToScene(args) {
|
|
|
336147
337846
|
var _a3;
|
|
336148
337847
|
const objects = [];
|
|
336149
337848
|
const shapeDimensions = [];
|
|
336150
|
-
const pushShape = (shape, name, groupName, color, treePath) => {
|
|
337849
|
+
const pushShape = (shape, name, groupName, color, treePath, tags = []) => {
|
|
336151
337850
|
const objectId = `obj-${objects.length + 1}`;
|
|
336152
337851
|
objects.push({
|
|
336153
337852
|
id: objectId,
|
|
@@ -336158,7 +337857,8 @@ function mapScriptResultToScene(args) {
|
|
|
336158
337857
|
materialProps: shape.materialProps,
|
|
336159
337858
|
geometryInfo: shape.geometryInfo(),
|
|
336160
337859
|
groupName,
|
|
336161
|
-
treePath: treePath && treePath.length > 0 ? [...treePath] : [name]
|
|
337860
|
+
treePath: treePath && treePath.length > 0 ? [...treePath] : [name],
|
|
337861
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
336162
337862
|
});
|
|
336163
337863
|
const dims = getShapeDimensions(shape);
|
|
336164
337864
|
dims.forEach((dim2) => {
|
|
@@ -336182,7 +337882,7 @@ function mapScriptResultToScene(args) {
|
|
|
336182
337882
|
});
|
|
336183
337883
|
}
|
|
336184
337884
|
};
|
|
336185
|
-
const pushSketch = (sketch, name, groupName, treePath) => {
|
|
337885
|
+
const pushSketch = (sketch, name, groupName, treePath, tags = []) => {
|
|
336186
337886
|
const meta2 = sketch instanceof ConstraintSketch ? sketch.constraintMeta : void 0;
|
|
336187
337887
|
objects.push({
|
|
336188
337888
|
id: `obj-${objects.length + 1}`,
|
|
@@ -336193,10 +337893,11 @@ function mapScriptResultToScene(args) {
|
|
|
336193
337893
|
sketchMeta: meta2,
|
|
336194
337894
|
color: sketch.colorHex,
|
|
336195
337895
|
groupName,
|
|
336196
|
-
treePath: treePath && treePath.length > 0 ? [...treePath] : [name]
|
|
337896
|
+
treePath: treePath && treePath.length > 0 ? [...treePath] : [name],
|
|
337897
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
336197
337898
|
});
|
|
336198
337899
|
};
|
|
336199
|
-
const pushSdf = (sdfShape, name, groupName, treePath, color) => {
|
|
337900
|
+
const pushSdf = (sdfShape, name, groupName, treePath, color, tags = []) => {
|
|
336200
337901
|
const preview = classifySdfPreviewNode(sdfShape._node);
|
|
336201
337902
|
const displayColor = color || sdfShape.colorHex;
|
|
336202
337903
|
const data = {
|
|
@@ -336216,7 +337917,8 @@ function mapScriptResultToScene(args) {
|
|
|
336216
337917
|
materialProps: sdfShape.materialProps,
|
|
336217
337918
|
geometryInfo: null,
|
|
336218
337919
|
groupName,
|
|
336219
|
-
treePath: treePath && treePath.length > 0 ? [...treePath] : [name]
|
|
337920
|
+
treePath: treePath && treePath.length > 0 ? [...treePath] : [name],
|
|
337921
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
336220
337922
|
});
|
|
336221
337923
|
};
|
|
336222
337924
|
const isNamedObject = (item) => {
|
|
@@ -336233,18 +337935,24 @@ function mapScriptResultToScene(args) {
|
|
|
336233
337935
|
const rootGroupChildLabel = (grp, index2) => {
|
|
336234
337936
|
return shapeGroupChildSegment(grp, index2, true);
|
|
336235
337937
|
};
|
|
336236
|
-
const flattenGroupChild = (child, label, groupName, treePath) => {
|
|
337938
|
+
const flattenGroupChild = (child, label, groupName, treePath, tags = []) => {
|
|
336237
337939
|
const resolvedTreePath = treePath && treePath.length > 0 ? treePath : [label];
|
|
336238
337940
|
if (child instanceof ShapeGroup) {
|
|
336239
337941
|
child.children.forEach((nested, i) => {
|
|
336240
|
-
flattenGroupChild(
|
|
337942
|
+
flattenGroupChild(
|
|
337943
|
+
nested,
|
|
337944
|
+
groupChildLabel(child, label, i),
|
|
337945
|
+
groupName,
|
|
337946
|
+
[...resolvedTreePath, shapeGroupChildSegment(child, i)],
|
|
337947
|
+
mergeSceneTags(tags, child.tagsForChild(i))
|
|
337948
|
+
);
|
|
336241
337949
|
});
|
|
336242
337950
|
return;
|
|
336243
337951
|
}
|
|
336244
337952
|
if (child instanceof Shape$1) {
|
|
336245
|
-
pushShape(child, label, groupName, void 0, resolvedTreePath);
|
|
337953
|
+
pushShape(child, label, groupName, void 0, resolvedTreePath, tags);
|
|
336246
337954
|
} else if (child instanceof Sketch) {
|
|
336247
|
-
pushSketch(child, label, groupName, resolvedTreePath);
|
|
337955
|
+
pushSketch(child, label, groupName, resolvedTreePath, tags);
|
|
336248
337956
|
}
|
|
336249
337957
|
};
|
|
336250
337958
|
const isPlainObject2 = (value) => {
|
|
@@ -336253,34 +337961,40 @@ function mapScriptResultToScene(args) {
|
|
|
336253
337961
|
return proto2 === Object.prototype || proto2 === null;
|
|
336254
337962
|
};
|
|
336255
337963
|
const joinName = (path2) => path2.join(".");
|
|
336256
|
-
const processRenderableTree = (value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = [], seen2 = /* @__PURE__ */ new WeakSet()) => {
|
|
337964
|
+
const processRenderableTree = (value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = [], inheritedTags = [], seen2 = /* @__PURE__ */ new WeakSet()) => {
|
|
336257
337965
|
const segment = fallbackSegment.trim().length > 0 ? fallbackSegment : fallbackLabel;
|
|
336258
337966
|
const treePath = [...parentTreePath, segment];
|
|
336259
337967
|
const name = joinName(treePath) || fallbackLabel;
|
|
336260
337968
|
if (value instanceof Assembly) {
|
|
336261
|
-
value.solve().toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath));
|
|
337969
|
+
value.solve().toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath, inheritedTags));
|
|
336262
337970
|
return;
|
|
336263
337971
|
}
|
|
336264
337972
|
if (value instanceof SolvedAssembly) {
|
|
336265
|
-
value.toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath));
|
|
337973
|
+
value.toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath, inheritedTags));
|
|
336266
337974
|
return;
|
|
336267
337975
|
}
|
|
336268
337976
|
if (value instanceof ShapeGroup) {
|
|
336269
337977
|
value.children.forEach((child, i) => {
|
|
336270
|
-
flattenGroupChild(
|
|
337978
|
+
flattenGroupChild(
|
|
337979
|
+
child,
|
|
337980
|
+
groupChildLabel(value, name, i),
|
|
337981
|
+
parentGroup,
|
|
337982
|
+
[...treePath, shapeGroupChildSegment(value, i)],
|
|
337983
|
+
mergeSceneTags(inheritedTags, value.tagsForChild(i))
|
|
337984
|
+
);
|
|
336271
337985
|
});
|
|
336272
337986
|
return;
|
|
336273
337987
|
}
|
|
336274
337988
|
if (value instanceof Shape$1) {
|
|
336275
|
-
pushShape(value, name, parentGroup, void 0, treePath);
|
|
337989
|
+
pushShape(value, name, parentGroup, void 0, treePath, inheritedTags);
|
|
336276
337990
|
return;
|
|
336277
337991
|
}
|
|
336278
337992
|
if (value instanceof Sketch) {
|
|
336279
|
-
pushSketch(value, name, parentGroup, treePath);
|
|
337993
|
+
pushSketch(value, name, parentGroup, treePath, inheritedTags);
|
|
336280
337994
|
return;
|
|
336281
337995
|
}
|
|
336282
337996
|
if (value instanceof SdfShape) {
|
|
336283
|
-
pushSdf(value, name, parentGroup, treePath);
|
|
337997
|
+
pushSdf(value, name, parentGroup, treePath, void 0, inheritedTags);
|
|
336284
337998
|
return;
|
|
336285
337999
|
}
|
|
336286
338000
|
if (value instanceof GCodeBuilder) {
|
|
@@ -336291,7 +338005,8 @@ function mapScriptResultToScene(args) {
|
|
|
336291
338005
|
sketch: null,
|
|
336292
338006
|
toolpath: value.build(),
|
|
336293
338007
|
geometryInfo: null,
|
|
336294
|
-
treePath
|
|
338008
|
+
treePath,
|
|
338009
|
+
...inheritedTags.length > 0 ? { tags: [...inheritedTags] } : {}
|
|
336295
338010
|
});
|
|
336296
338011
|
return;
|
|
336297
338012
|
}
|
|
@@ -336301,30 +338016,38 @@ function mapScriptResultToScene(args) {
|
|
|
336301
338016
|
value.forEach((item, index2) => {
|
|
336302
338017
|
const childSegment = `${index2 + 1}`;
|
|
336303
338018
|
const childLabel = `${name}.${childSegment}`;
|
|
336304
|
-
processRenderableTree(item, childLabel, childSegment, parentGroup, treePath, seen2);
|
|
338019
|
+
processRenderableTree(item, childLabel, childSegment, parentGroup, treePath, inheritedTags, seen2);
|
|
336305
338020
|
});
|
|
336306
338021
|
return;
|
|
336307
338022
|
}
|
|
336308
338023
|
if (isNamedObject(value)) {
|
|
336309
|
-
processNamedItem(value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath);
|
|
338024
|
+
processNamedItem(value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath, inheritedTags);
|
|
336310
338025
|
return;
|
|
336311
338026
|
}
|
|
336312
338027
|
if (isPlainObject2(value)) {
|
|
336313
338028
|
if (seen2.has(value)) return;
|
|
336314
338029
|
seen2.add(value);
|
|
336315
338030
|
Object.entries(value).forEach(([key, entry]) => {
|
|
336316
|
-
processRenderableTree(entry, key, key, parentGroup, treePath, seen2);
|
|
338031
|
+
processRenderableTree(entry, key, key, parentGroup, treePath, inheritedTags, seen2);
|
|
336317
338032
|
});
|
|
336318
338033
|
}
|
|
336319
338034
|
};
|
|
336320
|
-
const processNamedItem = (item, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = []) => {
|
|
338035
|
+
const processNamedItem = (item, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = [], inheritedTags = []) => {
|
|
338036
|
+
var _a4;
|
|
336321
338037
|
const name = typeof item.name === "string" && item.name.trim().length > 0 ? item.name : fallbackLabel;
|
|
336322
338038
|
const localSegment = typeof item.name === "string" && item.name.trim().length > 0 ? item.name : fallbackSegment;
|
|
336323
338039
|
const treePath = [...parentTreePath, localSegment];
|
|
336324
338040
|
const grp = parentGroup;
|
|
338041
|
+
const tags = mergeSceneTags(inheritedTags, (_a4 = item.metadata) == null ? void 0 : _a4.tags, item.tags);
|
|
336325
338042
|
if (item.group instanceof ShapeGroup) {
|
|
336326
338043
|
item.group.children.forEach((child, i) => {
|
|
336327
|
-
flattenGroupChild(
|
|
338044
|
+
flattenGroupChild(
|
|
338045
|
+
child,
|
|
338046
|
+
groupChildLabel(item.group, name, i),
|
|
338047
|
+
name,
|
|
338048
|
+
[...treePath, shapeGroupChildSegment(item.group, i)],
|
|
338049
|
+
mergeSceneTags(tags, item.group.tagsForChild(i))
|
|
338050
|
+
);
|
|
336328
338051
|
});
|
|
336329
338052
|
return;
|
|
336330
338053
|
}
|
|
@@ -336334,39 +338057,48 @@ function mapScriptResultToScene(args) {
|
|
|
336334
338057
|
const childTreePath = [...treePath, `${i + 1}`];
|
|
336335
338058
|
if (child instanceof ShapeGroup) {
|
|
336336
338059
|
child.children.forEach((nested, nestedIndex) => {
|
|
336337
|
-
flattenGroupChild(
|
|
336338
|
-
|
|
336339
|
-
|
|
336340
|
-
|
|
338060
|
+
flattenGroupChild(
|
|
338061
|
+
nested,
|
|
338062
|
+
groupChildLabel(child, name, nestedIndex),
|
|
338063
|
+
name,
|
|
338064
|
+
[...treePath, shapeGroupChildSegment(child, nestedIndex)],
|
|
338065
|
+
mergeSceneTags(tags, child.tagsForChild(nestedIndex))
|
|
338066
|
+
);
|
|
336341
338067
|
});
|
|
336342
338068
|
} else if (child instanceof Shape$1) {
|
|
336343
|
-
pushShape(child, childLabel, name, void 0, childTreePath);
|
|
338069
|
+
pushShape(child, childLabel, name, void 0, childTreePath, tags);
|
|
336344
338070
|
} else if (child instanceof Sketch) {
|
|
336345
|
-
pushSketch(child, childLabel, name, childTreePath);
|
|
338071
|
+
pushSketch(child, childLabel, name, childTreePath, tags);
|
|
336346
338072
|
} else if (child instanceof SdfShape) {
|
|
336347
|
-
pushSdf(child, childLabel, name, childTreePath);
|
|
338073
|
+
pushSdf(child, childLabel, name, childTreePath, void 0, tags);
|
|
336348
338074
|
} else if (isNamedObject(child)) {
|
|
336349
|
-
processNamedItem(child, childLabel, `${i + 1}`, name, treePath);
|
|
338075
|
+
processNamedItem(child, childLabel, `${i + 1}`, name, treePath, tags);
|
|
336350
338076
|
}
|
|
336351
338077
|
});
|
|
336352
338078
|
return;
|
|
336353
338079
|
}
|
|
336354
338080
|
if (item.shape instanceof ShapeGroup) {
|
|
336355
338081
|
item.shape.children.forEach(
|
|
336356
|
-
(child, i) => flattenGroupChild(
|
|
338082
|
+
(child, i) => flattenGroupChild(
|
|
338083
|
+
child,
|
|
338084
|
+
groupChildLabel(item.shape, name, i),
|
|
338085
|
+
name,
|
|
338086
|
+
[...treePath, shapeGroupChildSegment(item.shape, i)],
|
|
338087
|
+
mergeSceneTags(tags, item.shape.tagsForChild(i))
|
|
338088
|
+
)
|
|
336357
338089
|
);
|
|
336358
338090
|
return;
|
|
336359
338091
|
}
|
|
336360
338092
|
if (item.shape instanceof Shape$1) {
|
|
336361
|
-
pushShape(item.shape, name, grp, item.color, treePath);
|
|
338093
|
+
pushShape(item.shape, name, grp, item.color, treePath, tags);
|
|
336362
338094
|
return;
|
|
336363
338095
|
}
|
|
336364
338096
|
if (item.shape instanceof SdfShape) {
|
|
336365
|
-
pushSdf(item.shape, name, grp, treePath, item.color);
|
|
338097
|
+
pushSdf(item.shape, name, grp, treePath, item.color, tags);
|
|
336366
338098
|
return;
|
|
336367
338099
|
}
|
|
336368
338100
|
if (item.sdf instanceof SdfShape) {
|
|
336369
|
-
pushSdf(item.sdf, name, grp, treePath, item.color);
|
|
338101
|
+
pushSdf(item.sdf, name, grp, treePath, item.color, tags);
|
|
336370
338102
|
return;
|
|
336371
338103
|
}
|
|
336372
338104
|
if (item.sketch instanceof Sketch) {
|
|
@@ -336380,7 +338112,8 @@ function mapScriptResultToScene(args) {
|
|
|
336380
338112
|
sketchMeta: meta2,
|
|
336381
338113
|
color: item.color || item.sketch.colorHex,
|
|
336382
338114
|
groupName: grp,
|
|
336383
|
-
treePath
|
|
338115
|
+
treePath,
|
|
338116
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
336384
338117
|
});
|
|
336385
338118
|
}
|
|
336386
338119
|
};
|
|
@@ -336394,14 +338127,20 @@ function mapScriptResultToScene(args) {
|
|
|
336394
338127
|
} else if (result instanceof ShapeGroup) {
|
|
336395
338128
|
result.children.forEach((child, i) => {
|
|
336396
338129
|
const label = rootGroupChildLabel(result, i);
|
|
336397
|
-
flattenGroupChild(child, label, void 0, [label]);
|
|
338130
|
+
flattenGroupChild(child, label, void 0, [label], result.tagsForChild(i));
|
|
336398
338131
|
});
|
|
336399
338132
|
} else if (Array.isArray(result)) {
|
|
336400
338133
|
result.forEach((item, index2) => {
|
|
336401
338134
|
const label = `Object ${index2 + 1}`;
|
|
336402
338135
|
if (item instanceof ShapeGroup) {
|
|
336403
338136
|
item.children.forEach((child, i) => {
|
|
336404
|
-
flattenGroupChild(
|
|
338137
|
+
flattenGroupChild(
|
|
338138
|
+
child,
|
|
338139
|
+
groupChildLabel(item, label, i),
|
|
338140
|
+
void 0,
|
|
338141
|
+
[label, shapeGroupChildSegment(item, i)],
|
|
338142
|
+
item.tagsForChild(i)
|
|
338143
|
+
);
|
|
336405
338144
|
});
|
|
336406
338145
|
return;
|
|
336407
338146
|
}
|
|
@@ -336434,7 +338173,7 @@ function mapScriptResultToScene(args) {
|
|
|
336434
338173
|
} else if (defaultValue instanceof ShapeGroup) {
|
|
336435
338174
|
defaultValue.children.forEach((child, i) => {
|
|
336436
338175
|
const label = rootGroupChildLabel(defaultValue, i);
|
|
336437
|
-
flattenGroupChild(child, label, void 0, [label]);
|
|
338176
|
+
flattenGroupChild(child, label, void 0, [label], defaultValue.tagsForChild(i));
|
|
336438
338177
|
});
|
|
336439
338178
|
} else if (defaultValue instanceof Shape$1) {
|
|
336440
338179
|
pushShape(defaultValue, args.fileName, void 0, void 0, [args.fileName]);
|
|
@@ -336480,7 +338219,8 @@ function mapScriptResultToScene(args) {
|
|
|
336480
338219
|
name: `${mock2.name} (mock)`,
|
|
336481
338220
|
shape: mock2.shape,
|
|
336482
338221
|
sketch: null,
|
|
336483
|
-
mock: true
|
|
338222
|
+
mock: true,
|
|
338223
|
+
tags: ["mock"]
|
|
336484
338224
|
});
|
|
336485
338225
|
}
|
|
336486
338226
|
const hasSdfLeaves = objects.some((obj) => obj.sdf);
|