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
|
@@ -542,6 +542,47 @@ function cloneSdfFunctionConstants(constants) {
|
|
|
542
542
|
if (!constants) return void 0;
|
|
543
543
|
return Object.fromEntries(Object.entries(constants).map(([key, value]) => [key, cloneSdfFunctionConstant(value)]));
|
|
544
544
|
}
|
|
545
|
+
function cloneSdfSurfacePatternNode(pattern) {
|
|
546
|
+
switch (pattern.kind) {
|
|
547
|
+
case "surfacePattern:constant":
|
|
548
|
+
return { kind: "surfacePattern:constant", value: pattern.value };
|
|
549
|
+
case "surfacePattern:sineWave":
|
|
550
|
+
return {
|
|
551
|
+
kind: "surfacePattern:sineWave",
|
|
552
|
+
direction: [...pattern.direction],
|
|
553
|
+
wavelength: pattern.wavelength,
|
|
554
|
+
amplitude: pattern.amplitude,
|
|
555
|
+
phase: pattern.phase,
|
|
556
|
+
bias: pattern.bias
|
|
557
|
+
};
|
|
558
|
+
case "surfacePattern:stripes":
|
|
559
|
+
return {
|
|
560
|
+
kind: "surfacePattern:stripes",
|
|
561
|
+
direction: [...pattern.direction],
|
|
562
|
+
spacing: pattern.spacing,
|
|
563
|
+
width: pattern.width,
|
|
564
|
+
depth: pattern.depth
|
|
565
|
+
};
|
|
566
|
+
case "surfacePattern:overUnderWeave":
|
|
567
|
+
return {
|
|
568
|
+
kind: "surfacePattern:overUnderWeave",
|
|
569
|
+
spacing: [...pattern.spacing],
|
|
570
|
+
threadWidth: [...pattern.threadWidth],
|
|
571
|
+
depth: pattern.depth,
|
|
572
|
+
underScale: pattern.underScale
|
|
573
|
+
};
|
|
574
|
+
case "surfacePattern:abs":
|
|
575
|
+
case "surfacePattern:negate":
|
|
576
|
+
return { kind: pattern.kind, child: cloneSdfSurfacePatternNode(pattern.child) };
|
|
577
|
+
case "surfacePattern:add":
|
|
578
|
+
case "surfacePattern:multiply":
|
|
579
|
+
case "surfacePattern:min":
|
|
580
|
+
case "surfacePattern:max":
|
|
581
|
+
return { kind: pattern.kind, children: pattern.children.map(cloneSdfSurfacePatternNode) };
|
|
582
|
+
case "surfacePattern:clamp":
|
|
583
|
+
return { kind: "surfacePattern:clamp", child: cloneSdfSurfacePatternNode(pattern.child), min: pattern.min, max: pattern.max };
|
|
584
|
+
}
|
|
585
|
+
}
|
|
545
586
|
function cloneSdfNode(node) {
|
|
546
587
|
switch (node.kind) {
|
|
547
588
|
// Primitives — plain value types
|
|
@@ -592,6 +633,8 @@ function cloneSdfNode(node) {
|
|
|
592
633
|
return { kind: "sdf:bend", child: cloneSdfNode(node.child), radius: node.radius };
|
|
593
634
|
case "sdf:repeat":
|
|
594
635
|
return { kind: "sdf:repeat", child: cloneSdfNode(node.child), spacing: [...node.spacing], count: [...node.count] };
|
|
636
|
+
case "sdf:circularArray":
|
|
637
|
+
return { kind: "sdf:circularArray", child: cloneSdfNode(node.child), count: node.count, offset: node.offset };
|
|
595
638
|
case "sdf:shell":
|
|
596
639
|
return { kind: "sdf:shell", child: cloneSdfNode(node.child), thickness: node.thickness };
|
|
597
640
|
case "sdf:displace":
|
|
@@ -605,6 +648,7 @@ function cloneSdfNode(node) {
|
|
|
605
648
|
return {
|
|
606
649
|
kind: "sdf:surfaceDisplace",
|
|
607
650
|
child: cloneSdfNode(node.child),
|
|
651
|
+
...node.pattern ? { pattern: cloneSdfSurfacePatternNode(node.pattern) } : {},
|
|
608
652
|
patternBody: node.patternBody,
|
|
609
653
|
...node.constants ? { constants: cloneSdfFunctionConstants(node.constants) } : {},
|
|
610
654
|
...node.uvMode ? { uvMode: node.uvMode } : {},
|
|
@@ -4646,7 +4690,7 @@ for (var i = 0; i < 32; ++i)
|
|
|
4646
4690
|
fdt[i] = 5;
|
|
4647
4691
|
var flrm = /* @__PURE__ */ hMap(flt, 9, 1);
|
|
4648
4692
|
var fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);
|
|
4649
|
-
var max$
|
|
4693
|
+
var max$2 = function(a2) {
|
|
4650
4694
|
var m2 = a2[0];
|
|
4651
4695
|
for (var i = 1; i < a2.length; ++i) {
|
|
4652
4696
|
if (a2[i] > m2)
|
|
@@ -4746,7 +4790,7 @@ var inflt = function(dat, st, buf, dict) {
|
|
|
4746
4790
|
clt[clim[i]] = bits(dat, pos + i * 3, 7);
|
|
4747
4791
|
}
|
|
4748
4792
|
pos += hcLen * 3;
|
|
4749
|
-
var clb = max$
|
|
4793
|
+
var clb = max$2(clt), clbmsk = (1 << clb) - 1;
|
|
4750
4794
|
var clm = hMap(clt, clb, 1);
|
|
4751
4795
|
for (var i = 0; i < tl; ) {
|
|
4752
4796
|
var r = clm[bits(dat, pos, clbmsk)];
|
|
@@ -4767,8 +4811,8 @@ var inflt = function(dat, st, buf, dict) {
|
|
|
4767
4811
|
}
|
|
4768
4812
|
}
|
|
4769
4813
|
var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
|
|
4770
|
-
lbt = max$
|
|
4771
|
-
dbt = max$
|
|
4814
|
+
lbt = max$2(lt);
|
|
4815
|
+
dbt = max$2(dt);
|
|
4772
4816
|
lm = hMap(lt, lbt, 1);
|
|
4773
4817
|
dm = hMap(dt, dbt, 1);
|
|
4774
4818
|
} else
|
|
@@ -5125,8 +5169,8 @@ function parse3mf(data) {
|
|
|
5125
5169
|
while ((tMatch = trianglePattern.exec(meshXml)) !== null) {
|
|
5126
5170
|
const v1 = parseInt(tMatch[1], 10) + vertexOffset;
|
|
5127
5171
|
const v2 = parseInt(tMatch[2], 10) + vertexOffset;
|
|
5128
|
-
const
|
|
5129
|
-
allTriIndices.push(v1, v2,
|
|
5172
|
+
const v32 = parseInt(tMatch[3], 10) + vertexOffset;
|
|
5173
|
+
allTriIndices.push(v1, v2, v32);
|
|
5130
5174
|
}
|
|
5131
5175
|
for (let i = 0; i < meshVerts.length; i++) {
|
|
5132
5176
|
allPositions.push(meshVerts[i]);
|
|
@@ -5509,6 +5553,287 @@ function lowerShellShapeCompilePlanToConcretePlan(plan) {
|
|
|
5509
5553
|
}
|
|
5510
5554
|
return lowerBaseShellPlanToConcretePlan(plan.base, plan.thickness, normalizeShellOpenFaces(plan.openFaces));
|
|
5511
5555
|
}
|
|
5556
|
+
const DEFAULT_MAX_GRID_POINTS = 8e6;
|
|
5557
|
+
const DEFAULT_MIN_EDGE_LENGTH = 0.15;
|
|
5558
|
+
function resolveSdfMeshingSettings(tree, bounds, options = {}) {
|
|
5559
|
+
const quality = options.quality ?? "preview";
|
|
5560
|
+
const minEdgeLength = positiveOrDefault(options.minEdgeLength, DEFAULT_MIN_EDGE_LENGTH);
|
|
5561
|
+
const maxGridPoints = positiveOrDefault(options.maxGridPoints, DEFAULT_MAX_GRID_POINTS);
|
|
5562
|
+
const tolerance = options.tolerance !== void 0 ? requirePositiveFinite$3(options.tolerance, "SDF tolerance") : void 0;
|
|
5563
|
+
const minFeatureSize = options.minFeatureSize !== void 0 ? requirePositiveFinite$3(options.minFeatureSize, "SDF minFeatureSize") : void 0;
|
|
5564
|
+
const maxTriangles = options.maxTriangles !== void 0 ? Math.floor(requirePositiveFinite$3(options.maxTriangles, "SDF maxTriangles")) : void 0;
|
|
5565
|
+
const analysis = analyzeSdfTree(tree);
|
|
5566
|
+
const warnings = [];
|
|
5567
|
+
let edgeLength2;
|
|
5568
|
+
if (options.edgeLength !== void 0) {
|
|
5569
|
+
edgeLength2 = requirePositiveFinite$3(options.edgeLength, "SDF edgeLength");
|
|
5570
|
+
if (edgeLength2 < minEdgeLength) {
|
|
5571
|
+
warnings.push(`edgeLength ${formatMm(edgeLength2)} was clamped to minimum ${formatMm(minEdgeLength)}.`);
|
|
5572
|
+
edgeLength2 = minEdgeLength;
|
|
5573
|
+
}
|
|
5574
|
+
} else {
|
|
5575
|
+
edgeLength2 = resolveDefaultEdgeLength(bounds, quality, minEdgeLength, analysis, options);
|
|
5576
|
+
}
|
|
5577
|
+
if (analysis.minWallThickness < Infinity && analysis.minWallThickness < edgeLength2 * 2) {
|
|
5578
|
+
analysis.riskFlags.add("thin-shell");
|
|
5579
|
+
warnings.push(
|
|
5580
|
+
`shell/wall thickness ${formatMm(analysis.minWallThickness)} is below 2 x edgeLength ${formatMm(edgeLength2)}; thin features may be under-sampled.`
|
|
5581
|
+
);
|
|
5582
|
+
}
|
|
5583
|
+
if (!options.bounds && analysis.hasInfiniteRepeat) {
|
|
5584
|
+
warnings.push("infinite repeat bounds are heuristic; pass .toShape({ bounds }) for predictable clipping.");
|
|
5585
|
+
}
|
|
5586
|
+
if (!options.bounds && analysis.riskFlags.has("noise")) {
|
|
5587
|
+
warnings.push("noise field bounds are heuristic; pass .toShape({ bounds }) for predictable clipping.");
|
|
5588
|
+
}
|
|
5589
|
+
if (!options.bounds && (analysis.riskFlags.has("tpms") || analysis.riskFlags.has("voronoi"))) {
|
|
5590
|
+
warnings.push("TPMS/Voronoi bounds are heuristic unless clipped or passed explicitly.");
|
|
5591
|
+
}
|
|
5592
|
+
if (analysis.hasLegacyTpmsThreshold) {
|
|
5593
|
+
warnings.push("TPMS thickness is using legacy field-threshold units; use wallThickness for approximate millimeters.");
|
|
5594
|
+
}
|
|
5595
|
+
return {
|
|
5596
|
+
quality,
|
|
5597
|
+
edgeLength: edgeLength2,
|
|
5598
|
+
tolerance,
|
|
5599
|
+
minFeatureSize,
|
|
5600
|
+
minEdgeLength,
|
|
5601
|
+
simplify: resolveSimplificationMode(options.simplify, quality, analysis.riskFlags),
|
|
5602
|
+
maxTriangles,
|
|
5603
|
+
maxGridPoints,
|
|
5604
|
+
diagnostics: options.diagnostics === true,
|
|
5605
|
+
treeRiskFlags: [...analysis.riskFlags].sort(),
|
|
5606
|
+
warnings
|
|
5607
|
+
};
|
|
5608
|
+
}
|
|
5609
|
+
function withScaledSdfEdgeLength(settings, edgeLength2) {
|
|
5610
|
+
return { ...settings, edgeLength: Math.max(settings.minEdgeLength, edgeLength2) };
|
|
5611
|
+
}
|
|
5612
|
+
function createSdfMeshingDiagnostics(settings, bounds, paddedBounds) {
|
|
5613
|
+
const grid = estimateSdfGridDimensions(paddedBounds, settings.edgeLength);
|
|
5614
|
+
const estimatedSamples = grid[0] * grid[1] * grid[2];
|
|
5615
|
+
return {
|
|
5616
|
+
bounds: cloneBounds$2(bounds),
|
|
5617
|
+
paddedBounds: cloneBounds$2(paddedBounds),
|
|
5618
|
+
edgeLength: settings.edgeLength,
|
|
5619
|
+
grid,
|
|
5620
|
+
estimatedSamples,
|
|
5621
|
+
estimatedMemoryBytes: estimatedSamples * 8,
|
|
5622
|
+
treeRiskFlags: [...settings.treeRiskFlags],
|
|
5623
|
+
simplification: settings.simplify,
|
|
5624
|
+
capMode: "box",
|
|
5625
|
+
capInset: settings.edgeLength,
|
|
5626
|
+
warnings: [...settings.warnings]
|
|
5627
|
+
};
|
|
5628
|
+
}
|
|
5629
|
+
function assertSdfMeshingBudget(diagnostics, maxGridPoints) {
|
|
5630
|
+
if (diagnostics.estimatedSamples <= maxGridPoints) return;
|
|
5631
|
+
const suggestedEdge = suggestEdgeLengthForSampleBudget(diagnostics.paddedBounds, maxGridPoints);
|
|
5632
|
+
throw new Error(
|
|
5633
|
+
`SDF meshing would sample ${formatCount(diagnostics.estimatedSamples)} grid points (~${formatBytes(
|
|
5634
|
+
diagnostics.estimatedMemoryBytes
|
|
5635
|
+
)}). Reduce bounds or use edgeLength >= ${formatMm(suggestedEdge)}.`
|
|
5636
|
+
);
|
|
5637
|
+
}
|
|
5638
|
+
function estimateSdfGridDimensions(bounds, edgeLength2) {
|
|
5639
|
+
const dx = bounds.max[0] - bounds.min[0];
|
|
5640
|
+
const dy = bounds.max[1] - bounds.min[1];
|
|
5641
|
+
const dz = bounds.max[2] - bounds.min[2];
|
|
5642
|
+
return [
|
|
5643
|
+
Math.max(2, Math.ceil(dx / edgeLength2) + 1),
|
|
5644
|
+
Math.max(2, Math.ceil(dy / edgeLength2) + 1),
|
|
5645
|
+
Math.max(2, Math.ceil(dz / edgeLength2) + 1)
|
|
5646
|
+
];
|
|
5647
|
+
}
|
|
5648
|
+
function logSdfMeshingDiagnostics(prefix, diagnostics) {
|
|
5649
|
+
const warnings = diagnostics.warnings.length > 0 ? `, warnings=${diagnostics.warnings.join(" | ")}` : "";
|
|
5650
|
+
const evaluator = diagnostics.evaluator ? `, evaluator=${diagnostics.evaluator}${diagnostics.evaluatorUnsupportedReason ? ` (${diagnostics.evaluatorUnsupportedReason})` : ""}` : "";
|
|
5651
|
+
console.info(
|
|
5652
|
+
`${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}`
|
|
5653
|
+
);
|
|
5654
|
+
}
|
|
5655
|
+
function resolveDefaultEdgeLength(bounds, quality, minEdgeLength, analysis, options) {
|
|
5656
|
+
const dx = bounds.max[0] - bounds.min[0];
|
|
5657
|
+
const dy = bounds.max[1] - bounds.min[1];
|
|
5658
|
+
const dz = bounds.max[2] - bounds.min[2];
|
|
5659
|
+
const maxDim = Math.max(dx, dy, dz, minEdgeLength);
|
|
5660
|
+
const divisor = quality === "draft" ? 60 : quality === "export" ? 160 : 100;
|
|
5661
|
+
const candidates = [maxDim / divisor];
|
|
5662
|
+
if (options.tolerance !== void 0) candidates.push(requirePositiveFinite$3(options.tolerance, "SDF tolerance") * 2);
|
|
5663
|
+
if (options.minFeatureSize !== void 0) candidates.push(requirePositiveFinite$3(options.minFeatureSize, "SDF minFeatureSize") / 2.5);
|
|
5664
|
+
if (analysis.minMetricTpmsThickness < Infinity) candidates.push(analysis.minMetricTpmsThickness / 2);
|
|
5665
|
+
if (analysis.minTpmsCellSize < Infinity) candidates.push(analysis.minTpmsCellSize / 10);
|
|
5666
|
+
if (analysis.minRepeatSpacing < Infinity) candidates.push(analysis.minRepeatSpacing / 8);
|
|
5667
|
+
if (analysis.minWallThickness < Infinity) candidates.push(analysis.minWallThickness / 2.5);
|
|
5668
|
+
return Math.max(minEdgeLength, Math.min(...candidates.filter((v) => Number.isFinite(v) && v > 0)));
|
|
5669
|
+
}
|
|
5670
|
+
function resolveSimplificationMode(simplify, quality, riskFlags) {
|
|
5671
|
+
if (simplify === false) return "off";
|
|
5672
|
+
if (simplify === true || simplify === "safe") return "safe";
|
|
5673
|
+
if (quality === "export" && riskFlags.size > 0) return "off";
|
|
5674
|
+
return "safe";
|
|
5675
|
+
}
|
|
5676
|
+
function analyzeSdfTree(tree) {
|
|
5677
|
+
const analysis = {
|
|
5678
|
+
riskFlags: /* @__PURE__ */ new Set(),
|
|
5679
|
+
minTpmsCellSize: Infinity,
|
|
5680
|
+
minMetricTpmsThickness: Infinity,
|
|
5681
|
+
minRepeatSpacing: Infinity,
|
|
5682
|
+
minWallThickness: Infinity,
|
|
5683
|
+
hasInfiniteRepeat: false,
|
|
5684
|
+
hasLegacyTpmsThreshold: false
|
|
5685
|
+
};
|
|
5686
|
+
visitSdfNode(tree, analysis);
|
|
5687
|
+
return analysis;
|
|
5688
|
+
}
|
|
5689
|
+
function minPositive(...values) {
|
|
5690
|
+
let result = Infinity;
|
|
5691
|
+
for (const value of values) {
|
|
5692
|
+
if (value !== null && value !== void 0 && Number.isFinite(value) && value > 0) {
|
|
5693
|
+
result = Math.min(result, value);
|
|
5694
|
+
}
|
|
5695
|
+
}
|
|
5696
|
+
return result === Infinity ? null : result;
|
|
5697
|
+
}
|
|
5698
|
+
function estimateSurfacePatternSpacing(pattern) {
|
|
5699
|
+
switch (pattern.kind) {
|
|
5700
|
+
case "surfacePattern:constant":
|
|
5701
|
+
return null;
|
|
5702
|
+
case "surfacePattern:sineWave":
|
|
5703
|
+
return pattern.wavelength;
|
|
5704
|
+
case "surfacePattern:stripes":
|
|
5705
|
+
return Math.min(pattern.spacing, pattern.width);
|
|
5706
|
+
case "surfacePattern:overUnderWeave":
|
|
5707
|
+
return Math.min(...pattern.spacing, ...pattern.threadWidth);
|
|
5708
|
+
case "surfacePattern:abs":
|
|
5709
|
+
case "surfacePattern:negate":
|
|
5710
|
+
return estimateSurfacePatternSpacing(pattern.child);
|
|
5711
|
+
case "surfacePattern:add":
|
|
5712
|
+
case "surfacePattern:multiply":
|
|
5713
|
+
case "surfacePattern:min":
|
|
5714
|
+
case "surfacePattern:max":
|
|
5715
|
+
return minPositive(...pattern.children.map(estimateSurfacePatternSpacing));
|
|
5716
|
+
case "surfacePattern:clamp":
|
|
5717
|
+
return estimateSurfacePatternSpacing(pattern.child);
|
|
5718
|
+
}
|
|
5719
|
+
}
|
|
5720
|
+
function visitSdfNode(node, analysis) {
|
|
5721
|
+
switch (node.kind) {
|
|
5722
|
+
case "sdf:union":
|
|
5723
|
+
case "sdf:difference":
|
|
5724
|
+
case "sdf:intersection":
|
|
5725
|
+
case "sdf:smoothUnion":
|
|
5726
|
+
case "sdf:smoothDifference":
|
|
5727
|
+
case "sdf:smoothIntersection":
|
|
5728
|
+
for (const child of node.children) visitSdfNode(child, analysis);
|
|
5729
|
+
break;
|
|
5730
|
+
case "sdf:morph":
|
|
5731
|
+
case "sdf:spatialBlend":
|
|
5732
|
+
visitSdfNode(node.a, analysis);
|
|
5733
|
+
visitSdfNode(node.b, analysis);
|
|
5734
|
+
break;
|
|
5735
|
+
case "sdf:translate":
|
|
5736
|
+
case "sdf:rotate":
|
|
5737
|
+
case "sdf:scale":
|
|
5738
|
+
case "sdf:twist":
|
|
5739
|
+
case "sdf:bend":
|
|
5740
|
+
case "sdf:onion":
|
|
5741
|
+
visitSdfNode(node.child, analysis);
|
|
5742
|
+
break;
|
|
5743
|
+
case "sdf:repeat":
|
|
5744
|
+
analysis.riskFlags.add("repeat");
|
|
5745
|
+
for (let i = 0; i < 3; i++) {
|
|
5746
|
+
const spacing = node.spacing[i];
|
|
5747
|
+
if (spacing > 0) {
|
|
5748
|
+
analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, spacing);
|
|
5749
|
+
if (node.count[i] <= 0) analysis.hasInfiniteRepeat = true;
|
|
5750
|
+
}
|
|
5751
|
+
}
|
|
5752
|
+
visitSdfNode(node.child, analysis);
|
|
5753
|
+
break;
|
|
5754
|
+
case "sdf:circularArray": {
|
|
5755
|
+
analysis.riskFlags.add("repeat");
|
|
5756
|
+
if (node.offset > 0) {
|
|
5757
|
+
analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, 2 * Math.PI * node.offset / node.count);
|
|
5758
|
+
}
|
|
5759
|
+
visitSdfNode(node.child, analysis);
|
|
5760
|
+
break;
|
|
5761
|
+
}
|
|
5762
|
+
case "sdf:shell":
|
|
5763
|
+
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.thickness);
|
|
5764
|
+
visitSdfNode(node.child, analysis);
|
|
5765
|
+
break;
|
|
5766
|
+
case "sdf:displace":
|
|
5767
|
+
case "sdf:surfaceDisplace":
|
|
5768
|
+
analysis.riskFlags.add("displacement");
|
|
5769
|
+
if (node.kind === "sdf:surfaceDisplace" && node.pattern) {
|
|
5770
|
+
const spacing = estimateSurfacePatternSpacing(node.pattern);
|
|
5771
|
+
if (spacing !== null) analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, spacing);
|
|
5772
|
+
}
|
|
5773
|
+
visitSdfNode(node.child, analysis);
|
|
5774
|
+
break;
|
|
5775
|
+
case "sdf:gyroid":
|
|
5776
|
+
case "sdf:schwarzP":
|
|
5777
|
+
case "sdf:diamond":
|
|
5778
|
+
case "sdf:lidinoid":
|
|
5779
|
+
analysis.riskFlags.add("tpms");
|
|
5780
|
+
analysis.minTpmsCellSize = Math.min(analysis.minTpmsCellSize, node.cellSize);
|
|
5781
|
+
if (node.thicknessMode === "metric-approx") {
|
|
5782
|
+
analysis.minMetricTpmsThickness = Math.min(analysis.minMetricTpmsThickness, node.thickness);
|
|
5783
|
+
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.thickness);
|
|
5784
|
+
} else {
|
|
5785
|
+
analysis.hasLegacyTpmsThreshold = true;
|
|
5786
|
+
}
|
|
5787
|
+
break;
|
|
5788
|
+
case "sdf:noise":
|
|
5789
|
+
analysis.riskFlags.add("noise");
|
|
5790
|
+
break;
|
|
5791
|
+
case "sdf:voronoi":
|
|
5792
|
+
analysis.riskFlags.add("voronoi");
|
|
5793
|
+
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.wallThickness);
|
|
5794
|
+
if (node.surfaceChild) visitSdfNode(node.surfaceChild, analysis);
|
|
5795
|
+
break;
|
|
5796
|
+
case "sdf:custom":
|
|
5797
|
+
analysis.riskFlags.add("custom");
|
|
5798
|
+
break;
|
|
5799
|
+
}
|
|
5800
|
+
}
|
|
5801
|
+
function positiveOrDefault(value, fallback) {
|
|
5802
|
+
if (value === void 0) return fallback;
|
|
5803
|
+
return requirePositiveFinite$3(value, "SDF meshing option");
|
|
5804
|
+
}
|
|
5805
|
+
function requirePositiveFinite$3(value, name) {
|
|
5806
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
5807
|
+
throw new Error(`${name} must be a positive finite number.`);
|
|
5808
|
+
}
|
|
5809
|
+
return value;
|
|
5810
|
+
}
|
|
5811
|
+
function cloneBounds$2(bounds) {
|
|
5812
|
+
return { min: [...bounds.min], max: [...bounds.max] };
|
|
5813
|
+
}
|
|
5814
|
+
function suggestEdgeLengthForSampleBudget(bounds, maxGridPoints) {
|
|
5815
|
+
const dx = bounds.max[0] - bounds.min[0];
|
|
5816
|
+
const dy = bounds.max[1] - bounds.min[1];
|
|
5817
|
+
const dz = bounds.max[2] - bounds.min[2];
|
|
5818
|
+
const volume = Math.max(dx * dy * dz, 1);
|
|
5819
|
+
return Math.cbrt(volume / Math.max(maxGridPoints, 8));
|
|
5820
|
+
}
|
|
5821
|
+
function formatBounds(bounds) {
|
|
5822
|
+
return `[${bounds.min.map(formatNumber$1).join(",")}]-[${bounds.max.map(formatNumber$1).join(",")}]`;
|
|
5823
|
+
}
|
|
5824
|
+
function formatMm(value) {
|
|
5825
|
+
return `${formatNumber$1(value)}mm`;
|
|
5826
|
+
}
|
|
5827
|
+
function formatNumber$1(value) {
|
|
5828
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(3).replace(/0+$/, "").replace(/\.$/, "");
|
|
5829
|
+
}
|
|
5830
|
+
function formatCount(value) {
|
|
5831
|
+
return Math.round(value).toLocaleString("en-US");
|
|
5832
|
+
}
|
|
5833
|
+
function formatBytes(bytes) {
|
|
5834
|
+
if (bytes < 1024 * 1024) return `${Math.ceil(bytes / 1024)} KB`;
|
|
5835
|
+
return `${Math.ceil(bytes / (1024 * 1024))} MB`;
|
|
5836
|
+
}
|
|
5512
5837
|
const grad3 = new Float64Array([
|
|
5513
5838
|
1,
|
|
5514
5839
|
1,
|
|
@@ -5969,8 +6294,8 @@ function triplanarWeights(nx, ny, nz, sharpness) {
|
|
|
5969
6294
|
const inv = 1 / sum2;
|
|
5970
6295
|
return { wx: wx * inv, wy: wy * inv, wz: wz * inv };
|
|
5971
6296
|
}
|
|
5972
|
-
const { atan2, acos, cos: cos$
|
|
5973
|
-
const DEG$
|
|
6297
|
+
const { atan2, acos, cos: cos$3, sin: sin$3, sqrt: sqrt$3, PI: PI$3 } = Math;
|
|
6298
|
+
const DEG$3 = PI$3 / 180;
|
|
5974
6299
|
const IDENTITY = (p2) => p2;
|
|
5975
6300
|
function analyzeUV(node, override) {
|
|
5976
6301
|
if (override) {
|
|
@@ -5997,10 +6322,10 @@ function analyzeNodeUV(node, toLocal) {
|
|
|
5997
6322
|
return analyzeNodeUV(node.child, next);
|
|
5998
6323
|
}
|
|
5999
6324
|
case "sdf:rotate": {
|
|
6000
|
-
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$
|
|
6001
|
-
const cx = cos$
|
|
6002
|
-
const cy = cos$
|
|
6003
|
-
const cz = cos$
|
|
6325
|
+
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$3);
|
|
6326
|
+
const cx = cos$3(rx), sx = sin$3(rx);
|
|
6327
|
+
const cy = cos$3(ry), sy = sin$3(ry);
|
|
6328
|
+
const cz = cos$3(rz), sz = sin$3(rz);
|
|
6004
6329
|
const prev = toLocal;
|
|
6005
6330
|
const next = (p2) => {
|
|
6006
6331
|
const pp = prev(p2);
|
|
@@ -6057,7 +6382,7 @@ function compileUVFunction(analysis) {
|
|
|
6057
6382
|
return (p2) => {
|
|
6058
6383
|
const lp = toLocal(p2);
|
|
6059
6384
|
const u2 = atan2(lp[1], lp[0]) * R;
|
|
6060
|
-
const len2 = sqrt$
|
|
6385
|
+
const len2 = sqrt$3(lp[0] * lp[0] + lp[1] * lp[1] + lp[2] * lp[2]);
|
|
6061
6386
|
const v = acos(clampUnit(lp[2] / (len2 || 1))) * R;
|
|
6062
6387
|
return [u2, v];
|
|
6063
6388
|
};
|
|
@@ -6077,23 +6402,23 @@ function compileUVFunction(analysis) {
|
|
|
6077
6402
|
return (p2) => {
|
|
6078
6403
|
const lp = toLocal(p2);
|
|
6079
6404
|
const u2 = atan2(lp[1], lp[0]) * R;
|
|
6080
|
-
const xyDist = sqrt$
|
|
6405
|
+
const xyDist = sqrt$3(lp[0] * lp[0] + lp[1] * lp[1]) - R;
|
|
6081
6406
|
const v = atan2(lp[2], xyDist) * r;
|
|
6082
6407
|
return [u2, v];
|
|
6083
6408
|
};
|
|
6084
6409
|
}
|
|
6085
6410
|
}
|
|
6086
6411
|
}
|
|
6087
|
-
const { abs: abs$1, cos: cos$
|
|
6088
|
-
const TAU = 2 * PI$
|
|
6089
|
-
const GRAD_EPS = 1e-9;
|
|
6412
|
+
const { abs: abs$1, cos: cos$2, sin: sin$2, sqrt: sqrt$2, PI: PI$2 } = Math;
|
|
6413
|
+
const TAU$1 = 2 * PI$2;
|
|
6414
|
+
const GRAD_EPS$1 = 1e-9;
|
|
6090
6415
|
function gyroidValueAndGradient(x2, y2, z2, cellSize) {
|
|
6091
|
-
const s = TAU / cellSize;
|
|
6416
|
+
const s = TAU$1 / cellSize;
|
|
6092
6417
|
const xs = x2 * s;
|
|
6093
6418
|
const ys = y2 * s;
|
|
6094
6419
|
const zs = z2 * s;
|
|
6095
|
-
const sx = sin$
|
|
6096
|
-
const cx = cos$
|
|
6420
|
+
const sx = sin$2(xs), sy = sin$2(ys), sz = sin$2(zs);
|
|
6421
|
+
const cx = cos$2(xs), cy = cos$2(ys), cz = cos$2(zs);
|
|
6097
6422
|
return {
|
|
6098
6423
|
value: sx * cy + sy * cz + sz * cx,
|
|
6099
6424
|
gx: s * (cx * cy - sz * sx),
|
|
@@ -6102,24 +6427,24 @@ function gyroidValueAndGradient(x2, y2, z2, cellSize) {
|
|
|
6102
6427
|
};
|
|
6103
6428
|
}
|
|
6104
6429
|
function schwarzPValueAndGradient(x2, y2, z2, cellSize) {
|
|
6105
|
-
const s = TAU / cellSize;
|
|
6430
|
+
const s = TAU$1 / cellSize;
|
|
6106
6431
|
const xs = x2 * s;
|
|
6107
6432
|
const ys = y2 * s;
|
|
6108
6433
|
const zs = z2 * s;
|
|
6109
6434
|
return {
|
|
6110
|
-
value: cos$
|
|
6111
|
-
gx: -s * sin$
|
|
6112
|
-
gy: -s * sin$
|
|
6113
|
-
gz: -s * sin$
|
|
6435
|
+
value: cos$2(xs) + cos$2(ys) + cos$2(zs),
|
|
6436
|
+
gx: -s * sin$2(xs),
|
|
6437
|
+
gy: -s * sin$2(ys),
|
|
6438
|
+
gz: -s * sin$2(zs)
|
|
6114
6439
|
};
|
|
6115
6440
|
}
|
|
6116
6441
|
function diamondValueAndGradient(x2, y2, z2, cellSize) {
|
|
6117
|
-
const s = TAU / cellSize;
|
|
6442
|
+
const s = TAU$1 / cellSize;
|
|
6118
6443
|
const xs = x2 * s;
|
|
6119
6444
|
const ys = y2 * s;
|
|
6120
6445
|
const zs = z2 * s;
|
|
6121
|
-
const sx = sin$
|
|
6122
|
-
const cx = cos$
|
|
6446
|
+
const sx = sin$2(xs), sy = sin$2(ys), sz = sin$2(zs);
|
|
6447
|
+
const cx = cos$2(xs), cy = cos$2(ys), cz = cos$2(zs);
|
|
6123
6448
|
return {
|
|
6124
6449
|
value: sx * sy * sz + sx * cy * cz + cx * sy * cz + cx * cy * sz,
|
|
6125
6450
|
gx: s * (cx * sy * sz + cx * cy * cz - sx * sy * cz - sx * cy * sz),
|
|
@@ -6128,12 +6453,12 @@ function diamondValueAndGradient(x2, y2, z2, cellSize) {
|
|
|
6128
6453
|
};
|
|
6129
6454
|
}
|
|
6130
6455
|
function lidinoidValueAndGradient(x2, y2, z2, cellSize) {
|
|
6131
|
-
const s = TAU / cellSize;
|
|
6456
|
+
const s = TAU$1 / cellSize;
|
|
6132
6457
|
const sx2 = x2 * s, sy2 = y2 * s, sz2 = z2 * s;
|
|
6133
|
-
const sx = sin$
|
|
6134
|
-
const cx = cos$
|
|
6135
|
-
const s2x = sin$
|
|
6136
|
-
const c2x = cos$
|
|
6458
|
+
const sx = sin$2(sx2), sy = sin$2(sy2), sz = sin$2(sz2);
|
|
6459
|
+
const cx = cos$2(sx2), cy = cos$2(sy2), cz = cos$2(sz2);
|
|
6460
|
+
const s2x = sin$2(2 * sx2), s2y = sin$2(2 * sy2), s2z = sin$2(2 * sz2);
|
|
6461
|
+
const c2x = cos$2(2 * sx2), c2y = cos$2(2 * sy2), c2z = cos$2(2 * sz2);
|
|
6137
6462
|
const val = s2x * cy * sz + s2y * cz * sx + s2z * cx * sy - c2x * c2y - c2y * c2z - c2z * c2x + 0.3;
|
|
6138
6463
|
return {
|
|
6139
6464
|
value: val,
|
|
@@ -6156,8 +6481,8 @@ function lidinoid$1(x2, y2, z2, cellSize, thickness, thicknessMode) {
|
|
|
6156
6481
|
}
|
|
6157
6482
|
function tpmsDistance({ value, gx, gy, gz }, thickness, thicknessMode) {
|
|
6158
6483
|
if (thicknessMode !== "metric-approx") return abs$1(value) - thickness;
|
|
6159
|
-
const grad = sqrt$
|
|
6160
|
-
return abs$1(value) / Math.max(grad, GRAD_EPS) - thickness * 0.5;
|
|
6484
|
+
const grad = sqrt$2(gx * gx + gy * gy + gz * gz);
|
|
6485
|
+
return abs$1(value) / Math.max(grad, GRAD_EPS$1) - thickness * 0.5;
|
|
6161
6486
|
}
|
|
6162
6487
|
function mix(h) {
|
|
6163
6488
|
h = (h ^ h >>> 16) * 2246822507 | 0;
|
|
@@ -6253,76 +6578,76 @@ function seededWorley3Surface(seed) {
|
|
|
6253
6578
|
const s = seed | 0;
|
|
6254
6579
|
return (x2, y2, z2, nx, ny, nz, threshold) => worleySurface(x2, y2, z2, s, nx, ny, nz, threshold);
|
|
6255
6580
|
}
|
|
6256
|
-
const { abs, cos, max, min, sin, sqrt, PI } = Math;
|
|
6257
|
-
const DEG$
|
|
6581
|
+
const { abs, cos: cos$1, max: max$1, min, sin: sin$1, sqrt: sqrt$1, PI: PI$1 } = Math;
|
|
6582
|
+
const DEG$2 = PI$1 / 180;
|
|
6258
6583
|
function clamp$b(v, lo, hi) {
|
|
6259
6584
|
return v < lo ? lo : v > hi ? hi : v;
|
|
6260
6585
|
}
|
|
6261
|
-
function length2(x2, y2) {
|
|
6262
|
-
return sqrt(x2 * x2 + y2 * y2);
|
|
6586
|
+
function length2$1(x2, y2) {
|
|
6587
|
+
return sqrt$1(x2 * x2 + y2 * y2);
|
|
6263
6588
|
}
|
|
6264
|
-
function length3(x2, y2, z2) {
|
|
6265
|
-
return sqrt(x2 * x2 + y2 * y2 + z2 * z2);
|
|
6589
|
+
function length3$1(x2, y2, z2) {
|
|
6590
|
+
return sqrt$1(x2 * x2 + y2 * y2 + z2 * z2);
|
|
6266
6591
|
}
|
|
6267
|
-
function sdSphere(px, py, pz, r) {
|
|
6268
|
-
return length3(px, py, pz) - r;
|
|
6592
|
+
function sdSphere$1(px, py, pz, r) {
|
|
6593
|
+
return length3$1(px, py, pz) - r;
|
|
6269
6594
|
}
|
|
6270
|
-
function sdBox(px, py, pz, hx, hy, hz) {
|
|
6595
|
+
function sdBox$1(px, py, pz, hx, hy, hz) {
|
|
6271
6596
|
const dx = abs(px) - hx;
|
|
6272
6597
|
const dy = abs(py) - hy;
|
|
6273
6598
|
const dz = abs(pz) - hz;
|
|
6274
|
-
return length3(max(dx, 0), max(dy, 0), max(dz, 0)) + min(max(dx, dy, dz), 0);
|
|
6599
|
+
return length3$1(max$1(dx, 0), max$1(dy, 0), max$1(dz, 0)) + min(max$1(dx, dy, dz), 0);
|
|
6275
6600
|
}
|
|
6276
|
-
function sdCylinder(px, py, pz, h, r) {
|
|
6277
|
-
const dx = length2(px, py) - r;
|
|
6601
|
+
function sdCylinder$1(px, py, pz, h, r) {
|
|
6602
|
+
const dx = length2$1(px, py) - r;
|
|
6278
6603
|
const dz = abs(pz) - h * 0.5;
|
|
6279
|
-
return length2(max(dx, 0), max(dz, 0)) + min(max(dx, dz), 0);
|
|
6604
|
+
return length2$1(max$1(dx, 0), max$1(dz, 0)) + min(max$1(dx, dz), 0);
|
|
6280
6605
|
}
|
|
6281
|
-
function sdTorus(px, py, pz, R, r) {
|
|
6282
|
-
const qx = length2(px, py) - R;
|
|
6283
|
-
return length2(qx, pz) - r;
|
|
6606
|
+
function sdTorus$1(px, py, pz, R, r) {
|
|
6607
|
+
const qx = length2$1(px, py) - R;
|
|
6608
|
+
return length2$1(qx, pz) - r;
|
|
6284
6609
|
}
|
|
6285
|
-
function sdCapsule(px, py, pz, h, r) {
|
|
6610
|
+
function sdCapsule$1(px, py, pz, h, r) {
|
|
6286
6611
|
const halfH = h * 0.5;
|
|
6287
6612
|
const cz = clamp$b(pz, -halfH, halfH);
|
|
6288
|
-
return length3(px, py, pz - cz) - r;
|
|
6613
|
+
return length3$1(px, py, pz - cz) - r;
|
|
6289
6614
|
}
|
|
6290
|
-
function sdCone(px, py, pz, h, r) {
|
|
6291
|
-
const q = length2(px, py);
|
|
6292
|
-
const cLen = length2(h, r);
|
|
6615
|
+
function sdCone$1(px, py, pz, h, r) {
|
|
6616
|
+
const q = length2$1(px, py);
|
|
6617
|
+
const cLen = length2$1(h, r);
|
|
6293
6618
|
const nx = h / cLen;
|
|
6294
6619
|
const nz = -r / cLen;
|
|
6295
|
-
const d2 = max(nx * q + nz * (pz - h), -pz, pz - h);
|
|
6620
|
+
const d2 = max$1(nx * q + nz * (pz - h), -pz, pz - h);
|
|
6296
6621
|
return d2;
|
|
6297
6622
|
}
|
|
6298
|
-
function sdTaperedSegment(px, py, pz, ax, ay, az, bx, by, bz, ra, rb) {
|
|
6623
|
+
function sdTaperedSegment$1(px, py, pz, ax, ay, az, bx, by, bz, ra, rb) {
|
|
6299
6624
|
const vx = bx - ax;
|
|
6300
6625
|
const vy = by - ay;
|
|
6301
6626
|
const vz = bz - az;
|
|
6302
6627
|
const len2 = vx * vx + vy * vy + vz * vz;
|
|
6303
|
-
if (len2 <= 1e-12) return sdSphere(px - ax, py - ay, pz - az, max(ra, rb));
|
|
6628
|
+
if (len2 <= 1e-12) return sdSphere$1(px - ax, py - ay, pz - az, max$1(ra, rb));
|
|
6304
6629
|
const h = clamp$b(((px - ax) * vx + (py - ay) * vy + (pz - az) * vz) / len2, 0, 1);
|
|
6305
|
-
return length3(px - (ax + vx * h), py - (ay + vy * h), pz - (az + vz * h)) - (ra + (rb - ra) * h);
|
|
6630
|
+
return length3$1(px - (ax + vx * h), py - (ay + vy * h), pz - (az + vz * h)) - (ra + (rb - ra) * h);
|
|
6306
6631
|
}
|
|
6307
6632
|
function sdPolylineSweep3(node, x2, y2, z2) {
|
|
6308
6633
|
let d2 = 1e20;
|
|
6309
6634
|
for (let i = 0; i < node.points.length - 1; i++) {
|
|
6310
6635
|
const a2 = node.points[i];
|
|
6311
6636
|
const b = node.points[i + 1];
|
|
6312
|
-
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]);
|
|
6313
|
-
d2 = i === 0 ? segment : smin(d2, segment, node.blend);
|
|
6637
|
+
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]);
|
|
6638
|
+
d2 = i === 0 ? segment : smin$1(d2, segment, node.blend);
|
|
6314
6639
|
}
|
|
6315
6640
|
return d2;
|
|
6316
6641
|
}
|
|
6317
|
-
function smin(a2, b, k2) {
|
|
6642
|
+
function smin$1(a2, b, k2) {
|
|
6318
6643
|
if (k2 <= 0) return min(a2, b);
|
|
6319
|
-
const h = max(k2 - abs(a2 - b), 0) / k2;
|
|
6644
|
+
const h = max$1(k2 - abs(a2 - b), 0) / k2;
|
|
6320
6645
|
return min(a2, b) - h * h * h * k2 * (1 / 6);
|
|
6321
6646
|
}
|
|
6322
|
-
function smax(a2, b, k2) {
|
|
6323
|
-
return -smin(-a2, -b, k2);
|
|
6647
|
+
function smax$1(a2, b, k2) {
|
|
6648
|
+
return -smin$1(-a2, -b, k2);
|
|
6324
6649
|
}
|
|
6325
|
-
function repeatCoord(v, spacing, count) {
|
|
6650
|
+
function repeatCoord$1(v, spacing, count) {
|
|
6326
6651
|
if (spacing <= 0) return v;
|
|
6327
6652
|
if (count > 0) {
|
|
6328
6653
|
const center = (count - 1) * 0.5;
|
|
@@ -6331,31 +6656,138 @@ function repeatCoord(v, spacing, count) {
|
|
|
6331
6656
|
}
|
|
6332
6657
|
return v - spacing * Math.round(v / spacing);
|
|
6333
6658
|
}
|
|
6659
|
+
function positiveMod(v, period) {
|
|
6660
|
+
return (v % period + period) % period;
|
|
6661
|
+
}
|
|
6662
|
+
function evalStripesPattern(u2, v, directionX, directionY, spacing, width, depth) {
|
|
6663
|
+
const coord = u2 * directionX + v * directionY;
|
|
6664
|
+
const d2 = abs(coord - Math.round(coord / spacing) * spacing);
|
|
6665
|
+
const profile = max$1(0, 1 - d2 / (width * 0.5));
|
|
6666
|
+
return -(profile * profile) * depth;
|
|
6667
|
+
}
|
|
6668
|
+
function evalOverUnderWeavePattern(u2, v, spacingX, spacingY, widthX, widthY, depth, underScale) {
|
|
6669
|
+
const su = u2 / spacingX;
|
|
6670
|
+
const sv = v / spacingY;
|
|
6671
|
+
let pU = max$1(0, 1 - abs(su - Math.round(su)) * spacingX / (widthX * 0.5));
|
|
6672
|
+
let pV = max$1(0, 1 - abs(sv - Math.round(sv)) * spacingY / (widthY * 0.5));
|
|
6673
|
+
pU *= pU;
|
|
6674
|
+
pV *= pV;
|
|
6675
|
+
const checker = (Math.round(su) & 65535) + (Math.round(sv) & 65535) & 1;
|
|
6676
|
+
const top = checker ? pV : pU;
|
|
6677
|
+
const bot = checker ? pU : pV;
|
|
6678
|
+
return -max$1(top, bot * underScale) * depth;
|
|
6679
|
+
}
|
|
6680
|
+
function compileTypedSurfacePattern(pattern) {
|
|
6681
|
+
switch (pattern.kind) {
|
|
6682
|
+
case "surfacePattern:constant":
|
|
6683
|
+
return () => pattern.value;
|
|
6684
|
+
case "surfacePattern:sineWave": {
|
|
6685
|
+
const { direction: direction2, wavelength, amplitude, phase, bias } = pattern;
|
|
6686
|
+
const frequency = 2 * PI$1 / wavelength;
|
|
6687
|
+
return (u2, v) => bias + sin$1((u2 * direction2[0] + v * direction2[1]) * frequency + phase) * amplitude;
|
|
6688
|
+
}
|
|
6689
|
+
case "surfacePattern:stripes": {
|
|
6690
|
+
const { direction: direction2, spacing, width, depth } = pattern;
|
|
6691
|
+
return (u2, v) => evalStripesPattern(u2, v, direction2[0], direction2[1], spacing, width, depth);
|
|
6692
|
+
}
|
|
6693
|
+
case "surfacePattern:overUnderWeave": {
|
|
6694
|
+
const { spacing, threadWidth, depth, underScale } = pattern;
|
|
6695
|
+
return (u2, v) => evalOverUnderWeavePattern(u2, v, spacing[0], spacing[1], threadWidth[0], threadWidth[1], depth, underScale);
|
|
6696
|
+
}
|
|
6697
|
+
case "surfacePattern:abs": {
|
|
6698
|
+
const child = compileTypedSurfacePattern(pattern.child);
|
|
6699
|
+
return (u2, v) => abs(child(u2, v));
|
|
6700
|
+
}
|
|
6701
|
+
case "surfacePattern:negate": {
|
|
6702
|
+
const child = compileTypedSurfacePattern(pattern.child);
|
|
6703
|
+
return (u2, v) => -child(u2, v);
|
|
6704
|
+
}
|
|
6705
|
+
case "surfacePattern:add": {
|
|
6706
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
6707
|
+
return (u2, v) => children.reduce((sum2, child) => sum2 + child(u2, v), 0);
|
|
6708
|
+
}
|
|
6709
|
+
case "surfacePattern:multiply": {
|
|
6710
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
6711
|
+
return (u2, v) => children.reduce((product, child) => product * child(u2, v), 1);
|
|
6712
|
+
}
|
|
6713
|
+
case "surfacePattern:min": {
|
|
6714
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
6715
|
+
if (children.length === 0) return () => 0;
|
|
6716
|
+
return (u2, v) => children.reduce((value, child) => min(value, child(u2, v)), Infinity);
|
|
6717
|
+
}
|
|
6718
|
+
case "surfacePattern:max": {
|
|
6719
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
6720
|
+
if (children.length === 0) return () => 0;
|
|
6721
|
+
return (u2, v) => children.reduce((value, child) => max$1(value, child(u2, v)), -Infinity);
|
|
6722
|
+
}
|
|
6723
|
+
case "surfacePattern:clamp": {
|
|
6724
|
+
const child = compileTypedSurfacePattern(pattern.child);
|
|
6725
|
+
return (u2, v) => clamp$b(child(u2, v), pattern.min, pattern.max);
|
|
6726
|
+
}
|
|
6727
|
+
}
|
|
6728
|
+
}
|
|
6729
|
+
function estimateSurfacePatternAmplitude(pattern) {
|
|
6730
|
+
switch (pattern.kind) {
|
|
6731
|
+
case "surfacePattern:constant":
|
|
6732
|
+
return abs(pattern.value);
|
|
6733
|
+
case "surfacePattern:sineWave":
|
|
6734
|
+
return abs(pattern.bias) + abs(pattern.amplitude);
|
|
6735
|
+
case "surfacePattern:stripes":
|
|
6736
|
+
case "surfacePattern:overUnderWeave":
|
|
6737
|
+
return pattern.depth;
|
|
6738
|
+
case "surfacePattern:abs":
|
|
6739
|
+
case "surfacePattern:negate":
|
|
6740
|
+
return estimateSurfacePatternAmplitude(pattern.child);
|
|
6741
|
+
case "surfacePattern:add": {
|
|
6742
|
+
const amplitudes = pattern.children.map(estimateSurfacePatternAmplitude);
|
|
6743
|
+
return amplitudes.every((value) => value !== null) ? amplitudes.reduce((sum2, value) => sum2 + value, 0) : null;
|
|
6744
|
+
}
|
|
6745
|
+
case "surfacePattern:multiply": {
|
|
6746
|
+
const amplitudes = pattern.children.map(estimateSurfacePatternAmplitude);
|
|
6747
|
+
return amplitudes.every((value) => value !== null) ? amplitudes.reduce((product, value) => product * value, 1) : null;
|
|
6748
|
+
}
|
|
6749
|
+
case "surfacePattern:min":
|
|
6750
|
+
case "surfacePattern:max": {
|
|
6751
|
+
const amplitudes = pattern.children.map(estimateSurfacePatternAmplitude);
|
|
6752
|
+
return amplitudes.every((value) => value !== null) ? max$1(...amplitudes) : null;
|
|
6753
|
+
}
|
|
6754
|
+
case "surfacePattern:clamp":
|
|
6755
|
+
return max$1(abs(pattern.min), abs(pattern.max));
|
|
6756
|
+
}
|
|
6757
|
+
}
|
|
6758
|
+
function compileSurfacePattern(node) {
|
|
6759
|
+
if (node.pattern) return compileTypedSurfacePattern(node.pattern);
|
|
6760
|
+
const constEntries = Object.entries(node.constants ?? {});
|
|
6761
|
+
const constNames = constEntries.map(([k2]) => k2);
|
|
6762
|
+
const constValues = constEntries.map(([, v]) => v);
|
|
6763
|
+
const patternFn = new Function("u", "v", ...constNames, `return (${node.patternBody});`);
|
|
6764
|
+
return (u2, v) => patternFn(u2, v, ...constValues);
|
|
6765
|
+
}
|
|
6334
6766
|
function compileSdfNode3(node) {
|
|
6335
6767
|
switch (node.kind) {
|
|
6336
6768
|
case "sdf:sphere": {
|
|
6337
6769
|
const r = node.radius;
|
|
6338
|
-
return (x2, y2, z2) => sdSphere(x2, y2, z2, r);
|
|
6770
|
+
return (x2, y2, z2) => sdSphere$1(x2, y2, z2, r);
|
|
6339
6771
|
}
|
|
6340
6772
|
case "sdf:box": {
|
|
6341
6773
|
const [hx, hy, hz] = node.halfExtents;
|
|
6342
|
-
return (x2, y2, z2) => sdBox(x2, y2, z2, hx, hy, hz);
|
|
6774
|
+
return (x2, y2, z2) => sdBox$1(x2, y2, z2, hx, hy, hz);
|
|
6343
6775
|
}
|
|
6344
6776
|
case "sdf:cylinder": {
|
|
6345
6777
|
const { height: h, radius: r } = node;
|
|
6346
|
-
return (x2, y2, z2) => sdCylinder(x2, y2, z2, h, r);
|
|
6778
|
+
return (x2, y2, z2) => sdCylinder$1(x2, y2, z2, h, r);
|
|
6347
6779
|
}
|
|
6348
6780
|
case "sdf:torus": {
|
|
6349
6781
|
const { majorRadius: R, minorRadius: r } = node;
|
|
6350
|
-
return (x2, y2, z2) => sdTorus(x2, y2, z2, R, r);
|
|
6782
|
+
return (x2, y2, z2) => sdTorus$1(x2, y2, z2, R, r);
|
|
6351
6783
|
}
|
|
6352
6784
|
case "sdf:capsule": {
|
|
6353
6785
|
const { height: h, radius: r } = node;
|
|
6354
|
-
return (x2, y2, z2) => sdCapsule(x2, y2, z2, h, r);
|
|
6786
|
+
return (x2, y2, z2) => sdCapsule$1(x2, y2, z2, h, r);
|
|
6355
6787
|
}
|
|
6356
6788
|
case "sdf:cone": {
|
|
6357
6789
|
const { height: h, radius: r } = node;
|
|
6358
|
-
return (x2, y2, z2) => sdCone(x2, y2, z2, h, r);
|
|
6790
|
+
return (x2, y2, z2) => sdCone$1(x2, y2, z2, h, r);
|
|
6359
6791
|
}
|
|
6360
6792
|
case "sdf:polylineSweep": {
|
|
6361
6793
|
return (x2, y2, z2) => sdPolylineSweep3(node, x2, y2, z2);
|
|
@@ -6372,7 +6804,7 @@ function compileSdfNode3(node) {
|
|
|
6372
6804
|
const fns = node.children.map(compileSdfNode3);
|
|
6373
6805
|
return (x2, y2, z2) => {
|
|
6374
6806
|
let d2 = fns[0](x2, y2, z2);
|
|
6375
|
-
for (let i = 1; i < fns.length; i++) d2 = max(d2, -fns[i](x2, y2, z2));
|
|
6807
|
+
for (let i = 1; i < fns.length; i++) d2 = max$1(d2, -fns[i](x2, y2, z2));
|
|
6376
6808
|
return d2;
|
|
6377
6809
|
};
|
|
6378
6810
|
}
|
|
@@ -6380,7 +6812,7 @@ function compileSdfNode3(node) {
|
|
|
6380
6812
|
const fns = node.children.map(compileSdfNode3);
|
|
6381
6813
|
return (x2, y2, z2) => {
|
|
6382
6814
|
let d2 = fns[0](x2, y2, z2);
|
|
6383
|
-
for (let i = 1; i < fns.length; i++) d2 = max(d2, fns[i](x2, y2, z2));
|
|
6815
|
+
for (let i = 1; i < fns.length; i++) d2 = max$1(d2, fns[i](x2, y2, z2));
|
|
6384
6816
|
return d2;
|
|
6385
6817
|
};
|
|
6386
6818
|
}
|
|
@@ -6389,7 +6821,7 @@ function compileSdfNode3(node) {
|
|
|
6389
6821
|
const k2 = node.radius;
|
|
6390
6822
|
return (x2, y2, z2) => {
|
|
6391
6823
|
let d2 = fns[0](x2, y2, z2);
|
|
6392
|
-
for (let i = 1; i < fns.length; i++) d2 = smin(d2, fns[i](x2, y2, z2), k2);
|
|
6824
|
+
for (let i = 1; i < fns.length; i++) d2 = smin$1(d2, fns[i](x2, y2, z2), k2);
|
|
6393
6825
|
return d2;
|
|
6394
6826
|
};
|
|
6395
6827
|
}
|
|
@@ -6398,7 +6830,7 @@ function compileSdfNode3(node) {
|
|
|
6398
6830
|
const k2 = node.radius;
|
|
6399
6831
|
return (x2, y2, z2) => {
|
|
6400
6832
|
let d2 = fns[0](x2, y2, z2);
|
|
6401
|
-
for (let i = 1; i < fns.length; i++) d2 = smax(d2, -fns[i](x2, y2, z2), k2);
|
|
6833
|
+
for (let i = 1; i < fns.length; i++) d2 = smax$1(d2, -fns[i](x2, y2, z2), k2);
|
|
6402
6834
|
return d2;
|
|
6403
6835
|
};
|
|
6404
6836
|
}
|
|
@@ -6407,7 +6839,7 @@ function compileSdfNode3(node) {
|
|
|
6407
6839
|
const k2 = node.radius;
|
|
6408
6840
|
return (x2, y2, z2) => {
|
|
6409
6841
|
let d2 = fns[0](x2, y2, z2);
|
|
6410
|
-
for (let i = 1; i < fns.length; i++) d2 = smax(d2, fns[i](x2, y2, z2), k2);
|
|
6842
|
+
for (let i = 1; i < fns.length; i++) d2 = smax$1(d2, fns[i](x2, y2, z2), k2);
|
|
6411
6843
|
return d2;
|
|
6412
6844
|
};
|
|
6413
6845
|
}
|
|
@@ -6425,10 +6857,10 @@ function compileSdfNode3(node) {
|
|
|
6425
6857
|
}
|
|
6426
6858
|
case "sdf:rotate": {
|
|
6427
6859
|
const fn = compileSdfNode3(node.child);
|
|
6428
|
-
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$
|
|
6429
|
-
const cx = cos(rx), sx = sin(rx);
|
|
6430
|
-
const cy = cos(ry), sy = sin(ry);
|
|
6431
|
-
const cz = cos(rz), sz = sin(rz);
|
|
6860
|
+
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$2);
|
|
6861
|
+
const cx = cos$1(rx), sx = sin$1(rx);
|
|
6862
|
+
const cy = cos$1(ry), sy = sin$1(ry);
|
|
6863
|
+
const cz = cos$1(rz), sz = sin$1(rz);
|
|
6432
6864
|
return (x2, y2, z2) => {
|
|
6433
6865
|
const x1 = cz * x2 + sz * y2;
|
|
6434
6866
|
const y1 = -sz * x2 + cz * y2;
|
|
@@ -6447,10 +6879,10 @@ function compileSdfNode3(node) {
|
|
|
6447
6879
|
}
|
|
6448
6880
|
case "sdf:twist": {
|
|
6449
6881
|
const fn = compileSdfNode3(node.child);
|
|
6450
|
-
const k2 = node.degreesPerUnit * DEG$
|
|
6882
|
+
const k2 = node.degreesPerUnit * DEG$2;
|
|
6451
6883
|
return (x2, y2, z2) => {
|
|
6452
6884
|
const angle = k2 * z2;
|
|
6453
|
-
const c2 = cos(angle), s = sin(angle);
|
|
6885
|
+
const c2 = cos$1(angle), s = sin$1(angle);
|
|
6454
6886
|
return fn(c2 * x2 - s * y2, s * x2 + c2 * y2, z2);
|
|
6455
6887
|
};
|
|
6456
6888
|
}
|
|
@@ -6459,7 +6891,7 @@ function compileSdfNode3(node) {
|
|
|
6459
6891
|
const r = node.radius;
|
|
6460
6892
|
return (x2, y2, z2) => {
|
|
6461
6893
|
const angle = x2 / r;
|
|
6462
|
-
const c2 = cos(angle), s = sin(angle);
|
|
6894
|
+
const c2 = cos$1(angle), s = sin$1(angle);
|
|
6463
6895
|
return fn((r + y2) * s, (r + y2) * c2 - r, z2);
|
|
6464
6896
|
};
|
|
6465
6897
|
}
|
|
@@ -6467,7 +6899,19 @@ function compileSdfNode3(node) {
|
|
|
6467
6899
|
const fn = compileSdfNode3(node.child);
|
|
6468
6900
|
const [sx, sy, sz] = node.spacing;
|
|
6469
6901
|
const [cx, cy, cz] = node.count;
|
|
6470
|
-
return (x2, y2, z2) => fn(repeatCoord(x2, sx, cx), repeatCoord(y2, sy, cy), repeatCoord(z2, sz, cz));
|
|
6902
|
+
return (x2, y2, z2) => fn(repeatCoord$1(x2, sx, cx), repeatCoord$1(y2, sy, cy), repeatCoord$1(z2, sz, cz));
|
|
6903
|
+
}
|
|
6904
|
+
case "sdf:circularArray": {
|
|
6905
|
+
const fn = compileSdfNode3(node.child);
|
|
6906
|
+
const da = 2 * PI$1 / node.count;
|
|
6907
|
+
const offset2 = node.offset;
|
|
6908
|
+
return (x2, y2, z2) => {
|
|
6909
|
+
const r = length2$1(x2, y2);
|
|
6910
|
+
const a2 = positiveMod(Math.atan2(y2, x2), da);
|
|
6911
|
+
const d1 = fn(cos$1(a2 - da) * r - offset2, sin$1(a2 - da) * r, z2);
|
|
6912
|
+
const d2 = fn(cos$1(a2) * r - offset2, sin$1(a2) * r, z2);
|
|
6913
|
+
return min(d1, d2);
|
|
6914
|
+
};
|
|
6471
6915
|
}
|
|
6472
6916
|
case "sdf:shell": {
|
|
6473
6917
|
const fn = compileSdfNode3(node.child);
|
|
@@ -6484,10 +6928,7 @@ function compileSdfNode3(node) {
|
|
|
6484
6928
|
}
|
|
6485
6929
|
case "sdf:surfaceDisplace": {
|
|
6486
6930
|
const childFn = compileSdfNode3(node.child);
|
|
6487
|
-
const
|
|
6488
|
-
const constNames = constEntries.map(([k2]) => k2);
|
|
6489
|
-
const constValues = constEntries.map(([, v]) => v);
|
|
6490
|
-
const patternFn = new Function("u", "v", ...constNames, `return (${node.patternBody});`);
|
|
6931
|
+
const patternFn = compileSurfacePattern(node);
|
|
6491
6932
|
const uvMode = node.uvMode && node.uvMode !== "auto" ? node.uvMode : void 0;
|
|
6492
6933
|
const analysis = analyzeUV(node.child, uvMode);
|
|
6493
6934
|
const uvFn = compileUVFunction(analysis);
|
|
@@ -6499,7 +6940,7 @@ function compileSdfNode3(node) {
|
|
|
6499
6940
|
p2[1] = y2;
|
|
6500
6941
|
p2[2] = z2;
|
|
6501
6942
|
const [u2, v] = uvFn(p2);
|
|
6502
|
-
return d2 + patternFn(u2, v
|
|
6943
|
+
return d2 + patternFn(u2, v);
|
|
6503
6944
|
};
|
|
6504
6945
|
}
|
|
6505
6946
|
const sharpness = node.triplanarSharpness ?? 4;
|
|
@@ -6510,9 +6951,9 @@ function compileSdfNode3(node) {
|
|
|
6510
6951
|
const gy = childFn(x2, y2 + eps, z2) - childFn(x2, y2 - eps, z2);
|
|
6511
6952
|
const gz = childFn(x2, y2, z2 + eps) - childFn(x2, y2, z2 - eps);
|
|
6512
6953
|
const { wx, wy, wz } = triplanarWeights(gx, gy, gz, sharpness);
|
|
6513
|
-
const hX = patternFn(y2, z2
|
|
6514
|
-
const hY = patternFn(x2, z2
|
|
6515
|
-
const hZ = patternFn(x2, y2
|
|
6954
|
+
const hX = patternFn(y2, z2);
|
|
6955
|
+
const hY = patternFn(x2, z2);
|
|
6956
|
+
const hZ = patternFn(x2, y2);
|
|
6516
6957
|
return d2 + wx * hX + wy * hY + wz * hZ;
|
|
6517
6958
|
};
|
|
6518
6959
|
}
|
|
@@ -6582,7 +7023,7 @@ function compileSdfNode3(node) {
|
|
|
6582
7023
|
const gx = gradFn(x2 + eps, y2, z2) - gradFn(x2 - eps, y2, z2);
|
|
6583
7024
|
const gy = gradFn(x2, y2 + eps, z2) - gradFn(x2, y2 - eps, z2);
|
|
6584
7025
|
const gz = gradFn(x2, y2, z2 + eps) - gradFn(x2, y2, z2 - eps);
|
|
6585
|
-
const glen = sqrt(gx * gx + gy * gy + gz * gz);
|
|
7026
|
+
const glen = sqrt$1(gx * gx + gy * gy + gz * gz);
|
|
6586
7027
|
let nx = 0, ny = 0, nz = 0;
|
|
6587
7028
|
if (glen > 1e-10) {
|
|
6588
7029
|
const invG = 1 / glen;
|
|
@@ -6644,7 +7085,7 @@ function estimateSdfBounds(node) {
|
|
|
6644
7085
|
for (const point2 of node.points) {
|
|
6645
7086
|
for (let i = 0; i < 3; i++) {
|
|
6646
7087
|
minPoint[i] = min(minPoint[i], point2[i]);
|
|
6647
|
-
maxPoint[i] = max(maxPoint[i], point2[i]);
|
|
7088
|
+
maxPoint[i] = max$1(maxPoint[i], point2[i]);
|
|
6648
7089
|
}
|
|
6649
7090
|
}
|
|
6650
7091
|
return padBounds({ min: minPoint, max: maxPoint }, pad);
|
|
@@ -6675,7 +7116,7 @@ function estimateSdfBounds(node) {
|
|
|
6675
7116
|
}
|
|
6676
7117
|
case "sdf:rotate": {
|
|
6677
7118
|
const b = estimateSdfBounds(node.child);
|
|
6678
|
-
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])));
|
|
7119
|
+
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])));
|
|
6679
7120
|
return { min: [-r, -r, -r], max: [r, r, r] };
|
|
6680
7121
|
}
|
|
6681
7122
|
case "sdf:scale": {
|
|
@@ -6689,7 +7130,7 @@ function estimateSdfBounds(node) {
|
|
|
6689
7130
|
case "sdf:twist":
|
|
6690
7131
|
case "sdf:bend": {
|
|
6691
7132
|
const b = estimateSdfBounds(node.child);
|
|
6692
|
-
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;
|
|
7133
|
+
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;
|
|
6693
7134
|
return { min: [-r, -r, -r], max: [r, r, r] };
|
|
6694
7135
|
}
|
|
6695
7136
|
case "sdf:repeat": {
|
|
@@ -6710,16 +7151,29 @@ function estimateSdfBounds(node) {
|
|
|
6710
7151
|
const [zMin, zMax] = expand(sz, cz, b.min[2], b.max[2]);
|
|
6711
7152
|
return { min: [xMin, yMin, zMin], max: [xMax, yMax, zMax] };
|
|
6712
7153
|
}
|
|
7154
|
+
case "sdf:circularArray": {
|
|
7155
|
+
const b = estimateSdfBounds(node.child);
|
|
7156
|
+
const x0 = b.min[0] + node.offset;
|
|
7157
|
+
const x1 = b.max[0] + node.offset;
|
|
7158
|
+
const y0 = b.min[1];
|
|
7159
|
+
const y1 = b.max[1];
|
|
7160
|
+
const r = max$1(length2$1(x0, y0), length2$1(x0, y1), length2$1(x1, y0), length2$1(x1, y1));
|
|
7161
|
+
return { min: [-r, -r, b.min[2]], max: [r, r, b.max[2]] };
|
|
7162
|
+
}
|
|
6713
7163
|
case "sdf:shell": {
|
|
6714
7164
|
const b = estimateSdfBounds(node.child);
|
|
6715
7165
|
const t = node.thickness * 0.5;
|
|
6716
7166
|
return padBounds(b, t);
|
|
6717
7167
|
}
|
|
6718
|
-
case "sdf:displace":
|
|
6719
|
-
case "sdf:surfaceDisplace": {
|
|
7168
|
+
case "sdf:displace": {
|
|
6720
7169
|
const b = estimateSdfBounds(node.child);
|
|
6721
7170
|
return padBounds(b, 5);
|
|
6722
7171
|
}
|
|
7172
|
+
case "sdf:surfaceDisplace": {
|
|
7173
|
+
const b = estimateSdfBounds(node.child);
|
|
7174
|
+
if (!node.pattern) return padBounds(b, 5);
|
|
7175
|
+
return padBounds(b, estimateSurfacePatternAmplitude(node.pattern) ?? 5);
|
|
7176
|
+
}
|
|
6723
7177
|
case "sdf:onion": {
|
|
6724
7178
|
const b = estimateSdfBounds(node.child);
|
|
6725
7179
|
return padBounds(b, node.layers * node.thickness);
|
|
@@ -6756,7 +7210,7 @@ function unionBounds(bounds, pad) {
|
|
|
6756
7210
|
for (const b of bounds) {
|
|
6757
7211
|
for (let i = 0; i < 3; i++) {
|
|
6758
7212
|
result.min[i] = min(result.min[i], b.min[i]);
|
|
6759
|
-
result.max[i] = max(result.max[i], b.max[i]);
|
|
7213
|
+
result.max[i] = max$1(result.max[i], b.max[i]);
|
|
6760
7214
|
}
|
|
6761
7215
|
}
|
|
6762
7216
|
if (pad > 0) return padBounds(result, pad);
|
|
@@ -6769,7 +7223,7 @@ function intersectBounds(bounds, pad) {
|
|
|
6769
7223
|
};
|
|
6770
7224
|
for (const b of bounds) {
|
|
6771
7225
|
for (let i = 0; i < 3; i++) {
|
|
6772
|
-
result.min[i] = max(result.min[i], b.min[i]);
|
|
7226
|
+
result.min[i] = max$1(result.min[i], b.min[i]);
|
|
6773
7227
|
result.max[i] = min(result.max[i], b.max[i]);
|
|
6774
7228
|
}
|
|
6775
7229
|
}
|
|
@@ -6785,242 +7239,544 @@ function padBounds(b, pad) {
|
|
|
6785
7239
|
max: [b.max[0] + pad, b.max[1] + pad, b.max[2] + pad]
|
|
6786
7240
|
};
|
|
6787
7241
|
}
|
|
6788
|
-
const
|
|
6789
|
-
const
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
7242
|
+
const { PI } = Math;
|
|
7243
|
+
const DEG$1 = PI / 180;
|
|
7244
|
+
const TAU = 2 * PI;
|
|
7245
|
+
const GRAD_EPS = 1e-9;
|
|
7246
|
+
const Op = {
|
|
7247
|
+
Const: 0,
|
|
7248
|
+
Neg: 1,
|
|
7249
|
+
Abs: 2,
|
|
7250
|
+
Sqrt: 3,
|
|
7251
|
+
Sin: 4,
|
|
7252
|
+
Cos: 5,
|
|
7253
|
+
Round: 6,
|
|
7254
|
+
Add: 7,
|
|
7255
|
+
Sub: 8,
|
|
7256
|
+
Mul: 9,
|
|
7257
|
+
Div: 10,
|
|
7258
|
+
Min: 11,
|
|
7259
|
+
Max: 12
|
|
7260
|
+
};
|
|
7261
|
+
class UnsupportedSdfProgramNodeError extends Error {
|
|
7262
|
+
constructor(message) {
|
|
7263
|
+
super(message);
|
|
7264
|
+
this.name = "UnsupportedSdfProgramNodeError";
|
|
6808
7265
|
}
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
);
|
|
7266
|
+
}
|
|
7267
|
+
class SdfProgramBuilder {
|
|
7268
|
+
constructor() {
|
|
7269
|
+
__publicField(this, "opcodes", []);
|
|
7270
|
+
__publicField(this, "argA", []);
|
|
7271
|
+
__publicField(this, "argB", []);
|
|
7272
|
+
__publicField(this, "argC", []);
|
|
7273
|
+
__publicField(this, "constants", []);
|
|
7274
|
+
__publicField(this, "x", 0);
|
|
7275
|
+
__publicField(this, "y", 1);
|
|
7276
|
+
__publicField(this, "z", 2);
|
|
6814
7277
|
}
|
|
6815
|
-
|
|
6816
|
-
|
|
7278
|
+
constant(value) {
|
|
7279
|
+
const index2 = this.constants.length;
|
|
7280
|
+
this.constants.push(value);
|
|
7281
|
+
return this.push(Op.Const, 0, 0, index2);
|
|
6817
7282
|
}
|
|
6818
|
-
|
|
6819
|
-
|
|
7283
|
+
neg(a2) {
|
|
7284
|
+
return this.push(Op.Neg, a2);
|
|
6820
7285
|
}
|
|
6821
|
-
|
|
6822
|
-
|
|
7286
|
+
abs(a2) {
|
|
7287
|
+
return this.push(Op.Abs, a2);
|
|
6823
7288
|
}
|
|
6824
|
-
|
|
6825
|
-
|
|
7289
|
+
sqrt(a2) {
|
|
7290
|
+
return this.push(Op.Sqrt, a2);
|
|
6826
7291
|
}
|
|
7292
|
+
sin(a2) {
|
|
7293
|
+
return this.push(Op.Sin, a2);
|
|
7294
|
+
}
|
|
7295
|
+
cos(a2) {
|
|
7296
|
+
return this.push(Op.Cos, a2);
|
|
7297
|
+
}
|
|
7298
|
+
round(a2) {
|
|
7299
|
+
return this.push(Op.Round, a2);
|
|
7300
|
+
}
|
|
7301
|
+
add(a2, b) {
|
|
7302
|
+
return this.push(Op.Add, a2, b);
|
|
7303
|
+
}
|
|
7304
|
+
sub(a2, b) {
|
|
7305
|
+
return this.push(Op.Sub, a2, b);
|
|
7306
|
+
}
|
|
7307
|
+
mul(a2, b) {
|
|
7308
|
+
return this.push(Op.Mul, a2, b);
|
|
7309
|
+
}
|
|
7310
|
+
div(a2, b) {
|
|
7311
|
+
return this.push(Op.Div, a2, b);
|
|
7312
|
+
}
|
|
7313
|
+
min(a2, b) {
|
|
7314
|
+
return this.push(Op.Min, a2, b);
|
|
7315
|
+
}
|
|
7316
|
+
max(a2, b) {
|
|
7317
|
+
return this.push(Op.Max, a2, b);
|
|
7318
|
+
}
|
|
7319
|
+
finalize(output) {
|
|
7320
|
+
return {
|
|
7321
|
+
opcodes: Uint8Array.from(this.opcodes),
|
|
7322
|
+
argA: Int32Array.from(this.argA),
|
|
7323
|
+
argB: Int32Array.from(this.argB),
|
|
7324
|
+
argC: Int32Array.from(this.argC),
|
|
7325
|
+
constants: Float64Array.from(this.constants),
|
|
7326
|
+
output,
|
|
7327
|
+
slotCount: this.opcodes.length + 3
|
|
7328
|
+
};
|
|
7329
|
+
}
|
|
7330
|
+
push(op, a2 = 0, b = 0, c2 = 0) {
|
|
7331
|
+
const slot2 = this.opcodes.length + 3;
|
|
7332
|
+
this.opcodes.push(op);
|
|
7333
|
+
this.argA.push(a2);
|
|
7334
|
+
this.argB.push(b);
|
|
7335
|
+
this.argC.push(c2);
|
|
7336
|
+
return slot2;
|
|
7337
|
+
}
|
|
7338
|
+
}
|
|
7339
|
+
function compileSdfProgramEvaluator3(program) {
|
|
7340
|
+
const lines = ["const { abs, sqrt, sin, cos, round, min, max } = Math;", "let v0 = x;", "let v1 = y;", "let v2 = z;"];
|
|
7341
|
+
const { opcodes, argA, argB, argC, constants, output } = program;
|
|
7342
|
+
for (let i = 0; i < opcodes.length; i++) {
|
|
7343
|
+
const slot2 = `v${i + 3}`;
|
|
7344
|
+
const a2 = `v${argA[i]}`;
|
|
7345
|
+
const b = `v${argB[i]}`;
|
|
7346
|
+
switch (opcodes[i]) {
|
|
7347
|
+
case Op.Const:
|
|
7348
|
+
lines.push(`let ${slot2} = ${numberLiteral(constants[argC[i]])};`);
|
|
7349
|
+
break;
|
|
7350
|
+
case Op.Neg:
|
|
7351
|
+
lines.push(`let ${slot2} = -${a2};`);
|
|
7352
|
+
break;
|
|
7353
|
+
case Op.Abs:
|
|
7354
|
+
lines.push(`let ${slot2} = abs(${a2});`);
|
|
7355
|
+
break;
|
|
7356
|
+
case Op.Sqrt:
|
|
7357
|
+
lines.push(`let ${slot2} = sqrt(${a2});`);
|
|
7358
|
+
break;
|
|
7359
|
+
case Op.Sin:
|
|
7360
|
+
lines.push(`let ${slot2} = sin(${a2});`);
|
|
7361
|
+
break;
|
|
7362
|
+
case Op.Cos:
|
|
7363
|
+
lines.push(`let ${slot2} = cos(${a2});`);
|
|
7364
|
+
break;
|
|
7365
|
+
case Op.Round:
|
|
7366
|
+
lines.push(`let ${slot2} = round(${a2});`);
|
|
7367
|
+
break;
|
|
7368
|
+
case Op.Add:
|
|
7369
|
+
lines.push(`let ${slot2} = ${a2} + ${b};`);
|
|
7370
|
+
break;
|
|
7371
|
+
case Op.Sub:
|
|
7372
|
+
lines.push(`let ${slot2} = ${a2} - ${b};`);
|
|
7373
|
+
break;
|
|
7374
|
+
case Op.Mul:
|
|
7375
|
+
lines.push(`let ${slot2} = ${a2} * ${b};`);
|
|
7376
|
+
break;
|
|
7377
|
+
case Op.Div:
|
|
7378
|
+
lines.push(`let ${slot2} = ${a2} / ${b};`);
|
|
7379
|
+
break;
|
|
7380
|
+
case Op.Min:
|
|
7381
|
+
lines.push(`let ${slot2} = min(${a2}, ${b});`);
|
|
7382
|
+
break;
|
|
7383
|
+
case Op.Max:
|
|
7384
|
+
lines.push(`let ${slot2} = max(${a2}, ${b});`);
|
|
7385
|
+
break;
|
|
7386
|
+
default:
|
|
7387
|
+
throw new Error(`Unknown SdfProgram opcode ${opcodes[i]} at instruction ${i}.`);
|
|
7388
|
+
}
|
|
7389
|
+
}
|
|
7390
|
+
lines.push(`return v${output};`);
|
|
7391
|
+
return new Function("Math", `return function sdfProgramEval(x, y, z) {
|
|
7392
|
+
${lines.join("\n")}
|
|
7393
|
+
};`)(Math);
|
|
7394
|
+
}
|
|
7395
|
+
function numberLiteral(value) {
|
|
7396
|
+
if (Number.isNaN(value)) return "NaN";
|
|
7397
|
+
if (value === Number.POSITIVE_INFINITY) return "Infinity";
|
|
7398
|
+
if (value === Number.NEGATIVE_INFINITY) return "-Infinity";
|
|
7399
|
+
return String(value);
|
|
7400
|
+
}
|
|
7401
|
+
function clampSlot(b, v, lo, hi) {
|
|
7402
|
+
return b.min(b.max(v, b.constant(lo)), b.constant(hi));
|
|
7403
|
+
}
|
|
7404
|
+
function length2(b, x2, y2) {
|
|
7405
|
+
return b.sqrt(b.add(b.mul(x2, x2), b.mul(y2, y2)));
|
|
7406
|
+
}
|
|
7407
|
+
function length3(b, x2, y2, z2) {
|
|
7408
|
+
return b.sqrt(b.add(b.add(b.mul(x2, x2), b.mul(y2, y2)), b.mul(z2, z2)));
|
|
7409
|
+
}
|
|
7410
|
+
function smin(b, a2, child, k2) {
|
|
7411
|
+
if (k2 <= 0) return b.min(a2, child);
|
|
7412
|
+
const h = b.div(b.max(b.sub(b.constant(k2), b.abs(b.sub(a2, child))), b.constant(0)), b.constant(k2));
|
|
7413
|
+
return b.sub(b.min(a2, child), b.mul(b.mul(b.mul(h, h), h), b.constant(k2 / 6)));
|
|
7414
|
+
}
|
|
7415
|
+
function smax(b, a2, child, k2) {
|
|
7416
|
+
return b.neg(smin(b, b.neg(a2), b.neg(child), k2));
|
|
7417
|
+
}
|
|
7418
|
+
function emitScaledTrig(b, x2, y2, z2, cellSize) {
|
|
7419
|
+
const s = b.constant(TAU / cellSize);
|
|
7420
|
+
const xs = b.mul(x2, s);
|
|
7421
|
+
const ys = b.mul(y2, s);
|
|
7422
|
+
const zs = b.mul(z2, s);
|
|
6827
7423
|
return {
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
7424
|
+
scale: s,
|
|
7425
|
+
sx: b.sin(xs),
|
|
7426
|
+
sy: b.sin(ys),
|
|
7427
|
+
sz: b.sin(zs),
|
|
7428
|
+
cx: b.cos(xs),
|
|
7429
|
+
cy: b.cos(ys),
|
|
7430
|
+
cz: b.cos(zs),
|
|
7431
|
+
sx2: b.sin(b.mul(b.constant(2), xs)),
|
|
7432
|
+
sy2: b.sin(b.mul(b.constant(2), ys)),
|
|
7433
|
+
sz2: b.sin(b.mul(b.constant(2), zs)),
|
|
7434
|
+
cx2: b.cos(b.mul(b.constant(2), xs)),
|
|
7435
|
+
cy2: b.cos(b.mul(b.constant(2), ys)),
|
|
7436
|
+
cz2: b.cos(b.mul(b.constant(2), zs))
|
|
6839
7437
|
};
|
|
6840
7438
|
}
|
|
6841
|
-
function
|
|
6842
|
-
|
|
7439
|
+
function emitGyroidValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
7440
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
7441
|
+
return {
|
|
7442
|
+
value: b.add(b.add(b.mul(t.sx, t.cy), b.mul(t.sy, t.cz)), b.mul(t.sz, t.cx)),
|
|
7443
|
+
gx: b.mul(t.scale, b.sub(b.mul(t.cx, t.cy), b.mul(t.sz, t.sx))),
|
|
7444
|
+
gy: b.mul(t.scale, b.add(b.neg(b.mul(t.sx, t.sy)), b.mul(t.cy, t.cz))),
|
|
7445
|
+
gz: b.mul(t.scale, b.add(b.neg(b.mul(t.sy, t.sz)), b.mul(t.cz, t.cx)))
|
|
7446
|
+
};
|
|
6843
7447
|
}
|
|
6844
|
-
function
|
|
6845
|
-
const
|
|
6846
|
-
const estimatedSamples = grid[0] * grid[1] * grid[2];
|
|
7448
|
+
function emitSchwarzPValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
7449
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
6847
7450
|
return {
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
estimatedSamples,
|
|
6853
|
-
estimatedMemoryBytes: estimatedSamples * 8,
|
|
6854
|
-
treeRiskFlags: [...settings.treeRiskFlags],
|
|
6855
|
-
simplification: settings.simplify,
|
|
6856
|
-
capMode: "box",
|
|
6857
|
-
capInset: settings.edgeLength,
|
|
6858
|
-
warnings: [...settings.warnings]
|
|
7451
|
+
value: b.add(b.add(t.cx, t.cy), t.cz),
|
|
7452
|
+
gx: b.neg(b.mul(t.scale, t.sx)),
|
|
7453
|
+
gy: b.neg(b.mul(t.scale, t.sy)),
|
|
7454
|
+
gz: b.neg(b.mul(t.scale, t.sz))
|
|
6859
7455
|
};
|
|
6860
7456
|
}
|
|
6861
|
-
function
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
)
|
|
7457
|
+
function emitDiamondValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
7458
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
7459
|
+
return {
|
|
7460
|
+
value: b.add(
|
|
7461
|
+
b.add(b.mul(b.mul(t.sx, t.sy), t.sz), b.mul(b.mul(t.sx, t.cy), t.cz)),
|
|
7462
|
+
b.add(b.mul(b.mul(t.cx, t.sy), t.cz), b.mul(b.mul(t.cx, t.cy), t.sz))
|
|
7463
|
+
),
|
|
7464
|
+
gx: b.mul(
|
|
7465
|
+
t.scale,
|
|
7466
|
+
b.add(
|
|
7467
|
+
b.add(b.mul(b.mul(t.cx, t.sy), t.sz), b.mul(b.mul(t.cx, t.cy), t.cz)),
|
|
7468
|
+
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)))
|
|
7469
|
+
)
|
|
7470
|
+
),
|
|
7471
|
+
gy: b.mul(
|
|
7472
|
+
t.scale,
|
|
7473
|
+
b.add(
|
|
7474
|
+
b.add(b.mul(b.mul(t.sx, t.cy), t.sz), b.neg(b.mul(b.mul(t.sx, t.sy), t.cz))),
|
|
7475
|
+
b.add(b.mul(b.mul(t.cx, t.cy), t.cz), b.neg(b.mul(b.mul(t.cx, t.sy), t.sz)))
|
|
7476
|
+
)
|
|
7477
|
+
),
|
|
7478
|
+
gz: b.mul(
|
|
7479
|
+
t.scale,
|
|
7480
|
+
b.add(
|
|
7481
|
+
b.add(b.mul(b.mul(t.sx, t.sy), t.cz), b.neg(b.mul(b.mul(t.sx, t.cy), t.sz))),
|
|
7482
|
+
b.add(b.neg(b.mul(b.mul(t.cx, t.sy), t.sz)), b.mul(b.mul(t.cx, t.cy), t.cz))
|
|
7483
|
+
)
|
|
7484
|
+
)
|
|
7485
|
+
};
|
|
7486
|
+
}
|
|
7487
|
+
function emitLidinoidValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
7488
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
7489
|
+
const value = b.add(
|
|
7490
|
+
b.sub(
|
|
7491
|
+
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)),
|
|
7492
|
+
b.add(b.add(b.mul(t.cx2, t.cy2), b.mul(t.cy2, t.cz2)), b.mul(t.cz2, t.cx2))
|
|
7493
|
+
),
|
|
7494
|
+
b.constant(0.3)
|
|
6868
7495
|
);
|
|
7496
|
+
return {
|
|
7497
|
+
value,
|
|
7498
|
+
gx: b.mul(
|
|
7499
|
+
t.scale,
|
|
7500
|
+
b.add(
|
|
7501
|
+
b.add(
|
|
7502
|
+
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)),
|
|
7503
|
+
b.neg(b.mul(b.mul(t.sz2, t.sx), t.sy))
|
|
7504
|
+
),
|
|
7505
|
+
b.add(b.mul(b.mul(b.constant(2), t.sx2), t.cy2), b.mul(b.mul(b.constant(2), t.cz2), t.sx2))
|
|
7506
|
+
)
|
|
7507
|
+
),
|
|
7508
|
+
gy: b.mul(
|
|
7509
|
+
t.scale,
|
|
7510
|
+
b.add(
|
|
7511
|
+
b.add(
|
|
7512
|
+
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))),
|
|
7513
|
+
b.mul(b.mul(t.sz2, t.cx), t.cy)
|
|
7514
|
+
),
|
|
7515
|
+
b.add(b.mul(b.mul(b.constant(2), t.cx2), t.sy2), b.mul(b.mul(b.constant(2), t.sy2), t.cz2))
|
|
7516
|
+
)
|
|
7517
|
+
),
|
|
7518
|
+
gz: b.mul(
|
|
7519
|
+
t.scale,
|
|
7520
|
+
b.add(
|
|
7521
|
+
b.add(
|
|
7522
|
+
b.add(b.mul(b.mul(t.sx2, t.cy), t.cz), b.neg(b.mul(b.mul(t.sy2, t.sz), t.sx))),
|
|
7523
|
+
b.mul(b.mul(b.constant(2), t.cz2), b.mul(t.cx, t.sy))
|
|
7524
|
+
),
|
|
7525
|
+
b.add(b.mul(b.mul(b.constant(2), t.cy2), t.sz2), b.mul(b.mul(b.constant(2), t.sz2), t.cx2))
|
|
7526
|
+
)
|
|
7527
|
+
)
|
|
7528
|
+
};
|
|
6869
7529
|
}
|
|
6870
|
-
function
|
|
6871
|
-
|
|
6872
|
-
const
|
|
6873
|
-
|
|
6874
|
-
return [
|
|
6875
|
-
Math.max(2, Math.ceil(dx / edgeLength2) + 1),
|
|
6876
|
-
Math.max(2, Math.ceil(dy / edgeLength2) + 1),
|
|
6877
|
-
Math.max(2, Math.ceil(dz / edgeLength2) + 1)
|
|
6878
|
-
];
|
|
7530
|
+
function emitTpmsDistance(b, { value, gx, gy, gz }, thickness, thicknessMode) {
|
|
7531
|
+
if (thicknessMode !== "metric-approx") return b.sub(b.abs(value), b.constant(thickness));
|
|
7532
|
+
const grad = length3(b, gx, gy, gz);
|
|
7533
|
+
return b.sub(b.div(b.abs(value), b.max(grad, b.constant(GRAD_EPS))), b.constant(thickness * 0.5));
|
|
6879
7534
|
}
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
7535
|
+
const { cos, max, sin, sqrt } = Math;
|
|
7536
|
+
function emitSdfProgramNode(b, node, x2, y2, z2) {
|
|
7537
|
+
switch (node.kind) {
|
|
7538
|
+
case "sdf:sphere":
|
|
7539
|
+
return sdSphere(b, x2, y2, z2, node.radius);
|
|
7540
|
+
case "sdf:box": {
|
|
7541
|
+
const [hx, hy, hz] = node.halfExtents;
|
|
7542
|
+
return sdBox(b, x2, y2, z2, hx, hy, hz);
|
|
7543
|
+
}
|
|
7544
|
+
case "sdf:cylinder":
|
|
7545
|
+
return sdCylinder(b, x2, y2, z2, node.height, node.radius);
|
|
7546
|
+
case "sdf:torus":
|
|
7547
|
+
return sdTorus(b, x2, y2, z2, node.majorRadius, node.minorRadius);
|
|
7548
|
+
case "sdf:capsule":
|
|
7549
|
+
return sdCapsule(b, x2, y2, z2, node.height, node.radius);
|
|
7550
|
+
case "sdf:cone":
|
|
7551
|
+
return sdCone(b, x2, y2, z2, node.height, node.radius);
|
|
7552
|
+
case "sdf:polylineSweep":
|
|
7553
|
+
return sdPolylineSweep(b, node, x2, y2, z2);
|
|
7554
|
+
case "sdf:union":
|
|
7555
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => b.min(a2, child));
|
|
7556
|
+
case "sdf:difference":
|
|
7557
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => b.max(a2, b.neg(child)));
|
|
7558
|
+
case "sdf:intersection":
|
|
7559
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => b.max(a2, child));
|
|
7560
|
+
case "sdf:smoothUnion":
|
|
7561
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => smin(b, a2, child, node.radius));
|
|
7562
|
+
case "sdf:smoothDifference":
|
|
7563
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => smax(b, a2, b.neg(child), node.radius));
|
|
7564
|
+
case "sdf:smoothIntersection":
|
|
7565
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => smax(b, a2, child, node.radius));
|
|
7566
|
+
case "sdf:morph": {
|
|
7567
|
+
const a2 = emitSdfProgramNode(b, node.a, x2, y2, z2);
|
|
7568
|
+
const childB = emitSdfProgramNode(b, node.b, x2, y2, z2);
|
|
7569
|
+
return b.add(b.mul(a2, b.constant(1 - node.t)), b.mul(childB, b.constant(node.t)));
|
|
7570
|
+
}
|
|
7571
|
+
case "sdf:translate": {
|
|
7572
|
+
const [ox, oy, oz] = node.offset;
|
|
7573
|
+
return emitSdfProgramNode(b, node.child, b.sub(x2, b.constant(ox)), b.sub(y2, b.constant(oy)), b.sub(z2, b.constant(oz)));
|
|
7574
|
+
}
|
|
7575
|
+
case "sdf:rotate":
|
|
7576
|
+
return emitRotated(b, node, x2, y2, z2);
|
|
7577
|
+
case "sdf:scale": {
|
|
7578
|
+
const inv = 1 / node.factor;
|
|
7579
|
+
const child = emitSdfProgramNode(b, node.child, b.mul(x2, b.constant(inv)), b.mul(y2, b.constant(inv)), b.mul(z2, b.constant(inv)));
|
|
7580
|
+
return b.mul(child, b.constant(node.factor));
|
|
7581
|
+
}
|
|
7582
|
+
case "sdf:twist": {
|
|
7583
|
+
const angle = b.mul(b.constant(node.degreesPerUnit * DEG$1), z2);
|
|
7584
|
+
const c2 = b.cos(angle);
|
|
7585
|
+
const s = b.sin(angle);
|
|
7586
|
+
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);
|
|
7587
|
+
}
|
|
7588
|
+
case "sdf:bend": {
|
|
7589
|
+
const angle = b.div(x2, b.constant(node.radius));
|
|
7590
|
+
const c2 = b.cos(angle);
|
|
7591
|
+
const s = b.sin(angle);
|
|
7592
|
+
const radiusPlusY = b.add(b.constant(node.radius), y2);
|
|
7593
|
+
return emitSdfProgramNode(b, node.child, b.mul(radiusPlusY, s), b.sub(b.mul(radiusPlusY, c2), b.constant(node.radius)), z2);
|
|
7594
|
+
}
|
|
7595
|
+
case "sdf:repeat": {
|
|
7596
|
+
const [sx, sy, sz] = node.spacing;
|
|
7597
|
+
const [cx, cy, cz] = node.count;
|
|
7598
|
+
return emitSdfProgramNode(b, node.child, repeatCoord(b, x2, sx, cx), repeatCoord(b, y2, sy, cy), repeatCoord(b, z2, sz, cz));
|
|
7599
|
+
}
|
|
7600
|
+
case "sdf:shell": {
|
|
7601
|
+
const child = emitSdfProgramNode(b, node.child, x2, y2, z2);
|
|
7602
|
+
return b.sub(b.abs(child), b.constant(node.thickness * 0.5));
|
|
7603
|
+
}
|
|
7604
|
+
case "sdf:onion": {
|
|
7605
|
+
let d2 = emitSdfProgramNode(b, node.child, x2, y2, z2);
|
|
7606
|
+
for (let i = 0; i < node.layers; i++) d2 = b.sub(b.abs(d2), b.constant(node.thickness));
|
|
7607
|
+
return d2;
|
|
7608
|
+
}
|
|
7609
|
+
case "sdf:gyroid":
|
|
7610
|
+
return emitTpmsDistance(b, emitGyroidValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
7611
|
+
case "sdf:schwarzP":
|
|
7612
|
+
return emitTpmsDistance(b, emitSchwarzPValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
7613
|
+
case "sdf:diamond":
|
|
7614
|
+
return emitTpmsDistance(b, emitDiamondValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
7615
|
+
case "sdf:lidinoid":
|
|
7616
|
+
return emitTpmsDistance(b, emitLidinoidValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
7617
|
+
default:
|
|
7618
|
+
throw new UnsupportedSdfProgramNodeError(`SdfProgram does not support node kind ${node.kind} yet.`);
|
|
7619
|
+
}
|
|
6885
7620
|
}
|
|
6886
|
-
function
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
const maxDim = Math.max(dx, dy, dz, minEdgeLength);
|
|
6891
|
-
const divisor = quality === "draft" ? 60 : quality === "export" ? 160 : 100;
|
|
6892
|
-
const candidates = [maxDim / divisor];
|
|
6893
|
-
if (options.tolerance !== void 0) candidates.push(requirePositiveFinite$2(options.tolerance, "SDF tolerance") * 2);
|
|
6894
|
-
if (options.minFeatureSize !== void 0) candidates.push(requirePositiveFinite$2(options.minFeatureSize, "SDF minFeatureSize") / 2.5);
|
|
6895
|
-
if (analysis.minMetricTpmsThickness < Infinity) candidates.push(analysis.minMetricTpmsThickness / 2);
|
|
6896
|
-
if (analysis.minTpmsCellSize < Infinity) candidates.push(analysis.minTpmsCellSize / 10);
|
|
6897
|
-
if (analysis.minRepeatSpacing < Infinity) candidates.push(analysis.minRepeatSpacing / 8);
|
|
6898
|
-
if (analysis.minWallThickness < Infinity) candidates.push(analysis.minWallThickness / 2.5);
|
|
6899
|
-
return Math.max(minEdgeLength, Math.min(...candidates.filter((v) => Number.isFinite(v) && v > 0)));
|
|
7621
|
+
function foldChildren(b, children, x2, y2, z2, combine2) {
|
|
7622
|
+
let d2 = emitSdfProgramNode(b, children[0], x2, y2, z2);
|
|
7623
|
+
for (let i = 1; i < children.length; i++) d2 = combine2(d2, emitSdfProgramNode(b, children[i], x2, y2, z2));
|
|
7624
|
+
return d2;
|
|
6900
7625
|
}
|
|
6901
|
-
function
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
7626
|
+
function emitRotated(b, node, x2, y2, z2) {
|
|
7627
|
+
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$1);
|
|
7628
|
+
const cx = cos(rx);
|
|
7629
|
+
const sx = sin(rx);
|
|
7630
|
+
const cy = cos(ry);
|
|
7631
|
+
const sy = sin(ry);
|
|
7632
|
+
const cz = cos(rz);
|
|
7633
|
+
const sz = sin(rz);
|
|
7634
|
+
const x1 = b.add(b.mul(b.constant(cz), x2), b.mul(b.constant(sz), y2));
|
|
7635
|
+
const y1 = b.sub(b.mul(b.constant(cz), y2), b.mul(b.constant(sz), x2));
|
|
7636
|
+
const x22 = b.sub(b.mul(b.constant(cy), x1), b.mul(b.constant(sy), z2));
|
|
7637
|
+
const z22 = b.add(b.mul(b.constant(sy), x1), b.mul(b.constant(cy), z2));
|
|
7638
|
+
const y22 = b.add(b.mul(b.constant(cx), y1), b.mul(b.constant(sx), z22));
|
|
7639
|
+
const z3 = b.sub(b.mul(b.constant(cx), z22), b.mul(b.constant(sx), y1));
|
|
7640
|
+
return emitSdfProgramNode(b, node.child, x22, y22, z3);
|
|
7641
|
+
}
|
|
7642
|
+
function sdSphere(b, x2, y2, z2, r) {
|
|
7643
|
+
return b.sub(length3(b, x2, y2, z2), b.constant(r));
|
|
7644
|
+
}
|
|
7645
|
+
function sdBox(b, x2, y2, z2, hx, hy, hz) {
|
|
7646
|
+
const dx = b.sub(b.abs(x2), b.constant(hx));
|
|
7647
|
+
const dy = b.sub(b.abs(y2), b.constant(hy));
|
|
7648
|
+
const dz = b.sub(b.abs(z2), b.constant(hz));
|
|
7649
|
+
const outside = length3(b, b.max(dx, b.constant(0)), b.max(dy, b.constant(0)), b.max(dz, b.constant(0)));
|
|
7650
|
+
const inside = b.min(b.max(b.max(dx, dy), dz), b.constant(0));
|
|
7651
|
+
return b.add(outside, inside);
|
|
7652
|
+
}
|
|
7653
|
+
function sdCylinder(b, x2, y2, z2, h, r) {
|
|
7654
|
+
const dx = b.sub(length2(b, x2, y2), b.constant(r));
|
|
7655
|
+
const dz = b.sub(b.abs(z2), b.constant(h * 0.5));
|
|
7656
|
+
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)));
|
|
7657
|
+
}
|
|
7658
|
+
function sdTorus(b, x2, y2, z2, majorRadius, minorRadius) {
|
|
7659
|
+
return b.sub(length2(b, b.sub(length2(b, x2, y2), b.constant(majorRadius)), z2), b.constant(minorRadius));
|
|
7660
|
+
}
|
|
7661
|
+
function sdCapsule(b, x2, y2, z2, h, r) {
|
|
7662
|
+
const cz = clampSlot(b, z2, -h * 0.5, h * 0.5);
|
|
7663
|
+
return b.sub(length3(b, x2, y2, b.sub(z2, cz)), b.constant(r));
|
|
7664
|
+
}
|
|
7665
|
+
function sdCone(b, x2, y2, z2, h, r) {
|
|
7666
|
+
const q = length2(b, x2, y2);
|
|
7667
|
+
const cLen = sqrt(h * h + r * r);
|
|
7668
|
+
const side = b.add(b.mul(b.constant(h / cLen), q), b.mul(b.constant(-r / cLen), b.sub(z2, b.constant(h))));
|
|
7669
|
+
return b.max(b.max(side, b.neg(z2)), b.sub(z2, b.constant(h)));
|
|
7670
|
+
}
|
|
7671
|
+
function sdPolylineSweep(b, node, x2, y2, z2) {
|
|
7672
|
+
let d2 = sdTaperedSegment(b, x2, y2, z2, node.points[0], node.points[1], node.radii[0], node.radii[1]);
|
|
7673
|
+
for (let i = 1; i < node.points.length - 1; i++) {
|
|
7674
|
+
const segment = sdTaperedSegment(b, x2, y2, z2, node.points[i], node.points[i + 1], node.radii[i], node.radii[i + 1]);
|
|
7675
|
+
d2 = smin(b, d2, segment, node.blend);
|
|
7676
|
+
}
|
|
7677
|
+
return d2;
|
|
6906
7678
|
}
|
|
6907
|
-
function
|
|
6908
|
-
const
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
7679
|
+
function sdTaperedSegment(b, x2, y2, z2, a2, end, ra, rb) {
|
|
7680
|
+
const vx = end[0] - a2[0];
|
|
7681
|
+
const vy = end[1] - a2[1];
|
|
7682
|
+
const vz = end[2] - a2[2];
|
|
7683
|
+
const len2 = vx * vx + vy * vy + vz * vz;
|
|
7684
|
+
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));
|
|
7685
|
+
const h = clampSlot(
|
|
7686
|
+
b,
|
|
7687
|
+
b.div(
|
|
7688
|
+
b.add(
|
|
7689
|
+
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))),
|
|
7690
|
+
b.mul(b.sub(z2, b.constant(a2[2])), b.constant(vz))
|
|
7691
|
+
),
|
|
7692
|
+
b.constant(len2)
|
|
7693
|
+
),
|
|
7694
|
+
0,
|
|
7695
|
+
1
|
|
7696
|
+
);
|
|
7697
|
+
const sx = b.sub(x2, b.add(b.constant(a2[0]), b.mul(b.constant(vx), h)));
|
|
7698
|
+
const sy = b.sub(y2, b.add(b.constant(a2[1]), b.mul(b.constant(vy), h)));
|
|
7699
|
+
const sz = b.sub(z2, b.add(b.constant(a2[2]), b.mul(b.constant(vz), h)));
|
|
7700
|
+
const radius = b.add(b.constant(ra), b.mul(b.constant(rb - ra), h));
|
|
7701
|
+
return b.sub(length3(b, sx, sy, sz), radius);
|
|
6919
7702
|
}
|
|
6920
|
-
function
|
|
7703
|
+
function repeatCoord(b, v, spacing, count) {
|
|
7704
|
+
if (spacing <= 0) return v;
|
|
7705
|
+
if (count > 0) {
|
|
7706
|
+
const center = (count - 1) * 0.5;
|
|
7707
|
+
const index2 = clampSlot(b, b.round(b.add(b.div(v, b.constant(spacing)), b.constant(center))), 0, count - 1);
|
|
7708
|
+
return b.sub(v, b.mul(b.sub(index2, b.constant(center)), b.constant(spacing)));
|
|
7709
|
+
}
|
|
7710
|
+
return b.sub(v, b.mul(b.constant(spacing), b.round(b.div(v, b.constant(spacing)))));
|
|
7711
|
+
}
|
|
7712
|
+
function getUnsupportedSdfProgramReason(node) {
|
|
6921
7713
|
switch (node.kind) {
|
|
7714
|
+
case "sdf:displace":
|
|
7715
|
+
return "displace uses a dynamic JavaScript function body";
|
|
7716
|
+
case "sdf:surfaceDisplace":
|
|
7717
|
+
return "surfaceDisplace uses dynamic UV/pattern evaluation";
|
|
7718
|
+
case "sdf:spatialBlend":
|
|
7719
|
+
return "spatialBlend uses a dynamic JavaScript blend function";
|
|
7720
|
+
case "sdf:noise":
|
|
7721
|
+
return "noise depends on table-based simplex evaluation";
|
|
7722
|
+
case "sdf:voronoi":
|
|
7723
|
+
return "voronoi depends on table-based Worley evaluation";
|
|
7724
|
+
case "sdf:custom":
|
|
7725
|
+
return "custom uses a dynamic JavaScript function body";
|
|
7726
|
+
case "sdf:polylineSweep":
|
|
7727
|
+
if (node.points.length < 2) return "polylineSweep needs at least two points";
|
|
7728
|
+
if (node.points.length !== node.radii.length) return "polylineSweep point/radius counts differ";
|
|
7729
|
+
return void 0;
|
|
6922
7730
|
case "sdf:union":
|
|
6923
7731
|
case "sdf:difference":
|
|
6924
7732
|
case "sdf:intersection":
|
|
6925
7733
|
case "sdf:smoothUnion":
|
|
6926
7734
|
case "sdf:smoothDifference":
|
|
6927
7735
|
case "sdf:smoothIntersection":
|
|
6928
|
-
for (const child of node.children)
|
|
6929
|
-
|
|
7736
|
+
for (const child of node.children) {
|
|
7737
|
+
const reason = getUnsupportedSdfProgramReason(child);
|
|
7738
|
+
if (reason) return reason;
|
|
7739
|
+
}
|
|
7740
|
+
return void 0;
|
|
6930
7741
|
case "sdf:morph":
|
|
6931
|
-
|
|
6932
|
-
visitSdfNode(node.a, analysis);
|
|
6933
|
-
visitSdfNode(node.b, analysis);
|
|
6934
|
-
break;
|
|
7742
|
+
return getUnsupportedSdfProgramReason(node.a) ?? getUnsupportedSdfProgramReason(node.b);
|
|
6935
7743
|
case "sdf:translate":
|
|
6936
7744
|
case "sdf:rotate":
|
|
6937
7745
|
case "sdf:scale":
|
|
6938
7746
|
case "sdf:twist":
|
|
6939
7747
|
case "sdf:bend":
|
|
6940
|
-
case "sdf:onion":
|
|
6941
|
-
visitSdfNode(node.child, analysis);
|
|
6942
|
-
break;
|
|
6943
7748
|
case "sdf:repeat":
|
|
6944
|
-
analysis.riskFlags.add("repeat");
|
|
6945
|
-
for (let i = 0; i < 3; i++) {
|
|
6946
|
-
const spacing = node.spacing[i];
|
|
6947
|
-
if (spacing > 0) {
|
|
6948
|
-
analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, spacing);
|
|
6949
|
-
if (node.count[i] <= 0) analysis.hasInfiniteRepeat = true;
|
|
6950
|
-
}
|
|
6951
|
-
}
|
|
6952
|
-
visitSdfNode(node.child, analysis);
|
|
6953
|
-
break;
|
|
6954
7749
|
case "sdf:shell":
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
case "sdf:surfaceDisplace":
|
|
6960
|
-
analysis.riskFlags.add("displacement");
|
|
6961
|
-
visitSdfNode(node.child, analysis);
|
|
6962
|
-
break;
|
|
6963
|
-
case "sdf:gyroid":
|
|
6964
|
-
case "sdf:schwarzP":
|
|
6965
|
-
case "sdf:diamond":
|
|
6966
|
-
case "sdf:lidinoid":
|
|
6967
|
-
analysis.riskFlags.add("tpms");
|
|
6968
|
-
analysis.minTpmsCellSize = Math.min(analysis.minTpmsCellSize, node.cellSize);
|
|
6969
|
-
if (node.thicknessMode === "metric-approx") {
|
|
6970
|
-
analysis.minMetricTpmsThickness = Math.min(analysis.minMetricTpmsThickness, node.thickness);
|
|
6971
|
-
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.thickness);
|
|
6972
|
-
} else {
|
|
6973
|
-
analysis.hasLegacyTpmsThreshold = true;
|
|
6974
|
-
}
|
|
6975
|
-
break;
|
|
6976
|
-
case "sdf:noise":
|
|
6977
|
-
analysis.riskFlags.add("noise");
|
|
6978
|
-
break;
|
|
6979
|
-
case "sdf:voronoi":
|
|
6980
|
-
analysis.riskFlags.add("voronoi");
|
|
6981
|
-
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.wallThickness);
|
|
6982
|
-
if (node.surfaceChild) visitSdfNode(node.surfaceChild, analysis);
|
|
6983
|
-
break;
|
|
6984
|
-
case "sdf:custom":
|
|
6985
|
-
analysis.riskFlags.add("custom");
|
|
6986
|
-
break;
|
|
7750
|
+
case "sdf:onion":
|
|
7751
|
+
return getUnsupportedSdfProgramReason(node.child);
|
|
7752
|
+
default:
|
|
7753
|
+
return void 0;
|
|
6987
7754
|
}
|
|
6988
7755
|
}
|
|
6989
|
-
function
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
}
|
|
6993
|
-
function requirePositiveFinite$2(value, name) {
|
|
6994
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
6995
|
-
throw new Error(`${name} must be a positive finite number.`);
|
|
7756
|
+
function compileSdfProgram(node) {
|
|
7757
|
+
const unsupportedReason = getUnsupportedSdfProgramReason(node);
|
|
7758
|
+
if (unsupportedReason) {
|
|
7759
|
+
throw new UnsupportedSdfProgramNodeError(`SdfProgram does not support this tree yet: ${unsupportedReason}.`);
|
|
6996
7760
|
}
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
function cloneBounds$2(bounds) {
|
|
7000
|
-
return { min: [...bounds.min], max: [...bounds.max] };
|
|
7001
|
-
}
|
|
7002
|
-
function suggestEdgeLengthForSampleBudget(bounds, maxGridPoints) {
|
|
7003
|
-
const dx = bounds.max[0] - bounds.min[0];
|
|
7004
|
-
const dy = bounds.max[1] - bounds.min[1];
|
|
7005
|
-
const dz = bounds.max[2] - bounds.min[2];
|
|
7006
|
-
const volume = Math.max(dx * dy * dz, 1);
|
|
7007
|
-
return Math.cbrt(volume / Math.max(maxGridPoints, 8));
|
|
7761
|
+
const builder = new SdfProgramBuilder();
|
|
7762
|
+
return builder.finalize(emitSdfProgramNode(builder, node, builder.x, builder.y, builder.z));
|
|
7008
7763
|
}
|
|
7009
|
-
function
|
|
7010
|
-
return
|
|
7764
|
+
function compileSdfProgram3(node) {
|
|
7765
|
+
return compileSdfProgramEvaluator3(compileSdfProgram(node));
|
|
7011
7766
|
}
|
|
7012
|
-
function
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
}
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7767
|
+
function compileSdfMaterializationEvaluator3(node) {
|
|
7768
|
+
const unsupportedReason = getUnsupportedSdfProgramReason(node);
|
|
7769
|
+
if (unsupportedReason) {
|
|
7770
|
+
return {
|
|
7771
|
+
fn: compileSdfNode3(node),
|
|
7772
|
+
engine: "closure",
|
|
7773
|
+
unsupportedReason
|
|
7774
|
+
};
|
|
7775
|
+
}
|
|
7776
|
+
return {
|
|
7777
|
+
fn: compileSdfProgram3(node),
|
|
7778
|
+
engine: "program"
|
|
7779
|
+
};
|
|
7024
7780
|
}
|
|
7025
7781
|
function midpoint$3(a2, b) {
|
|
7026
7782
|
return [(a2[0] + b[0]) / 2, (a2[1] + b[1]) / 2, (a2[2] + b[2]) / 2];
|
|
@@ -7486,7 +8242,7 @@ function buildCircleExtrusionTopology(circ, height, center = false) {
|
|
|
7486
8242
|
);
|
|
7487
8243
|
return { faces, edges };
|
|
7488
8244
|
}
|
|
7489
|
-
function requireFinite$
|
|
8245
|
+
function requireFinite$9(v, label) {
|
|
7490
8246
|
if (!Number.isFinite(v)) throw new Error(`nurbsSurface: ${label} must be finite, got ${v}`);
|
|
7491
8247
|
}
|
|
7492
8248
|
function normalizeSurfaceTessellation(tessellation) {
|
|
@@ -7496,11 +8252,11 @@ function normalizeSurfaceTessellation(tessellation) {
|
|
|
7496
8252
|
throw new Error(`nurbsSurface: tessellation.mode must be "uniform" or "adaptive", got ${mode}`);
|
|
7497
8253
|
}
|
|
7498
8254
|
if (tessellation.tolerance !== void 0) {
|
|
7499
|
-
requireFinite$
|
|
8255
|
+
requireFinite$9(tessellation.tolerance, "tessellation.tolerance");
|
|
7500
8256
|
if (tessellation.tolerance <= 0) throw new Error("nurbsSurface: tessellation.tolerance must be > 0");
|
|
7501
8257
|
}
|
|
7502
|
-
if (tessellation.minResolution !== void 0) requireFinite$
|
|
7503
|
-
if (tessellation.maxResolution !== void 0) requireFinite$
|
|
8258
|
+
if (tessellation.minResolution !== void 0) requireFinite$9(tessellation.minResolution, "tessellation.minResolution");
|
|
8259
|
+
if (tessellation.maxResolution !== void 0) requireFinite$9(tessellation.maxResolution, "tessellation.maxResolution");
|
|
7504
8260
|
const minResolution = tessellation.minResolution === void 0 ? void 0 : Math.max(2, Math.round(tessellation.minResolution));
|
|
7505
8261
|
const maxResolution = tessellation.maxResolution === void 0 ? void 0 : Math.max(2, Math.round(tessellation.maxResolution));
|
|
7506
8262
|
if (minResolution !== void 0 && maxResolution !== void 0 && minResolution > maxResolution) {
|
|
@@ -7519,10 +8275,10 @@ function normalizeSurfaceDomain(domain) {
|
|
|
7519
8275
|
const uMax = domain.uMax ?? 1;
|
|
7520
8276
|
const vMin = domain.vMin ?? 0;
|
|
7521
8277
|
const vMax = domain.vMax ?? 1;
|
|
7522
|
-
requireFinite$
|
|
7523
|
-
requireFinite$
|
|
7524
|
-
requireFinite$
|
|
7525
|
-
requireFinite$
|
|
8278
|
+
requireFinite$9(uMin, "domain.uMin");
|
|
8279
|
+
requireFinite$9(uMax, "domain.uMax");
|
|
8280
|
+
requireFinite$9(vMin, "domain.vMin");
|
|
8281
|
+
requireFinite$9(vMax, "domain.vMax");
|
|
7526
8282
|
if (uMin < 0 || uMax > 1 || vMin < 0 || vMax > 1) {
|
|
7527
8283
|
throw new Error("nurbsSurface: domain bounds must stay within [0, 1]");
|
|
7528
8284
|
}
|
|
@@ -7534,8 +8290,8 @@ function normalizeSurfaceDomain(domain) {
|
|
|
7534
8290
|
function normalizeTrimLoop(loop, label) {
|
|
7535
8291
|
if (loop.length < 3) throw new Error(`nurbsSurface: ${label} requires at least 3 points`);
|
|
7536
8292
|
const normalized = loop.map(([u2, v], idx) => {
|
|
7537
|
-
requireFinite$
|
|
7538
|
-
requireFinite$
|
|
8293
|
+
requireFinite$9(u2, `${label}[${idx}][0]`);
|
|
8294
|
+
requireFinite$9(v, `${label}[${idx}][1]`);
|
|
7539
8295
|
if (u2 < 0 || u2 > 1 || v < 0 || v > 1) throw new Error(`nurbsSurface: ${label}[${idx}] must stay within [0, 1]`);
|
|
7540
8296
|
return [u2, v];
|
|
7541
8297
|
});
|
|
@@ -7558,8 +8314,8 @@ function normalizeTrimCurve(curve, label) {
|
|
|
7558
8314
|
throw new Error(`nurbsSurface: ${label} needs at least ${degree + 1} control points for degree=${degree}`);
|
|
7559
8315
|
}
|
|
7560
8316
|
const normalizedControlPoints = controlPoints.map(([u2, v], idx) => {
|
|
7561
|
-
requireFinite$
|
|
7562
|
-
requireFinite$
|
|
8317
|
+
requireFinite$9(u2, `${label}.controlPoints[${idx}][0]`);
|
|
8318
|
+
requireFinite$9(v, `${label}.controlPoints[${idx}][1]`);
|
|
7563
8319
|
if (u2 < 0 || u2 > 1 || v < 0 || v > 1) {
|
|
7564
8320
|
throw new Error(`nurbsSurface: ${label}.controlPoints[${idx}] must stay within [0, 1]`);
|
|
7565
8321
|
}
|
|
@@ -7570,7 +8326,7 @@ function normalizeTrimCurve(curve, label) {
|
|
|
7570
8326
|
throw new Error(`nurbsSurface: ${label}.weights length must match controlPoints length`);
|
|
7571
8327
|
}
|
|
7572
8328
|
for (let idx = 0; idx < weights.length; idx += 1) {
|
|
7573
|
-
requireFinite$
|
|
8329
|
+
requireFinite$9(weights[idx], `${label}.weights[${idx}]`);
|
|
7574
8330
|
if (weights[idx] <= 0) throw new Error(`nurbsSurface: ${label}.weights[${idx}] must be > 0`);
|
|
7575
8331
|
}
|
|
7576
8332
|
const knots = curve.knots ?? generateClampedKnots(controlPoints.length, degree);
|
|
@@ -7578,7 +8334,7 @@ function normalizeTrimCurve(curve, label) {
|
|
|
7578
8334
|
throw new Error(`nurbsSurface: ${label}.knots.length should be ${controlPoints.length + degree + 1}, got ${knots.length}`);
|
|
7579
8335
|
}
|
|
7580
8336
|
for (let idx = 0; idx < knots.length; idx += 1) {
|
|
7581
|
-
requireFinite$
|
|
8337
|
+
requireFinite$9(knots[idx], `${label}.knots[${idx}]`);
|
|
7582
8338
|
if (idx > 0 && knots[idx] < knots[idx - 1]) throw new Error(`nurbsSurface: ${label}.knots must be non-decreasing`);
|
|
7583
8339
|
}
|
|
7584
8340
|
if (knots[degree] >= knots[controlPoints.length]) {
|
|
@@ -7758,16 +8514,16 @@ class NurbsSurface {
|
|
|
7758
8514
|
for (let i = 0; i < nU; i++) {
|
|
7759
8515
|
if (controlGrid[i].length !== nV) throw new Error(`nurbsSurface: row ${i} has ${controlGrid[i].length} points, expected ${nV}`);
|
|
7760
8516
|
for (let j = 0; j < nV; j++) {
|
|
7761
|
-
requireFinite$
|
|
7762
|
-
requireFinite$
|
|
7763
|
-
requireFinite$
|
|
8517
|
+
requireFinite$9(controlGrid[i][j][0], `controlGrid[${i}][${j}][0]`);
|
|
8518
|
+
requireFinite$9(controlGrid[i][j][1], `controlGrid[${i}][${j}][1]`);
|
|
8519
|
+
requireFinite$9(controlGrid[i][j][2], `controlGrid[${i}][${j}][2]`);
|
|
7764
8520
|
}
|
|
7765
8521
|
}
|
|
7766
8522
|
const weightsGrid = options.weights ?? controlGrid.map((row) => row.map(() => 1));
|
|
7767
8523
|
for (let i = 0; i < nU; i++) {
|
|
7768
8524
|
if (weightsGrid[i].length !== nV) throw new Error(`nurbsSurface: weights row ${i} length mismatch`);
|
|
7769
8525
|
for (let j = 0; j < nV; j++) {
|
|
7770
|
-
requireFinite$
|
|
8526
|
+
requireFinite$9(weightsGrid[i][j], `weights[${i}][${j}]`);
|
|
7771
8527
|
if (weightsGrid[i][j] <= 0) throw new Error(`nurbsSurface: weights[${i}][${j}] must be > 0`);
|
|
7772
8528
|
}
|
|
7773
8529
|
}
|
|
@@ -9157,8 +9913,8 @@ function stitchSingleLoopLoft(loops, heights, wasm) {
|
|
|
9157
9913
|
const v0 = baseIdx + j;
|
|
9158
9914
|
const v1 = nextIdx + j;
|
|
9159
9915
|
const v2 = nextIdx + j1;
|
|
9160
|
-
const
|
|
9161
|
-
triangles.push(v0,
|
|
9916
|
+
const v32 = baseIdx + j1;
|
|
9917
|
+
triangles.push(v0, v32, v2);
|
|
9162
9918
|
triangles.push(v0, v2, v1);
|
|
9163
9919
|
}
|
|
9164
9920
|
}
|
|
@@ -9199,7 +9955,7 @@ let _wasm$1 = null;
|
|
|
9199
9955
|
async function initManifoldWasm() {
|
|
9200
9956
|
if (_wasm$1) return _wasm$1;
|
|
9201
9957
|
performance.mark("manifold:start");
|
|
9202
|
-
const Module = (await import("./manifold-
|
|
9958
|
+
const Module = (await import("./manifold-Dp6pvFr6.js")).default;
|
|
9203
9959
|
performance.mark("manifold:imported");
|
|
9204
9960
|
const wasm = await Module();
|
|
9205
9961
|
wasm.setup();
|
|
@@ -9481,8 +10237,8 @@ function stitchLoopAlongPath(loop, _path, frames, wasm) {
|
|
|
9481
10237
|
const v0 = baseIdx + j;
|
|
9482
10238
|
const v1 = nextIdx + j;
|
|
9483
10239
|
const v2 = nextIdx + j1;
|
|
9484
|
-
const
|
|
9485
|
-
triangles.push(v0,
|
|
10240
|
+
const v32 = baseIdx + j1;
|
|
10241
|
+
triangles.push(v0, v32, v2);
|
|
9486
10242
|
triangles.push(v0, v2, v1);
|
|
9487
10243
|
}
|
|
9488
10244
|
}
|
|
@@ -10828,8 +11584,16 @@ function lowerShapeCompilePlanToManifold(plan, wasm) {
|
|
|
10828
11584
|
case "importedMesh":
|
|
10829
11585
|
return lowerImportedMeshToManifold(plan.fileData, plan.format, plan.filePath, wasm);
|
|
10830
11586
|
case "sdf": {
|
|
10831
|
-
const
|
|
10832
|
-
return lowerSdfToManifold(
|
|
11587
|
+
const evaluator = compileSdfMaterializationEvaluator3(plan.tree);
|
|
11588
|
+
return lowerSdfToManifold(
|
|
11589
|
+
evaluator.fn,
|
|
11590
|
+
plan.bounds,
|
|
11591
|
+
plan.edgeLength,
|
|
11592
|
+
wasm,
|
|
11593
|
+
plan.meshing,
|
|
11594
|
+
evaluator.engine,
|
|
11595
|
+
evaluator.unsupportedReason
|
|
11596
|
+
);
|
|
10833
11597
|
}
|
|
10834
11598
|
case "fromSlices":
|
|
10835
11599
|
return lowerFromSlicesToManifold(plan, wasm);
|
|
@@ -10847,8 +11611,12 @@ function lowerShapeCompilePlanToManifold(plan, wasm) {
|
|
|
10847
11611
|
assertExhaustive(plan);
|
|
10848
11612
|
}
|
|
10849
11613
|
}
|
|
10850
|
-
function lowerSdfToManifold(evalFn, bounds, edgeLength2, wasm, meshing) {
|
|
11614
|
+
function lowerSdfToManifold(evalFn, bounds, edgeLength2, wasm, meshing, evaluatorEngine, evaluatorUnsupportedReason) {
|
|
10851
11615
|
const diagnostics = (meshing == null ? void 0 : meshing.diagnostics) ? { ...meshing.diagnostics } : void 0;
|
|
11616
|
+
if (diagnostics && evaluatorEngine) {
|
|
11617
|
+
diagnostics.evaluator = evaluatorEngine;
|
|
11618
|
+
if (evaluatorUnsupportedReason) diagnostics.evaluatorUnsupportedReason = evaluatorUnsupportedReason;
|
|
11619
|
+
}
|
|
10852
11620
|
const inset = edgeLength2;
|
|
10853
11621
|
const cappedEvalFn = (x2, y2, z2) => {
|
|
10854
11622
|
const bx = Math.max(bounds.min[0] + inset - x2, x2 - bounds.max[0] + inset);
|
|
@@ -16294,9 +17062,9 @@ function requireClipper() {
|
|
|
16294
17062
|
if (ClipperLib2.use_xyz) j.OffPt.Z = OffPt.Z;
|
|
16295
17063
|
this.m_Joins.push(j);
|
|
16296
17064
|
};
|
|
16297
|
-
ClipperLib2.Clipper.prototype.AddGhostJoin = function(
|
|
17065
|
+
ClipperLib2.Clipper.prototype.AddGhostJoin = function(Op2, OffPt) {
|
|
16298
17066
|
var j = new ClipperLib2.Join();
|
|
16299
|
-
j.OutPt1 =
|
|
17067
|
+
j.OutPt1 = Op2;
|
|
16300
17068
|
j.OffPt.X = OffPt.X;
|
|
16301
17069
|
j.OffPt.Y = OffPt.Y;
|
|
16302
17070
|
if (ClipperLib2.use_xyz) j.OffPt.Z = OffPt.Z;
|
|
@@ -19198,7 +19966,7 @@ function requireClipper() {
|
|
|
19198
19966
|
}
|
|
19199
19967
|
var clipperExports = requireClipper();
|
|
19200
19968
|
var ClipperLib = /* @__PURE__ */ getDefaultExportFromCjs(clipperExports);
|
|
19201
|
-
let f$
|
|
19969
|
+
let f$3 = class f {
|
|
19202
19970
|
constructor(t, e) {
|
|
19203
19971
|
this.next = null, this.key = t, this.data = e, this.left = null, this.right = null;
|
|
19204
19972
|
}
|
|
@@ -19207,7 +19975,7 @@ function d(n, t) {
|
|
|
19207
19975
|
return n > t ? 1 : n < t ? -1 : 0;
|
|
19208
19976
|
}
|
|
19209
19977
|
function u$1(n, t, e) {
|
|
19210
|
-
const r = new f$
|
|
19978
|
+
const r = new f$3(null, null);
|
|
19211
19979
|
let l = r, i = r;
|
|
19212
19980
|
for (; ; ) {
|
|
19213
19981
|
const o = e(n, t.key);
|
|
@@ -19230,7 +19998,7 @@ function u$1(n, t, e) {
|
|
|
19230
19998
|
return l.right = t.left, i.left = t.right, t.left = r.right, t.right = r.left, t;
|
|
19231
19999
|
}
|
|
19232
20000
|
function c(n, t, e, r) {
|
|
19233
|
-
const l = new f$
|
|
20001
|
+
const l = new f$3(n, t);
|
|
19234
20002
|
if (e === null)
|
|
19235
20003
|
return l.left = l.right = null, l;
|
|
19236
20004
|
e = u$1(n, e, r);
|
|
@@ -19271,7 +20039,7 @@ class z {
|
|
|
19271
20039
|
* Adds a key, if it is not present in the tree
|
|
19272
20040
|
*/
|
|
19273
20041
|
add(t, e) {
|
|
19274
|
-
const r = new f$
|
|
20042
|
+
const r = new f$3(t, e);
|
|
19275
20043
|
this._root === null && (r.left = r.right = null, this._size++, this._root = r);
|
|
19276
20044
|
const l = this._comparator, i = u$1(t, this._root, l), o = l(t, i.key);
|
|
19277
20045
|
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;
|
|
@@ -19484,23 +20252,23 @@ class z {
|
|
|
19484
20252
|
function a(n, t, e, r) {
|
|
19485
20253
|
const l = r - e;
|
|
19486
20254
|
if (l > 0) {
|
|
19487
|
-
const i = e + Math.floor(l / 2), o = n[i], s = t[i], h = new f$
|
|
20255
|
+
const i = e + Math.floor(l / 2), o = n[i], s = t[i], h = new f$3(o, s);
|
|
19488
20256
|
return h.left = a(n, t, e, i), h.right = a(n, t, i + 1, r), h;
|
|
19489
20257
|
}
|
|
19490
20258
|
return null;
|
|
19491
20259
|
}
|
|
19492
20260
|
function x(n, t) {
|
|
19493
|
-
const e = new f$
|
|
20261
|
+
const e = new f$3(null, null);
|
|
19494
20262
|
let r = e;
|
|
19495
20263
|
for (let l = 0; l < n.length; l++)
|
|
19496
|
-
r = r.next = new f$
|
|
20264
|
+
r = r.next = new f$3(n[l], t[l]);
|
|
19497
20265
|
return r.next = null, e.next;
|
|
19498
20266
|
}
|
|
19499
20267
|
function k(n) {
|
|
19500
20268
|
let t = n;
|
|
19501
20269
|
const e = [];
|
|
19502
20270
|
let r = false;
|
|
19503
|
-
const l = new f$
|
|
20271
|
+
const l = new f$3(null, null);
|
|
19504
20272
|
let i = l;
|
|
19505
20273
|
for (; !r; )
|
|
19506
20274
|
t ? (e.push(t), t = t.left) : e.length > 0 ? (t = i = i.next = e.pop(), t = t.right) : r = true;
|
|
@@ -19515,7 +20283,7 @@ function p(n, t, e) {
|
|
|
19515
20283
|
return null;
|
|
19516
20284
|
}
|
|
19517
20285
|
function y(n, t, e) {
|
|
19518
|
-
const r = new f$
|
|
20286
|
+
const r = new f$3(null, null);
|
|
19519
20287
|
let l = r, i = n, o = t;
|
|
19520
20288
|
for (; i !== null && o !== null; )
|
|
19521
20289
|
e(i.key, o.key) < 0 ? (l.next = i, i = i.next) : (l.next = o, o = o.next), l = l.next;
|
|
@@ -24500,7 +25268,13 @@ function normalizeTruckShapeForBooleanInput(shape) {
|
|
|
24500
25268
|
return normalized;
|
|
24501
25269
|
}
|
|
24502
25270
|
function lowerSdfPlan(plan) {
|
|
24503
|
-
|
|
25271
|
+
var _a3, _b3, _c2;
|
|
25272
|
+
const evaluator = compileSdfMaterializationEvaluator3(plan.tree);
|
|
25273
|
+
if ((_a3 = plan.meshing) == null ? void 0 : _a3.diagnostics) {
|
|
25274
|
+
plan.meshing.diagnostics.evaluator = evaluator.engine;
|
|
25275
|
+
if (evaluator.unsupportedReason) plan.meshing.diagnostics.evaluatorUnsupportedReason = evaluator.unsupportedReason;
|
|
25276
|
+
}
|
|
25277
|
+
const evalFn = evaluator.fn;
|
|
24504
25278
|
const inset = plan.edgeLength;
|
|
24505
25279
|
const cappedEvalFn = (x2, y2, z2) => {
|
|
24506
25280
|
const bx = Math.max(plan.bounds.min[0] + inset - x2, x2 - plan.bounds.max[0] + inset);
|
|
@@ -24512,14 +25286,18 @@ function lowerSdfPlan(plan) {
|
|
|
24512
25286
|
assertSdfMeshBudget(mesh, plan);
|
|
24513
25287
|
let surfaceNetsError;
|
|
24514
25288
|
try {
|
|
24515
|
-
|
|
25289
|
+
const shape = lowerExtractedSdfMesh(mesh, cappedEvalFn, true);
|
|
25290
|
+
if ((_b3 = plan.meshing) == null ? void 0 : _b3.diagnostics) logSdfMeshingDiagnostics("SDF meshing result", plan.meshing.diagnostics);
|
|
25291
|
+
return shape;
|
|
24516
25292
|
} catch (error) {
|
|
24517
25293
|
surfaceNetsError = error;
|
|
24518
25294
|
}
|
|
24519
25295
|
const tetraMesh = marchingTetrahedra(cappedEvalFn, plan.bounds, plan.edgeLength);
|
|
24520
25296
|
assertSdfMeshBudget(tetraMesh, plan);
|
|
24521
25297
|
try {
|
|
24522
|
-
|
|
25298
|
+
const shape = lowerExtractedSdfMesh(tetraMesh, cappedEvalFn, false);
|
|
25299
|
+
if ((_c2 = plan.meshing) == null ? void 0 : _c2.diagnostics) logSdfMeshingDiagnostics("SDF meshing result", plan.meshing.diagnostics);
|
|
25300
|
+
return shape;
|
|
24523
25301
|
} catch (error) {
|
|
24524
25302
|
throw new Error(
|
|
24525
25303
|
`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)}`
|
|
@@ -24883,7 +25661,9 @@ function lowerOffsetSolidPlan(plan) {
|
|
|
24883
25661
|
if (base.kind === "transform") {
|
|
24884
25662
|
return lowerTransformedOffsetSolidPlan(base, plan.thickness);
|
|
24885
25663
|
}
|
|
24886
|
-
return truckUnsupported(
|
|
25664
|
+
return truckUnsupported(
|
|
25665
|
+
`compile plan "${plan.kind}" for non-vertical-prism/non-revolved/non-loft/non-straight-sweep/non-straight-variable-sweep solids`
|
|
25666
|
+
);
|
|
24887
25667
|
}
|
|
24888
25668
|
function lowerLoftPlan(plan) {
|
|
24889
25669
|
return wrapTruckShapeBackend(
|
|
@@ -32185,6 +32965,37 @@ function mergeSketchPlacementModel(sketches) {
|
|
|
32185
32965
|
}
|
|
32186
32966
|
return first;
|
|
32187
32967
|
}
|
|
32968
|
+
function normalizeSceneTags(value, label = "tags") {
|
|
32969
|
+
if (value == null) return [];
|
|
32970
|
+
const rawTags = typeof value === "string" ? [value] : value;
|
|
32971
|
+
if (!Array.isArray(rawTags)) {
|
|
32972
|
+
throw new Error(`${label} must be a string or array of strings`);
|
|
32973
|
+
}
|
|
32974
|
+
const out = [];
|
|
32975
|
+
const seen = /* @__PURE__ */ new Set();
|
|
32976
|
+
rawTags.forEach((tag, index2) => {
|
|
32977
|
+
if (typeof tag !== "string") {
|
|
32978
|
+
throw new Error(`${label}[${index2}] must be a string`);
|
|
32979
|
+
}
|
|
32980
|
+
const trimmed = tag.trim();
|
|
32981
|
+
if (!trimmed || seen.has(trimmed)) return;
|
|
32982
|
+
seen.add(trimmed);
|
|
32983
|
+
out.push(trimmed);
|
|
32984
|
+
});
|
|
32985
|
+
return out;
|
|
32986
|
+
}
|
|
32987
|
+
function mergeSceneTags(...values) {
|
|
32988
|
+
const out = [];
|
|
32989
|
+
const seen = /* @__PURE__ */ new Set();
|
|
32990
|
+
values.forEach((value) => {
|
|
32991
|
+
normalizeSceneTags(value).forEach((tag) => {
|
|
32992
|
+
if (seen.has(tag)) return;
|
|
32993
|
+
seen.add(tag);
|
|
32994
|
+
out.push(tag);
|
|
32995
|
+
});
|
|
32996
|
+
});
|
|
32997
|
+
return out;
|
|
32998
|
+
}
|
|
32188
32999
|
const _groupPlacementRefs = /* @__PURE__ */ new WeakMap();
|
|
32189
33000
|
const _groupExplodeHint = /* @__PURE__ */ new WeakMap();
|
|
32190
33001
|
function getGroupRefs(g2) {
|
|
@@ -32208,7 +33019,7 @@ function transformGroupRefs(source, dest, matrix) {
|
|
|
32208
33019
|
}
|
|
32209
33020
|
return dest;
|
|
32210
33021
|
}
|
|
32211
|
-
function requireFiniteAngle(v, method) {
|
|
33022
|
+
function requireFiniteAngle$1(v, method) {
|
|
32212
33023
|
if (typeof v !== "number" || !Number.isFinite(v))
|
|
32213
33024
|
throw new Error(`${method} angleDeg must be a finite number, got ${typeof v === "number" ? v : typeof v}`);
|
|
32214
33025
|
}
|
|
@@ -32269,31 +33080,46 @@ function resolveNamedGroupChild(item) {
|
|
|
32269
33080
|
function normalizeGroupInputs(items) {
|
|
32270
33081
|
const children = [];
|
|
32271
33082
|
const childNames = [];
|
|
33083
|
+
const childTags = [];
|
|
32272
33084
|
items.forEach((item) => {
|
|
32273
33085
|
if (isNamedGroupChild(item)) {
|
|
32274
33086
|
children.push(resolveNamedGroupChild(item));
|
|
32275
33087
|
childNames.push(normalizeChildName(item.name));
|
|
33088
|
+
childTags.push(normalizeSceneTags(item.tags, `group(...) named item "${item.name}" tags`));
|
|
32276
33089
|
return;
|
|
32277
33090
|
}
|
|
32278
33091
|
children.push(item);
|
|
32279
33092
|
childNames.push(void 0);
|
|
33093
|
+
childTags.push([]);
|
|
32280
33094
|
});
|
|
32281
|
-
return { children, childNames };
|
|
33095
|
+
return { children, childNames, childTags };
|
|
32282
33096
|
}
|
|
32283
33097
|
class ShapeGroup {
|
|
32284
|
-
constructor(children, childNames) {
|
|
33098
|
+
constructor(children, childNames, childTags) {
|
|
32285
33099
|
__publicField(this, "children");
|
|
32286
33100
|
__publicField(this, "childNames");
|
|
33101
|
+
__publicField(this, "childTags");
|
|
32287
33102
|
if (childNames && childNames.length !== children.length) {
|
|
32288
33103
|
throw new Error("ShapeGroup childNames must match children length");
|
|
32289
33104
|
}
|
|
33105
|
+
if (childTags && childTags.length !== children.length) {
|
|
33106
|
+
throw new Error("ShapeGroup childTags must match children length");
|
|
33107
|
+
}
|
|
32290
33108
|
this.children = [...children];
|
|
32291
33109
|
this.childNames = this.children.map((_2, index2) => normalizeChildName(childNames == null ? void 0 : childNames[index2]));
|
|
33110
|
+
this.childTags = this.children.map((_2, index2) => normalizeSceneTags(childTags == null ? void 0 : childTags[index2], "ShapeGroup childTags"));
|
|
32292
33111
|
}
|
|
32293
33112
|
/** Return the optional name of the child at `index`. */
|
|
32294
33113
|
childName(index2) {
|
|
32295
33114
|
return this.childNames[index2];
|
|
32296
33115
|
}
|
|
33116
|
+
/**
|
|
33117
|
+
* Return tags attached to the child at `index`.
|
|
33118
|
+
* @internal
|
|
33119
|
+
*/
|
|
33120
|
+
tagsForChild(index2) {
|
|
33121
|
+
return [...this.childTags[index2] ?? []];
|
|
33122
|
+
}
|
|
32297
33123
|
/**
|
|
32298
33124
|
* Return the named child by name. Throws if not found.
|
|
32299
33125
|
* Useful when importing a multipart group and working on components individually.
|
|
@@ -32308,13 +33134,13 @@ class ShapeGroup {
|
|
|
32308
33134
|
}
|
|
32309
33135
|
/** Apply fn to all children, producing a new ShapeGroup that also copies placement refs. */
|
|
32310
33136
|
mapChildren(fn) {
|
|
32311
|
-
const next = new ShapeGroup(this.children.map(fn), this.childNames);
|
|
33137
|
+
const next = new ShapeGroup(this.children.map(fn), this.childNames, this.childTags);
|
|
32312
33138
|
copyGroupPorts(this, next);
|
|
32313
33139
|
return copyGroupRefs(this, next);
|
|
32314
33140
|
}
|
|
32315
33141
|
/** Apply fn to all children and also transform placement refs by the given matrix. */
|
|
32316
33142
|
mapChildrenTransform(fn, matrix) {
|
|
32317
|
-
const next = new ShapeGroup(this.children.map(fn), this.childNames);
|
|
33143
|
+
const next = new ShapeGroup(this.children.map(fn), this.childNames, this.childTags);
|
|
32318
33144
|
transformGroupPortsHelper(this, next, matrix);
|
|
32319
33145
|
return transformGroupRefs(this, next, matrix);
|
|
32320
33146
|
}
|
|
@@ -32441,25 +33267,25 @@ class ShapeGroup {
|
|
|
32441
33267
|
/** Rotate the group around an arbitrary axis through the origin. */
|
|
32442
33268
|
rotate(axis, angleDeg, options) {
|
|
32443
33269
|
requireRotateAxis(axis, "ShapeGroup.rotate()");
|
|
32444
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotate()");
|
|
33270
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotate()");
|
|
32445
33271
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotate()");
|
|
32446
33272
|
return this.rotateAroundAxis(axis, angleDeg, options == null ? void 0 : options.pivot);
|
|
32447
33273
|
}
|
|
32448
33274
|
/** Rotate the group around the X axis. */
|
|
32449
33275
|
rotateX(angleDeg, options) {
|
|
32450
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotateX()");
|
|
33276
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotateX()");
|
|
32451
33277
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotateX()");
|
|
32452
33278
|
return this.rotateAroundAxis([1, 0, 0], angleDeg, options == null ? void 0 : options.pivot);
|
|
32453
33279
|
}
|
|
32454
33280
|
/** Rotate the group around the Y axis. */
|
|
32455
33281
|
rotateY(angleDeg, options) {
|
|
32456
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotateY()");
|
|
33282
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotateY()");
|
|
32457
33283
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotateY()");
|
|
32458
33284
|
return this.rotateAroundAxis([0, 1, 0], angleDeg, options == null ? void 0 : options.pivot);
|
|
32459
33285
|
}
|
|
32460
33286
|
/** Rotate the group around the Z axis. */
|
|
32461
33287
|
rotateZ(angleDeg, options) {
|
|
32462
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotateZ()");
|
|
33288
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotateZ()");
|
|
32463
33289
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotateZ()");
|
|
32464
33290
|
return this.rotateAroundAxis([0, 0, 1], angleDeg, options == null ? void 0 : options.pivot);
|
|
32465
33291
|
}
|
|
@@ -32502,7 +33328,8 @@ class ShapeGroup {
|
|
|
32502
33328
|
"ShapeGroup.transform only supports 3D children (Shape/ShapeGroup). For Sketch children, use 2D transforms (translate/rotate/scale/mirror)."
|
|
32503
33329
|
);
|
|
32504
33330
|
}),
|
|
32505
|
-
this.childNames
|
|
33331
|
+
this.childNames,
|
|
33332
|
+
this.childTags
|
|
32506
33333
|
);
|
|
32507
33334
|
transformGroupPortsHelper(this, next, matrix);
|
|
32508
33335
|
return transformGroupRefs(this, next, matrix);
|
|
@@ -32570,7 +33397,7 @@ class ShapeGroup {
|
|
|
32570
33397
|
* ```
|
|
32571
33398
|
*/
|
|
32572
33399
|
withReferences(refs) {
|
|
32573
|
-
const next = new ShapeGroup(this.children, this.childNames);
|
|
33400
|
+
const next = new ShapeGroup(this.children, this.childNames, this.childTags);
|
|
32574
33401
|
const merged = applyPlacementReferenceInput(getGroupRefs(this), refs);
|
|
32575
33402
|
return setGroupRefs(next, merged);
|
|
32576
33403
|
}
|
|
@@ -32638,7 +33465,7 @@ class ShapeGroup {
|
|
|
32638
33465
|
/** Attach named connectors — attachment points that survive transforms.
|
|
32639
33466
|
* Connectors can be bare (position + orientation) or typed (with connectorType/gender for compatibility matching). */
|
|
32640
33467
|
withConnectors(connectors) {
|
|
32641
|
-
const next = new ShapeGroup(this.children, this.childNames);
|
|
33468
|
+
const next = new ShapeGroup(this.children, this.childNames, this.childTags);
|
|
32642
33469
|
copyGroupRefs(this, next);
|
|
32643
33470
|
const existing = getGroupPorts(this);
|
|
32644
33471
|
const incoming = normalizeConnectorMapInput(connectors);
|
|
@@ -32688,7 +33515,7 @@ class ShapeGroup {
|
|
|
32688
33515
|
}
|
|
32689
33516
|
function group(...items) {
|
|
32690
33517
|
const normalized = normalizeGroupInputs(items);
|
|
32691
|
-
return new ShapeGroup(normalized.children, normalized.childNames);
|
|
33518
|
+
return new ShapeGroup(normalized.children, normalized.childNames, normalized.childTags);
|
|
32692
33519
|
}
|
|
32693
33520
|
function getTargetPortsForGroup(target) {
|
|
32694
33521
|
if (target instanceof Shape) {
|
|
@@ -34859,7 +35686,7 @@ function buildSdfFunctionDefinition(source, options) {
|
|
|
34859
35686
|
jsExpression: expression,
|
|
34860
35687
|
...shader.ok ? { shaderExpression: shader.expression } : { shaderUnsupportedReason: shader.reason },
|
|
34861
35688
|
raymarchStepLimit: resolveRaymarchStepLimit(options.bounds, options.maxStep),
|
|
34862
|
-
...options.lipschitz !== void 0 ? { raymarchLipschitz: requirePositiveFinite$
|
|
35689
|
+
...options.lipschitz !== void 0 ? { raymarchLipschitz: requirePositiveFinite$2(options.lipschitz, "sdf.fromFunction() lipschitz") } : {}
|
|
34863
35690
|
};
|
|
34864
35691
|
}
|
|
34865
35692
|
function extractSdfExpression(source) {
|
|
@@ -35027,7 +35854,7 @@ function formatNumericLiteralsForGlsl(source) {
|
|
|
35027
35854
|
return result;
|
|
35028
35855
|
}
|
|
35029
35856
|
function resolveRaymarchStepLimit(bounds, maxStep) {
|
|
35030
|
-
if (maxStep !== void 0) return requirePositiveFinite$
|
|
35857
|
+
if (maxStep !== void 0) return requirePositiveFinite$2(maxStep, "sdf.fromFunction() maxStep");
|
|
35031
35858
|
const dx = bounds.max[0] - bounds.min[0];
|
|
35032
35859
|
const dy = bounds.max[1] - bounds.min[1];
|
|
35033
35860
|
const dz = bounds.max[2] - bounds.min[2];
|
|
@@ -35035,7 +35862,7 @@ function resolveRaymarchStepLimit(bounds, maxStep) {
|
|
|
35035
35862
|
if (!Number.isFinite(diagonal) || diagonal <= 0) return 0.1;
|
|
35036
35863
|
return Math.max(0.025, Math.min(0.5, diagonal / 240));
|
|
35037
35864
|
}
|
|
35038
|
-
function requirePositiveFinite$
|
|
35865
|
+
function requirePositiveFinite$2(value, label) {
|
|
35039
35866
|
if (!Number.isFinite(value) || value <= 0) throw new Error(`${label} must be a positive finite number.`);
|
|
35040
35867
|
return value;
|
|
35041
35868
|
}
|
|
@@ -35062,6 +35889,199 @@ class SurfacePattern {
|
|
|
35062
35889
|
this.constants = constants;
|
|
35063
35890
|
}
|
|
35064
35891
|
}
|
|
35892
|
+
const typedSurfacePatterns = /* @__PURE__ */ new WeakMap();
|
|
35893
|
+
function getTypedSurfacePattern(pattern) {
|
|
35894
|
+
return typedSurfacePatterns.get(pattern);
|
|
35895
|
+
}
|
|
35896
|
+
class Pattern2D extends SurfacePattern {
|
|
35897
|
+
constructor(body) {
|
|
35898
|
+
super(body);
|
|
35899
|
+
}
|
|
35900
|
+
/** Add this pattern to one or more patterns or constant height offsets. */
|
|
35901
|
+
add(...patterns) {
|
|
35902
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
35903
|
+
}
|
|
35904
|
+
/** Subtract another pattern or constant height offset from this pattern. */
|
|
35905
|
+
subtract(pattern) {
|
|
35906
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
35907
|
+
}
|
|
35908
|
+
/** Multiply this pattern by one or more patterns or numeric scale factors. */
|
|
35909
|
+
multiply(...patterns) {
|
|
35910
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
35911
|
+
}
|
|
35912
|
+
/** Keep the lower height between this pattern and one or more other patterns. */
|
|
35913
|
+
min(...patterns) {
|
|
35914
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
35915
|
+
}
|
|
35916
|
+
/** Keep the higher height between this pattern and one or more other patterns. */
|
|
35917
|
+
max(...patterns) {
|
|
35918
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
35919
|
+
}
|
|
35920
|
+
/** Limit pattern height to the inclusive `[min, max]` range in millimeters. */
|
|
35921
|
+
clamp(min2, max2) {
|
|
35922
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
35923
|
+
}
|
|
35924
|
+
/** Convert negative heights to positive heights. */
|
|
35925
|
+
abs() {
|
|
35926
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
35927
|
+
}
|
|
35928
|
+
/** Flip the pattern height sign. */
|
|
35929
|
+
negate() {
|
|
35930
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
35931
|
+
}
|
|
35932
|
+
}
|
|
35933
|
+
class Pattern2DImpl extends Pattern2D {
|
|
35934
|
+
constructor(node) {
|
|
35935
|
+
super(emitSurfacePatternJsExpression(node));
|
|
35936
|
+
__publicField(this, "node");
|
|
35937
|
+
this.node = node;
|
|
35938
|
+
typedSurfacePatterns.set(this, node);
|
|
35939
|
+
}
|
|
35940
|
+
add(...patterns) {
|
|
35941
|
+
return new Pattern2DImpl({ kind: "surfacePattern:add", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
35942
|
+
}
|
|
35943
|
+
subtract(pattern) {
|
|
35944
|
+
return this.add(new Pattern2DImpl({ kind: "surfacePattern:negate", child: patternNodeFromInput(pattern) }));
|
|
35945
|
+
}
|
|
35946
|
+
multiply(...patterns) {
|
|
35947
|
+
return new Pattern2DImpl({ kind: "surfacePattern:multiply", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
35948
|
+
}
|
|
35949
|
+
min(...patterns) {
|
|
35950
|
+
return new Pattern2DImpl({ kind: "surfacePattern:min", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
35951
|
+
}
|
|
35952
|
+
max(...patterns) {
|
|
35953
|
+
return new Pattern2DImpl({ kind: "surfacePattern:max", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
35954
|
+
}
|
|
35955
|
+
clamp(min2, max2) {
|
|
35956
|
+
const lo = requireFinite$8(min2, "Pattern2D.clamp() min");
|
|
35957
|
+
const hi = requireFinite$8(max2, "Pattern2D.clamp() max");
|
|
35958
|
+
if (lo > hi) throw new Error(`Pattern2D.clamp() min must be <= max. Received: ${lo} > ${hi}`);
|
|
35959
|
+
return new Pattern2DImpl({ kind: "surfacePattern:clamp", child: this.node, min: lo, max: hi });
|
|
35960
|
+
}
|
|
35961
|
+
abs() {
|
|
35962
|
+
return new Pattern2DImpl({ kind: "surfacePattern:abs", child: this.node });
|
|
35963
|
+
}
|
|
35964
|
+
negate() {
|
|
35965
|
+
return new Pattern2DImpl({ kind: "surfacePattern:negate", child: this.node });
|
|
35966
|
+
}
|
|
35967
|
+
}
|
|
35968
|
+
class Pattern2DBuilder {
|
|
35969
|
+
/** Create a constant-height pattern in millimeters. */
|
|
35970
|
+
constant(value = 0) {
|
|
35971
|
+
return new Pattern2DImpl({ kind: "surfacePattern:constant", value: requireFinite$8(value, "sdf.pattern2d().constant() value") });
|
|
35972
|
+
}
|
|
35973
|
+
/** Create a sinusoidal wave pattern in UV space. */
|
|
35974
|
+
sineWave(options) {
|
|
35975
|
+
return new Pattern2DImpl({
|
|
35976
|
+
kind: "surfacePattern:sineWave",
|
|
35977
|
+
direction: normalizeDirection$1(options.direction ?? [1, 0], "sdf.pattern2d().sineWave() direction"),
|
|
35978
|
+
wavelength: requirePositiveFinite$1(options.wavelength, "sdf.pattern2d().sineWave() wavelength"),
|
|
35979
|
+
amplitude: requireFinite$8(options.amplitude ?? 1, "sdf.pattern2d().sineWave() amplitude"),
|
|
35980
|
+
phase: requireFinite$8(options.phase ?? 0, "sdf.pattern2d().sineWave() phase"),
|
|
35981
|
+
bias: requireFinite$8(options.bias ?? 0, "sdf.pattern2d().sineWave() bias")
|
|
35982
|
+
});
|
|
35983
|
+
}
|
|
35984
|
+
/** Create recessed stripe bands in UV space. */
|
|
35985
|
+
stripes(options) {
|
|
35986
|
+
return new Pattern2DImpl({
|
|
35987
|
+
kind: "surfacePattern:stripes",
|
|
35988
|
+
direction: normalizeDirection$1(options.direction ?? [1, 0], "sdf.pattern2d().stripes() direction"),
|
|
35989
|
+
spacing: requirePositiveFinite$1(options.spacing, "sdf.pattern2d().stripes() spacing"),
|
|
35990
|
+
width: requirePositiveFinite$1(options.width, "sdf.pattern2d().stripes() width"),
|
|
35991
|
+
depth: requireNonNegativeFinite$1(options.depth ?? 1, "sdf.pattern2d().stripes() depth")
|
|
35992
|
+
});
|
|
35993
|
+
}
|
|
35994
|
+
/** Create an over-under woven relief pattern in UV space. */
|
|
35995
|
+
overUnderWeave(options) {
|
|
35996
|
+
return new Pattern2DImpl({
|
|
35997
|
+
kind: "surfacePattern:overUnderWeave",
|
|
35998
|
+
spacing: normalizeVec2(options.spacing, "sdf.pattern2d().overUnderWeave() spacing", requirePositiveFinite$1),
|
|
35999
|
+
threadWidth: normalizeVec2(options.threadWidth, "sdf.pattern2d().overUnderWeave() threadWidth", requirePositiveFinite$1),
|
|
36000
|
+
depth: requireNonNegativeFinite$1(options.depth ?? 0.8, "sdf.pattern2d().overUnderWeave() depth"),
|
|
36001
|
+
underScale: requireNonNegativeFinite$1(options.underScale ?? 0.15, "sdf.pattern2d().overUnderWeave() underScale")
|
|
36002
|
+
});
|
|
36003
|
+
}
|
|
36004
|
+
}
|
|
36005
|
+
function pattern2d() {
|
|
36006
|
+
return new Pattern2DBuilder();
|
|
36007
|
+
}
|
|
36008
|
+
function patternNodeFromInput(input) {
|
|
36009
|
+
if (input instanceof SurfacePattern) {
|
|
36010
|
+
const node = getTypedSurfacePattern(input);
|
|
36011
|
+
if (node) return node;
|
|
36012
|
+
}
|
|
36013
|
+
if (typeof input === "number") {
|
|
36014
|
+
return { kind: "surfacePattern:constant", value: requireFinite$8(input, "Pattern2D numeric input") };
|
|
36015
|
+
}
|
|
36016
|
+
throw new Error("Pattern2D composition expects another typed Pattern2D or a number.");
|
|
36017
|
+
}
|
|
36018
|
+
function requireFinite$8(value, label) {
|
|
36019
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
36020
|
+
throw new Error(`${label} must be a finite number. Received: ${String(value)}`);
|
|
36021
|
+
}
|
|
36022
|
+
return value;
|
|
36023
|
+
}
|
|
36024
|
+
function requirePositiveFinite$1(value, label) {
|
|
36025
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
36026
|
+
throw new Error(`${label} must be a positive finite number. Received: ${String(value)}`);
|
|
36027
|
+
}
|
|
36028
|
+
return value;
|
|
36029
|
+
}
|
|
36030
|
+
function requireNonNegativeFinite$1(value, label) {
|
|
36031
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
36032
|
+
throw new Error(`${label} must be a non-negative finite number. Received: ${String(value)}`);
|
|
36033
|
+
}
|
|
36034
|
+
return value;
|
|
36035
|
+
}
|
|
36036
|
+
function normalizeVec2(value, label, validate) {
|
|
36037
|
+
if (typeof value === "number") {
|
|
36038
|
+
const n = validate(value, label);
|
|
36039
|
+
return [n, n];
|
|
36040
|
+
}
|
|
36041
|
+
return [validate(value[0], `${label}[0]`), validate(value[1], `${label}[1]`)];
|
|
36042
|
+
}
|
|
36043
|
+
function normalizeDirection$1(value, label) {
|
|
36044
|
+
const x2 = requireFinite$8(value[0], `${label}[0]`);
|
|
36045
|
+
const y2 = requireFinite$8(value[1], `${label}[1]`);
|
|
36046
|
+
const length4 = Math.hypot(x2, y2);
|
|
36047
|
+
if (length4 <= 0) throw new Error(`${label} must not be the zero vector.`);
|
|
36048
|
+
return [x2 / length4, y2 / length4];
|
|
36049
|
+
}
|
|
36050
|
+
function f$2(value) {
|
|
36051
|
+
if (!Number.isFinite(value)) return "0";
|
|
36052
|
+
return Number(value.toPrecision(12)).toString();
|
|
36053
|
+
}
|
|
36054
|
+
function emitSurfacePatternJsExpression(node) {
|
|
36055
|
+
switch (node.kind) {
|
|
36056
|
+
case "surfacePattern:constant":
|
|
36057
|
+
return f$2(node.value);
|
|
36058
|
+
case "surfacePattern:sineWave": {
|
|
36059
|
+
const coord = `(u * ${f$2(node.direction[0])} + v * ${f$2(node.direction[1])})`;
|
|
36060
|
+
const phase = `(${coord} * ${f$2(2 * Math.PI / node.wavelength)} + ${f$2(node.phase)})`;
|
|
36061
|
+
return `(${f$2(node.bias)} + Math.sin(${phase}) * ${f$2(node.amplitude)})`;
|
|
36062
|
+
}
|
|
36063
|
+
case "surfacePattern:stripes": {
|
|
36064
|
+
const coord = `(u * ${f$2(node.direction[0])} + v * ${f$2(node.direction[1])})`;
|
|
36065
|
+
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)};})()`;
|
|
36066
|
+
}
|
|
36067
|
+
case "surfacePattern:overUnderWeave":
|
|
36068
|
+
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)};})()`;
|
|
36069
|
+
case "surfacePattern:abs":
|
|
36070
|
+
return `Math.abs(${emitSurfacePatternJsExpression(node.child)})`;
|
|
36071
|
+
case "surfacePattern:negate":
|
|
36072
|
+
return `(-(${emitSurfacePatternJsExpression(node.child)}))`;
|
|
36073
|
+
case "surfacePattern:add":
|
|
36074
|
+
return node.children.length === 0 ? "0" : `(${node.children.map(emitSurfacePatternJsExpression).join(" + ")})`;
|
|
36075
|
+
case "surfacePattern:multiply":
|
|
36076
|
+
return node.children.length === 0 ? "1" : `(${node.children.map(emitSurfacePatternJsExpression).join(" * ")})`;
|
|
36077
|
+
case "surfacePattern:min":
|
|
36078
|
+
return node.children.length === 0 ? "0" : `Math.min(${node.children.map(emitSurfacePatternJsExpression).join(", ")})`;
|
|
36079
|
+
case "surfacePattern:max":
|
|
36080
|
+
return node.children.length === 0 ? "0" : `Math.max(${node.children.map(emitSurfacePatternJsExpression).join(", ")})`;
|
|
36081
|
+
case "surfacePattern:clamp":
|
|
36082
|
+
return `Math.min(${f$2(node.max)}, Math.max(${f$2(node.min)}, ${emitSurfacePatternJsExpression(node.child)}))`;
|
|
36083
|
+
}
|
|
36084
|
+
}
|
|
35065
36085
|
const SCULPT_MATERIAL_PRESETS = {
|
|
35066
36086
|
ceramic: {
|
|
35067
36087
|
color: "#f4f0e6",
|
|
@@ -35131,6 +36151,18 @@ function requirePositiveFinite(value, label) {
|
|
|
35131
36151
|
}
|
|
35132
36152
|
return value;
|
|
35133
36153
|
}
|
|
36154
|
+
function requirePositiveInteger(value, label) {
|
|
36155
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value < 1) {
|
|
36156
|
+
throw new Error(`${label} must be a positive integer. Received: ${String(value)}`);
|
|
36157
|
+
}
|
|
36158
|
+
return value;
|
|
36159
|
+
}
|
|
36160
|
+
function requireNonNegativeFinite(value, label) {
|
|
36161
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
36162
|
+
throw new Error(`${label} must be a non-negative finite number. Received: ${String(value)}`);
|
|
36163
|
+
}
|
|
36164
|
+
return value;
|
|
36165
|
+
}
|
|
35134
36166
|
function resolveBlendRadius(input, label, fallback = 4) {
|
|
35135
36167
|
if (typeof input === "number") return requirePositiveFinite(input, `${label} radius`);
|
|
35136
36168
|
if ((input == null ? void 0 : input.radius) !== void 0) return requirePositiveFinite(input.radius, `${label} radius`);
|
|
@@ -35377,6 +36409,29 @@ class SdfShape {
|
|
|
35377
36409
|
clipBox(x2, y2, z2) {
|
|
35378
36410
|
return this.intersect(box$1(x2, y2, z2));
|
|
35379
36411
|
}
|
|
36412
|
+
/** Keep only the material where this shape overlaps another SDF pattern. */
|
|
36413
|
+
fillWith(pattern) {
|
|
36414
|
+
if (!(pattern instanceof SdfShape)) {
|
|
36415
|
+
throw new Error("SdfShape.fillWith() expects an SdfShape pattern, such as sdf.gyroid({ cellSize, wallThickness }).");
|
|
36416
|
+
}
|
|
36417
|
+
return this.intersect(pattern);
|
|
36418
|
+
}
|
|
36419
|
+
/** Keep only the gyroid lattice inside this shape. */
|
|
36420
|
+
fillWithGyroid(options) {
|
|
36421
|
+
return this.fillWith(gyroid(options));
|
|
36422
|
+
}
|
|
36423
|
+
/** Keep only the Schwarz-P lattice inside this shape. */
|
|
36424
|
+
fillWithSchwarzP(options) {
|
|
36425
|
+
return this.fillWith(schwarzP(options));
|
|
36426
|
+
}
|
|
36427
|
+
/** Keep only the diamond TPMS lattice inside this shape. */
|
|
36428
|
+
fillWithDiamond(options) {
|
|
36429
|
+
return this.fillWith(diamond(options));
|
|
36430
|
+
}
|
|
36431
|
+
/** Keep only the lidinoid TPMS lattice inside this shape. */
|
|
36432
|
+
fillWithLidinoid(options) {
|
|
36433
|
+
return this.fillWith(lidinoid(options));
|
|
36434
|
+
}
|
|
35380
36435
|
/** Smooth union — blends shapes together with a smooth radius. */
|
|
35381
36436
|
smoothUnion(other, radius) {
|
|
35382
36437
|
return this.withNode({ kind: "sdf:smoothUnion", children: [this._node, other._node], radius });
|
|
@@ -35437,6 +36492,21 @@ class SdfShape {
|
|
|
35437
36492
|
repeat(spacing, count) {
|
|
35438
36493
|
return this.withNode({ kind: "sdf:repeat", child: this._node, spacing, count: count ?? [0, 0, 0] });
|
|
35439
36494
|
}
|
|
36495
|
+
/**
|
|
36496
|
+
* Arrange this SDF in a circular array around the Z axis.
|
|
36497
|
+
*
|
|
36498
|
+
* The source shape is translated by `offset` in +X before arraying. This uses
|
|
36499
|
+
* angular domain folding, so evaluation stays O(1): the source SDF is sampled
|
|
36500
|
+
* twice no matter how many copies are requested.
|
|
36501
|
+
*/
|
|
36502
|
+
circularArray(count, offset2 = 0) {
|
|
36503
|
+
return this.withNode({
|
|
36504
|
+
kind: "sdf:circularArray",
|
|
36505
|
+
child: this._node,
|
|
36506
|
+
count: requirePositiveInteger(count, "SdfShape.circularArray() count"),
|
|
36507
|
+
offset: requireNonNegativeFinite(offset2, "SdfShape.circularArray() offset")
|
|
36508
|
+
});
|
|
36509
|
+
}
|
|
35440
36510
|
/** Hollow out, keeping only a shell of given thickness. */
|
|
35441
36511
|
shell(thickness) {
|
|
35442
36512
|
return this.withNode({ kind: "sdf:shell", child: this._node, thickness });
|
|
@@ -35448,8 +36518,8 @@ class SdfShape {
|
|
|
35448
36518
|
* // Function displacement
|
|
35449
36519
|
* shape.displace((x, y, z) => Math.sin(x) * 0.5)
|
|
35450
36520
|
*
|
|
35451
|
-
* // Pattern displacement
|
|
35452
|
-
* shape.displace(sdf.
|
|
36521
|
+
* // Pattern displacement from a 3D SDF field
|
|
36522
|
+
* shape.displace(sdf.knurl({ pitch: 2, depth: 0.3 }))
|
|
35453
36523
|
* ```
|
|
35454
36524
|
*/
|
|
35455
36525
|
displace(fn, constants) {
|
|
@@ -35473,10 +36543,18 @@ class SdfShape {
|
|
|
35473
36543
|
* UV coordinates are in **surface millimeters** — patterns defined with `spacing: 3`
|
|
35474
36544
|
* always produce 3mm spacing, regardless of shape size.
|
|
35475
36545
|
*
|
|
36546
|
+
* Prefer `sdf.pattern2d()` or built-in surface patterns when the relief should
|
|
36547
|
+
* stay on the native shader and meshing path. Callback functions are supported
|
|
36548
|
+
* for experimentation, but they are opaque to the typed pattern optimizer.
|
|
36549
|
+
*
|
|
35476
36550
|
* ```js
|
|
35477
|
-
* //
|
|
36551
|
+
* // Native typed pattern — auto-detects sphere UV
|
|
36552
|
+
* const p = sdf.pattern2d()
|
|
36553
|
+
* const ribs = p.stripes({ spacing: 3, width: 0.8, depth: 0.35 })
|
|
36554
|
+
* .add(p.sineWave({ direction: [0, 1], wavelength: 14, amplitude: 0.08 }))
|
|
36555
|
+
*
|
|
35478
36556
|
* sdf.sphere(27).shell(3)
|
|
35479
|
-
* .surfaceDisplace(
|
|
36557
|
+
* .surfaceDisplace(ribs)
|
|
35480
36558
|
* .toShape()
|
|
35481
36559
|
*
|
|
35482
36560
|
* // Custom 2D pattern via function
|
|
@@ -35486,15 +36564,18 @@ class SdfShape {
|
|
|
35486
36564
|
surfaceDisplace(pattern, options) {
|
|
35487
36565
|
let body;
|
|
35488
36566
|
let constants;
|
|
36567
|
+
let typedPattern;
|
|
35489
36568
|
if (pattern instanceof SurfacePattern) {
|
|
35490
36569
|
body = pattern.body;
|
|
35491
36570
|
constants = pattern.constants;
|
|
36571
|
+
typedPattern = getTypedSurfacePattern(pattern);
|
|
35492
36572
|
} else {
|
|
35493
36573
|
body = extractFunctionBody(pattern);
|
|
35494
36574
|
}
|
|
35495
36575
|
return this.withNode({
|
|
35496
36576
|
kind: "sdf:surfaceDisplace",
|
|
35497
36577
|
child: this._node,
|
|
36578
|
+
...typedPattern ? { pattern: typedPattern } : {},
|
|
35498
36579
|
patternBody: body,
|
|
35499
36580
|
constants,
|
|
35500
36581
|
...(options == null ? void 0 : options.uv) ? { uvMode: options.uv } : {},
|
|
@@ -35713,24 +36794,10 @@ function weave(options) {
|
|
|
35713
36794
|
});
|
|
35714
36795
|
}
|
|
35715
36796
|
function basketWeave(options) {
|
|
35716
|
-
const SP = (options == null ? void 0 : options.spacing) ?? 3;
|
|
35717
|
-
const TW = (options == null ? void 0 : options.threadWidth) ?? 1.5;
|
|
35718
|
-
const D2 = (options == null ? void 0 : options.depth) ?? 0.8;
|
|
35719
|
-
|
|
35720
|
-
const body = `(function() {
|
|
35721
|
-
var su = u / ${SP};
|
|
35722
|
-
var sv = v / ${SP};
|
|
35723
|
-
var du = Math.abs(su - Math.round(su)) * ${SP};
|
|
35724
|
-
var dv = Math.abs(sv - Math.round(sv)) * ${SP};
|
|
35725
|
-
var hw = ${hw};
|
|
35726
|
-
var pU = Math.max(0, 1 - du / hw); pU *= pU;
|
|
35727
|
-
var pV = Math.max(0, 1 - dv / hw); pV *= pV;
|
|
35728
|
-
var checker = ((Math.round(su) & 65535) + (Math.round(sv) & 65535)) & 1;
|
|
35729
|
-
var top = checker ? pV : pU;
|
|
35730
|
-
var bot = checker ? pU : pV;
|
|
35731
|
-
return -(top > bot * 0.15 ? top : bot * 0.15) * ${D2};
|
|
35732
|
-
})()`;
|
|
35733
|
-
return new SurfacePattern(body);
|
|
36797
|
+
const SP = requirePositiveFinite((options == null ? void 0 : options.spacing) ?? 3, "sdf.basketWeave() spacing");
|
|
36798
|
+
const TW = requirePositiveFinite((options == null ? void 0 : options.threadWidth) ?? 1.5, "sdf.basketWeave() threadWidth");
|
|
36799
|
+
const D2 = requireNonNegativeFinite((options == null ? void 0 : options.depth) ?? 0.8, "sdf.basketWeave() depth");
|
|
36800
|
+
return pattern2d().overUnderWeave({ spacing: SP, threadWidth: TW, depth: D2 });
|
|
35734
36801
|
}
|
|
35735
36802
|
function fromFunction(fn, options) {
|
|
35736
36803
|
if (!options || typeof options !== "object") {
|
|
@@ -35763,6 +36830,9 @@ function bend(shape, radius) {
|
|
|
35763
36830
|
function repeat(shape, spacing, count) {
|
|
35764
36831
|
return shape.repeat(spacing, count);
|
|
35765
36832
|
}
|
|
36833
|
+
function circularArray(shape, count, offset2 = 0) {
|
|
36834
|
+
return shape.circularArray(count, offset2);
|
|
36835
|
+
}
|
|
35766
36836
|
function resolveTpmsOptions(options) {
|
|
35767
36837
|
const wallThickness = options.wallThickness;
|
|
35768
36838
|
const thickness = wallThickness ?? options.thickness;
|
|
@@ -36203,12 +37273,16 @@ const sdf = {
|
|
|
36203
37273
|
weave,
|
|
36204
37274
|
/** Basket weave surface pattern — threads with over-under crossings in UV space. Returns a SurfacePattern for use with `.surfaceDisplace()`. */
|
|
36205
37275
|
basketWeave,
|
|
37276
|
+
/** Create typed, composable 2D surface patterns for `.surfaceDisplace()`. */
|
|
37277
|
+
pattern2d,
|
|
36206
37278
|
/** Twist an SDF shape around the Z axis. */
|
|
36207
37279
|
twist,
|
|
36208
37280
|
/** Bend an SDF shape around the Z axis. */
|
|
36209
37281
|
bend,
|
|
36210
37282
|
/** Repeat an SDF shape in space. */
|
|
36211
37283
|
repeat,
|
|
37284
|
+
/** Arrange an SDF shape in a circular array around the Z axis with O(1) folded-domain evaluation. */
|
|
37285
|
+
circularArray,
|
|
36212
37286
|
/** A 2D surface pattern — a heightmap function for use with `.surfaceDisplace()`. */
|
|
36213
37287
|
SurfacePattern,
|
|
36214
37288
|
/** Create a custom SDF from one expression; shader-safe expressions raymarch directly. */
|
|
@@ -41128,13 +42202,16 @@ class SolvedAssembly {
|
|
|
41128
42202
|
* @category Assembly
|
|
41129
42203
|
*/
|
|
41130
42204
|
toGroup() {
|
|
42205
|
+
var _a3;
|
|
41131
42206
|
const children = [];
|
|
41132
42207
|
const childNames = [];
|
|
41133
|
-
|
|
42208
|
+
const childTags = [];
|
|
42209
|
+
for (const [name, rec] of this.parts) {
|
|
41134
42210
|
children.push(this.getPart(name));
|
|
41135
42211
|
childNames.push(name);
|
|
42212
|
+
childTags.push(normalizeSceneTags((_a3 = rec.metadata) == null ? void 0 : _a3.tags, `Assembly part "${name}" metadata.tags`));
|
|
41136
42213
|
}
|
|
41137
|
-
return new ShapeGroup(children, childNames);
|
|
42214
|
+
return new ShapeGroup(children, childNames, childTags);
|
|
41138
42215
|
}
|
|
41139
42216
|
/**
|
|
41140
42217
|
* Return an array of named scene objects for the viewport renderer.
|
|
@@ -41168,17 +42245,18 @@ class SolvedAssembly {
|
|
|
41168
42245
|
const used = usedByPart.get(partName);
|
|
41169
42246
|
if (used && used.length > 0) markShapePortsUsed(shape, used);
|
|
41170
42247
|
};
|
|
41171
|
-
const appendGroupChildren = (grp, prefix, partName, out2) => {
|
|
42248
|
+
const appendGroupChildren = (grp, prefix, partName, out2, inheritedTags = []) => {
|
|
41172
42249
|
grp.children.forEach((child, index2) => {
|
|
41173
42250
|
const childName = grp.childName(index2);
|
|
41174
42251
|
const label = childName ? `${prefix}.${childName}` : `${prefix}.${index2 + 1}`;
|
|
42252
|
+
const tags = mergeSceneTags(inheritedTags, grp.tagsForChild(index2));
|
|
41175
42253
|
if (child instanceof ShapeGroup) {
|
|
41176
|
-
appendGroupChildren(child, label, partName, out2);
|
|
42254
|
+
appendGroupChildren(child, label, partName, out2, tags);
|
|
41177
42255
|
return;
|
|
41178
42256
|
}
|
|
41179
42257
|
if (child instanceof Shape) {
|
|
41180
42258
|
markUsedOnShape(child, partName);
|
|
41181
|
-
out2.push({ name: label, shape: child });
|
|
42259
|
+
out2.push({ name: label, shape: child, ...tags.length > 0 ? { tags } : {} });
|
|
41182
42260
|
}
|
|
41183
42261
|
});
|
|
41184
42262
|
};
|
|
@@ -41544,7 +42622,7 @@ class Assembly {
|
|
|
41544
42622
|
*
|
|
41545
42623
|
* @param name - Unique part name (must not already exist)
|
|
41546
42624
|
* @param part - The `Shape` or `ShapeGroup` geometry
|
|
41547
|
-
* @param options - Optional `{ transform, metadata }` (material, process, qty, etc.)
|
|
42625
|
+
* @param options - Optional `{ transform, metadata }` (material, process, qty, tags, etc.)
|
|
41548
42626
|
* @returns `this` for chaining
|
|
41549
42627
|
* @category Assembly
|
|
41550
42628
|
*/
|
|
@@ -42498,15 +43576,18 @@ class ImportedAssembly {
|
|
|
42498
43576
|
* Any stored placement offset and placement references are forwarded to the group.
|
|
42499
43577
|
*/
|
|
42500
43578
|
toGroup(state) {
|
|
43579
|
+
var _a3;
|
|
42501
43580
|
const solved = this._assembly.solve(state);
|
|
42502
43581
|
const def = this._assembly.describe();
|
|
42503
43582
|
const children = [];
|
|
42504
43583
|
const childNames = [];
|
|
43584
|
+
const childTags = [];
|
|
42505
43585
|
for (const p2 of def.parts) {
|
|
42506
43586
|
children.push(solved.getPart(p2.name));
|
|
42507
43587
|
childNames.push(p2.name);
|
|
43588
|
+
childTags.push(normalizeSceneTags((_a3 = p2.metadata) == null ? void 0 : _a3.tags, `Assembly part "${p2.name}" metadata.tags`));
|
|
42508
43589
|
}
|
|
42509
|
-
let result = new ShapeGroup(children, childNames);
|
|
43590
|
+
let result = new ShapeGroup(children, childNames, childTags);
|
|
42510
43591
|
const [dx, dy, dz] = this._offset;
|
|
42511
43592
|
if (dx !== 0 || dy !== 0 || dz !== 0) {
|
|
42512
43593
|
result = result.translate(dx, dy, dz);
|
|
@@ -43052,7 +44133,7 @@ class GCodeBuilder {
|
|
|
43052
44133
|
this.lines.push("G1 E-0.8 F1800 ; retract");
|
|
43053
44134
|
this.lines.push("");
|
|
43054
44135
|
const safeZ = Math.min(maxZ + 5, p2.bedZ - 1);
|
|
43055
|
-
this.lines.push(`G1 Z${
|
|
44136
|
+
this.lines.push(`G1 Z${f$1(safeZ)} F900 ; lift nozzle above print`);
|
|
43056
44137
|
this.lines.push("");
|
|
43057
44138
|
this.lines.push("M140 S0 ; bed off");
|
|
43058
44139
|
this.lines.push("M104 S0 ; hotend off");
|
|
@@ -43096,7 +44177,7 @@ class GCodeBuilder {
|
|
|
43096
44177
|
travelTo(x2, y2, z2) {
|
|
43097
44178
|
this.retract();
|
|
43098
44179
|
const from = [...this.pos];
|
|
43099
|
-
this.lines.push(`G0 X${
|
|
44180
|
+
this.lines.push(`G0 X${f$1(x2)} Y${f$1(y2)} Z${f$1(z2)} F${Math.round(this.profile.travelSpeed)}`);
|
|
43100
44181
|
if (this.posInitialized) {
|
|
43101
44182
|
this._segments.push({ from, to: [x2, y2, z2], extrude: false, speed: this.profile.travelSpeed });
|
|
43102
44183
|
}
|
|
@@ -43128,7 +44209,7 @@ class GCodeBuilder {
|
|
|
43128
44209
|
const beadArea = this.profile.layerHeight * this.profile.nozzle;
|
|
43129
44210
|
const eIncrement = beadArea * dist4 / this.filamentArea;
|
|
43130
44211
|
this.e += eIncrement;
|
|
43131
|
-
this.lines.push(`G1 X${
|
|
44212
|
+
this.lines.push(`G1 X${f$1(x2)} Y${f$1(y2)} Z${f$1(z2)} E${f$1(this.e)} F${Math.round(this.currentSpeed)}`);
|
|
43132
44213
|
if (this.posInitialized) {
|
|
43133
44214
|
this._segments.push({ from, to: [x2, y2, z2], extrude: true, speed: this.currentSpeed });
|
|
43134
44215
|
}
|
|
@@ -43226,13 +44307,13 @@ class GCodeBuilder {
|
|
|
43226
44307
|
retract() {
|
|
43227
44308
|
if (this.retracted) return;
|
|
43228
44309
|
this.e -= this.profile.retractionDistance;
|
|
43229
|
-
this.lines.push(`G1 E${
|
|
44310
|
+
this.lines.push(`G1 E${f$1(this.e)} F${Math.round(this.profile.retractionSpeed)}`);
|
|
43230
44311
|
this.retracted = true;
|
|
43231
44312
|
}
|
|
43232
44313
|
unretract() {
|
|
43233
44314
|
if (!this.retracted) return;
|
|
43234
44315
|
this.e += this.profile.retractionDistance;
|
|
43235
|
-
this.lines.push(`G1 E${
|
|
44316
|
+
this.lines.push(`G1 E${f$1(this.e)} F${Math.round(this.profile.retractionSpeed)}`);
|
|
43236
44317
|
this.retracted = false;
|
|
43237
44318
|
}
|
|
43238
44319
|
// ---- Bounds tracking ----
|
|
@@ -43303,7 +44384,7 @@ class GCodeBuilder {
|
|
|
43303
44384
|
return this.lines.join("\n") + "\n";
|
|
43304
44385
|
}
|
|
43305
44386
|
}
|
|
43306
|
-
function
|
|
44387
|
+
function f$1(n) {
|
|
43307
44388
|
return n.toFixed(5).replace(/\.?0+$/, "");
|
|
43308
44389
|
}
|
|
43309
44390
|
function bambuModelName(preset) {
|
|
@@ -46814,7 +47895,8 @@ function explode(items, options = {}) {
|
|
|
46814
47895
|
if (child instanceof ShapeGroup) return explodeGroup(child, p2, depth + 1, total, groupCenter, motion.branchDirection);
|
|
46815
47896
|
return explodeLeaf(child, explodeAdd(total, leafMotion(child, p2, depth + 1, groupCenter, motion.branchDirection).offset));
|
|
46816
47897
|
}),
|
|
46817
|
-
grp.childNames
|
|
47898
|
+
grp.childNames,
|
|
47899
|
+
grp.children.map((_2, i) => grp.tagsForChild(i))
|
|
46818
47900
|
);
|
|
46819
47901
|
};
|
|
46820
47902
|
const explodeItemNode = (item, path2, depth, inherited, parentCenter, parentDirection) => {
|
|
@@ -46850,7 +47932,8 @@ function explode(items, options = {}) {
|
|
|
46850
47932
|
if (child instanceof ShapeGroup) return explodeGroup(child, p2, 1, [0, 0, 0], rootCenter, void 0);
|
|
46851
47933
|
return explodeLeaf(child, nodeMotion(child, p2, 1, rootCenter, void 0).offset);
|
|
46852
47934
|
}),
|
|
46853
|
-
items.childNames
|
|
47935
|
+
items.childNames,
|
|
47936
|
+
items.children.map((_2, i) => items.tagsForChild(i))
|
|
46854
47937
|
);
|
|
46855
47938
|
}
|
|
46856
47939
|
return items.map((item, i) => {
|
|
@@ -47619,6 +48702,398 @@ function spurGear(options) {
|
|
|
47619
48702
|
});
|
|
47620
48703
|
return attachGearMeta(shapeWithConnectors, meta2);
|
|
47621
48704
|
}
|
|
48705
|
+
function requirePositive$7(scope, name, value) {
|
|
48706
|
+
if (!isFinitePositive(value)) throw new Error(`${scope}: "${name}" must be > 0`);
|
|
48707
|
+
}
|
|
48708
|
+
function requireOptionalBore(scope, boreDiameter, maxDiameter) {
|
|
48709
|
+
const bore = boreDiameter ?? 0;
|
|
48710
|
+
if (!Number.isFinite(bore) || bore < 0) throw new Error(`${scope}: "boreDiameter" must be >= 0`);
|
|
48711
|
+
if (bore > 0 && bore >= maxDiameter) throw new Error(`${scope}: bore is too large for the body`);
|
|
48712
|
+
return bore;
|
|
48713
|
+
}
|
|
48714
|
+
function resolveSegments(segments) {
|
|
48715
|
+
if (segments === void 0) return void 0;
|
|
48716
|
+
if (!Number.isInteger(segments) || segments < 12) throw new Error('gear body: "segments" must be an integer >= 12');
|
|
48717
|
+
return segments;
|
|
48718
|
+
}
|
|
48719
|
+
function cutBore$1(shape, boreDiameter) {
|
|
48720
|
+
if (boreDiameter <= 0) return shape;
|
|
48721
|
+
const bounds = shape.boundingBox();
|
|
48722
|
+
const height = bounds.max[2] - bounds.min[2] + 2;
|
|
48723
|
+
const cutter = cylinder(height, boreDiameter * 0.5, void 0, 64).translate(0, 0, bounds.min[2] - 1);
|
|
48724
|
+
return shape.subtract(cutter);
|
|
48725
|
+
}
|
|
48726
|
+
function gearBodyDisk(options) {
|
|
48727
|
+
requirePositive$7("gearBodyDisk", "outerRadius", options.outerRadius);
|
|
48728
|
+
requirePositive$7("gearBodyDisk", "faceWidth", options.faceWidth);
|
|
48729
|
+
const bore = requireOptionalBore("gearBodyDisk", options.boreDiameter, options.outerRadius * 2);
|
|
48730
|
+
const segments = resolveSegments(options.segments);
|
|
48731
|
+
const outer = circle2d(options.outerRadius, segments);
|
|
48732
|
+
const profile = bore > 0 ? difference2d(outer, circle2d(bore * 0.5, segments)) : outer;
|
|
48733
|
+
return sketchExtrude(profile, options.faceWidth);
|
|
48734
|
+
}
|
|
48735
|
+
function gearBodyDiskWithHub(options) {
|
|
48736
|
+
requirePositive$7("gearBodyDiskWithHub", "hubDiameter", options.hubDiameter);
|
|
48737
|
+
if (options.hubDiameter >= options.outerRadius * 2) {
|
|
48738
|
+
throw new Error('gearBodyDiskWithHub: "hubDiameter" must be smaller than the outer diameter');
|
|
48739
|
+
}
|
|
48740
|
+
const bore = requireOptionalBore("gearBodyDiskWithHub", options.boreDiameter, options.hubDiameter);
|
|
48741
|
+
const base = gearBodyDisk({ ...options, boreDiameter: 0 });
|
|
48742
|
+
const hubFaceWidth = options.hubFaceWidth ?? options.faceWidth * 1.5;
|
|
48743
|
+
requirePositive$7("gearBodyDiskWithHub", "hubFaceWidth", hubFaceWidth);
|
|
48744
|
+
const hub = cylinder(hubFaceWidth, options.hubDiameter * 0.5, void 0, options.segments).translate(
|
|
48745
|
+
0,
|
|
48746
|
+
0,
|
|
48747
|
+
(options.faceWidth - hubFaceWidth) * 0.5
|
|
48748
|
+
);
|
|
48749
|
+
return cutBore$1(base.add(hub), bore);
|
|
48750
|
+
}
|
|
48751
|
+
function gearBodySpoked(options) {
|
|
48752
|
+
requirePositive$7("gearBodySpoked", "outerRadius", options.outerRadius);
|
|
48753
|
+
requirePositive$7("gearBodySpoked", "faceWidth", options.faceWidth);
|
|
48754
|
+
requirePositive$7("gearBodySpoked", "rimWidth", options.rimWidth);
|
|
48755
|
+
requirePositive$7("gearBodySpoked", "hubDiameter", options.hubDiameter);
|
|
48756
|
+
requirePositive$7("gearBodySpoked", "spokeWidth", options.spokeWidth);
|
|
48757
|
+
if (!Number.isInteger(options.spokeCount) || options.spokeCount < 2) {
|
|
48758
|
+
throw new Error('gearBodySpoked: "spokeCount" must be an integer >= 2');
|
|
48759
|
+
}
|
|
48760
|
+
const hubRadius = options.hubDiameter * 0.5;
|
|
48761
|
+
const rimInnerRadius = options.outerRadius - options.rimWidth;
|
|
48762
|
+
if (rimInnerRadius <= hubRadius) throw new Error("gearBodySpoked: rim overlaps the hub");
|
|
48763
|
+
const bore = requireOptionalBore("gearBodySpoked", options.boreDiameter, options.hubDiameter);
|
|
48764
|
+
const segments = resolveSegments(options.segments);
|
|
48765
|
+
const rim = difference2d(circle2d(options.outerRadius, segments), circle2d(rimInnerRadius, segments));
|
|
48766
|
+
const hub = circle2d(hubRadius, segments);
|
|
48767
|
+
const spokeLength = rimInnerRadius - hubRadius + options.spokeWidth;
|
|
48768
|
+
const spokeCenter = hubRadius + spokeLength * 0.5 - options.spokeWidth * 0.5;
|
|
48769
|
+
const spoke = sketchTranslate(rect(spokeLength, options.spokeWidth), spokeCenter, 0);
|
|
48770
|
+
const spokes = [];
|
|
48771
|
+
for (let i = 0; i < options.spokeCount; i++) {
|
|
48772
|
+
spokes.push(sketchRotateAround(spoke, 360 / options.spokeCount * i, [0, 0]));
|
|
48773
|
+
}
|
|
48774
|
+
const profile = bore > 0 ? difference2d(union2d(rim, hub, ...spokes), circle2d(bore * 0.5, segments)) : union2d(rim, hub, ...spokes);
|
|
48775
|
+
return sketchExtrude(profile, options.faceWidth);
|
|
48776
|
+
}
|
|
48777
|
+
function gearBodyFromProfile(profile, options) {
|
|
48778
|
+
if (!(profile instanceof Sketch)) throw new Error('gearBodyFromProfile: "profile" must be a Sketch');
|
|
48779
|
+
requirePositive$7("gearBodyFromProfile", "faceWidth", options.faceWidth);
|
|
48780
|
+
const bore = options.boreDiameter ?? 0;
|
|
48781
|
+
if (!Number.isFinite(bore) || bore < 0) throw new Error('gearBodyFromProfile: "boreDiameter" must be >= 0');
|
|
48782
|
+
return cutBore$1(sketchExtrude(profile, options.faceWidth), bore);
|
|
48783
|
+
}
|
|
48784
|
+
function requirePositive$6(scope, name, value) {
|
|
48785
|
+
if (!isFinitePositive(value)) throw new Error(`${scope}: "${name}" must be > 0`);
|
|
48786
|
+
}
|
|
48787
|
+
function requireFiniteAngle(scope, name, value) {
|
|
48788
|
+
if (value !== void 0 && !Number.isFinite(value)) throw new Error(`${scope}: "${name}" must be finite`);
|
|
48789
|
+
}
|
|
48790
|
+
function cutBore(shape, boreDiameter) {
|
|
48791
|
+
if (boreDiameter <= 0) return shape;
|
|
48792
|
+
const bounds = shape.boundingBox();
|
|
48793
|
+
const height = bounds.max[2] - bounds.min[2] + 2;
|
|
48794
|
+
const cutter = cylinder(height, boreDiameter * 0.5, void 0, 64).translate(0, 0, bounds.min[2] - 1);
|
|
48795
|
+
return shape.subtract(cutter);
|
|
48796
|
+
}
|
|
48797
|
+
function bodyOuterRadius(shape) {
|
|
48798
|
+
const bounds = shape.boundingBox();
|
|
48799
|
+
return Math.max(Math.abs(bounds.min[0]), Math.abs(bounds.max[0]), Math.abs(bounds.min[1]), Math.abs(bounds.max[1]));
|
|
48800
|
+
}
|
|
48801
|
+
function buildSpurTeethRegion(options, name, faceWidth) {
|
|
48802
|
+
const scope = "driveWheel.addSpurTeethBetween";
|
|
48803
|
+
const teethOnFullCircle = options.teethOnFullCircle;
|
|
48804
|
+
if (!Number.isInteger(teethOnFullCircle) || teethOnFullCircle < 6) {
|
|
48805
|
+
throw new Error(`${scope}: "teethOnFullCircle" must be an integer >= 6`);
|
|
48806
|
+
}
|
|
48807
|
+
const toothCount = options.toothCount;
|
|
48808
|
+
if (!Number.isInteger(toothCount) || toothCount < 1 || toothCount > teethOnFullCircle) {
|
|
48809
|
+
throw new Error(`${scope}: "toothCount" must be an integer in [1, teethOnFullCircle]`);
|
|
48810
|
+
}
|
|
48811
|
+
const firstTooth = options.firstTooth ?? 0;
|
|
48812
|
+
if (!Number.isInteger(firstTooth) || firstTooth < 0 || firstTooth >= teethOnFullCircle) {
|
|
48813
|
+
throw new Error(`${scope}: "firstTooth" must be an integer in [0, teethOnFullCircle)`);
|
|
48814
|
+
}
|
|
48815
|
+
let normalized;
|
|
48816
|
+
try {
|
|
48817
|
+
normalized = normalizeSpurGearOptions({ ...options, teeth: teethOnFullCircle, faceWidth, boreDiameter: 0 });
|
|
48818
|
+
} catch (error) {
|
|
48819
|
+
remapErrorPrefix(error, "spurGear", scope);
|
|
48820
|
+
}
|
|
48821
|
+
const gearMeta = buildSpurGearMeta(normalized);
|
|
48822
|
+
const pitchStepDeg = 360 / teethOnFullCircle;
|
|
48823
|
+
const fromAngleDeg = firstTooth * pitchStepDeg - pitchStepDeg * 0.5;
|
|
48824
|
+
const toAngleDeg = (firstTooth + toothCount - 1) * pitchStepDeg + pitchStepDeg * 0.5;
|
|
48825
|
+
const profile = buildSpurToothRegionProfile(gearMeta, firstTooth, toothCount, normalized.segmentsPerTooth);
|
|
48826
|
+
return {
|
|
48827
|
+
shape: sketchExtrude(profile, faceWidth),
|
|
48828
|
+
gearMeta,
|
|
48829
|
+
meta: {
|
|
48830
|
+
name,
|
|
48831
|
+
kind: "spurTeeth",
|
|
48832
|
+
fromAngleDeg,
|
|
48833
|
+
toAngleDeg,
|
|
48834
|
+
outerRadius: gearMeta.outerRadius,
|
|
48835
|
+
rootRadius: gearMeta.rootRadius,
|
|
48836
|
+
pitchRadius: gearMeta.pitchRadius,
|
|
48837
|
+
module: normalized.module,
|
|
48838
|
+
teethOnFullCircle,
|
|
48839
|
+
toothCount,
|
|
48840
|
+
faceWidth
|
|
48841
|
+
}
|
|
48842
|
+
};
|
|
48843
|
+
}
|
|
48844
|
+
function buildSolidArcRegion(options, name, faceWidth) {
|
|
48845
|
+
const scope = "driveWheel.addSolidArcBetween";
|
|
48846
|
+
requirePositive$6(scope, "outerRadius", options.outerRadius);
|
|
48847
|
+
const innerRadius = options.innerRadius ?? 0;
|
|
48848
|
+
if (!Number.isFinite(innerRadius) || innerRadius < 0) throw new Error(`${scope}: "innerRadius" must be >= 0`);
|
|
48849
|
+
if (innerRadius >= options.outerRadius) throw new Error(`${scope}: "innerRadius" must be smaller than "outerRadius"`);
|
|
48850
|
+
const sweepDeg = normalizedSweep(scope, options.fromAngleDeg, options.toAngleDeg);
|
|
48851
|
+
return {
|
|
48852
|
+
shape: sketchExtrude(buildSolidArcProfile(options, sweepDeg), faceWidth),
|
|
48853
|
+
meta: {
|
|
48854
|
+
name,
|
|
48855
|
+
kind: "solidArc",
|
|
48856
|
+
fromAngleDeg: options.fromAngleDeg,
|
|
48857
|
+
toAngleDeg: options.fromAngleDeg + sweepDeg,
|
|
48858
|
+
innerRadius,
|
|
48859
|
+
outerRadius: options.outerRadius,
|
|
48860
|
+
faceWidth
|
|
48861
|
+
}
|
|
48862
|
+
};
|
|
48863
|
+
}
|
|
48864
|
+
function normalizedSweep(scope, fromAngleDeg, toAngleDeg) {
|
|
48865
|
+
if (!Number.isFinite(fromAngleDeg)) throw new Error(`${scope}: "fromAngleDeg" must be finite`);
|
|
48866
|
+
if (!Number.isFinite(toAngleDeg)) throw new Error(`${scope}: "toAngleDeg" must be finite`);
|
|
48867
|
+
let sweep2 = toAngleDeg - fromAngleDeg;
|
|
48868
|
+
while (sweep2 <= 0) sweep2 += 360;
|
|
48869
|
+
if (sweep2 > 360 + EPSILON$1) throw new Error(`${scope}: angular sweep must be <= 360 degrees`);
|
|
48870
|
+
return Math.min(360, sweep2);
|
|
48871
|
+
}
|
|
48872
|
+
function buildSpurToothRegionProfile(meta2, firstTooth, toothCount, segmentsPerTooth) {
|
|
48873
|
+
const tooth = createSpurToothSketch(meta2, segmentsPerTooth);
|
|
48874
|
+
const teeth = [];
|
|
48875
|
+
for (let i = 0; i < toothCount; i++) {
|
|
48876
|
+
teeth.push(sketchRotateAround(tooth, 360 / meta2.teeth * (firstTooth + i), [0, 0]));
|
|
48877
|
+
}
|
|
48878
|
+
return union2d(...teeth);
|
|
48879
|
+
}
|
|
48880
|
+
function buildSolidArcProfile(options, sweepDeg) {
|
|
48881
|
+
const innerRadius = options.innerRadius ?? 0;
|
|
48882
|
+
const segments = options.segments ?? Math.max(16, Math.ceil(sweepDeg / 6));
|
|
48883
|
+
if (!Number.isInteger(segments) || segments < 4) throw new Error('driveWheel.addSolidArcBetween: "segments" must be an integer >= 4');
|
|
48884
|
+
if (Math.abs(sweepDeg - 360) < EPSILON$1) {
|
|
48885
|
+
const outer = circle2d(options.outerRadius, segments);
|
|
48886
|
+
return innerRadius > 0 ? difference2d(outer, circle2d(innerRadius, segments)) : outer;
|
|
48887
|
+
}
|
|
48888
|
+
const start = options.fromAngleDeg * Math.PI / 180;
|
|
48889
|
+
const end = start + sweepDeg * Math.PI / 180;
|
|
48890
|
+
const pts = [];
|
|
48891
|
+
if (innerRadius <= 0) pts.push([0, 0]);
|
|
48892
|
+
addArcPoints(pts, options.outerRadius, start, end, segments, true, true);
|
|
48893
|
+
if (innerRadius > 0) addArcPoints(pts, innerRadius, end, start, segments, true, true);
|
|
48894
|
+
return polygon(pts);
|
|
48895
|
+
}
|
|
48896
|
+
const DRIVE_WHEEL_META_KEY = Symbol.for("forgecad.library.driveWheelMeta");
|
|
48897
|
+
function attachDriveWheelMeta(shape, meta2) {
|
|
48898
|
+
shape[DRIVE_WHEEL_META_KEY] = meta2;
|
|
48899
|
+
return shape;
|
|
48900
|
+
}
|
|
48901
|
+
function readDriveWheelMeta(shape) {
|
|
48902
|
+
const meta2 = shape[DRIVE_WHEEL_META_KEY];
|
|
48903
|
+
return meta2 ?? null;
|
|
48904
|
+
}
|
|
48905
|
+
class DriveWheelBuilder {
|
|
48906
|
+
constructor(options = {}) {
|
|
48907
|
+
__publicField(this, "body");
|
|
48908
|
+
__publicField(this, "faceWidth");
|
|
48909
|
+
__publicField(this, "boreDiameter");
|
|
48910
|
+
__publicField(this, "regions", []);
|
|
48911
|
+
if (options.body !== void 0 && !(options.body instanceof Shape)) throw new Error('driveWheel: "body" must be a Shape');
|
|
48912
|
+
if (options.faceWidth !== void 0) requirePositive$6("driveWheel", "faceWidth", options.faceWidth);
|
|
48913
|
+
const boreDiameter = options.boreDiameter ?? 0;
|
|
48914
|
+
if (!Number.isFinite(boreDiameter) || boreDiameter < 0) throw new Error('driveWheel: "boreDiameter" must be >= 0');
|
|
48915
|
+
this.body = options.body;
|
|
48916
|
+
this.faceWidth = options.faceWidth;
|
|
48917
|
+
this.boreDiameter = boreDiameter;
|
|
48918
|
+
}
|
|
48919
|
+
/**
|
|
48920
|
+
* Add an involute spur-tooth window on part of the pitch circle.
|
|
48921
|
+
*/
|
|
48922
|
+
addSpurTeethBetween(options) {
|
|
48923
|
+
const faceWidth = this.resolveFaceWidth("driveWheel.addSpurTeethBetween", options.faceWidth);
|
|
48924
|
+
this.regions.push(buildSpurTeethRegion(options, this.resolveName("teeth", options.name), faceWidth));
|
|
48925
|
+
return this;
|
|
48926
|
+
}
|
|
48927
|
+
/**
|
|
48928
|
+
* Add a constant-radius solid arc region such as a dwell, stop, or pusher.
|
|
48929
|
+
*/
|
|
48930
|
+
addSolidArcBetween(options) {
|
|
48931
|
+
const faceWidth = this.resolveFaceWidth("driveWheel.addSolidArcBetween", options.faceWidth);
|
|
48932
|
+
this.regions.push(buildSolidArcRegion(options, this.resolveName("arc", options.name), faceWidth));
|
|
48933
|
+
return this;
|
|
48934
|
+
}
|
|
48935
|
+
/**
|
|
48936
|
+
* Add a fully custom region shape while preserving region metadata.
|
|
48937
|
+
*/
|
|
48938
|
+
addShapeRegion(name, shape, options = {}) {
|
|
48939
|
+
const scope = "driveWheel.addShapeRegion";
|
|
48940
|
+
if (typeof name !== "string" || name.trim().length === 0) throw new Error(`${scope}: "name" must be a non-empty string`);
|
|
48941
|
+
if (!(shape instanceof Shape)) throw new Error(`${scope}: "shape" must be a Shape`);
|
|
48942
|
+
requireFiniteAngle(scope, "fromAngleDeg", options.fromAngleDeg);
|
|
48943
|
+
requireFiniteAngle(scope, "toAngleDeg", options.toAngleDeg);
|
|
48944
|
+
if (options.innerRadius !== void 0 && (!Number.isFinite(options.innerRadius) || options.innerRadius < 0)) {
|
|
48945
|
+
throw new Error(`${scope}: "innerRadius" must be >= 0`);
|
|
48946
|
+
}
|
|
48947
|
+
if (options.outerRadius !== void 0) requirePositive$6(scope, "outerRadius", options.outerRadius);
|
|
48948
|
+
this.regions.push({
|
|
48949
|
+
shape: shape.clone(),
|
|
48950
|
+
meta: {
|
|
48951
|
+
name: this.resolveName("region", name),
|
|
48952
|
+
kind: "custom",
|
|
48953
|
+
...options
|
|
48954
|
+
}
|
|
48955
|
+
});
|
|
48956
|
+
return this;
|
|
48957
|
+
}
|
|
48958
|
+
/**
|
|
48959
|
+
* Build the final wheel shape with a bore connector and region metadata.
|
|
48960
|
+
*/
|
|
48961
|
+
build() {
|
|
48962
|
+
var _a3, _b3;
|
|
48963
|
+
if (this.regions.length === 0 && this.body === void 0) {
|
|
48964
|
+
throw new Error("driveWheel: add a body or at least one region before build()");
|
|
48965
|
+
}
|
|
48966
|
+
const faceWidth = this.resolveBuildFaceWidth();
|
|
48967
|
+
const firstGearRegion = (_a3 = this.regions.find((region) => region.gearMeta)) == null ? void 0 : _a3.gearMeta;
|
|
48968
|
+
if (firstGearRegion && this.boreDiameter * 0.5 >= firstGearRegion.rootRadius - EPSILON$1) {
|
|
48969
|
+
throw new Error("driveWheel: bore is too large for the first spur-tooth region");
|
|
48970
|
+
}
|
|
48971
|
+
const body = ((_b3 = this.body) == null ? void 0 : _b3.clone()) ?? gearBodyDisk({ outerRadius: (firstGearRegion == null ? void 0 : firstGearRegion.rootRadius) ?? this.defaultBodyRadius(), faceWidth });
|
|
48972
|
+
let combined = body;
|
|
48973
|
+
for (const region of this.regions) combined = combined.add(region.shape);
|
|
48974
|
+
combined = cutBore(combined, this.boreDiameter);
|
|
48975
|
+
const withConnectors = combined.withConnectors({
|
|
48976
|
+
bore: connectorFactory(
|
|
48977
|
+
"drive-wheel-bore",
|
|
48978
|
+
{ origin: [0, 0, faceWidth / 2], axis: [0, 0, 1], kind: "revolute" },
|
|
48979
|
+
this.measurements(faceWidth)
|
|
48980
|
+
)
|
|
48981
|
+
});
|
|
48982
|
+
return attachDriveWheelMeta(withConnectors, {
|
|
48983
|
+
kind: "driveWheel",
|
|
48984
|
+
faceWidth,
|
|
48985
|
+
boreDiameter: this.boreDiameter,
|
|
48986
|
+
regions: this.regionMetadata(body, faceWidth)
|
|
48987
|
+
});
|
|
48988
|
+
}
|
|
48989
|
+
measurements(faceWidth) {
|
|
48990
|
+
var _a3;
|
|
48991
|
+
const firstGearRegion = (_a3 = this.regions.find((region) => region.gearMeta)) == null ? void 0 : _a3.gearMeta;
|
|
48992
|
+
return {
|
|
48993
|
+
faceWidth,
|
|
48994
|
+
boreDiameter: this.boreDiameter,
|
|
48995
|
+
regionCount: this.regions.length,
|
|
48996
|
+
...firstGearRegion ? {
|
|
48997
|
+
module: firstGearRegion.module,
|
|
48998
|
+
teethOnFullCircle: firstGearRegion.teeth,
|
|
48999
|
+
pitchRadius: firstGearRegion.pitchRadius,
|
|
49000
|
+
outerRadius: firstGearRegion.outerRadius
|
|
49001
|
+
} : {}
|
|
49002
|
+
};
|
|
49003
|
+
}
|
|
49004
|
+
regionMetadata(body, faceWidth) {
|
|
49005
|
+
return [
|
|
49006
|
+
{ name: "body", kind: "body", outerRadius: bodyOuterRadius(body), faceWidth },
|
|
49007
|
+
...this.regions.map((region) => ({ ...region.meta }))
|
|
49008
|
+
];
|
|
49009
|
+
}
|
|
49010
|
+
resolveFaceWidth(scope, localFaceWidth) {
|
|
49011
|
+
const faceWidth = localFaceWidth ?? this.faceWidth;
|
|
49012
|
+
if (faceWidth === void 0) throw new Error(`${scope}: "faceWidth" is required unless driveWheel({ faceWidth }) was set`);
|
|
49013
|
+
requirePositive$6(scope, "faceWidth", faceWidth);
|
|
49014
|
+
if (this.faceWidth !== void 0 && localFaceWidth !== void 0 && Math.abs(this.faceWidth - localFaceWidth) > EPSILON$1) {
|
|
49015
|
+
throw new Error(`${scope}: region faceWidth must match driveWheel faceWidth`);
|
|
49016
|
+
}
|
|
49017
|
+
return faceWidth;
|
|
49018
|
+
}
|
|
49019
|
+
resolveBuildFaceWidth() {
|
|
49020
|
+
var _a3;
|
|
49021
|
+
const faceWidth = this.faceWidth ?? ((_a3 = this.regions.find((region) => region.meta.faceWidth !== void 0)) == null ? void 0 : _a3.meta.faceWidth);
|
|
49022
|
+
if (faceWidth === void 0) throw new Error('driveWheel: "faceWidth" is required before build()');
|
|
49023
|
+
return faceWidth;
|
|
49024
|
+
}
|
|
49025
|
+
defaultBodyRadius() {
|
|
49026
|
+
const outerRadius = this.regions.reduce((max2, region) => Math.max(max2, region.meta.outerRadius ?? 0), 0);
|
|
49027
|
+
if (outerRadius <= 0) throw new Error('driveWheel: "body" is required when regions do not define an outer radius');
|
|
49028
|
+
return outerRadius;
|
|
49029
|
+
}
|
|
49030
|
+
resolveName(prefix, requested) {
|
|
49031
|
+
const base = (requested == null ? void 0 : requested.trim()) || prefix;
|
|
49032
|
+
if (this.regions.every((region) => region.meta.name !== base)) return base;
|
|
49033
|
+
for (let i = 2; ; i++) {
|
|
49034
|
+
const candidate = `${base}${i}`;
|
|
49035
|
+
if (this.regions.every((region) => region.meta.name !== candidate)) return candidate;
|
|
49036
|
+
}
|
|
49037
|
+
}
|
|
49038
|
+
}
|
|
49039
|
+
function driveWheel(options = {}) {
|
|
49040
|
+
return new DriveWheelBuilder(options);
|
|
49041
|
+
}
|
|
49042
|
+
function normalizeSectorGearOptions(options) {
|
|
49043
|
+
const teethOnFullCircle = options.teethOnFullCircle;
|
|
49044
|
+
if (!Number.isInteger(teethOnFullCircle) || teethOnFullCircle < 6) {
|
|
49045
|
+
throw new Error('sectorGear: "teethOnFullCircle" must be an integer >= 6');
|
|
49046
|
+
}
|
|
49047
|
+
const toothCount = options.toothCount;
|
|
49048
|
+
if (!Number.isInteger(toothCount) || toothCount < 1 || toothCount > teethOnFullCircle) {
|
|
49049
|
+
throw new Error('sectorGear: "toothCount" must be an integer in [1, teethOnFullCircle]');
|
|
49050
|
+
}
|
|
49051
|
+
const firstTooth = options.firstTooth ?? 0;
|
|
49052
|
+
if (!Number.isInteger(firstTooth) || firstTooth < 0 || firstTooth >= teethOnFullCircle) {
|
|
49053
|
+
throw new Error('sectorGear: "firstTooth" must be an integer in [0, teethOnFullCircle)');
|
|
49054
|
+
}
|
|
49055
|
+
return {
|
|
49056
|
+
...normalizeSpurGearOptions({ ...options, teeth: teethOnFullCircle }),
|
|
49057
|
+
teethOnFullCircle,
|
|
49058
|
+
toothCount,
|
|
49059
|
+
firstTooth,
|
|
49060
|
+
boreDiameter: options.boreDiameter ?? 0
|
|
49061
|
+
};
|
|
49062
|
+
}
|
|
49063
|
+
function sectorGear(options) {
|
|
49064
|
+
const normalized = normalizeSectorGearOptions(options);
|
|
49065
|
+
if (options.body !== void 0 && !(options.body instanceof Shape)) {
|
|
49066
|
+
throw new Error('sectorGear: "body" must be a Shape');
|
|
49067
|
+
}
|
|
49068
|
+
const spurMeta = buildSpurGearMeta(normalized);
|
|
49069
|
+
const pitchStepDeg = 360 / normalized.teethOnFullCircle;
|
|
49070
|
+
const activeAngleStartDeg = normalized.firstTooth * pitchStepDeg - pitchStepDeg * 0.5;
|
|
49071
|
+
const activeAngleEndDeg = (normalized.firstTooth + normalized.toothCount - 1) * pitchStepDeg + pitchStepDeg * 0.5;
|
|
49072
|
+
const meta2 = {
|
|
49073
|
+
...spurMeta,
|
|
49074
|
+
kind: "sector",
|
|
49075
|
+
teethOnFullCircle: normalized.teethOnFullCircle,
|
|
49076
|
+
firstTooth: normalized.firstTooth,
|
|
49077
|
+
toothCount: normalized.toothCount,
|
|
49078
|
+
activeAngleStartDeg,
|
|
49079
|
+
activeAngleEndDeg
|
|
49080
|
+
};
|
|
49081
|
+
const wheel = driveWheel({ body: options.body, faceWidth: normalized.faceWidth, boreDiameter: normalized.boreDiameter }).addSpurTeethBetween({
|
|
49082
|
+
name: "teeth",
|
|
49083
|
+
module: normalized.module,
|
|
49084
|
+
teethOnFullCircle: normalized.teethOnFullCircle,
|
|
49085
|
+
toothCount: normalized.toothCount,
|
|
49086
|
+
firstTooth: normalized.firstTooth,
|
|
49087
|
+
pressureAngleDeg: normalized.pressureAngleDeg,
|
|
49088
|
+
faceWidth: normalized.faceWidth,
|
|
49089
|
+
backlash: normalized.backlash,
|
|
49090
|
+
clearance: normalized.clearance,
|
|
49091
|
+
addendum: normalized.addendum,
|
|
49092
|
+
dedendum: normalized.dedendum,
|
|
49093
|
+
segmentsPerTooth: normalized.segmentsPerTooth
|
|
49094
|
+
}).build();
|
|
49095
|
+
return attachGearMeta(wheel, meta2);
|
|
49096
|
+
}
|
|
47622
49097
|
function normalizeSideGearOptions(options) {
|
|
47623
49098
|
let normalizedSpur;
|
|
47624
49099
|
try {
|
|
@@ -48598,6 +50073,12 @@ function boltPattern(options) {
|
|
|
48598
50073
|
}
|
|
48599
50074
|
};
|
|
48600
50075
|
}
|
|
50076
|
+
const gearBodies = {
|
|
50077
|
+
disk: gearBodyDisk,
|
|
50078
|
+
diskWithHub: gearBodyDiskWithHub,
|
|
50079
|
+
spoked: gearBodySpoked,
|
|
50080
|
+
fromProfile: gearBodyFromProfile
|
|
50081
|
+
};
|
|
48601
50082
|
function thread(diameter, pitch, length4, options) {
|
|
48602
50083
|
const r = diameter / 2;
|
|
48603
50084
|
const depth = (options == null ? void 0 : options.depth) ?? pitch * 0.35;
|
|
@@ -48763,7 +50244,23 @@ const partLibrary = {
|
|
|
48763
50244
|
gearRatio,
|
|
48764
50245
|
rackRatio,
|
|
48765
50246
|
planetaryRatio,
|
|
48766
|
-
boltPattern
|
|
50247
|
+
boltPattern,
|
|
50248
|
+
/** Start a composable exceptional gear or drive wheel. */
|
|
50249
|
+
driveWheel,
|
|
50250
|
+
/** Read functional-region metadata from a drive wheel shape. */
|
|
50251
|
+
readDriveWheelMeta,
|
|
50252
|
+
/** Involute sector gear with teeth on only part of the pitch circle. */
|
|
50253
|
+
sectorGear,
|
|
50254
|
+
/** Gear body preset namespace: disk, diskWithHub, spoked, and fromProfile. */
|
|
50255
|
+
gearBodies,
|
|
50256
|
+
/** Solid disk/ring gear body, independent from any tooth geometry. */
|
|
50257
|
+
gearBodyDisk,
|
|
50258
|
+
/** Disk gear body with a raised center hub. */
|
|
50259
|
+
gearBodyDiskWithHub,
|
|
50260
|
+
/** Spoked gear body with an outer rim, center hub, and radial spokes. */
|
|
50261
|
+
gearBodySpoked,
|
|
50262
|
+
/** Extrude a custom 2D profile into a gear body. */
|
|
50263
|
+
gearBodyFromProfile
|
|
48767
50264
|
};
|
|
48768
50265
|
/**
|
|
48769
50266
|
* @license
|
|
@@ -58234,7 +59731,7 @@ class ProductStationBuilder {
|
|
|
58234
59731
|
this.profileValue = profileFromSketch(sketch, "custom", width, depth);
|
|
58235
59732
|
return this;
|
|
58236
59733
|
}
|
|
58237
|
-
/**
|
|
59734
|
+
/** Set the station crown amount for soft product-section intent. */
|
|
58238
59735
|
crown(amount) {
|
|
58239
59736
|
if (!Number.isFinite(amount)) throw new Error("station.crown(amount) requires a finite number");
|
|
58240
59737
|
this.crownValue = amount;
|
|
@@ -59565,7 +61062,7 @@ class ProductSkinBuilder {
|
|
|
59565
61062
|
this.stationsValue = stations.map(toStationSpec).sort((a2, b) => axisPosition(this.axisValue, a2.center) - axisPosition(this.axisValue, b.center));
|
|
59566
61063
|
return this;
|
|
59567
61064
|
}
|
|
59568
|
-
/** Attach guide rails
|
|
61065
|
+
/** Attach named guide rails for product-skin construction and downstream surface references. */
|
|
59569
61066
|
rails(rails) {
|
|
59570
61067
|
this.railsValue = { ...rails };
|
|
59571
61068
|
return this;
|
|
@@ -59599,7 +61096,7 @@ class ProductSkinBuilder {
|
|
|
59599
61096
|
this.edgeLengthValue = value;
|
|
59600
61097
|
return this;
|
|
59601
61098
|
}
|
|
59602
|
-
/**
|
|
61099
|
+
/** Record intended wall thickness for product design metadata. Use explicit shelling when the model needs real inner-wall geometry. */
|
|
59603
61100
|
wall(thickness) {
|
|
59604
61101
|
if (!Number.isFinite(thickness) || thickness <= 0) throw new Error("Product.skin().wall(thickness) requires a positive finite number");
|
|
59605
61102
|
this.wallValue = thickness;
|
|
@@ -62741,7 +64238,7 @@ class SurfaceMemberBuilder {
|
|
|
62741
64238
|
this.record.features.push({ ...normalizeFeature(name, feature), type: "counterbore" });
|
|
62742
64239
|
return this;
|
|
62743
64240
|
}
|
|
62744
|
-
/** Add a named anchor at a carrier surface coordinate for
|
|
64241
|
+
/** Add a named anchor at a carrier surface coordinate for explicit member joins. */
|
|
62745
64242
|
anchorAt(name, coordinate) {
|
|
62746
64243
|
if (!name.trim()) throw new Error("SurfaceMemberBuilder.anchorAt(name, coordinate) requires a non-empty name");
|
|
62747
64244
|
const explicitAnchors = this.record.spec.explicitAnchors ?? [];
|
|
@@ -74017,8 +75514,8 @@ tinf_build_bits_base(dist_bits, dist_base, 2, 1);
|
|
|
74017
75514
|
length_bits[28] = 0;
|
|
74018
75515
|
length_base[28] = 258;
|
|
74019
75516
|
var tinyInflate = tinf_uncompress;
|
|
74020
|
-
function derive(v0, v1, v2,
|
|
74021
|
-
return Math.pow(1 - t, 3) * v0 + 3 * Math.pow(1 - t, 2) * t * v1 + 3 * (1 - t) * Math.pow(t, 2) * v2 + Math.pow(t, 3) *
|
|
75517
|
+
function derive(v0, v1, v2, v32, t) {
|
|
75518
|
+
return Math.pow(1 - t, 3) * v0 + 3 * Math.pow(1 - t, 2) * t * v1 + 3 * (1 - t) * Math.pow(t, 2) * v2 + Math.pow(t, 3) * v32;
|
|
74022
75519
|
}
|
|
74023
75520
|
function BoundingBox() {
|
|
74024
75521
|
this.x1 = Number.NaN;
|
|
@@ -302829,6 +304326,7 @@ function classifySdfPreviewNode(node) {
|
|
|
302829
304326
|
case "sdf:twist":
|
|
302830
304327
|
case "sdf:bend":
|
|
302831
304328
|
case "sdf:repeat":
|
|
304329
|
+
case "sdf:circularArray":
|
|
302832
304330
|
case "sdf:shell":
|
|
302833
304331
|
case "sdf:onion":
|
|
302834
304332
|
return classifySdfPreviewNode(node.child);
|
|
@@ -302838,10 +304336,7 @@ function classifySdfPreviewNode(node) {
|
|
|
302838
304336
|
reason: "This SDF uses a custom JavaScript displacement function that cannot be compiled for raymarch preview."
|
|
302839
304337
|
};
|
|
302840
304338
|
case "sdf:surfaceDisplace":
|
|
302841
|
-
return
|
|
302842
|
-
mode: "unsupported",
|
|
302843
|
-
reason: "This SDF uses surface displacement that is not yet available in the raymarch shader."
|
|
302844
|
-
};
|
|
304339
|
+
return classifySurfaceDisplacePreviewNode(node);
|
|
302845
304340
|
case "sdf:spatialBlend":
|
|
302846
304341
|
return {
|
|
302847
304342
|
mode: "unsupported",
|
|
@@ -302867,6 +304362,79 @@ ${node.shaderUnsupportedReason}` : ""}`
|
|
|
302867
304362
|
};
|
|
302868
304363
|
}
|
|
302869
304364
|
}
|
|
304365
|
+
function classifySurfaceDisplacePreviewNode(node) {
|
|
304366
|
+
if (!node.pattern) {
|
|
304367
|
+
return {
|
|
304368
|
+
mode: "unsupported",
|
|
304369
|
+
reason: "This SDF uses a custom JavaScript surface pattern that cannot be compiled for raymarch preview."
|
|
304370
|
+
};
|
|
304371
|
+
}
|
|
304372
|
+
const childResult = classifySdfPreviewNode(node.child);
|
|
304373
|
+
if (childResult.mode !== "raymarch") return childResult;
|
|
304374
|
+
const uv = analyzeShaderSurfaceUv(node.child, "p", node.uvMode);
|
|
304375
|
+
if (uv.mode === "triplanar") {
|
|
304376
|
+
return {
|
|
304377
|
+
mode: "unsupported",
|
|
304378
|
+
reason: "Typed surface displacement raymarch preview currently supports sphere, cylinder, and torus UV mappings."
|
|
304379
|
+
};
|
|
304380
|
+
}
|
|
304381
|
+
return { mode: "raymarch" };
|
|
304382
|
+
}
|
|
304383
|
+
function f2(value) {
|
|
304384
|
+
if (!Number.isFinite(value)) return "0.0";
|
|
304385
|
+
const text = Number(value.toPrecision(9)).toString();
|
|
304386
|
+
return text.includes(".") || text.includes("e") ? text : `${text}.0`;
|
|
304387
|
+
}
|
|
304388
|
+
function v3(value) {
|
|
304389
|
+
return `vec3(${f2(value[0])}, ${f2(value[1])}, ${f2(value[2])})`;
|
|
304390
|
+
}
|
|
304391
|
+
function analyzeShaderSurfaceUv(node, p2, override) {
|
|
304392
|
+
const analysis = analyzeShaderSurfaceUvNode(node, p2);
|
|
304393
|
+
if (!override || override === "auto") return analysis;
|
|
304394
|
+
if (override === "triplanar") return { mode: "triplanar" };
|
|
304395
|
+
if (analysis.mode === "triplanar") return analysis;
|
|
304396
|
+
if (override === analysis.mode) return analysis;
|
|
304397
|
+
if (override === "sphere" || override === "cylinder") {
|
|
304398
|
+
return { mode: override, localPoint: analysis.localPoint, radius: analysis.radius };
|
|
304399
|
+
}
|
|
304400
|
+
return analysis.mode === "torus" ? analysis : { mode: "triplanar" };
|
|
304401
|
+
}
|
|
304402
|
+
function analyzeShaderSurfaceUvNode(node, p2) {
|
|
304403
|
+
switch (node.kind) {
|
|
304404
|
+
case "sdf:sphere":
|
|
304405
|
+
return { mode: "sphere", localPoint: p2, radius: node.radius };
|
|
304406
|
+
case "sdf:cylinder":
|
|
304407
|
+
return { mode: "cylinder", localPoint: p2, radius: node.radius };
|
|
304408
|
+
case "sdf:torus":
|
|
304409
|
+
return { mode: "torus", localPoint: p2, radius: node.minorRadius, majorRadius: node.majorRadius };
|
|
304410
|
+
case "sdf:translate":
|
|
304411
|
+
return analyzeShaderSurfaceUvNode(node.child, `(${p2} - ${v3(node.offset)})`);
|
|
304412
|
+
case "sdf:rotate":
|
|
304413
|
+
return analyzeShaderSurfaceUvNode(node.child, `rotateInvEuler(${p2}, ${v3(node.degrees)})`);
|
|
304414
|
+
case "sdf:scale": {
|
|
304415
|
+
const result = analyzeShaderSurfaceUvNode(node.child, `(${p2} / ${f2(node.factor)})`);
|
|
304416
|
+
if (result.mode === "triplanar") return result;
|
|
304417
|
+
return {
|
|
304418
|
+
...result,
|
|
304419
|
+
radius: result.radius * node.factor,
|
|
304420
|
+
...result.mode === "torus" ? { majorRadius: result.majorRadius * node.factor } : {}
|
|
304421
|
+
};
|
|
304422
|
+
}
|
|
304423
|
+
case "sdf:shell":
|
|
304424
|
+
return analyzeShaderSurfaceUvNode(node.child, p2);
|
|
304425
|
+
case "sdf:union":
|
|
304426
|
+
case "sdf:smoothUnion":
|
|
304427
|
+
case "sdf:intersection":
|
|
304428
|
+
case "sdf:smoothIntersection":
|
|
304429
|
+
case "sdf:difference":
|
|
304430
|
+
case "sdf:smoothDifference":
|
|
304431
|
+
return node.children.length > 0 ? analyzeShaderSurfaceUvNode(node.children[0], p2) : { mode: "triplanar" };
|
|
304432
|
+
case "sdf:morph":
|
|
304433
|
+
return analyzeShaderSurfaceUvNode(node.a, p2);
|
|
304434
|
+
default:
|
|
304435
|
+
return { mode: "triplanar" };
|
|
304436
|
+
}
|
|
304437
|
+
}
|
|
302870
304438
|
function describeScriptResultType(value) {
|
|
302871
304439
|
var _a3, _b3;
|
|
302872
304440
|
if (value == null) return String(value);
|
|
@@ -302927,7 +304495,7 @@ function mapScriptResultToScene(args) {
|
|
|
302927
304495
|
var _a3;
|
|
302928
304496
|
const objects = [];
|
|
302929
304497
|
const shapeDimensions = [];
|
|
302930
|
-
const pushShape = (shape, name, groupName, color, treePath) => {
|
|
304498
|
+
const pushShape = (shape, name, groupName, color, treePath, tags = []) => {
|
|
302931
304499
|
const objectId = `obj-${objects.length + 1}`;
|
|
302932
304500
|
objects.push({
|
|
302933
304501
|
id: objectId,
|
|
@@ -302938,7 +304506,8 @@ function mapScriptResultToScene(args) {
|
|
|
302938
304506
|
materialProps: shape.materialProps,
|
|
302939
304507
|
geometryInfo: shape.geometryInfo(),
|
|
302940
304508
|
groupName,
|
|
302941
|
-
treePath: treePath && treePath.length > 0 ? [...treePath] : [name]
|
|
304509
|
+
treePath: treePath && treePath.length > 0 ? [...treePath] : [name],
|
|
304510
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
302942
304511
|
});
|
|
302943
304512
|
const dims = getShapeDimensions(shape);
|
|
302944
304513
|
dims.forEach((dim2) => {
|
|
@@ -302962,7 +304531,7 @@ function mapScriptResultToScene(args) {
|
|
|
302962
304531
|
});
|
|
302963
304532
|
}
|
|
302964
304533
|
};
|
|
302965
|
-
const pushSketch = (sketch, name, groupName, treePath) => {
|
|
304534
|
+
const pushSketch = (sketch, name, groupName, treePath, tags = []) => {
|
|
302966
304535
|
const meta2 = sketch instanceof ConstraintSketch ? sketch.constraintMeta : void 0;
|
|
302967
304536
|
objects.push({
|
|
302968
304537
|
id: `obj-${objects.length + 1}`,
|
|
@@ -302973,10 +304542,11 @@ function mapScriptResultToScene(args) {
|
|
|
302973
304542
|
sketchMeta: meta2,
|
|
302974
304543
|
color: sketch.colorHex,
|
|
302975
304544
|
groupName,
|
|
302976
|
-
treePath: treePath && treePath.length > 0 ? [...treePath] : [name]
|
|
304545
|
+
treePath: treePath && treePath.length > 0 ? [...treePath] : [name],
|
|
304546
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
302977
304547
|
});
|
|
302978
304548
|
};
|
|
302979
|
-
const pushSdf = (sdfShape, name, groupName, treePath, color) => {
|
|
304549
|
+
const pushSdf = (sdfShape, name, groupName, treePath, color, tags = []) => {
|
|
302980
304550
|
const preview = classifySdfPreviewNode(sdfShape._node);
|
|
302981
304551
|
const displayColor = color || sdfShape.colorHex;
|
|
302982
304552
|
const data = {
|
|
@@ -302996,7 +304566,8 @@ function mapScriptResultToScene(args) {
|
|
|
302996
304566
|
materialProps: sdfShape.materialProps,
|
|
302997
304567
|
geometryInfo: null,
|
|
302998
304568
|
groupName,
|
|
302999
|
-
treePath: treePath && treePath.length > 0 ? [...treePath] : [name]
|
|
304569
|
+
treePath: treePath && treePath.length > 0 ? [...treePath] : [name],
|
|
304570
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
303000
304571
|
});
|
|
303001
304572
|
};
|
|
303002
304573
|
const isNamedObject = (item) => {
|
|
@@ -303013,18 +304584,24 @@ function mapScriptResultToScene(args) {
|
|
|
303013
304584
|
const rootGroupChildLabel = (grp, index2) => {
|
|
303014
304585
|
return shapeGroupChildSegment(grp, index2, true);
|
|
303015
304586
|
};
|
|
303016
|
-
const flattenGroupChild = (child, label, groupName, treePath) => {
|
|
304587
|
+
const flattenGroupChild = (child, label, groupName, treePath, tags = []) => {
|
|
303017
304588
|
const resolvedTreePath = treePath && treePath.length > 0 ? treePath : [label];
|
|
303018
304589
|
if (child instanceof ShapeGroup) {
|
|
303019
304590
|
child.children.forEach((nested, i) => {
|
|
303020
|
-
flattenGroupChild(
|
|
304591
|
+
flattenGroupChild(
|
|
304592
|
+
nested,
|
|
304593
|
+
groupChildLabel(child, label, i),
|
|
304594
|
+
groupName,
|
|
304595
|
+
[...resolvedTreePath, shapeGroupChildSegment(child, i)],
|
|
304596
|
+
mergeSceneTags(tags, child.tagsForChild(i))
|
|
304597
|
+
);
|
|
303021
304598
|
});
|
|
303022
304599
|
return;
|
|
303023
304600
|
}
|
|
303024
304601
|
if (child instanceof Shape) {
|
|
303025
|
-
pushShape(child, label, groupName, void 0, resolvedTreePath);
|
|
304602
|
+
pushShape(child, label, groupName, void 0, resolvedTreePath, tags);
|
|
303026
304603
|
} else if (child instanceof Sketch) {
|
|
303027
|
-
pushSketch(child, label, groupName, resolvedTreePath);
|
|
304604
|
+
pushSketch(child, label, groupName, resolvedTreePath, tags);
|
|
303028
304605
|
}
|
|
303029
304606
|
};
|
|
303030
304607
|
const isPlainObject2 = (value) => {
|
|
@@ -303033,34 +304610,40 @@ function mapScriptResultToScene(args) {
|
|
|
303033
304610
|
return proto2 === Object.prototype || proto2 === null;
|
|
303034
304611
|
};
|
|
303035
304612
|
const joinName = (path2) => path2.join(".");
|
|
303036
|
-
const processRenderableTree = (value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = [], seen = /* @__PURE__ */ new WeakSet()) => {
|
|
304613
|
+
const processRenderableTree = (value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = [], inheritedTags = [], seen = /* @__PURE__ */ new WeakSet()) => {
|
|
303037
304614
|
const segment = fallbackSegment.trim().length > 0 ? fallbackSegment : fallbackLabel;
|
|
303038
304615
|
const treePath = [...parentTreePath, segment];
|
|
303039
304616
|
const name = joinName(treePath) || fallbackLabel;
|
|
303040
304617
|
if (value instanceof Assembly) {
|
|
303041
|
-
value.solve().toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath));
|
|
304618
|
+
value.solve().toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath, inheritedTags));
|
|
303042
304619
|
return;
|
|
303043
304620
|
}
|
|
303044
304621
|
if (value instanceof SolvedAssembly) {
|
|
303045
|
-
value.toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath));
|
|
304622
|
+
value.toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath, inheritedTags));
|
|
303046
304623
|
return;
|
|
303047
304624
|
}
|
|
303048
304625
|
if (value instanceof ShapeGroup) {
|
|
303049
304626
|
value.children.forEach((child, i) => {
|
|
303050
|
-
flattenGroupChild(
|
|
304627
|
+
flattenGroupChild(
|
|
304628
|
+
child,
|
|
304629
|
+
groupChildLabel(value, name, i),
|
|
304630
|
+
parentGroup,
|
|
304631
|
+
[...treePath, shapeGroupChildSegment(value, i)],
|
|
304632
|
+
mergeSceneTags(inheritedTags, value.tagsForChild(i))
|
|
304633
|
+
);
|
|
303051
304634
|
});
|
|
303052
304635
|
return;
|
|
303053
304636
|
}
|
|
303054
304637
|
if (value instanceof Shape) {
|
|
303055
|
-
pushShape(value, name, parentGroup, void 0, treePath);
|
|
304638
|
+
pushShape(value, name, parentGroup, void 0, treePath, inheritedTags);
|
|
303056
304639
|
return;
|
|
303057
304640
|
}
|
|
303058
304641
|
if (value instanceof Sketch) {
|
|
303059
|
-
pushSketch(value, name, parentGroup, treePath);
|
|
304642
|
+
pushSketch(value, name, parentGroup, treePath, inheritedTags);
|
|
303060
304643
|
return;
|
|
303061
304644
|
}
|
|
303062
304645
|
if (value instanceof SdfShape) {
|
|
303063
|
-
pushSdf(value, name, parentGroup, treePath);
|
|
304646
|
+
pushSdf(value, name, parentGroup, treePath, void 0, inheritedTags);
|
|
303064
304647
|
return;
|
|
303065
304648
|
}
|
|
303066
304649
|
if (value instanceof GCodeBuilder) {
|
|
@@ -303071,7 +304654,8 @@ function mapScriptResultToScene(args) {
|
|
|
303071
304654
|
sketch: null,
|
|
303072
304655
|
toolpath: value.build(),
|
|
303073
304656
|
geometryInfo: null,
|
|
303074
|
-
treePath
|
|
304657
|
+
treePath,
|
|
304658
|
+
...inheritedTags.length > 0 ? { tags: [...inheritedTags] } : {}
|
|
303075
304659
|
});
|
|
303076
304660
|
return;
|
|
303077
304661
|
}
|
|
@@ -303081,30 +304665,38 @@ function mapScriptResultToScene(args) {
|
|
|
303081
304665
|
value.forEach((item, index2) => {
|
|
303082
304666
|
const childSegment = `${index2 + 1}`;
|
|
303083
304667
|
const childLabel = `${name}.${childSegment}`;
|
|
303084
|
-
processRenderableTree(item, childLabel, childSegment, parentGroup, treePath, seen);
|
|
304668
|
+
processRenderableTree(item, childLabel, childSegment, parentGroup, treePath, inheritedTags, seen);
|
|
303085
304669
|
});
|
|
303086
304670
|
return;
|
|
303087
304671
|
}
|
|
303088
304672
|
if (isNamedObject(value)) {
|
|
303089
|
-
processNamedItem(value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath);
|
|
304673
|
+
processNamedItem(value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath, inheritedTags);
|
|
303090
304674
|
return;
|
|
303091
304675
|
}
|
|
303092
304676
|
if (isPlainObject2(value)) {
|
|
303093
304677
|
if (seen.has(value)) return;
|
|
303094
304678
|
seen.add(value);
|
|
303095
304679
|
Object.entries(value).forEach(([key, entry]) => {
|
|
303096
|
-
processRenderableTree(entry, key, key, parentGroup, treePath, seen);
|
|
304680
|
+
processRenderableTree(entry, key, key, parentGroup, treePath, inheritedTags, seen);
|
|
303097
304681
|
});
|
|
303098
304682
|
}
|
|
303099
304683
|
};
|
|
303100
|
-
const processNamedItem = (item, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = []) => {
|
|
304684
|
+
const processNamedItem = (item, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = [], inheritedTags = []) => {
|
|
304685
|
+
var _a4;
|
|
303101
304686
|
const name = typeof item.name === "string" && item.name.trim().length > 0 ? item.name : fallbackLabel;
|
|
303102
304687
|
const localSegment = typeof item.name === "string" && item.name.trim().length > 0 ? item.name : fallbackSegment;
|
|
303103
304688
|
const treePath = [...parentTreePath, localSegment];
|
|
303104
304689
|
const grp = parentGroup;
|
|
304690
|
+
const tags = mergeSceneTags(inheritedTags, (_a4 = item.metadata) == null ? void 0 : _a4.tags, item.tags);
|
|
303105
304691
|
if (item.group instanceof ShapeGroup) {
|
|
303106
304692
|
item.group.children.forEach((child, i) => {
|
|
303107
|
-
flattenGroupChild(
|
|
304693
|
+
flattenGroupChild(
|
|
304694
|
+
child,
|
|
304695
|
+
groupChildLabel(item.group, name, i),
|
|
304696
|
+
name,
|
|
304697
|
+
[...treePath, shapeGroupChildSegment(item.group, i)],
|
|
304698
|
+
mergeSceneTags(tags, item.group.tagsForChild(i))
|
|
304699
|
+
);
|
|
303108
304700
|
});
|
|
303109
304701
|
return;
|
|
303110
304702
|
}
|
|
@@ -303114,39 +304706,48 @@ function mapScriptResultToScene(args) {
|
|
|
303114
304706
|
const childTreePath = [...treePath, `${i + 1}`];
|
|
303115
304707
|
if (child instanceof ShapeGroup) {
|
|
303116
304708
|
child.children.forEach((nested, nestedIndex) => {
|
|
303117
|
-
flattenGroupChild(
|
|
303118
|
-
|
|
303119
|
-
|
|
303120
|
-
|
|
304709
|
+
flattenGroupChild(
|
|
304710
|
+
nested,
|
|
304711
|
+
groupChildLabel(child, name, nestedIndex),
|
|
304712
|
+
name,
|
|
304713
|
+
[...treePath, shapeGroupChildSegment(child, nestedIndex)],
|
|
304714
|
+
mergeSceneTags(tags, child.tagsForChild(nestedIndex))
|
|
304715
|
+
);
|
|
303121
304716
|
});
|
|
303122
304717
|
} else if (child instanceof Shape) {
|
|
303123
|
-
pushShape(child, childLabel, name, void 0, childTreePath);
|
|
304718
|
+
pushShape(child, childLabel, name, void 0, childTreePath, tags);
|
|
303124
304719
|
} else if (child instanceof Sketch) {
|
|
303125
|
-
pushSketch(child, childLabel, name, childTreePath);
|
|
304720
|
+
pushSketch(child, childLabel, name, childTreePath, tags);
|
|
303126
304721
|
} else if (child instanceof SdfShape) {
|
|
303127
|
-
pushSdf(child, childLabel, name, childTreePath);
|
|
304722
|
+
pushSdf(child, childLabel, name, childTreePath, void 0, tags);
|
|
303128
304723
|
} else if (isNamedObject(child)) {
|
|
303129
|
-
processNamedItem(child, childLabel, `${i + 1}`, name, treePath);
|
|
304724
|
+
processNamedItem(child, childLabel, `${i + 1}`, name, treePath, tags);
|
|
303130
304725
|
}
|
|
303131
304726
|
});
|
|
303132
304727
|
return;
|
|
303133
304728
|
}
|
|
303134
304729
|
if (item.shape instanceof ShapeGroup) {
|
|
303135
304730
|
item.shape.children.forEach(
|
|
303136
|
-
(child, i) => flattenGroupChild(
|
|
304731
|
+
(child, i) => flattenGroupChild(
|
|
304732
|
+
child,
|
|
304733
|
+
groupChildLabel(item.shape, name, i),
|
|
304734
|
+
name,
|
|
304735
|
+
[...treePath, shapeGroupChildSegment(item.shape, i)],
|
|
304736
|
+
mergeSceneTags(tags, item.shape.tagsForChild(i))
|
|
304737
|
+
)
|
|
303137
304738
|
);
|
|
303138
304739
|
return;
|
|
303139
304740
|
}
|
|
303140
304741
|
if (item.shape instanceof Shape) {
|
|
303141
|
-
pushShape(item.shape, name, grp, item.color, treePath);
|
|
304742
|
+
pushShape(item.shape, name, grp, item.color, treePath, tags);
|
|
303142
304743
|
return;
|
|
303143
304744
|
}
|
|
303144
304745
|
if (item.shape instanceof SdfShape) {
|
|
303145
|
-
pushSdf(item.shape, name, grp, treePath, item.color);
|
|
304746
|
+
pushSdf(item.shape, name, grp, treePath, item.color, tags);
|
|
303146
304747
|
return;
|
|
303147
304748
|
}
|
|
303148
304749
|
if (item.sdf instanceof SdfShape) {
|
|
303149
|
-
pushSdf(item.sdf, name, grp, treePath, item.color);
|
|
304750
|
+
pushSdf(item.sdf, name, grp, treePath, item.color, tags);
|
|
303150
304751
|
return;
|
|
303151
304752
|
}
|
|
303152
304753
|
if (item.sketch instanceof Sketch) {
|
|
@@ -303160,7 +304761,8 @@ function mapScriptResultToScene(args) {
|
|
|
303160
304761
|
sketchMeta: meta2,
|
|
303161
304762
|
color: item.color || item.sketch.colorHex,
|
|
303162
304763
|
groupName: grp,
|
|
303163
|
-
treePath
|
|
304764
|
+
treePath,
|
|
304765
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
303164
304766
|
});
|
|
303165
304767
|
}
|
|
303166
304768
|
};
|
|
@@ -303174,14 +304776,20 @@ function mapScriptResultToScene(args) {
|
|
|
303174
304776
|
} else if (result instanceof ShapeGroup) {
|
|
303175
304777
|
result.children.forEach((child, i) => {
|
|
303176
304778
|
const label = rootGroupChildLabel(result, i);
|
|
303177
|
-
flattenGroupChild(child, label, void 0, [label]);
|
|
304779
|
+
flattenGroupChild(child, label, void 0, [label], result.tagsForChild(i));
|
|
303178
304780
|
});
|
|
303179
304781
|
} else if (Array.isArray(result)) {
|
|
303180
304782
|
result.forEach((item, index2) => {
|
|
303181
304783
|
const label = `Object ${index2 + 1}`;
|
|
303182
304784
|
if (item instanceof ShapeGroup) {
|
|
303183
304785
|
item.children.forEach((child, i) => {
|
|
303184
|
-
flattenGroupChild(
|
|
304786
|
+
flattenGroupChild(
|
|
304787
|
+
child,
|
|
304788
|
+
groupChildLabel(item, label, i),
|
|
304789
|
+
void 0,
|
|
304790
|
+
[label, shapeGroupChildSegment(item, i)],
|
|
304791
|
+
item.tagsForChild(i)
|
|
304792
|
+
);
|
|
303185
304793
|
});
|
|
303186
304794
|
return;
|
|
303187
304795
|
}
|
|
@@ -303214,7 +304822,7 @@ function mapScriptResultToScene(args) {
|
|
|
303214
304822
|
} else if (defaultValue instanceof ShapeGroup) {
|
|
303215
304823
|
defaultValue.children.forEach((child, i) => {
|
|
303216
304824
|
const label = rootGroupChildLabel(defaultValue, i);
|
|
303217
|
-
flattenGroupChild(child, label, void 0, [label]);
|
|
304825
|
+
flattenGroupChild(child, label, void 0, [label], defaultValue.tagsForChild(i));
|
|
303218
304826
|
});
|
|
303219
304827
|
} else if (defaultValue instanceof Shape) {
|
|
303220
304828
|
pushShape(defaultValue, args.fileName, void 0, void 0, [args.fileName]);
|
|
@@ -303260,7 +304868,8 @@ function mapScriptResultToScene(args) {
|
|
|
303260
304868
|
name: `${mock2.name} (mock)`,
|
|
303261
304869
|
shape: mock2.shape,
|
|
303262
304870
|
sketch: null,
|
|
303263
|
-
mock: true
|
|
304871
|
+
mock: true,
|
|
304872
|
+
tags: ["mock"]
|
|
303264
304873
|
});
|
|
303265
304874
|
}
|
|
303266
304875
|
const hasSdfLeaves = objects.some((obj) => obj.sdf);
|