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 flm = /* @__PURE__ */ hMap(flt, 9, 0), flrm = /* @__PURE__ */ hMap(flt, 9, 1);
|
|
4648
4692
|
var fdm = /* @__PURE__ */ hMap(fdt, 5, 0), 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
|
|
@@ -5621,8 +5665,8 @@ function parse3mf(data) {
|
|
|
5621
5665
|
while ((tMatch = trianglePattern.exec(meshXml)) !== null) {
|
|
5622
5666
|
const v1 = parseInt(tMatch[1], 10) + vertexOffset;
|
|
5623
5667
|
const v2 = parseInt(tMatch[2], 10) + vertexOffset;
|
|
5624
|
-
const
|
|
5625
|
-
allTriIndices.push(v1, v2,
|
|
5668
|
+
const v32 = parseInt(tMatch[3], 10) + vertexOffset;
|
|
5669
|
+
allTriIndices.push(v1, v2, v32);
|
|
5626
5670
|
}
|
|
5627
5671
|
for (let i = 0; i < meshVerts.length; i++) {
|
|
5628
5672
|
allPositions.push(meshVerts[i]);
|
|
@@ -6005,6 +6049,287 @@ function lowerShellShapeCompilePlanToConcretePlan(plan) {
|
|
|
6005
6049
|
}
|
|
6006
6050
|
return lowerBaseShellPlanToConcretePlan(plan.base, plan.thickness, normalizeShellOpenFaces(plan.openFaces));
|
|
6007
6051
|
}
|
|
6052
|
+
const DEFAULT_MAX_GRID_POINTS = 8e6;
|
|
6053
|
+
const DEFAULT_MIN_EDGE_LENGTH = 0.15;
|
|
6054
|
+
function resolveSdfMeshingSettings(tree, bounds, options = {}) {
|
|
6055
|
+
const quality = options.quality ?? "preview";
|
|
6056
|
+
const minEdgeLength = positiveOrDefault(options.minEdgeLength, DEFAULT_MIN_EDGE_LENGTH);
|
|
6057
|
+
const maxGridPoints = positiveOrDefault(options.maxGridPoints, DEFAULT_MAX_GRID_POINTS);
|
|
6058
|
+
const tolerance = options.tolerance !== void 0 ? requirePositiveFinite$3(options.tolerance, "SDF tolerance") : void 0;
|
|
6059
|
+
const minFeatureSize = options.minFeatureSize !== void 0 ? requirePositiveFinite$3(options.minFeatureSize, "SDF minFeatureSize") : void 0;
|
|
6060
|
+
const maxTriangles = options.maxTriangles !== void 0 ? Math.floor(requirePositiveFinite$3(options.maxTriangles, "SDF maxTriangles")) : void 0;
|
|
6061
|
+
const analysis = analyzeSdfTree(tree);
|
|
6062
|
+
const warnings = [];
|
|
6063
|
+
let edgeLength2;
|
|
6064
|
+
if (options.edgeLength !== void 0) {
|
|
6065
|
+
edgeLength2 = requirePositiveFinite$3(options.edgeLength, "SDF edgeLength");
|
|
6066
|
+
if (edgeLength2 < minEdgeLength) {
|
|
6067
|
+
warnings.push(`edgeLength ${formatMm(edgeLength2)} was clamped to minimum ${formatMm(minEdgeLength)}.`);
|
|
6068
|
+
edgeLength2 = minEdgeLength;
|
|
6069
|
+
}
|
|
6070
|
+
} else {
|
|
6071
|
+
edgeLength2 = resolveDefaultEdgeLength(bounds, quality, minEdgeLength, analysis, options);
|
|
6072
|
+
}
|
|
6073
|
+
if (analysis.minWallThickness < Infinity && analysis.minWallThickness < edgeLength2 * 2) {
|
|
6074
|
+
analysis.riskFlags.add("thin-shell");
|
|
6075
|
+
warnings.push(
|
|
6076
|
+
`shell/wall thickness ${formatMm(analysis.minWallThickness)} is below 2 x edgeLength ${formatMm(edgeLength2)}; thin features may be under-sampled.`
|
|
6077
|
+
);
|
|
6078
|
+
}
|
|
6079
|
+
if (!options.bounds && analysis.hasInfiniteRepeat) {
|
|
6080
|
+
warnings.push("infinite repeat bounds are heuristic; pass .toShape({ bounds }) for predictable clipping.");
|
|
6081
|
+
}
|
|
6082
|
+
if (!options.bounds && analysis.riskFlags.has("noise")) {
|
|
6083
|
+
warnings.push("noise field bounds are heuristic; pass .toShape({ bounds }) for predictable clipping.");
|
|
6084
|
+
}
|
|
6085
|
+
if (!options.bounds && (analysis.riskFlags.has("tpms") || analysis.riskFlags.has("voronoi"))) {
|
|
6086
|
+
warnings.push("TPMS/Voronoi bounds are heuristic unless clipped or passed explicitly.");
|
|
6087
|
+
}
|
|
6088
|
+
if (analysis.hasLegacyTpmsThreshold) {
|
|
6089
|
+
warnings.push("TPMS thickness is using legacy field-threshold units; use wallThickness for approximate millimeters.");
|
|
6090
|
+
}
|
|
6091
|
+
return {
|
|
6092
|
+
quality,
|
|
6093
|
+
edgeLength: edgeLength2,
|
|
6094
|
+
tolerance,
|
|
6095
|
+
minFeatureSize,
|
|
6096
|
+
minEdgeLength,
|
|
6097
|
+
simplify: resolveSimplificationMode(options.simplify, quality, analysis.riskFlags),
|
|
6098
|
+
maxTriangles,
|
|
6099
|
+
maxGridPoints,
|
|
6100
|
+
diagnostics: options.diagnostics === true,
|
|
6101
|
+
treeRiskFlags: [...analysis.riskFlags].sort(),
|
|
6102
|
+
warnings
|
|
6103
|
+
};
|
|
6104
|
+
}
|
|
6105
|
+
function withScaledSdfEdgeLength(settings, edgeLength2) {
|
|
6106
|
+
return { ...settings, edgeLength: Math.max(settings.minEdgeLength, edgeLength2) };
|
|
6107
|
+
}
|
|
6108
|
+
function createSdfMeshingDiagnostics(settings, bounds, paddedBounds) {
|
|
6109
|
+
const grid = estimateSdfGridDimensions(paddedBounds, settings.edgeLength);
|
|
6110
|
+
const estimatedSamples = grid[0] * grid[1] * grid[2];
|
|
6111
|
+
return {
|
|
6112
|
+
bounds: cloneBounds$2(bounds),
|
|
6113
|
+
paddedBounds: cloneBounds$2(paddedBounds),
|
|
6114
|
+
edgeLength: settings.edgeLength,
|
|
6115
|
+
grid,
|
|
6116
|
+
estimatedSamples,
|
|
6117
|
+
estimatedMemoryBytes: estimatedSamples * 8,
|
|
6118
|
+
treeRiskFlags: [...settings.treeRiskFlags],
|
|
6119
|
+
simplification: settings.simplify,
|
|
6120
|
+
capMode: "box",
|
|
6121
|
+
capInset: settings.edgeLength,
|
|
6122
|
+
warnings: [...settings.warnings]
|
|
6123
|
+
};
|
|
6124
|
+
}
|
|
6125
|
+
function assertSdfMeshingBudget(diagnostics, maxGridPoints) {
|
|
6126
|
+
if (diagnostics.estimatedSamples <= maxGridPoints) return;
|
|
6127
|
+
const suggestedEdge = suggestEdgeLengthForSampleBudget(diagnostics.paddedBounds, maxGridPoints);
|
|
6128
|
+
throw new Error(
|
|
6129
|
+
`SDF meshing would sample ${formatCount(diagnostics.estimatedSamples)} grid points (~${formatBytes(
|
|
6130
|
+
diagnostics.estimatedMemoryBytes
|
|
6131
|
+
)}). Reduce bounds or use edgeLength >= ${formatMm(suggestedEdge)}.`
|
|
6132
|
+
);
|
|
6133
|
+
}
|
|
6134
|
+
function estimateSdfGridDimensions(bounds, edgeLength2) {
|
|
6135
|
+
const dx = bounds.max[0] - bounds.min[0];
|
|
6136
|
+
const dy = bounds.max[1] - bounds.min[1];
|
|
6137
|
+
const dz = bounds.max[2] - bounds.min[2];
|
|
6138
|
+
return [
|
|
6139
|
+
Math.max(2, Math.ceil(dx / edgeLength2) + 1),
|
|
6140
|
+
Math.max(2, Math.ceil(dy / edgeLength2) + 1),
|
|
6141
|
+
Math.max(2, Math.ceil(dz / edgeLength2) + 1)
|
|
6142
|
+
];
|
|
6143
|
+
}
|
|
6144
|
+
function logSdfMeshingDiagnostics(prefix, diagnostics) {
|
|
6145
|
+
const warnings = diagnostics.warnings.length > 0 ? `, warnings=${diagnostics.warnings.join(" | ")}` : "";
|
|
6146
|
+
const evaluator = diagnostics.evaluator ? `, evaluator=${diagnostics.evaluator}${diagnostics.evaluatorUnsupportedReason ? ` (${diagnostics.evaluatorUnsupportedReason})` : ""}` : "";
|
|
6147
|
+
console.info(
|
|
6148
|
+
`${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}`
|
|
6149
|
+
);
|
|
6150
|
+
}
|
|
6151
|
+
function resolveDefaultEdgeLength(bounds, quality, minEdgeLength, analysis, options) {
|
|
6152
|
+
const dx = bounds.max[0] - bounds.min[0];
|
|
6153
|
+
const dy = bounds.max[1] - bounds.min[1];
|
|
6154
|
+
const dz = bounds.max[2] - bounds.min[2];
|
|
6155
|
+
const maxDim = Math.max(dx, dy, dz, minEdgeLength);
|
|
6156
|
+
const divisor = quality === "draft" ? 60 : quality === "export" ? 160 : 100;
|
|
6157
|
+
const candidates = [maxDim / divisor];
|
|
6158
|
+
if (options.tolerance !== void 0) candidates.push(requirePositiveFinite$3(options.tolerance, "SDF tolerance") * 2);
|
|
6159
|
+
if (options.minFeatureSize !== void 0) candidates.push(requirePositiveFinite$3(options.minFeatureSize, "SDF minFeatureSize") / 2.5);
|
|
6160
|
+
if (analysis.minMetricTpmsThickness < Infinity) candidates.push(analysis.minMetricTpmsThickness / 2);
|
|
6161
|
+
if (analysis.minTpmsCellSize < Infinity) candidates.push(analysis.minTpmsCellSize / 10);
|
|
6162
|
+
if (analysis.minRepeatSpacing < Infinity) candidates.push(analysis.minRepeatSpacing / 8);
|
|
6163
|
+
if (analysis.minWallThickness < Infinity) candidates.push(analysis.minWallThickness / 2.5);
|
|
6164
|
+
return Math.max(minEdgeLength, Math.min(...candidates.filter((v) => Number.isFinite(v) && v > 0)));
|
|
6165
|
+
}
|
|
6166
|
+
function resolveSimplificationMode(simplify, quality, riskFlags) {
|
|
6167
|
+
if (simplify === false) return "off";
|
|
6168
|
+
if (simplify === true || simplify === "safe") return "safe";
|
|
6169
|
+
if (quality === "export" && riskFlags.size > 0) return "off";
|
|
6170
|
+
return "safe";
|
|
6171
|
+
}
|
|
6172
|
+
function analyzeSdfTree(tree) {
|
|
6173
|
+
const analysis = {
|
|
6174
|
+
riskFlags: /* @__PURE__ */ new Set(),
|
|
6175
|
+
minTpmsCellSize: Infinity,
|
|
6176
|
+
minMetricTpmsThickness: Infinity,
|
|
6177
|
+
minRepeatSpacing: Infinity,
|
|
6178
|
+
minWallThickness: Infinity,
|
|
6179
|
+
hasInfiniteRepeat: false,
|
|
6180
|
+
hasLegacyTpmsThreshold: false
|
|
6181
|
+
};
|
|
6182
|
+
visitSdfNode(tree, analysis);
|
|
6183
|
+
return analysis;
|
|
6184
|
+
}
|
|
6185
|
+
function minPositive(...values) {
|
|
6186
|
+
let result = Infinity;
|
|
6187
|
+
for (const value of values) {
|
|
6188
|
+
if (value !== null && value !== void 0 && Number.isFinite(value) && value > 0) {
|
|
6189
|
+
result = Math.min(result, value);
|
|
6190
|
+
}
|
|
6191
|
+
}
|
|
6192
|
+
return result === Infinity ? null : result;
|
|
6193
|
+
}
|
|
6194
|
+
function estimateSurfacePatternSpacing(pattern) {
|
|
6195
|
+
switch (pattern.kind) {
|
|
6196
|
+
case "surfacePattern:constant":
|
|
6197
|
+
return null;
|
|
6198
|
+
case "surfacePattern:sineWave":
|
|
6199
|
+
return pattern.wavelength;
|
|
6200
|
+
case "surfacePattern:stripes":
|
|
6201
|
+
return Math.min(pattern.spacing, pattern.width);
|
|
6202
|
+
case "surfacePattern:overUnderWeave":
|
|
6203
|
+
return Math.min(...pattern.spacing, ...pattern.threadWidth);
|
|
6204
|
+
case "surfacePattern:abs":
|
|
6205
|
+
case "surfacePattern:negate":
|
|
6206
|
+
return estimateSurfacePatternSpacing(pattern.child);
|
|
6207
|
+
case "surfacePattern:add":
|
|
6208
|
+
case "surfacePattern:multiply":
|
|
6209
|
+
case "surfacePattern:min":
|
|
6210
|
+
case "surfacePattern:max":
|
|
6211
|
+
return minPositive(...pattern.children.map(estimateSurfacePatternSpacing));
|
|
6212
|
+
case "surfacePattern:clamp":
|
|
6213
|
+
return estimateSurfacePatternSpacing(pattern.child);
|
|
6214
|
+
}
|
|
6215
|
+
}
|
|
6216
|
+
function visitSdfNode(node, analysis) {
|
|
6217
|
+
switch (node.kind) {
|
|
6218
|
+
case "sdf:union":
|
|
6219
|
+
case "sdf:difference":
|
|
6220
|
+
case "sdf:intersection":
|
|
6221
|
+
case "sdf:smoothUnion":
|
|
6222
|
+
case "sdf:smoothDifference":
|
|
6223
|
+
case "sdf:smoothIntersection":
|
|
6224
|
+
for (const child of node.children) visitSdfNode(child, analysis);
|
|
6225
|
+
break;
|
|
6226
|
+
case "sdf:morph":
|
|
6227
|
+
case "sdf:spatialBlend":
|
|
6228
|
+
visitSdfNode(node.a, analysis);
|
|
6229
|
+
visitSdfNode(node.b, analysis);
|
|
6230
|
+
break;
|
|
6231
|
+
case "sdf:translate":
|
|
6232
|
+
case "sdf:rotate":
|
|
6233
|
+
case "sdf:scale":
|
|
6234
|
+
case "sdf:twist":
|
|
6235
|
+
case "sdf:bend":
|
|
6236
|
+
case "sdf:onion":
|
|
6237
|
+
visitSdfNode(node.child, analysis);
|
|
6238
|
+
break;
|
|
6239
|
+
case "sdf:repeat":
|
|
6240
|
+
analysis.riskFlags.add("repeat");
|
|
6241
|
+
for (let i = 0; i < 3; i++) {
|
|
6242
|
+
const spacing = node.spacing[i];
|
|
6243
|
+
if (spacing > 0) {
|
|
6244
|
+
analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, spacing);
|
|
6245
|
+
if (node.count[i] <= 0) analysis.hasInfiniteRepeat = true;
|
|
6246
|
+
}
|
|
6247
|
+
}
|
|
6248
|
+
visitSdfNode(node.child, analysis);
|
|
6249
|
+
break;
|
|
6250
|
+
case "sdf:circularArray": {
|
|
6251
|
+
analysis.riskFlags.add("repeat");
|
|
6252
|
+
if (node.offset > 0) {
|
|
6253
|
+
analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, 2 * Math.PI * node.offset / node.count);
|
|
6254
|
+
}
|
|
6255
|
+
visitSdfNode(node.child, analysis);
|
|
6256
|
+
break;
|
|
6257
|
+
}
|
|
6258
|
+
case "sdf:shell":
|
|
6259
|
+
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.thickness);
|
|
6260
|
+
visitSdfNode(node.child, analysis);
|
|
6261
|
+
break;
|
|
6262
|
+
case "sdf:displace":
|
|
6263
|
+
case "sdf:surfaceDisplace":
|
|
6264
|
+
analysis.riskFlags.add("displacement");
|
|
6265
|
+
if (node.kind === "sdf:surfaceDisplace" && node.pattern) {
|
|
6266
|
+
const spacing = estimateSurfacePatternSpacing(node.pattern);
|
|
6267
|
+
if (spacing !== null) analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, spacing);
|
|
6268
|
+
}
|
|
6269
|
+
visitSdfNode(node.child, analysis);
|
|
6270
|
+
break;
|
|
6271
|
+
case "sdf:gyroid":
|
|
6272
|
+
case "sdf:schwarzP":
|
|
6273
|
+
case "sdf:diamond":
|
|
6274
|
+
case "sdf:lidinoid":
|
|
6275
|
+
analysis.riskFlags.add("tpms");
|
|
6276
|
+
analysis.minTpmsCellSize = Math.min(analysis.minTpmsCellSize, node.cellSize);
|
|
6277
|
+
if (node.thicknessMode === "metric-approx") {
|
|
6278
|
+
analysis.minMetricTpmsThickness = Math.min(analysis.minMetricTpmsThickness, node.thickness);
|
|
6279
|
+
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.thickness);
|
|
6280
|
+
} else {
|
|
6281
|
+
analysis.hasLegacyTpmsThreshold = true;
|
|
6282
|
+
}
|
|
6283
|
+
break;
|
|
6284
|
+
case "sdf:noise":
|
|
6285
|
+
analysis.riskFlags.add("noise");
|
|
6286
|
+
break;
|
|
6287
|
+
case "sdf:voronoi":
|
|
6288
|
+
analysis.riskFlags.add("voronoi");
|
|
6289
|
+
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.wallThickness);
|
|
6290
|
+
if (node.surfaceChild) visitSdfNode(node.surfaceChild, analysis);
|
|
6291
|
+
break;
|
|
6292
|
+
case "sdf:custom":
|
|
6293
|
+
analysis.riskFlags.add("custom");
|
|
6294
|
+
break;
|
|
6295
|
+
}
|
|
6296
|
+
}
|
|
6297
|
+
function positiveOrDefault(value, fallback) {
|
|
6298
|
+
if (value === void 0) return fallback;
|
|
6299
|
+
return requirePositiveFinite$3(value, "SDF meshing option");
|
|
6300
|
+
}
|
|
6301
|
+
function requirePositiveFinite$3(value, name) {
|
|
6302
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
6303
|
+
throw new Error(`${name} must be a positive finite number.`);
|
|
6304
|
+
}
|
|
6305
|
+
return value;
|
|
6306
|
+
}
|
|
6307
|
+
function cloneBounds$2(bounds) {
|
|
6308
|
+
return { min: [...bounds.min], max: [...bounds.max] };
|
|
6309
|
+
}
|
|
6310
|
+
function suggestEdgeLengthForSampleBudget(bounds, maxGridPoints) {
|
|
6311
|
+
const dx = bounds.max[0] - bounds.min[0];
|
|
6312
|
+
const dy = bounds.max[1] - bounds.min[1];
|
|
6313
|
+
const dz = bounds.max[2] - bounds.min[2];
|
|
6314
|
+
const volume = Math.max(dx * dy * dz, 1);
|
|
6315
|
+
return Math.cbrt(volume / Math.max(maxGridPoints, 8));
|
|
6316
|
+
}
|
|
6317
|
+
function formatBounds(bounds) {
|
|
6318
|
+
return `[${bounds.min.map(formatNumber).join(",")}]-[${bounds.max.map(formatNumber).join(",")}]`;
|
|
6319
|
+
}
|
|
6320
|
+
function formatMm(value) {
|
|
6321
|
+
return `${formatNumber(value)}mm`;
|
|
6322
|
+
}
|
|
6323
|
+
function formatNumber(value) {
|
|
6324
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(3).replace(/0+$/, "").replace(/\.$/, "");
|
|
6325
|
+
}
|
|
6326
|
+
function formatCount(value) {
|
|
6327
|
+
return Math.round(value).toLocaleString("en-US");
|
|
6328
|
+
}
|
|
6329
|
+
function formatBytes(bytes) {
|
|
6330
|
+
if (bytes < 1024 * 1024) return `${Math.ceil(bytes / 1024)} KB`;
|
|
6331
|
+
return `${Math.ceil(bytes / (1024 * 1024))} MB`;
|
|
6332
|
+
}
|
|
6008
6333
|
const grad3 = new Float64Array([
|
|
6009
6334
|
1,
|
|
6010
6335
|
1,
|
|
@@ -6465,8 +6790,8 @@ function triplanarWeights(nx, ny, nz, sharpness) {
|
|
|
6465
6790
|
const inv = 1 / sum2;
|
|
6466
6791
|
return { wx: wx * inv, wy: wy * inv, wz: wz * inv };
|
|
6467
6792
|
}
|
|
6468
|
-
const { atan2, acos, cos: cos$
|
|
6469
|
-
const DEG$
|
|
6793
|
+
const { atan2, acos, cos: cos$3, sin: sin$3, sqrt: sqrt$3, PI: PI$3 } = Math;
|
|
6794
|
+
const DEG$3 = PI$3 / 180;
|
|
6470
6795
|
const IDENTITY = (p2) => p2;
|
|
6471
6796
|
function analyzeUV(node, override) {
|
|
6472
6797
|
if (override) {
|
|
@@ -6493,10 +6818,10 @@ function analyzeNodeUV(node, toLocal) {
|
|
|
6493
6818
|
return analyzeNodeUV(node.child, next);
|
|
6494
6819
|
}
|
|
6495
6820
|
case "sdf:rotate": {
|
|
6496
|
-
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$
|
|
6497
|
-
const cx = cos$
|
|
6498
|
-
const cy = cos$
|
|
6499
|
-
const cz = cos$
|
|
6821
|
+
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$3);
|
|
6822
|
+
const cx = cos$3(rx), sx = sin$3(rx);
|
|
6823
|
+
const cy = cos$3(ry), sy = sin$3(ry);
|
|
6824
|
+
const cz = cos$3(rz), sz = sin$3(rz);
|
|
6500
6825
|
const prev = toLocal;
|
|
6501
6826
|
const next = (p2) => {
|
|
6502
6827
|
const pp = prev(p2);
|
|
@@ -6553,7 +6878,7 @@ function compileUVFunction(analysis) {
|
|
|
6553
6878
|
return (p2) => {
|
|
6554
6879
|
const lp = toLocal(p2);
|
|
6555
6880
|
const u2 = atan2(lp[1], lp[0]) * R;
|
|
6556
|
-
const len2 = sqrt$
|
|
6881
|
+
const len2 = sqrt$3(lp[0] * lp[0] + lp[1] * lp[1] + lp[2] * lp[2]);
|
|
6557
6882
|
const v = acos(clampUnit(lp[2] / (len2 || 1))) * R;
|
|
6558
6883
|
return [u2, v];
|
|
6559
6884
|
};
|
|
@@ -6573,23 +6898,23 @@ function compileUVFunction(analysis) {
|
|
|
6573
6898
|
return (p2) => {
|
|
6574
6899
|
const lp = toLocal(p2);
|
|
6575
6900
|
const u2 = atan2(lp[1], lp[0]) * R;
|
|
6576
|
-
const xyDist = sqrt$
|
|
6901
|
+
const xyDist = sqrt$3(lp[0] * lp[0] + lp[1] * lp[1]) - R;
|
|
6577
6902
|
const v = atan2(lp[2], xyDist) * r;
|
|
6578
6903
|
return [u2, v];
|
|
6579
6904
|
};
|
|
6580
6905
|
}
|
|
6581
6906
|
}
|
|
6582
6907
|
}
|
|
6583
|
-
const { abs: abs$1, cos: cos$
|
|
6584
|
-
const TAU = 2 * PI$
|
|
6585
|
-
const GRAD_EPS = 1e-9;
|
|
6908
|
+
const { abs: abs$1, cos: cos$2, sin: sin$2, sqrt: sqrt$2, PI: PI$2 } = Math;
|
|
6909
|
+
const TAU$1 = 2 * PI$2;
|
|
6910
|
+
const GRAD_EPS$1 = 1e-9;
|
|
6586
6911
|
function gyroidValueAndGradient(x2, y2, z2, cellSize) {
|
|
6587
|
-
const s = TAU / cellSize;
|
|
6912
|
+
const s = TAU$1 / cellSize;
|
|
6588
6913
|
const xs = x2 * s;
|
|
6589
6914
|
const ys = y2 * s;
|
|
6590
6915
|
const zs = z2 * s;
|
|
6591
|
-
const sx = sin$
|
|
6592
|
-
const cx = cos$
|
|
6916
|
+
const sx = sin$2(xs), sy = sin$2(ys), sz = sin$2(zs);
|
|
6917
|
+
const cx = cos$2(xs), cy = cos$2(ys), cz = cos$2(zs);
|
|
6593
6918
|
return {
|
|
6594
6919
|
value: sx * cy + sy * cz + sz * cx,
|
|
6595
6920
|
gx: s * (cx * cy - sz * sx),
|
|
@@ -6598,24 +6923,24 @@ function gyroidValueAndGradient(x2, y2, z2, cellSize) {
|
|
|
6598
6923
|
};
|
|
6599
6924
|
}
|
|
6600
6925
|
function schwarzPValueAndGradient(x2, y2, z2, cellSize) {
|
|
6601
|
-
const s = TAU / cellSize;
|
|
6926
|
+
const s = TAU$1 / cellSize;
|
|
6602
6927
|
const xs = x2 * s;
|
|
6603
6928
|
const ys = y2 * s;
|
|
6604
6929
|
const zs = z2 * s;
|
|
6605
6930
|
return {
|
|
6606
|
-
value: cos$
|
|
6607
|
-
gx: -s * sin$
|
|
6608
|
-
gy: -s * sin$
|
|
6609
|
-
gz: -s * sin$
|
|
6931
|
+
value: cos$2(xs) + cos$2(ys) + cos$2(zs),
|
|
6932
|
+
gx: -s * sin$2(xs),
|
|
6933
|
+
gy: -s * sin$2(ys),
|
|
6934
|
+
gz: -s * sin$2(zs)
|
|
6610
6935
|
};
|
|
6611
6936
|
}
|
|
6612
6937
|
function diamondValueAndGradient(x2, y2, z2, cellSize) {
|
|
6613
|
-
const s = TAU / cellSize;
|
|
6938
|
+
const s = TAU$1 / cellSize;
|
|
6614
6939
|
const xs = x2 * s;
|
|
6615
6940
|
const ys = y2 * s;
|
|
6616
6941
|
const zs = z2 * s;
|
|
6617
|
-
const sx = sin$
|
|
6618
|
-
const cx = cos$
|
|
6942
|
+
const sx = sin$2(xs), sy = sin$2(ys), sz = sin$2(zs);
|
|
6943
|
+
const cx = cos$2(xs), cy = cos$2(ys), cz = cos$2(zs);
|
|
6619
6944
|
return {
|
|
6620
6945
|
value: sx * sy * sz + sx * cy * cz + cx * sy * cz + cx * cy * sz,
|
|
6621
6946
|
gx: s * (cx * sy * sz + cx * cy * cz - sx * sy * cz - sx * cy * sz),
|
|
@@ -6624,12 +6949,12 @@ function diamondValueAndGradient(x2, y2, z2, cellSize) {
|
|
|
6624
6949
|
};
|
|
6625
6950
|
}
|
|
6626
6951
|
function lidinoidValueAndGradient(x2, y2, z2, cellSize) {
|
|
6627
|
-
const s = TAU / cellSize;
|
|
6952
|
+
const s = TAU$1 / cellSize;
|
|
6628
6953
|
const sx2 = x2 * s, sy2 = y2 * s, sz2 = z2 * s;
|
|
6629
|
-
const sx = sin$
|
|
6630
|
-
const cx = cos$
|
|
6631
|
-
const s2x = sin$
|
|
6632
|
-
const c2x = cos$
|
|
6954
|
+
const sx = sin$2(sx2), sy = sin$2(sy2), sz = sin$2(sz2);
|
|
6955
|
+
const cx = cos$2(sx2), cy = cos$2(sy2), cz = cos$2(sz2);
|
|
6956
|
+
const s2x = sin$2(2 * sx2), s2y = sin$2(2 * sy2), s2z = sin$2(2 * sz2);
|
|
6957
|
+
const c2x = cos$2(2 * sx2), c2y = cos$2(2 * sy2), c2z = cos$2(2 * sz2);
|
|
6633
6958
|
const val = s2x * cy * sz + s2y * cz * sx + s2z * cx * sy - c2x * c2y - c2y * c2z - c2z * c2x + 0.3;
|
|
6634
6959
|
return {
|
|
6635
6960
|
value: val,
|
|
@@ -6652,8 +6977,8 @@ function lidinoid$1(x2, y2, z2, cellSize, thickness, thicknessMode) {
|
|
|
6652
6977
|
}
|
|
6653
6978
|
function tpmsDistance({ value, gx, gy, gz }, thickness, thicknessMode) {
|
|
6654
6979
|
if (thicknessMode !== "metric-approx") return abs$1(value) - thickness;
|
|
6655
|
-
const grad = sqrt$
|
|
6656
|
-
return abs$1(value) / Math.max(grad, GRAD_EPS) - thickness * 0.5;
|
|
6980
|
+
const grad = sqrt$2(gx * gx + gy * gy + gz * gz);
|
|
6981
|
+
return abs$1(value) / Math.max(grad, GRAD_EPS$1) - thickness * 0.5;
|
|
6657
6982
|
}
|
|
6658
6983
|
function mix(h) {
|
|
6659
6984
|
h = (h ^ h >>> 16) * 2246822507 | 0;
|
|
@@ -6749,76 +7074,76 @@ function seededWorley3Surface(seed) {
|
|
|
6749
7074
|
const s = seed | 0;
|
|
6750
7075
|
return (x2, y2, z2, nx, ny, nz, threshold) => worleySurface(x2, y2, z2, s, nx, ny, nz, threshold);
|
|
6751
7076
|
}
|
|
6752
|
-
const { abs, cos, max, min, sin, sqrt, PI } = Math;
|
|
6753
|
-
const DEG$
|
|
7077
|
+
const { abs, cos: cos$1, max: max$1, min, sin: sin$1, sqrt: sqrt$1, PI: PI$1 } = Math;
|
|
7078
|
+
const DEG$2 = PI$1 / 180;
|
|
6754
7079
|
function clamp$a(v, lo, hi) {
|
|
6755
7080
|
return v < lo ? lo : v > hi ? hi : v;
|
|
6756
7081
|
}
|
|
6757
|
-
function length2(x2, y2) {
|
|
6758
|
-
return sqrt(x2 * x2 + y2 * y2);
|
|
7082
|
+
function length2$1(x2, y2) {
|
|
7083
|
+
return sqrt$1(x2 * x2 + y2 * y2);
|
|
6759
7084
|
}
|
|
6760
|
-
function length3(x2, y2, z2) {
|
|
6761
|
-
return sqrt(x2 * x2 + y2 * y2 + z2 * z2);
|
|
7085
|
+
function length3$1(x2, y2, z2) {
|
|
7086
|
+
return sqrt$1(x2 * x2 + y2 * y2 + z2 * z2);
|
|
6762
7087
|
}
|
|
6763
|
-
function sdSphere(px, py, pz, r) {
|
|
6764
|
-
return length3(px, py, pz) - r;
|
|
7088
|
+
function sdSphere$1(px, py, pz, r) {
|
|
7089
|
+
return length3$1(px, py, pz) - r;
|
|
6765
7090
|
}
|
|
6766
|
-
function sdBox(px, py, pz, hx, hy, hz) {
|
|
7091
|
+
function sdBox$1(px, py, pz, hx, hy, hz) {
|
|
6767
7092
|
const dx = abs(px) - hx;
|
|
6768
7093
|
const dy = abs(py) - hy;
|
|
6769
7094
|
const dz = abs(pz) - hz;
|
|
6770
|
-
return length3(max(dx, 0), max(dy, 0), max(dz, 0)) + min(max(dx, dy, dz), 0);
|
|
7095
|
+
return length3$1(max$1(dx, 0), max$1(dy, 0), max$1(dz, 0)) + min(max$1(dx, dy, dz), 0);
|
|
6771
7096
|
}
|
|
6772
|
-
function sdCylinder(px, py, pz, h, r) {
|
|
6773
|
-
const dx = length2(px, py) - r;
|
|
7097
|
+
function sdCylinder$1(px, py, pz, h, r) {
|
|
7098
|
+
const dx = length2$1(px, py) - r;
|
|
6774
7099
|
const dz = abs(pz) - h * 0.5;
|
|
6775
|
-
return length2(max(dx, 0), max(dz, 0)) + min(max(dx, dz), 0);
|
|
7100
|
+
return length2$1(max$1(dx, 0), max$1(dz, 0)) + min(max$1(dx, dz), 0);
|
|
6776
7101
|
}
|
|
6777
|
-
function sdTorus(px, py, pz, R, r) {
|
|
6778
|
-
const qx = length2(px, py) - R;
|
|
6779
|
-
return length2(qx, pz) - r;
|
|
7102
|
+
function sdTorus$1(px, py, pz, R, r) {
|
|
7103
|
+
const qx = length2$1(px, py) - R;
|
|
7104
|
+
return length2$1(qx, pz) - r;
|
|
6780
7105
|
}
|
|
6781
|
-
function sdCapsule(px, py, pz, h, r) {
|
|
7106
|
+
function sdCapsule$1(px, py, pz, h, r) {
|
|
6782
7107
|
const halfH = h * 0.5;
|
|
6783
7108
|
const cz = clamp$a(pz, -halfH, halfH);
|
|
6784
|
-
return length3(px, py, pz - cz) - r;
|
|
7109
|
+
return length3$1(px, py, pz - cz) - r;
|
|
6785
7110
|
}
|
|
6786
|
-
function sdCone(px, py, pz, h, r) {
|
|
6787
|
-
const q = length2(px, py);
|
|
6788
|
-
const cLen = length2(h, r);
|
|
7111
|
+
function sdCone$1(px, py, pz, h, r) {
|
|
7112
|
+
const q = length2$1(px, py);
|
|
7113
|
+
const cLen = length2$1(h, r);
|
|
6789
7114
|
const nx = h / cLen;
|
|
6790
7115
|
const nz = -r / cLen;
|
|
6791
|
-
const d2 = max(nx * q + nz * (pz - h), -pz, pz - h);
|
|
7116
|
+
const d2 = max$1(nx * q + nz * (pz - h), -pz, pz - h);
|
|
6792
7117
|
return d2;
|
|
6793
7118
|
}
|
|
6794
|
-
function sdTaperedSegment(px, py, pz, ax, ay, az, bx, by, bz, ra, rb) {
|
|
7119
|
+
function sdTaperedSegment$1(px, py, pz, ax, ay, az, bx, by, bz, ra, rb) {
|
|
6795
7120
|
const vx = bx - ax;
|
|
6796
7121
|
const vy = by - ay;
|
|
6797
7122
|
const vz = bz - az;
|
|
6798
7123
|
const len2 = vx * vx + vy * vy + vz * vz;
|
|
6799
|
-
if (len2 <= 1e-12) return sdSphere(px - ax, py - ay, pz - az, max(ra, rb));
|
|
7124
|
+
if (len2 <= 1e-12) return sdSphere$1(px - ax, py - ay, pz - az, max$1(ra, rb));
|
|
6800
7125
|
const h = clamp$a(((px - ax) * vx + (py - ay) * vy + (pz - az) * vz) / len2, 0, 1);
|
|
6801
|
-
return length3(px - (ax + vx * h), py - (ay + vy * h), pz - (az + vz * h)) - (ra + (rb - ra) * h);
|
|
7126
|
+
return length3$1(px - (ax + vx * h), py - (ay + vy * h), pz - (az + vz * h)) - (ra + (rb - ra) * h);
|
|
6802
7127
|
}
|
|
6803
7128
|
function sdPolylineSweep3(node, x2, y2, z2) {
|
|
6804
7129
|
let d2 = 1e20;
|
|
6805
7130
|
for (let i = 0; i < node.points.length - 1; i++) {
|
|
6806
7131
|
const a2 = node.points[i];
|
|
6807
7132
|
const b = node.points[i + 1];
|
|
6808
|
-
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]);
|
|
6809
|
-
d2 = i === 0 ? segment : smin(d2, segment, node.blend);
|
|
7133
|
+
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]);
|
|
7134
|
+
d2 = i === 0 ? segment : smin$1(d2, segment, node.blend);
|
|
6810
7135
|
}
|
|
6811
7136
|
return d2;
|
|
6812
7137
|
}
|
|
6813
|
-
function smin(a2, b, k2) {
|
|
7138
|
+
function smin$1(a2, b, k2) {
|
|
6814
7139
|
if (k2 <= 0) return min(a2, b);
|
|
6815
|
-
const h = max(k2 - abs(a2 - b), 0) / k2;
|
|
7140
|
+
const h = max$1(k2 - abs(a2 - b), 0) / k2;
|
|
6816
7141
|
return min(a2, b) - h * h * h * k2 * (1 / 6);
|
|
6817
7142
|
}
|
|
6818
|
-
function smax(a2, b, k2) {
|
|
6819
|
-
return -smin(-a2, -b, k2);
|
|
7143
|
+
function smax$1(a2, b, k2) {
|
|
7144
|
+
return -smin$1(-a2, -b, k2);
|
|
6820
7145
|
}
|
|
6821
|
-
function repeatCoord(v, spacing, count) {
|
|
7146
|
+
function repeatCoord$1(v, spacing, count) {
|
|
6822
7147
|
if (spacing <= 0) return v;
|
|
6823
7148
|
if (count > 0) {
|
|
6824
7149
|
const center = (count - 1) * 0.5;
|
|
@@ -6827,31 +7152,138 @@ function repeatCoord(v, spacing, count) {
|
|
|
6827
7152
|
}
|
|
6828
7153
|
return v - spacing * Math.round(v / spacing);
|
|
6829
7154
|
}
|
|
7155
|
+
function positiveMod(v, period) {
|
|
7156
|
+
return (v % period + period) % period;
|
|
7157
|
+
}
|
|
7158
|
+
function evalStripesPattern(u2, v, directionX, directionY, spacing, width, depth) {
|
|
7159
|
+
const coord = u2 * directionX + v * directionY;
|
|
7160
|
+
const d2 = abs(coord - Math.round(coord / spacing) * spacing);
|
|
7161
|
+
const profile = max$1(0, 1 - d2 / (width * 0.5));
|
|
7162
|
+
return -(profile * profile) * depth;
|
|
7163
|
+
}
|
|
7164
|
+
function evalOverUnderWeavePattern(u2, v, spacingX, spacingY, widthX, widthY, depth, underScale) {
|
|
7165
|
+
const su = u2 / spacingX;
|
|
7166
|
+
const sv = v / spacingY;
|
|
7167
|
+
let pU = max$1(0, 1 - abs(su - Math.round(su)) * spacingX / (widthX * 0.5));
|
|
7168
|
+
let pV = max$1(0, 1 - abs(sv - Math.round(sv)) * spacingY / (widthY * 0.5));
|
|
7169
|
+
pU *= pU;
|
|
7170
|
+
pV *= pV;
|
|
7171
|
+
const checker = (Math.round(su) & 65535) + (Math.round(sv) & 65535) & 1;
|
|
7172
|
+
const top = checker ? pV : pU;
|
|
7173
|
+
const bot = checker ? pU : pV;
|
|
7174
|
+
return -max$1(top, bot * underScale) * depth;
|
|
7175
|
+
}
|
|
7176
|
+
function compileTypedSurfacePattern(pattern) {
|
|
7177
|
+
switch (pattern.kind) {
|
|
7178
|
+
case "surfacePattern:constant":
|
|
7179
|
+
return () => pattern.value;
|
|
7180
|
+
case "surfacePattern:sineWave": {
|
|
7181
|
+
const { direction: direction2, wavelength, amplitude, phase, bias } = pattern;
|
|
7182
|
+
const frequency = 2 * PI$1 / wavelength;
|
|
7183
|
+
return (u2, v) => bias + sin$1((u2 * direction2[0] + v * direction2[1]) * frequency + phase) * amplitude;
|
|
7184
|
+
}
|
|
7185
|
+
case "surfacePattern:stripes": {
|
|
7186
|
+
const { direction: direction2, spacing, width, depth } = pattern;
|
|
7187
|
+
return (u2, v) => evalStripesPattern(u2, v, direction2[0], direction2[1], spacing, width, depth);
|
|
7188
|
+
}
|
|
7189
|
+
case "surfacePattern:overUnderWeave": {
|
|
7190
|
+
const { spacing, threadWidth, depth, underScale } = pattern;
|
|
7191
|
+
return (u2, v) => evalOverUnderWeavePattern(u2, v, spacing[0], spacing[1], threadWidth[0], threadWidth[1], depth, underScale);
|
|
7192
|
+
}
|
|
7193
|
+
case "surfacePattern:abs": {
|
|
7194
|
+
const child = compileTypedSurfacePattern(pattern.child);
|
|
7195
|
+
return (u2, v) => abs(child(u2, v));
|
|
7196
|
+
}
|
|
7197
|
+
case "surfacePattern:negate": {
|
|
7198
|
+
const child = compileTypedSurfacePattern(pattern.child);
|
|
7199
|
+
return (u2, v) => -child(u2, v);
|
|
7200
|
+
}
|
|
7201
|
+
case "surfacePattern:add": {
|
|
7202
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
7203
|
+
return (u2, v) => children.reduce((sum2, child) => sum2 + child(u2, v), 0);
|
|
7204
|
+
}
|
|
7205
|
+
case "surfacePattern:multiply": {
|
|
7206
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
7207
|
+
return (u2, v) => children.reduce((product, child) => product * child(u2, v), 1);
|
|
7208
|
+
}
|
|
7209
|
+
case "surfacePattern:min": {
|
|
7210
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
7211
|
+
if (children.length === 0) return () => 0;
|
|
7212
|
+
return (u2, v) => children.reduce((value, child) => min(value, child(u2, v)), Infinity);
|
|
7213
|
+
}
|
|
7214
|
+
case "surfacePattern:max": {
|
|
7215
|
+
const children = pattern.children.map(compileTypedSurfacePattern);
|
|
7216
|
+
if (children.length === 0) return () => 0;
|
|
7217
|
+
return (u2, v) => children.reduce((value, child) => max$1(value, child(u2, v)), -Infinity);
|
|
7218
|
+
}
|
|
7219
|
+
case "surfacePattern:clamp": {
|
|
7220
|
+
const child = compileTypedSurfacePattern(pattern.child);
|
|
7221
|
+
return (u2, v) => clamp$a(child(u2, v), pattern.min, pattern.max);
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7224
|
+
}
|
|
7225
|
+
function estimateSurfacePatternAmplitude(pattern) {
|
|
7226
|
+
switch (pattern.kind) {
|
|
7227
|
+
case "surfacePattern:constant":
|
|
7228
|
+
return abs(pattern.value);
|
|
7229
|
+
case "surfacePattern:sineWave":
|
|
7230
|
+
return abs(pattern.bias) + abs(pattern.amplitude);
|
|
7231
|
+
case "surfacePattern:stripes":
|
|
7232
|
+
case "surfacePattern:overUnderWeave":
|
|
7233
|
+
return pattern.depth;
|
|
7234
|
+
case "surfacePattern:abs":
|
|
7235
|
+
case "surfacePattern:negate":
|
|
7236
|
+
return estimateSurfacePatternAmplitude(pattern.child);
|
|
7237
|
+
case "surfacePattern:add": {
|
|
7238
|
+
const amplitudes = pattern.children.map(estimateSurfacePatternAmplitude);
|
|
7239
|
+
return amplitudes.every((value) => value !== null) ? amplitudes.reduce((sum2, value) => sum2 + value, 0) : null;
|
|
7240
|
+
}
|
|
7241
|
+
case "surfacePattern:multiply": {
|
|
7242
|
+
const amplitudes = pattern.children.map(estimateSurfacePatternAmplitude);
|
|
7243
|
+
return amplitudes.every((value) => value !== null) ? amplitudes.reduce((product, value) => product * value, 1) : null;
|
|
7244
|
+
}
|
|
7245
|
+
case "surfacePattern:min":
|
|
7246
|
+
case "surfacePattern:max": {
|
|
7247
|
+
const amplitudes = pattern.children.map(estimateSurfacePatternAmplitude);
|
|
7248
|
+
return amplitudes.every((value) => value !== null) ? max$1(...amplitudes) : null;
|
|
7249
|
+
}
|
|
7250
|
+
case "surfacePattern:clamp":
|
|
7251
|
+
return max$1(abs(pattern.min), abs(pattern.max));
|
|
7252
|
+
}
|
|
7253
|
+
}
|
|
7254
|
+
function compileSurfacePattern(node) {
|
|
7255
|
+
if (node.pattern) return compileTypedSurfacePattern(node.pattern);
|
|
7256
|
+
const constEntries = Object.entries(node.constants ?? {});
|
|
7257
|
+
const constNames = constEntries.map(([k2]) => k2);
|
|
7258
|
+
const constValues = constEntries.map(([, v]) => v);
|
|
7259
|
+
const patternFn = new Function("u", "v", ...constNames, `return (${node.patternBody});`);
|
|
7260
|
+
return (u2, v) => patternFn(u2, v, ...constValues);
|
|
7261
|
+
}
|
|
6830
7262
|
function compileSdfNode3(node) {
|
|
6831
7263
|
switch (node.kind) {
|
|
6832
7264
|
case "sdf:sphere": {
|
|
6833
7265
|
const r = node.radius;
|
|
6834
|
-
return (x2, y2, z2) => sdSphere(x2, y2, z2, r);
|
|
7266
|
+
return (x2, y2, z2) => sdSphere$1(x2, y2, z2, r);
|
|
6835
7267
|
}
|
|
6836
7268
|
case "sdf:box": {
|
|
6837
7269
|
const [hx, hy, hz] = node.halfExtents;
|
|
6838
|
-
return (x2, y2, z2) => sdBox(x2, y2, z2, hx, hy, hz);
|
|
7270
|
+
return (x2, y2, z2) => sdBox$1(x2, y2, z2, hx, hy, hz);
|
|
6839
7271
|
}
|
|
6840
7272
|
case "sdf:cylinder": {
|
|
6841
7273
|
const { height: h, radius: r } = node;
|
|
6842
|
-
return (x2, y2, z2) => sdCylinder(x2, y2, z2, h, r);
|
|
7274
|
+
return (x2, y2, z2) => sdCylinder$1(x2, y2, z2, h, r);
|
|
6843
7275
|
}
|
|
6844
7276
|
case "sdf:torus": {
|
|
6845
7277
|
const { majorRadius: R, minorRadius: r } = node;
|
|
6846
|
-
return (x2, y2, z2) => sdTorus(x2, y2, z2, R, r);
|
|
7278
|
+
return (x2, y2, z2) => sdTorus$1(x2, y2, z2, R, r);
|
|
6847
7279
|
}
|
|
6848
7280
|
case "sdf:capsule": {
|
|
6849
7281
|
const { height: h, radius: r } = node;
|
|
6850
|
-
return (x2, y2, z2) => sdCapsule(x2, y2, z2, h, r);
|
|
7282
|
+
return (x2, y2, z2) => sdCapsule$1(x2, y2, z2, h, r);
|
|
6851
7283
|
}
|
|
6852
7284
|
case "sdf:cone": {
|
|
6853
7285
|
const { height: h, radius: r } = node;
|
|
6854
|
-
return (x2, y2, z2) => sdCone(x2, y2, z2, h, r);
|
|
7286
|
+
return (x2, y2, z2) => sdCone$1(x2, y2, z2, h, r);
|
|
6855
7287
|
}
|
|
6856
7288
|
case "sdf:polylineSweep": {
|
|
6857
7289
|
return (x2, y2, z2) => sdPolylineSweep3(node, x2, y2, z2);
|
|
@@ -6868,7 +7300,7 @@ function compileSdfNode3(node) {
|
|
|
6868
7300
|
const fns = node.children.map(compileSdfNode3);
|
|
6869
7301
|
return (x2, y2, z2) => {
|
|
6870
7302
|
let d2 = fns[0](x2, y2, z2);
|
|
6871
|
-
for (let i = 1; i < fns.length; i++) d2 = max(d2, -fns[i](x2, y2, z2));
|
|
7303
|
+
for (let i = 1; i < fns.length; i++) d2 = max$1(d2, -fns[i](x2, y2, z2));
|
|
6872
7304
|
return d2;
|
|
6873
7305
|
};
|
|
6874
7306
|
}
|
|
@@ -6876,7 +7308,7 @@ function compileSdfNode3(node) {
|
|
|
6876
7308
|
const fns = node.children.map(compileSdfNode3);
|
|
6877
7309
|
return (x2, y2, z2) => {
|
|
6878
7310
|
let d2 = fns[0](x2, y2, z2);
|
|
6879
|
-
for (let i = 1; i < fns.length; i++) d2 = max(d2, fns[i](x2, y2, z2));
|
|
7311
|
+
for (let i = 1; i < fns.length; i++) d2 = max$1(d2, fns[i](x2, y2, z2));
|
|
6880
7312
|
return d2;
|
|
6881
7313
|
};
|
|
6882
7314
|
}
|
|
@@ -6885,7 +7317,7 @@ function compileSdfNode3(node) {
|
|
|
6885
7317
|
const k2 = node.radius;
|
|
6886
7318
|
return (x2, y2, z2) => {
|
|
6887
7319
|
let d2 = fns[0](x2, y2, z2);
|
|
6888
|
-
for (let i = 1; i < fns.length; i++) d2 = smin(d2, fns[i](x2, y2, z2), k2);
|
|
7320
|
+
for (let i = 1; i < fns.length; i++) d2 = smin$1(d2, fns[i](x2, y2, z2), k2);
|
|
6889
7321
|
return d2;
|
|
6890
7322
|
};
|
|
6891
7323
|
}
|
|
@@ -6894,7 +7326,7 @@ function compileSdfNode3(node) {
|
|
|
6894
7326
|
const k2 = node.radius;
|
|
6895
7327
|
return (x2, y2, z2) => {
|
|
6896
7328
|
let d2 = fns[0](x2, y2, z2);
|
|
6897
|
-
for (let i = 1; i < fns.length; i++) d2 = smax(d2, -fns[i](x2, y2, z2), k2);
|
|
7329
|
+
for (let i = 1; i < fns.length; i++) d2 = smax$1(d2, -fns[i](x2, y2, z2), k2);
|
|
6898
7330
|
return d2;
|
|
6899
7331
|
};
|
|
6900
7332
|
}
|
|
@@ -6903,7 +7335,7 @@ function compileSdfNode3(node) {
|
|
|
6903
7335
|
const k2 = node.radius;
|
|
6904
7336
|
return (x2, y2, z2) => {
|
|
6905
7337
|
let d2 = fns[0](x2, y2, z2);
|
|
6906
|
-
for (let i = 1; i < fns.length; i++) d2 = smax(d2, fns[i](x2, y2, z2), k2);
|
|
7338
|
+
for (let i = 1; i < fns.length; i++) d2 = smax$1(d2, fns[i](x2, y2, z2), k2);
|
|
6907
7339
|
return d2;
|
|
6908
7340
|
};
|
|
6909
7341
|
}
|
|
@@ -6921,10 +7353,10 @@ function compileSdfNode3(node) {
|
|
|
6921
7353
|
}
|
|
6922
7354
|
case "sdf:rotate": {
|
|
6923
7355
|
const fn = compileSdfNode3(node.child);
|
|
6924
|
-
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$
|
|
6925
|
-
const cx = cos(rx), sx = sin(rx);
|
|
6926
|
-
const cy = cos(ry), sy = sin(ry);
|
|
6927
|
-
const cz = cos(rz), sz = sin(rz);
|
|
7356
|
+
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$2);
|
|
7357
|
+
const cx = cos$1(rx), sx = sin$1(rx);
|
|
7358
|
+
const cy = cos$1(ry), sy = sin$1(ry);
|
|
7359
|
+
const cz = cos$1(rz), sz = sin$1(rz);
|
|
6928
7360
|
return (x2, y2, z2) => {
|
|
6929
7361
|
const x1 = cz * x2 + sz * y2;
|
|
6930
7362
|
const y1 = -sz * x2 + cz * y2;
|
|
@@ -6943,10 +7375,10 @@ function compileSdfNode3(node) {
|
|
|
6943
7375
|
}
|
|
6944
7376
|
case "sdf:twist": {
|
|
6945
7377
|
const fn = compileSdfNode3(node.child);
|
|
6946
|
-
const k2 = node.degreesPerUnit * DEG$
|
|
7378
|
+
const k2 = node.degreesPerUnit * DEG$2;
|
|
6947
7379
|
return (x2, y2, z2) => {
|
|
6948
7380
|
const angle = k2 * z2;
|
|
6949
|
-
const c2 = cos(angle), s = sin(angle);
|
|
7381
|
+
const c2 = cos$1(angle), s = sin$1(angle);
|
|
6950
7382
|
return fn(c2 * x2 - s * y2, s * x2 + c2 * y2, z2);
|
|
6951
7383
|
};
|
|
6952
7384
|
}
|
|
@@ -6955,7 +7387,7 @@ function compileSdfNode3(node) {
|
|
|
6955
7387
|
const r = node.radius;
|
|
6956
7388
|
return (x2, y2, z2) => {
|
|
6957
7389
|
const angle = x2 / r;
|
|
6958
|
-
const c2 = cos(angle), s = sin(angle);
|
|
7390
|
+
const c2 = cos$1(angle), s = sin$1(angle);
|
|
6959
7391
|
return fn((r + y2) * s, (r + y2) * c2 - r, z2);
|
|
6960
7392
|
};
|
|
6961
7393
|
}
|
|
@@ -6963,7 +7395,19 @@ function compileSdfNode3(node) {
|
|
|
6963
7395
|
const fn = compileSdfNode3(node.child);
|
|
6964
7396
|
const [sx, sy, sz] = node.spacing;
|
|
6965
7397
|
const [cx, cy, cz] = node.count;
|
|
6966
|
-
return (x2, y2, z2) => fn(repeatCoord(x2, sx, cx), repeatCoord(y2, sy, cy), repeatCoord(z2, sz, cz));
|
|
7398
|
+
return (x2, y2, z2) => fn(repeatCoord$1(x2, sx, cx), repeatCoord$1(y2, sy, cy), repeatCoord$1(z2, sz, cz));
|
|
7399
|
+
}
|
|
7400
|
+
case "sdf:circularArray": {
|
|
7401
|
+
const fn = compileSdfNode3(node.child);
|
|
7402
|
+
const da = 2 * PI$1 / node.count;
|
|
7403
|
+
const offset2 = node.offset;
|
|
7404
|
+
return (x2, y2, z2) => {
|
|
7405
|
+
const r = length2$1(x2, y2);
|
|
7406
|
+
const a2 = positiveMod(Math.atan2(y2, x2), da);
|
|
7407
|
+
const d1 = fn(cos$1(a2 - da) * r - offset2, sin$1(a2 - da) * r, z2);
|
|
7408
|
+
const d2 = fn(cos$1(a2) * r - offset2, sin$1(a2) * r, z2);
|
|
7409
|
+
return min(d1, d2);
|
|
7410
|
+
};
|
|
6967
7411
|
}
|
|
6968
7412
|
case "sdf:shell": {
|
|
6969
7413
|
const fn = compileSdfNode3(node.child);
|
|
@@ -6980,10 +7424,7 @@ function compileSdfNode3(node) {
|
|
|
6980
7424
|
}
|
|
6981
7425
|
case "sdf:surfaceDisplace": {
|
|
6982
7426
|
const childFn = compileSdfNode3(node.child);
|
|
6983
|
-
const
|
|
6984
|
-
const constNames = constEntries.map(([k2]) => k2);
|
|
6985
|
-
const constValues = constEntries.map(([, v]) => v);
|
|
6986
|
-
const patternFn = new Function("u", "v", ...constNames, `return (${node.patternBody});`);
|
|
7427
|
+
const patternFn = compileSurfacePattern(node);
|
|
6987
7428
|
const uvMode = node.uvMode && node.uvMode !== "auto" ? node.uvMode : void 0;
|
|
6988
7429
|
const analysis = analyzeUV(node.child, uvMode);
|
|
6989
7430
|
const uvFn = compileUVFunction(analysis);
|
|
@@ -6995,7 +7436,7 @@ function compileSdfNode3(node) {
|
|
|
6995
7436
|
p2[1] = y2;
|
|
6996
7437
|
p2[2] = z2;
|
|
6997
7438
|
const [u2, v] = uvFn(p2);
|
|
6998
|
-
return d2 + patternFn(u2, v
|
|
7439
|
+
return d2 + patternFn(u2, v);
|
|
6999
7440
|
};
|
|
7000
7441
|
}
|
|
7001
7442
|
const sharpness = node.triplanarSharpness ?? 4;
|
|
@@ -7006,9 +7447,9 @@ function compileSdfNode3(node) {
|
|
|
7006
7447
|
const gy = childFn(x2, y2 + eps, z2) - childFn(x2, y2 - eps, z2);
|
|
7007
7448
|
const gz = childFn(x2, y2, z2 + eps) - childFn(x2, y2, z2 - eps);
|
|
7008
7449
|
const { wx, wy, wz } = triplanarWeights(gx, gy, gz, sharpness);
|
|
7009
|
-
const hX = patternFn(y2, z2
|
|
7010
|
-
const hY = patternFn(x2, z2
|
|
7011
|
-
const hZ = patternFn(x2, y2
|
|
7450
|
+
const hX = patternFn(y2, z2);
|
|
7451
|
+
const hY = patternFn(x2, z2);
|
|
7452
|
+
const hZ = patternFn(x2, y2);
|
|
7012
7453
|
return d2 + wx * hX + wy * hY + wz * hZ;
|
|
7013
7454
|
};
|
|
7014
7455
|
}
|
|
@@ -7078,7 +7519,7 @@ function compileSdfNode3(node) {
|
|
|
7078
7519
|
const gx = gradFn(x2 + eps, y2, z2) - gradFn(x2 - eps, y2, z2);
|
|
7079
7520
|
const gy = gradFn(x2, y2 + eps, z2) - gradFn(x2, y2 - eps, z2);
|
|
7080
7521
|
const gz = gradFn(x2, y2, z2 + eps) - gradFn(x2, y2, z2 - eps);
|
|
7081
|
-
const glen = sqrt(gx * gx + gy * gy + gz * gz);
|
|
7522
|
+
const glen = sqrt$1(gx * gx + gy * gy + gz * gz);
|
|
7082
7523
|
let nx = 0, ny = 0, nz = 0;
|
|
7083
7524
|
if (glen > 1e-10) {
|
|
7084
7525
|
const invG = 1 / glen;
|
|
@@ -7140,7 +7581,7 @@ function estimateSdfBounds(node) {
|
|
|
7140
7581
|
for (const point2 of node.points) {
|
|
7141
7582
|
for (let i = 0; i < 3; i++) {
|
|
7142
7583
|
minPoint[i] = min(minPoint[i], point2[i]);
|
|
7143
|
-
maxPoint[i] = max(maxPoint[i], point2[i]);
|
|
7584
|
+
maxPoint[i] = max$1(maxPoint[i], point2[i]);
|
|
7144
7585
|
}
|
|
7145
7586
|
}
|
|
7146
7587
|
return padBounds({ min: minPoint, max: maxPoint }, pad);
|
|
@@ -7171,7 +7612,7 @@ function estimateSdfBounds(node) {
|
|
|
7171
7612
|
}
|
|
7172
7613
|
case "sdf:rotate": {
|
|
7173
7614
|
const b = estimateSdfBounds(node.child);
|
|
7174
|
-
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])));
|
|
7615
|
+
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])));
|
|
7175
7616
|
return { min: [-r, -r, -r], max: [r, r, r] };
|
|
7176
7617
|
}
|
|
7177
7618
|
case "sdf:scale": {
|
|
@@ -7185,7 +7626,7 @@ function estimateSdfBounds(node) {
|
|
|
7185
7626
|
case "sdf:twist":
|
|
7186
7627
|
case "sdf:bend": {
|
|
7187
7628
|
const b = estimateSdfBounds(node.child);
|
|
7188
|
-
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;
|
|
7629
|
+
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;
|
|
7189
7630
|
return { min: [-r, -r, -r], max: [r, r, r] };
|
|
7190
7631
|
}
|
|
7191
7632
|
case "sdf:repeat": {
|
|
@@ -7206,16 +7647,29 @@ function estimateSdfBounds(node) {
|
|
|
7206
7647
|
const [zMin, zMax] = expand(sz, cz, b.min[2], b.max[2]);
|
|
7207
7648
|
return { min: [xMin, yMin, zMin], max: [xMax, yMax, zMax] };
|
|
7208
7649
|
}
|
|
7650
|
+
case "sdf:circularArray": {
|
|
7651
|
+
const b = estimateSdfBounds(node.child);
|
|
7652
|
+
const x0 = b.min[0] + node.offset;
|
|
7653
|
+
const x1 = b.max[0] + node.offset;
|
|
7654
|
+
const y0 = b.min[1];
|
|
7655
|
+
const y1 = b.max[1];
|
|
7656
|
+
const r = max$1(length2$1(x0, y0), length2$1(x0, y1), length2$1(x1, y0), length2$1(x1, y1));
|
|
7657
|
+
return { min: [-r, -r, b.min[2]], max: [r, r, b.max[2]] };
|
|
7658
|
+
}
|
|
7209
7659
|
case "sdf:shell": {
|
|
7210
7660
|
const b = estimateSdfBounds(node.child);
|
|
7211
7661
|
const t = node.thickness * 0.5;
|
|
7212
7662
|
return padBounds(b, t);
|
|
7213
7663
|
}
|
|
7214
|
-
case "sdf:displace":
|
|
7215
|
-
case "sdf:surfaceDisplace": {
|
|
7664
|
+
case "sdf:displace": {
|
|
7216
7665
|
const b = estimateSdfBounds(node.child);
|
|
7217
7666
|
return padBounds(b, 5);
|
|
7218
7667
|
}
|
|
7668
|
+
case "sdf:surfaceDisplace": {
|
|
7669
|
+
const b = estimateSdfBounds(node.child);
|
|
7670
|
+
if (!node.pattern) return padBounds(b, 5);
|
|
7671
|
+
return padBounds(b, estimateSurfacePatternAmplitude(node.pattern) ?? 5);
|
|
7672
|
+
}
|
|
7219
7673
|
case "sdf:onion": {
|
|
7220
7674
|
const b = estimateSdfBounds(node.child);
|
|
7221
7675
|
return padBounds(b, node.layers * node.thickness);
|
|
@@ -7252,7 +7706,7 @@ function unionBounds(bounds, pad) {
|
|
|
7252
7706
|
for (const b of bounds) {
|
|
7253
7707
|
for (let i = 0; i < 3; i++) {
|
|
7254
7708
|
result.min[i] = min(result.min[i], b.min[i]);
|
|
7255
|
-
result.max[i] = max(result.max[i], b.max[i]);
|
|
7709
|
+
result.max[i] = max$1(result.max[i], b.max[i]);
|
|
7256
7710
|
}
|
|
7257
7711
|
}
|
|
7258
7712
|
if (pad > 0) return padBounds(result, pad);
|
|
@@ -7265,7 +7719,7 @@ function intersectBounds(bounds, pad) {
|
|
|
7265
7719
|
};
|
|
7266
7720
|
for (const b of bounds) {
|
|
7267
7721
|
for (let i = 0; i < 3; i++) {
|
|
7268
|
-
result.min[i] = max(result.min[i], b.min[i]);
|
|
7722
|
+
result.min[i] = max$1(result.min[i], b.min[i]);
|
|
7269
7723
|
result.max[i] = min(result.max[i], b.max[i]);
|
|
7270
7724
|
}
|
|
7271
7725
|
}
|
|
@@ -7281,242 +7735,544 @@ function padBounds(b, pad) {
|
|
|
7281
7735
|
max: [b.max[0] + pad, b.max[1] + pad, b.max[2] + pad]
|
|
7282
7736
|
};
|
|
7283
7737
|
}
|
|
7284
|
-
const
|
|
7285
|
-
const
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7738
|
+
const { PI } = Math;
|
|
7739
|
+
const DEG$1 = PI / 180;
|
|
7740
|
+
const TAU = 2 * PI;
|
|
7741
|
+
const GRAD_EPS = 1e-9;
|
|
7742
|
+
const Op = {
|
|
7743
|
+
Const: 0,
|
|
7744
|
+
Neg: 1,
|
|
7745
|
+
Abs: 2,
|
|
7746
|
+
Sqrt: 3,
|
|
7747
|
+
Sin: 4,
|
|
7748
|
+
Cos: 5,
|
|
7749
|
+
Round: 6,
|
|
7750
|
+
Add: 7,
|
|
7751
|
+
Sub: 8,
|
|
7752
|
+
Mul: 9,
|
|
7753
|
+
Div: 10,
|
|
7754
|
+
Min: 11,
|
|
7755
|
+
Max: 12
|
|
7756
|
+
};
|
|
7757
|
+
class UnsupportedSdfProgramNodeError extends Error {
|
|
7758
|
+
constructor(message) {
|
|
7759
|
+
super(message);
|
|
7760
|
+
this.name = "UnsupportedSdfProgramNodeError";
|
|
7304
7761
|
}
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
);
|
|
7762
|
+
}
|
|
7763
|
+
class SdfProgramBuilder {
|
|
7764
|
+
constructor() {
|
|
7765
|
+
__publicField(this, "opcodes", []);
|
|
7766
|
+
__publicField(this, "argA", []);
|
|
7767
|
+
__publicField(this, "argB", []);
|
|
7768
|
+
__publicField(this, "argC", []);
|
|
7769
|
+
__publicField(this, "constants", []);
|
|
7770
|
+
__publicField(this, "x", 0);
|
|
7771
|
+
__publicField(this, "y", 1);
|
|
7772
|
+
__publicField(this, "z", 2);
|
|
7310
7773
|
}
|
|
7311
|
-
|
|
7312
|
-
|
|
7774
|
+
constant(value) {
|
|
7775
|
+
const index2 = this.constants.length;
|
|
7776
|
+
this.constants.push(value);
|
|
7777
|
+
return this.push(Op.Const, 0, 0, index2);
|
|
7313
7778
|
}
|
|
7314
|
-
|
|
7315
|
-
|
|
7779
|
+
neg(a2) {
|
|
7780
|
+
return this.push(Op.Neg, a2);
|
|
7316
7781
|
}
|
|
7317
|
-
|
|
7318
|
-
|
|
7782
|
+
abs(a2) {
|
|
7783
|
+
return this.push(Op.Abs, a2);
|
|
7319
7784
|
}
|
|
7320
|
-
|
|
7321
|
-
|
|
7785
|
+
sqrt(a2) {
|
|
7786
|
+
return this.push(Op.Sqrt, a2);
|
|
7322
7787
|
}
|
|
7788
|
+
sin(a2) {
|
|
7789
|
+
return this.push(Op.Sin, a2);
|
|
7790
|
+
}
|
|
7791
|
+
cos(a2) {
|
|
7792
|
+
return this.push(Op.Cos, a2);
|
|
7793
|
+
}
|
|
7794
|
+
round(a2) {
|
|
7795
|
+
return this.push(Op.Round, a2);
|
|
7796
|
+
}
|
|
7797
|
+
add(a2, b) {
|
|
7798
|
+
return this.push(Op.Add, a2, b);
|
|
7799
|
+
}
|
|
7800
|
+
sub(a2, b) {
|
|
7801
|
+
return this.push(Op.Sub, a2, b);
|
|
7802
|
+
}
|
|
7803
|
+
mul(a2, b) {
|
|
7804
|
+
return this.push(Op.Mul, a2, b);
|
|
7805
|
+
}
|
|
7806
|
+
div(a2, b) {
|
|
7807
|
+
return this.push(Op.Div, a2, b);
|
|
7808
|
+
}
|
|
7809
|
+
min(a2, b) {
|
|
7810
|
+
return this.push(Op.Min, a2, b);
|
|
7811
|
+
}
|
|
7812
|
+
max(a2, b) {
|
|
7813
|
+
return this.push(Op.Max, a2, b);
|
|
7814
|
+
}
|
|
7815
|
+
finalize(output) {
|
|
7816
|
+
return {
|
|
7817
|
+
opcodes: Uint8Array.from(this.opcodes),
|
|
7818
|
+
argA: Int32Array.from(this.argA),
|
|
7819
|
+
argB: Int32Array.from(this.argB),
|
|
7820
|
+
argC: Int32Array.from(this.argC),
|
|
7821
|
+
constants: Float64Array.from(this.constants),
|
|
7822
|
+
output,
|
|
7823
|
+
slotCount: this.opcodes.length + 3
|
|
7824
|
+
};
|
|
7825
|
+
}
|
|
7826
|
+
push(op, a2 = 0, b = 0, c2 = 0) {
|
|
7827
|
+
const slot2 = this.opcodes.length + 3;
|
|
7828
|
+
this.opcodes.push(op);
|
|
7829
|
+
this.argA.push(a2);
|
|
7830
|
+
this.argB.push(b);
|
|
7831
|
+
this.argC.push(c2);
|
|
7832
|
+
return slot2;
|
|
7833
|
+
}
|
|
7834
|
+
}
|
|
7835
|
+
function compileSdfProgramEvaluator3(program) {
|
|
7836
|
+
const lines = ["const { abs, sqrt, sin, cos, round, min, max } = Math;", "let v0 = x;", "let v1 = y;", "let v2 = z;"];
|
|
7837
|
+
const { opcodes, argA, argB, argC, constants, output } = program;
|
|
7838
|
+
for (let i = 0; i < opcodes.length; i++) {
|
|
7839
|
+
const slot2 = `v${i + 3}`;
|
|
7840
|
+
const a2 = `v${argA[i]}`;
|
|
7841
|
+
const b = `v${argB[i]}`;
|
|
7842
|
+
switch (opcodes[i]) {
|
|
7843
|
+
case Op.Const:
|
|
7844
|
+
lines.push(`let ${slot2} = ${numberLiteral(constants[argC[i]])};`);
|
|
7845
|
+
break;
|
|
7846
|
+
case Op.Neg:
|
|
7847
|
+
lines.push(`let ${slot2} = -${a2};`);
|
|
7848
|
+
break;
|
|
7849
|
+
case Op.Abs:
|
|
7850
|
+
lines.push(`let ${slot2} = abs(${a2});`);
|
|
7851
|
+
break;
|
|
7852
|
+
case Op.Sqrt:
|
|
7853
|
+
lines.push(`let ${slot2} = sqrt(${a2});`);
|
|
7854
|
+
break;
|
|
7855
|
+
case Op.Sin:
|
|
7856
|
+
lines.push(`let ${slot2} = sin(${a2});`);
|
|
7857
|
+
break;
|
|
7858
|
+
case Op.Cos:
|
|
7859
|
+
lines.push(`let ${slot2} = cos(${a2});`);
|
|
7860
|
+
break;
|
|
7861
|
+
case Op.Round:
|
|
7862
|
+
lines.push(`let ${slot2} = round(${a2});`);
|
|
7863
|
+
break;
|
|
7864
|
+
case Op.Add:
|
|
7865
|
+
lines.push(`let ${slot2} = ${a2} + ${b};`);
|
|
7866
|
+
break;
|
|
7867
|
+
case Op.Sub:
|
|
7868
|
+
lines.push(`let ${slot2} = ${a2} - ${b};`);
|
|
7869
|
+
break;
|
|
7870
|
+
case Op.Mul:
|
|
7871
|
+
lines.push(`let ${slot2} = ${a2} * ${b};`);
|
|
7872
|
+
break;
|
|
7873
|
+
case Op.Div:
|
|
7874
|
+
lines.push(`let ${slot2} = ${a2} / ${b};`);
|
|
7875
|
+
break;
|
|
7876
|
+
case Op.Min:
|
|
7877
|
+
lines.push(`let ${slot2} = min(${a2}, ${b});`);
|
|
7878
|
+
break;
|
|
7879
|
+
case Op.Max:
|
|
7880
|
+
lines.push(`let ${slot2} = max(${a2}, ${b});`);
|
|
7881
|
+
break;
|
|
7882
|
+
default:
|
|
7883
|
+
throw new Error(`Unknown SdfProgram opcode ${opcodes[i]} at instruction ${i}.`);
|
|
7884
|
+
}
|
|
7885
|
+
}
|
|
7886
|
+
lines.push(`return v${output};`);
|
|
7887
|
+
return new Function("Math", `return function sdfProgramEval(x, y, z) {
|
|
7888
|
+
${lines.join("\n")}
|
|
7889
|
+
};`)(Math);
|
|
7890
|
+
}
|
|
7891
|
+
function numberLiteral(value) {
|
|
7892
|
+
if (Number.isNaN(value)) return "NaN";
|
|
7893
|
+
if (value === Number.POSITIVE_INFINITY) return "Infinity";
|
|
7894
|
+
if (value === Number.NEGATIVE_INFINITY) return "-Infinity";
|
|
7895
|
+
return String(value);
|
|
7896
|
+
}
|
|
7897
|
+
function clampSlot(b, v, lo, hi) {
|
|
7898
|
+
return b.min(b.max(v, b.constant(lo)), b.constant(hi));
|
|
7899
|
+
}
|
|
7900
|
+
function length2(b, x2, y2) {
|
|
7901
|
+
return b.sqrt(b.add(b.mul(x2, x2), b.mul(y2, y2)));
|
|
7902
|
+
}
|
|
7903
|
+
function length3(b, x2, y2, z2) {
|
|
7904
|
+
return b.sqrt(b.add(b.add(b.mul(x2, x2), b.mul(y2, y2)), b.mul(z2, z2)));
|
|
7905
|
+
}
|
|
7906
|
+
function smin(b, a2, child, k2) {
|
|
7907
|
+
if (k2 <= 0) return b.min(a2, child);
|
|
7908
|
+
const h = b.div(b.max(b.sub(b.constant(k2), b.abs(b.sub(a2, child))), b.constant(0)), b.constant(k2));
|
|
7909
|
+
return b.sub(b.min(a2, child), b.mul(b.mul(b.mul(h, h), h), b.constant(k2 / 6)));
|
|
7910
|
+
}
|
|
7911
|
+
function smax(b, a2, child, k2) {
|
|
7912
|
+
return b.neg(smin(b, b.neg(a2), b.neg(child), k2));
|
|
7913
|
+
}
|
|
7914
|
+
function emitScaledTrig(b, x2, y2, z2, cellSize) {
|
|
7915
|
+
const s = b.constant(TAU / cellSize);
|
|
7916
|
+
const xs = b.mul(x2, s);
|
|
7917
|
+
const ys = b.mul(y2, s);
|
|
7918
|
+
const zs = b.mul(z2, s);
|
|
7323
7919
|
return {
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7920
|
+
scale: s,
|
|
7921
|
+
sx: b.sin(xs),
|
|
7922
|
+
sy: b.sin(ys),
|
|
7923
|
+
sz: b.sin(zs),
|
|
7924
|
+
cx: b.cos(xs),
|
|
7925
|
+
cy: b.cos(ys),
|
|
7926
|
+
cz: b.cos(zs),
|
|
7927
|
+
sx2: b.sin(b.mul(b.constant(2), xs)),
|
|
7928
|
+
sy2: b.sin(b.mul(b.constant(2), ys)),
|
|
7929
|
+
sz2: b.sin(b.mul(b.constant(2), zs)),
|
|
7930
|
+
cx2: b.cos(b.mul(b.constant(2), xs)),
|
|
7931
|
+
cy2: b.cos(b.mul(b.constant(2), ys)),
|
|
7932
|
+
cz2: b.cos(b.mul(b.constant(2), zs))
|
|
7335
7933
|
};
|
|
7336
7934
|
}
|
|
7337
|
-
function
|
|
7338
|
-
|
|
7935
|
+
function emitGyroidValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
7936
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
7937
|
+
return {
|
|
7938
|
+
value: b.add(b.add(b.mul(t.sx, t.cy), b.mul(t.sy, t.cz)), b.mul(t.sz, t.cx)),
|
|
7939
|
+
gx: b.mul(t.scale, b.sub(b.mul(t.cx, t.cy), b.mul(t.sz, t.sx))),
|
|
7940
|
+
gy: b.mul(t.scale, b.add(b.neg(b.mul(t.sx, t.sy)), b.mul(t.cy, t.cz))),
|
|
7941
|
+
gz: b.mul(t.scale, b.add(b.neg(b.mul(t.sy, t.sz)), b.mul(t.cz, t.cx)))
|
|
7942
|
+
};
|
|
7339
7943
|
}
|
|
7340
|
-
function
|
|
7341
|
-
const
|
|
7342
|
-
const estimatedSamples = grid[0] * grid[1] * grid[2];
|
|
7944
|
+
function emitSchwarzPValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
7945
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
7343
7946
|
return {
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
estimatedSamples,
|
|
7349
|
-
estimatedMemoryBytes: estimatedSamples * 8,
|
|
7350
|
-
treeRiskFlags: [...settings.treeRiskFlags],
|
|
7351
|
-
simplification: settings.simplify,
|
|
7352
|
-
capMode: "box",
|
|
7353
|
-
capInset: settings.edgeLength,
|
|
7354
|
-
warnings: [...settings.warnings]
|
|
7947
|
+
value: b.add(b.add(t.cx, t.cy), t.cz),
|
|
7948
|
+
gx: b.neg(b.mul(t.scale, t.sx)),
|
|
7949
|
+
gy: b.neg(b.mul(t.scale, t.sy)),
|
|
7950
|
+
gz: b.neg(b.mul(t.scale, t.sz))
|
|
7355
7951
|
};
|
|
7356
7952
|
}
|
|
7357
|
-
function
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
)
|
|
7953
|
+
function emitDiamondValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
7954
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
7955
|
+
return {
|
|
7956
|
+
value: b.add(
|
|
7957
|
+
b.add(b.mul(b.mul(t.sx, t.sy), t.sz), b.mul(b.mul(t.sx, t.cy), t.cz)),
|
|
7958
|
+
b.add(b.mul(b.mul(t.cx, t.sy), t.cz), b.mul(b.mul(t.cx, t.cy), t.sz))
|
|
7959
|
+
),
|
|
7960
|
+
gx: b.mul(
|
|
7961
|
+
t.scale,
|
|
7962
|
+
b.add(
|
|
7963
|
+
b.add(b.mul(b.mul(t.cx, t.sy), t.sz), b.mul(b.mul(t.cx, t.cy), t.cz)),
|
|
7964
|
+
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)))
|
|
7965
|
+
)
|
|
7966
|
+
),
|
|
7967
|
+
gy: b.mul(
|
|
7968
|
+
t.scale,
|
|
7969
|
+
b.add(
|
|
7970
|
+
b.add(b.mul(b.mul(t.sx, t.cy), t.sz), b.neg(b.mul(b.mul(t.sx, t.sy), t.cz))),
|
|
7971
|
+
b.add(b.mul(b.mul(t.cx, t.cy), t.cz), b.neg(b.mul(b.mul(t.cx, t.sy), t.sz)))
|
|
7972
|
+
)
|
|
7973
|
+
),
|
|
7974
|
+
gz: b.mul(
|
|
7975
|
+
t.scale,
|
|
7976
|
+
b.add(
|
|
7977
|
+
b.add(b.mul(b.mul(t.sx, t.sy), t.cz), b.neg(b.mul(b.mul(t.sx, t.cy), t.sz))),
|
|
7978
|
+
b.add(b.neg(b.mul(b.mul(t.cx, t.sy), t.sz)), b.mul(b.mul(t.cx, t.cy), t.cz))
|
|
7979
|
+
)
|
|
7980
|
+
)
|
|
7981
|
+
};
|
|
7982
|
+
}
|
|
7983
|
+
function emitLidinoidValueAndGradient(b, x2, y2, z2, cellSize) {
|
|
7984
|
+
const t = emitScaledTrig(b, x2, y2, z2, cellSize);
|
|
7985
|
+
const value = b.add(
|
|
7986
|
+
b.sub(
|
|
7987
|
+
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)),
|
|
7988
|
+
b.add(b.add(b.mul(t.cx2, t.cy2), b.mul(t.cy2, t.cz2)), b.mul(t.cz2, t.cx2))
|
|
7989
|
+
),
|
|
7990
|
+
b.constant(0.3)
|
|
7364
7991
|
);
|
|
7992
|
+
return {
|
|
7993
|
+
value,
|
|
7994
|
+
gx: b.mul(
|
|
7995
|
+
t.scale,
|
|
7996
|
+
b.add(
|
|
7997
|
+
b.add(
|
|
7998
|
+
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)),
|
|
7999
|
+
b.neg(b.mul(b.mul(t.sz2, t.sx), t.sy))
|
|
8000
|
+
),
|
|
8001
|
+
b.add(b.mul(b.mul(b.constant(2), t.sx2), t.cy2), b.mul(b.mul(b.constant(2), t.cz2), t.sx2))
|
|
8002
|
+
)
|
|
8003
|
+
),
|
|
8004
|
+
gy: b.mul(
|
|
8005
|
+
t.scale,
|
|
8006
|
+
b.add(
|
|
8007
|
+
b.add(
|
|
8008
|
+
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))),
|
|
8009
|
+
b.mul(b.mul(t.sz2, t.cx), t.cy)
|
|
8010
|
+
),
|
|
8011
|
+
b.add(b.mul(b.mul(b.constant(2), t.cx2), t.sy2), b.mul(b.mul(b.constant(2), t.sy2), t.cz2))
|
|
8012
|
+
)
|
|
8013
|
+
),
|
|
8014
|
+
gz: b.mul(
|
|
8015
|
+
t.scale,
|
|
8016
|
+
b.add(
|
|
8017
|
+
b.add(
|
|
8018
|
+
b.add(b.mul(b.mul(t.sx2, t.cy), t.cz), b.neg(b.mul(b.mul(t.sy2, t.sz), t.sx))),
|
|
8019
|
+
b.mul(b.mul(b.constant(2), t.cz2), b.mul(t.cx, t.sy))
|
|
8020
|
+
),
|
|
8021
|
+
b.add(b.mul(b.mul(b.constant(2), t.cy2), t.sz2), b.mul(b.mul(b.constant(2), t.sz2), t.cx2))
|
|
8022
|
+
)
|
|
8023
|
+
)
|
|
8024
|
+
};
|
|
7365
8025
|
}
|
|
7366
|
-
function
|
|
7367
|
-
|
|
7368
|
-
const
|
|
7369
|
-
|
|
7370
|
-
return [
|
|
7371
|
-
Math.max(2, Math.ceil(dx / edgeLength2) + 1),
|
|
7372
|
-
Math.max(2, Math.ceil(dy / edgeLength2) + 1),
|
|
7373
|
-
Math.max(2, Math.ceil(dz / edgeLength2) + 1)
|
|
7374
|
-
];
|
|
8026
|
+
function emitTpmsDistance(b, { value, gx, gy, gz }, thickness, thicknessMode) {
|
|
8027
|
+
if (thicknessMode !== "metric-approx") return b.sub(b.abs(value), b.constant(thickness));
|
|
8028
|
+
const grad = length3(b, gx, gy, gz);
|
|
8029
|
+
return b.sub(b.div(b.abs(value), b.max(grad, b.constant(GRAD_EPS))), b.constant(thickness * 0.5));
|
|
7375
8030
|
}
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
8031
|
+
const { cos, max, sin, sqrt } = Math;
|
|
8032
|
+
function emitSdfProgramNode(b, node, x2, y2, z2) {
|
|
8033
|
+
switch (node.kind) {
|
|
8034
|
+
case "sdf:sphere":
|
|
8035
|
+
return sdSphere(b, x2, y2, z2, node.radius);
|
|
8036
|
+
case "sdf:box": {
|
|
8037
|
+
const [hx, hy, hz] = node.halfExtents;
|
|
8038
|
+
return sdBox(b, x2, y2, z2, hx, hy, hz);
|
|
8039
|
+
}
|
|
8040
|
+
case "sdf:cylinder":
|
|
8041
|
+
return sdCylinder(b, x2, y2, z2, node.height, node.radius);
|
|
8042
|
+
case "sdf:torus":
|
|
8043
|
+
return sdTorus(b, x2, y2, z2, node.majorRadius, node.minorRadius);
|
|
8044
|
+
case "sdf:capsule":
|
|
8045
|
+
return sdCapsule(b, x2, y2, z2, node.height, node.radius);
|
|
8046
|
+
case "sdf:cone":
|
|
8047
|
+
return sdCone(b, x2, y2, z2, node.height, node.radius);
|
|
8048
|
+
case "sdf:polylineSweep":
|
|
8049
|
+
return sdPolylineSweep(b, node, x2, y2, z2);
|
|
8050
|
+
case "sdf:union":
|
|
8051
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => b.min(a2, child));
|
|
8052
|
+
case "sdf:difference":
|
|
8053
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => b.max(a2, b.neg(child)));
|
|
8054
|
+
case "sdf:intersection":
|
|
8055
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => b.max(a2, child));
|
|
8056
|
+
case "sdf:smoothUnion":
|
|
8057
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => smin(b, a2, child, node.radius));
|
|
8058
|
+
case "sdf:smoothDifference":
|
|
8059
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => smax(b, a2, b.neg(child), node.radius));
|
|
8060
|
+
case "sdf:smoothIntersection":
|
|
8061
|
+
return foldChildren(b, node.children, x2, y2, z2, (a2, child) => smax(b, a2, child, node.radius));
|
|
8062
|
+
case "sdf:morph": {
|
|
8063
|
+
const a2 = emitSdfProgramNode(b, node.a, x2, y2, z2);
|
|
8064
|
+
const childB = emitSdfProgramNode(b, node.b, x2, y2, z2);
|
|
8065
|
+
return b.add(b.mul(a2, b.constant(1 - node.t)), b.mul(childB, b.constant(node.t)));
|
|
8066
|
+
}
|
|
8067
|
+
case "sdf:translate": {
|
|
8068
|
+
const [ox, oy, oz] = node.offset;
|
|
8069
|
+
return emitSdfProgramNode(b, node.child, b.sub(x2, b.constant(ox)), b.sub(y2, b.constant(oy)), b.sub(z2, b.constant(oz)));
|
|
8070
|
+
}
|
|
8071
|
+
case "sdf:rotate":
|
|
8072
|
+
return emitRotated(b, node, x2, y2, z2);
|
|
8073
|
+
case "sdf:scale": {
|
|
8074
|
+
const inv = 1 / node.factor;
|
|
8075
|
+
const child = emitSdfProgramNode(b, node.child, b.mul(x2, b.constant(inv)), b.mul(y2, b.constant(inv)), b.mul(z2, b.constant(inv)));
|
|
8076
|
+
return b.mul(child, b.constant(node.factor));
|
|
8077
|
+
}
|
|
8078
|
+
case "sdf:twist": {
|
|
8079
|
+
const angle = b.mul(b.constant(node.degreesPerUnit * DEG$1), z2);
|
|
8080
|
+
const c2 = b.cos(angle);
|
|
8081
|
+
const s = b.sin(angle);
|
|
8082
|
+
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);
|
|
8083
|
+
}
|
|
8084
|
+
case "sdf:bend": {
|
|
8085
|
+
const angle = b.div(x2, b.constant(node.radius));
|
|
8086
|
+
const c2 = b.cos(angle);
|
|
8087
|
+
const s = b.sin(angle);
|
|
8088
|
+
const radiusPlusY = b.add(b.constant(node.radius), y2);
|
|
8089
|
+
return emitSdfProgramNode(b, node.child, b.mul(radiusPlusY, s), b.sub(b.mul(radiusPlusY, c2), b.constant(node.radius)), z2);
|
|
8090
|
+
}
|
|
8091
|
+
case "sdf:repeat": {
|
|
8092
|
+
const [sx, sy, sz] = node.spacing;
|
|
8093
|
+
const [cx, cy, cz] = node.count;
|
|
8094
|
+
return emitSdfProgramNode(b, node.child, repeatCoord(b, x2, sx, cx), repeatCoord(b, y2, sy, cy), repeatCoord(b, z2, sz, cz));
|
|
8095
|
+
}
|
|
8096
|
+
case "sdf:shell": {
|
|
8097
|
+
const child = emitSdfProgramNode(b, node.child, x2, y2, z2);
|
|
8098
|
+
return b.sub(b.abs(child), b.constant(node.thickness * 0.5));
|
|
8099
|
+
}
|
|
8100
|
+
case "sdf:onion": {
|
|
8101
|
+
let d2 = emitSdfProgramNode(b, node.child, x2, y2, z2);
|
|
8102
|
+
for (let i = 0; i < node.layers; i++) d2 = b.sub(b.abs(d2), b.constant(node.thickness));
|
|
8103
|
+
return d2;
|
|
8104
|
+
}
|
|
8105
|
+
case "sdf:gyroid":
|
|
8106
|
+
return emitTpmsDistance(b, emitGyroidValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
8107
|
+
case "sdf:schwarzP":
|
|
8108
|
+
return emitTpmsDistance(b, emitSchwarzPValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
8109
|
+
case "sdf:diamond":
|
|
8110
|
+
return emitTpmsDistance(b, emitDiamondValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
8111
|
+
case "sdf:lidinoid":
|
|
8112
|
+
return emitTpmsDistance(b, emitLidinoidValueAndGradient(b, x2, y2, z2, node.cellSize), node.thickness, node.thicknessMode);
|
|
8113
|
+
default:
|
|
8114
|
+
throw new UnsupportedSdfProgramNodeError(`SdfProgram does not support node kind ${node.kind} yet.`);
|
|
8115
|
+
}
|
|
7381
8116
|
}
|
|
7382
|
-
function
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
const maxDim = Math.max(dx, dy, dz, minEdgeLength);
|
|
7387
|
-
const divisor = quality === "draft" ? 60 : quality === "export" ? 160 : 100;
|
|
7388
|
-
const candidates = [maxDim / divisor];
|
|
7389
|
-
if (options.tolerance !== void 0) candidates.push(requirePositiveFinite$2(options.tolerance, "SDF tolerance") * 2);
|
|
7390
|
-
if (options.minFeatureSize !== void 0) candidates.push(requirePositiveFinite$2(options.minFeatureSize, "SDF minFeatureSize") / 2.5);
|
|
7391
|
-
if (analysis.minMetricTpmsThickness < Infinity) candidates.push(analysis.minMetricTpmsThickness / 2);
|
|
7392
|
-
if (analysis.minTpmsCellSize < Infinity) candidates.push(analysis.minTpmsCellSize / 10);
|
|
7393
|
-
if (analysis.minRepeatSpacing < Infinity) candidates.push(analysis.minRepeatSpacing / 8);
|
|
7394
|
-
if (analysis.minWallThickness < Infinity) candidates.push(analysis.minWallThickness / 2.5);
|
|
7395
|
-
return Math.max(minEdgeLength, Math.min(...candidates.filter((v) => Number.isFinite(v) && v > 0)));
|
|
8117
|
+
function foldChildren(b, children, x2, y2, z2, combine2) {
|
|
8118
|
+
let d2 = emitSdfProgramNode(b, children[0], x2, y2, z2);
|
|
8119
|
+
for (let i = 1; i < children.length; i++) d2 = combine2(d2, emitSdfProgramNode(b, children[i], x2, y2, z2));
|
|
8120
|
+
return d2;
|
|
7396
8121
|
}
|
|
7397
|
-
function
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
8122
|
+
function emitRotated(b, node, x2, y2, z2) {
|
|
8123
|
+
const [rx, ry, rz] = node.degrees.map((d2) => d2 * DEG$1);
|
|
8124
|
+
const cx = cos(rx);
|
|
8125
|
+
const sx = sin(rx);
|
|
8126
|
+
const cy = cos(ry);
|
|
8127
|
+
const sy = sin(ry);
|
|
8128
|
+
const cz = cos(rz);
|
|
8129
|
+
const sz = sin(rz);
|
|
8130
|
+
const x1 = b.add(b.mul(b.constant(cz), x2), b.mul(b.constant(sz), y2));
|
|
8131
|
+
const y1 = b.sub(b.mul(b.constant(cz), y2), b.mul(b.constant(sz), x2));
|
|
8132
|
+
const x22 = b.sub(b.mul(b.constant(cy), x1), b.mul(b.constant(sy), z2));
|
|
8133
|
+
const z22 = b.add(b.mul(b.constant(sy), x1), b.mul(b.constant(cy), z2));
|
|
8134
|
+
const y22 = b.add(b.mul(b.constant(cx), y1), b.mul(b.constant(sx), z22));
|
|
8135
|
+
const z3 = b.sub(b.mul(b.constant(cx), z22), b.mul(b.constant(sx), y1));
|
|
8136
|
+
return emitSdfProgramNode(b, node.child, x22, y22, z3);
|
|
8137
|
+
}
|
|
8138
|
+
function sdSphere(b, x2, y2, z2, r) {
|
|
8139
|
+
return b.sub(length3(b, x2, y2, z2), b.constant(r));
|
|
8140
|
+
}
|
|
8141
|
+
function sdBox(b, x2, y2, z2, hx, hy, hz) {
|
|
8142
|
+
const dx = b.sub(b.abs(x2), b.constant(hx));
|
|
8143
|
+
const dy = b.sub(b.abs(y2), b.constant(hy));
|
|
8144
|
+
const dz = b.sub(b.abs(z2), b.constant(hz));
|
|
8145
|
+
const outside = length3(b, b.max(dx, b.constant(0)), b.max(dy, b.constant(0)), b.max(dz, b.constant(0)));
|
|
8146
|
+
const inside = b.min(b.max(b.max(dx, dy), dz), b.constant(0));
|
|
8147
|
+
return b.add(outside, inside);
|
|
8148
|
+
}
|
|
8149
|
+
function sdCylinder(b, x2, y2, z2, h, r) {
|
|
8150
|
+
const dx = b.sub(length2(b, x2, y2), b.constant(r));
|
|
8151
|
+
const dz = b.sub(b.abs(z2), b.constant(h * 0.5));
|
|
8152
|
+
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)));
|
|
8153
|
+
}
|
|
8154
|
+
function sdTorus(b, x2, y2, z2, majorRadius, minorRadius) {
|
|
8155
|
+
return b.sub(length2(b, b.sub(length2(b, x2, y2), b.constant(majorRadius)), z2), b.constant(minorRadius));
|
|
8156
|
+
}
|
|
8157
|
+
function sdCapsule(b, x2, y2, z2, h, r) {
|
|
8158
|
+
const cz = clampSlot(b, z2, -h * 0.5, h * 0.5);
|
|
8159
|
+
return b.sub(length3(b, x2, y2, b.sub(z2, cz)), b.constant(r));
|
|
8160
|
+
}
|
|
8161
|
+
function sdCone(b, x2, y2, z2, h, r) {
|
|
8162
|
+
const q = length2(b, x2, y2);
|
|
8163
|
+
const cLen = sqrt(h * h + r * r);
|
|
8164
|
+
const side = b.add(b.mul(b.constant(h / cLen), q), b.mul(b.constant(-r / cLen), b.sub(z2, b.constant(h))));
|
|
8165
|
+
return b.max(b.max(side, b.neg(z2)), b.sub(z2, b.constant(h)));
|
|
8166
|
+
}
|
|
8167
|
+
function sdPolylineSweep(b, node, x2, y2, z2) {
|
|
8168
|
+
let d2 = sdTaperedSegment(b, x2, y2, z2, node.points[0], node.points[1], node.radii[0], node.radii[1]);
|
|
8169
|
+
for (let i = 1; i < node.points.length - 1; i++) {
|
|
8170
|
+
const segment = sdTaperedSegment(b, x2, y2, z2, node.points[i], node.points[i + 1], node.radii[i], node.radii[i + 1]);
|
|
8171
|
+
d2 = smin(b, d2, segment, node.blend);
|
|
8172
|
+
}
|
|
8173
|
+
return d2;
|
|
7402
8174
|
}
|
|
7403
|
-
function
|
|
7404
|
-
const
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
8175
|
+
function sdTaperedSegment(b, x2, y2, z2, a2, end, ra, rb) {
|
|
8176
|
+
const vx = end[0] - a2[0];
|
|
8177
|
+
const vy = end[1] - a2[1];
|
|
8178
|
+
const vz = end[2] - a2[2];
|
|
8179
|
+
const len2 = vx * vx + vy * vy + vz * vz;
|
|
8180
|
+
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));
|
|
8181
|
+
const h = clampSlot(
|
|
8182
|
+
b,
|
|
8183
|
+
b.div(
|
|
8184
|
+
b.add(
|
|
8185
|
+
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))),
|
|
8186
|
+
b.mul(b.sub(z2, b.constant(a2[2])), b.constant(vz))
|
|
8187
|
+
),
|
|
8188
|
+
b.constant(len2)
|
|
8189
|
+
),
|
|
8190
|
+
0,
|
|
8191
|
+
1
|
|
8192
|
+
);
|
|
8193
|
+
const sx = b.sub(x2, b.add(b.constant(a2[0]), b.mul(b.constant(vx), h)));
|
|
8194
|
+
const sy = b.sub(y2, b.add(b.constant(a2[1]), b.mul(b.constant(vy), h)));
|
|
8195
|
+
const sz = b.sub(z2, b.add(b.constant(a2[2]), b.mul(b.constant(vz), h)));
|
|
8196
|
+
const radius = b.add(b.constant(ra), b.mul(b.constant(rb - ra), h));
|
|
8197
|
+
return b.sub(length3(b, sx, sy, sz), radius);
|
|
7415
8198
|
}
|
|
7416
|
-
function
|
|
8199
|
+
function repeatCoord(b, v, spacing, count) {
|
|
8200
|
+
if (spacing <= 0) return v;
|
|
8201
|
+
if (count > 0) {
|
|
8202
|
+
const center = (count - 1) * 0.5;
|
|
8203
|
+
const index2 = clampSlot(b, b.round(b.add(b.div(v, b.constant(spacing)), b.constant(center))), 0, count - 1);
|
|
8204
|
+
return b.sub(v, b.mul(b.sub(index2, b.constant(center)), b.constant(spacing)));
|
|
8205
|
+
}
|
|
8206
|
+
return b.sub(v, b.mul(b.constant(spacing), b.round(b.div(v, b.constant(spacing)))));
|
|
8207
|
+
}
|
|
8208
|
+
function getUnsupportedSdfProgramReason(node) {
|
|
7417
8209
|
switch (node.kind) {
|
|
8210
|
+
case "sdf:displace":
|
|
8211
|
+
return "displace uses a dynamic JavaScript function body";
|
|
8212
|
+
case "sdf:surfaceDisplace":
|
|
8213
|
+
return "surfaceDisplace uses dynamic UV/pattern evaluation";
|
|
8214
|
+
case "sdf:spatialBlend":
|
|
8215
|
+
return "spatialBlend uses a dynamic JavaScript blend function";
|
|
8216
|
+
case "sdf:noise":
|
|
8217
|
+
return "noise depends on table-based simplex evaluation";
|
|
8218
|
+
case "sdf:voronoi":
|
|
8219
|
+
return "voronoi depends on table-based Worley evaluation";
|
|
8220
|
+
case "sdf:custom":
|
|
8221
|
+
return "custom uses a dynamic JavaScript function body";
|
|
8222
|
+
case "sdf:polylineSweep":
|
|
8223
|
+
if (node.points.length < 2) return "polylineSweep needs at least two points";
|
|
8224
|
+
if (node.points.length !== node.radii.length) return "polylineSweep point/radius counts differ";
|
|
8225
|
+
return void 0;
|
|
7418
8226
|
case "sdf:union":
|
|
7419
8227
|
case "sdf:difference":
|
|
7420
8228
|
case "sdf:intersection":
|
|
7421
8229
|
case "sdf:smoothUnion":
|
|
7422
8230
|
case "sdf:smoothDifference":
|
|
7423
8231
|
case "sdf:smoothIntersection":
|
|
7424
|
-
for (const child of node.children)
|
|
7425
|
-
|
|
8232
|
+
for (const child of node.children) {
|
|
8233
|
+
const reason = getUnsupportedSdfProgramReason(child);
|
|
8234
|
+
if (reason) return reason;
|
|
8235
|
+
}
|
|
8236
|
+
return void 0;
|
|
7426
8237
|
case "sdf:morph":
|
|
7427
|
-
|
|
7428
|
-
visitSdfNode(node.a, analysis);
|
|
7429
|
-
visitSdfNode(node.b, analysis);
|
|
7430
|
-
break;
|
|
8238
|
+
return getUnsupportedSdfProgramReason(node.a) ?? getUnsupportedSdfProgramReason(node.b);
|
|
7431
8239
|
case "sdf:translate":
|
|
7432
8240
|
case "sdf:rotate":
|
|
7433
8241
|
case "sdf:scale":
|
|
7434
8242
|
case "sdf:twist":
|
|
7435
8243
|
case "sdf:bend":
|
|
7436
|
-
case "sdf:onion":
|
|
7437
|
-
visitSdfNode(node.child, analysis);
|
|
7438
|
-
break;
|
|
7439
8244
|
case "sdf:repeat":
|
|
7440
|
-
analysis.riskFlags.add("repeat");
|
|
7441
|
-
for (let i = 0; i < 3; i++) {
|
|
7442
|
-
const spacing = node.spacing[i];
|
|
7443
|
-
if (spacing > 0) {
|
|
7444
|
-
analysis.minRepeatSpacing = Math.min(analysis.minRepeatSpacing, spacing);
|
|
7445
|
-
if (node.count[i] <= 0) analysis.hasInfiniteRepeat = true;
|
|
7446
|
-
}
|
|
7447
|
-
}
|
|
7448
|
-
visitSdfNode(node.child, analysis);
|
|
7449
|
-
break;
|
|
7450
8245
|
case "sdf:shell":
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
case "sdf:surfaceDisplace":
|
|
7456
|
-
analysis.riskFlags.add("displacement");
|
|
7457
|
-
visitSdfNode(node.child, analysis);
|
|
7458
|
-
break;
|
|
7459
|
-
case "sdf:gyroid":
|
|
7460
|
-
case "sdf:schwarzP":
|
|
7461
|
-
case "sdf:diamond":
|
|
7462
|
-
case "sdf:lidinoid":
|
|
7463
|
-
analysis.riskFlags.add("tpms");
|
|
7464
|
-
analysis.minTpmsCellSize = Math.min(analysis.minTpmsCellSize, node.cellSize);
|
|
7465
|
-
if (node.thicknessMode === "metric-approx") {
|
|
7466
|
-
analysis.minMetricTpmsThickness = Math.min(analysis.minMetricTpmsThickness, node.thickness);
|
|
7467
|
-
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.thickness);
|
|
7468
|
-
} else {
|
|
7469
|
-
analysis.hasLegacyTpmsThreshold = true;
|
|
7470
|
-
}
|
|
7471
|
-
break;
|
|
7472
|
-
case "sdf:noise":
|
|
7473
|
-
analysis.riskFlags.add("noise");
|
|
7474
|
-
break;
|
|
7475
|
-
case "sdf:voronoi":
|
|
7476
|
-
analysis.riskFlags.add("voronoi");
|
|
7477
|
-
analysis.minWallThickness = Math.min(analysis.minWallThickness, node.wallThickness);
|
|
7478
|
-
if (node.surfaceChild) visitSdfNode(node.surfaceChild, analysis);
|
|
7479
|
-
break;
|
|
7480
|
-
case "sdf:custom":
|
|
7481
|
-
analysis.riskFlags.add("custom");
|
|
7482
|
-
break;
|
|
8246
|
+
case "sdf:onion":
|
|
8247
|
+
return getUnsupportedSdfProgramReason(node.child);
|
|
8248
|
+
default:
|
|
8249
|
+
return void 0;
|
|
7483
8250
|
}
|
|
7484
8251
|
}
|
|
7485
|
-
function
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
}
|
|
7489
|
-
function requirePositiveFinite$2(value, name) {
|
|
7490
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
7491
|
-
throw new Error(`${name} must be a positive finite number.`);
|
|
8252
|
+
function compileSdfProgram(node) {
|
|
8253
|
+
const unsupportedReason = getUnsupportedSdfProgramReason(node);
|
|
8254
|
+
if (unsupportedReason) {
|
|
8255
|
+
throw new UnsupportedSdfProgramNodeError(`SdfProgram does not support this tree yet: ${unsupportedReason}.`);
|
|
7492
8256
|
}
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
function cloneBounds$2(bounds) {
|
|
7496
|
-
return { min: [...bounds.min], max: [...bounds.max] };
|
|
7497
|
-
}
|
|
7498
|
-
function suggestEdgeLengthForSampleBudget(bounds, maxGridPoints) {
|
|
7499
|
-
const dx = bounds.max[0] - bounds.min[0];
|
|
7500
|
-
const dy = bounds.max[1] - bounds.min[1];
|
|
7501
|
-
const dz = bounds.max[2] - bounds.min[2];
|
|
7502
|
-
const volume = Math.max(dx * dy * dz, 1);
|
|
7503
|
-
return Math.cbrt(volume / Math.max(maxGridPoints, 8));
|
|
8257
|
+
const builder = new SdfProgramBuilder();
|
|
8258
|
+
return builder.finalize(emitSdfProgramNode(builder, node, builder.x, builder.y, builder.z));
|
|
7504
8259
|
}
|
|
7505
|
-
function
|
|
7506
|
-
return
|
|
8260
|
+
function compileSdfProgram3(node) {
|
|
8261
|
+
return compileSdfProgramEvaluator3(compileSdfProgram(node));
|
|
7507
8262
|
}
|
|
7508
|
-
function
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
}
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
8263
|
+
function compileSdfMaterializationEvaluator3(node) {
|
|
8264
|
+
const unsupportedReason = getUnsupportedSdfProgramReason(node);
|
|
8265
|
+
if (unsupportedReason) {
|
|
8266
|
+
return {
|
|
8267
|
+
fn: compileSdfNode3(node),
|
|
8268
|
+
engine: "closure",
|
|
8269
|
+
unsupportedReason
|
|
8270
|
+
};
|
|
8271
|
+
}
|
|
8272
|
+
return {
|
|
8273
|
+
fn: compileSdfProgram3(node),
|
|
8274
|
+
engine: "program"
|
|
8275
|
+
};
|
|
7520
8276
|
}
|
|
7521
8277
|
function midpoint$3(a2, b) {
|
|
7522
8278
|
return [(a2[0] + b[0]) / 2, (a2[1] + b[1]) / 2, (a2[2] + b[2]) / 2];
|
|
@@ -7982,7 +8738,7 @@ function buildCircleExtrusionTopology(circ, height, center = false) {
|
|
|
7982
8738
|
);
|
|
7983
8739
|
return { faces, edges };
|
|
7984
8740
|
}
|
|
7985
|
-
function requireFinite$
|
|
8741
|
+
function requireFinite$9(v, label) {
|
|
7986
8742
|
if (!Number.isFinite(v)) throw new Error(`nurbsSurface: ${label} must be finite, got ${v}`);
|
|
7987
8743
|
}
|
|
7988
8744
|
function normalizeSurfaceTessellation(tessellation) {
|
|
@@ -7992,11 +8748,11 @@ function normalizeSurfaceTessellation(tessellation) {
|
|
|
7992
8748
|
throw new Error(`nurbsSurface: tessellation.mode must be "uniform" or "adaptive", got ${mode}`);
|
|
7993
8749
|
}
|
|
7994
8750
|
if (tessellation.tolerance !== void 0) {
|
|
7995
|
-
requireFinite$
|
|
8751
|
+
requireFinite$9(tessellation.tolerance, "tessellation.tolerance");
|
|
7996
8752
|
if (tessellation.tolerance <= 0) throw new Error("nurbsSurface: tessellation.tolerance must be > 0");
|
|
7997
8753
|
}
|
|
7998
|
-
if (tessellation.minResolution !== void 0) requireFinite$
|
|
7999
|
-
if (tessellation.maxResolution !== void 0) requireFinite$
|
|
8754
|
+
if (tessellation.minResolution !== void 0) requireFinite$9(tessellation.minResolution, "tessellation.minResolution");
|
|
8755
|
+
if (tessellation.maxResolution !== void 0) requireFinite$9(tessellation.maxResolution, "tessellation.maxResolution");
|
|
8000
8756
|
const minResolution = tessellation.minResolution === void 0 ? void 0 : Math.max(2, Math.round(tessellation.minResolution));
|
|
8001
8757
|
const maxResolution = tessellation.maxResolution === void 0 ? void 0 : Math.max(2, Math.round(tessellation.maxResolution));
|
|
8002
8758
|
if (minResolution !== void 0 && maxResolution !== void 0 && minResolution > maxResolution) {
|
|
@@ -8015,10 +8771,10 @@ function normalizeSurfaceDomain(domain) {
|
|
|
8015
8771
|
const uMax = domain.uMax ?? 1;
|
|
8016
8772
|
const vMin = domain.vMin ?? 0;
|
|
8017
8773
|
const vMax = domain.vMax ?? 1;
|
|
8018
|
-
requireFinite$
|
|
8019
|
-
requireFinite$
|
|
8020
|
-
requireFinite$
|
|
8021
|
-
requireFinite$
|
|
8774
|
+
requireFinite$9(uMin, "domain.uMin");
|
|
8775
|
+
requireFinite$9(uMax, "domain.uMax");
|
|
8776
|
+
requireFinite$9(vMin, "domain.vMin");
|
|
8777
|
+
requireFinite$9(vMax, "domain.vMax");
|
|
8022
8778
|
if (uMin < 0 || uMax > 1 || vMin < 0 || vMax > 1) {
|
|
8023
8779
|
throw new Error("nurbsSurface: domain bounds must stay within [0, 1]");
|
|
8024
8780
|
}
|
|
@@ -8030,8 +8786,8 @@ function normalizeSurfaceDomain(domain) {
|
|
|
8030
8786
|
function normalizeTrimLoop(loop, label) {
|
|
8031
8787
|
if (loop.length < 3) throw new Error(`nurbsSurface: ${label} requires at least 3 points`);
|
|
8032
8788
|
const normalized = loop.map(([u2, v], idx) => {
|
|
8033
|
-
requireFinite$
|
|
8034
|
-
requireFinite$
|
|
8789
|
+
requireFinite$9(u2, `${label}[${idx}][0]`);
|
|
8790
|
+
requireFinite$9(v, `${label}[${idx}][1]`);
|
|
8035
8791
|
if (u2 < 0 || u2 > 1 || v < 0 || v > 1) throw new Error(`nurbsSurface: ${label}[${idx}] must stay within [0, 1]`);
|
|
8036
8792
|
return [u2, v];
|
|
8037
8793
|
});
|
|
@@ -8054,8 +8810,8 @@ function normalizeTrimCurve(curve, label) {
|
|
|
8054
8810
|
throw new Error(`nurbsSurface: ${label} needs at least ${degree + 1} control points for degree=${degree}`);
|
|
8055
8811
|
}
|
|
8056
8812
|
const normalizedControlPoints = controlPoints.map(([u2, v], idx) => {
|
|
8057
|
-
requireFinite$
|
|
8058
|
-
requireFinite$
|
|
8813
|
+
requireFinite$9(u2, `${label}.controlPoints[${idx}][0]`);
|
|
8814
|
+
requireFinite$9(v, `${label}.controlPoints[${idx}][1]`);
|
|
8059
8815
|
if (u2 < 0 || u2 > 1 || v < 0 || v > 1) {
|
|
8060
8816
|
throw new Error(`nurbsSurface: ${label}.controlPoints[${idx}] must stay within [0, 1]`);
|
|
8061
8817
|
}
|
|
@@ -8066,7 +8822,7 @@ function normalizeTrimCurve(curve, label) {
|
|
|
8066
8822
|
throw new Error(`nurbsSurface: ${label}.weights length must match controlPoints length`);
|
|
8067
8823
|
}
|
|
8068
8824
|
for (let idx = 0; idx < weights.length; idx += 1) {
|
|
8069
|
-
requireFinite$
|
|
8825
|
+
requireFinite$9(weights[idx], `${label}.weights[${idx}]`);
|
|
8070
8826
|
if (weights[idx] <= 0) throw new Error(`nurbsSurface: ${label}.weights[${idx}] must be > 0`);
|
|
8071
8827
|
}
|
|
8072
8828
|
const knots = curve.knots ?? generateClampedKnots(controlPoints.length, degree);
|
|
@@ -8074,7 +8830,7 @@ function normalizeTrimCurve(curve, label) {
|
|
|
8074
8830
|
throw new Error(`nurbsSurface: ${label}.knots.length should be ${controlPoints.length + degree + 1}, got ${knots.length}`);
|
|
8075
8831
|
}
|
|
8076
8832
|
for (let idx = 0; idx < knots.length; idx += 1) {
|
|
8077
|
-
requireFinite$
|
|
8833
|
+
requireFinite$9(knots[idx], `${label}.knots[${idx}]`);
|
|
8078
8834
|
if (idx > 0 && knots[idx] < knots[idx - 1]) throw new Error(`nurbsSurface: ${label}.knots must be non-decreasing`);
|
|
8079
8835
|
}
|
|
8080
8836
|
if (knots[degree] >= knots[controlPoints.length]) {
|
|
@@ -8254,16 +9010,16 @@ class NurbsSurface {
|
|
|
8254
9010
|
for (let i = 0; i < nU; i++) {
|
|
8255
9011
|
if (controlGrid[i].length !== nV) throw new Error(`nurbsSurface: row ${i} has ${controlGrid[i].length} points, expected ${nV}`);
|
|
8256
9012
|
for (let j = 0; j < nV; j++) {
|
|
8257
|
-
requireFinite$
|
|
8258
|
-
requireFinite$
|
|
8259
|
-
requireFinite$
|
|
9013
|
+
requireFinite$9(controlGrid[i][j][0], `controlGrid[${i}][${j}][0]`);
|
|
9014
|
+
requireFinite$9(controlGrid[i][j][1], `controlGrid[${i}][${j}][1]`);
|
|
9015
|
+
requireFinite$9(controlGrid[i][j][2], `controlGrid[${i}][${j}][2]`);
|
|
8260
9016
|
}
|
|
8261
9017
|
}
|
|
8262
9018
|
const weightsGrid = options.weights ?? controlGrid.map((row) => row.map(() => 1));
|
|
8263
9019
|
for (let i = 0; i < nU; i++) {
|
|
8264
9020
|
if (weightsGrid[i].length !== nV) throw new Error(`nurbsSurface: weights row ${i} length mismatch`);
|
|
8265
9021
|
for (let j = 0; j < nV; j++) {
|
|
8266
|
-
requireFinite$
|
|
9022
|
+
requireFinite$9(weightsGrid[i][j], `weights[${i}][${j}]`);
|
|
8267
9023
|
if (weightsGrid[i][j] <= 0) throw new Error(`nurbsSurface: weights[${i}][${j}] must be > 0`);
|
|
8268
9024
|
}
|
|
8269
9025
|
}
|
|
@@ -9653,8 +10409,8 @@ function stitchSingleLoopLoft(loops, heights, wasm) {
|
|
|
9653
10409
|
const v0 = baseIdx + j;
|
|
9654
10410
|
const v1 = nextIdx + j;
|
|
9655
10411
|
const v2 = nextIdx + j1;
|
|
9656
|
-
const
|
|
9657
|
-
triangles.push(v0,
|
|
10412
|
+
const v32 = baseIdx + j1;
|
|
10413
|
+
triangles.push(v0, v32, v2);
|
|
9658
10414
|
triangles.push(v0, v2, v1);
|
|
9659
10415
|
}
|
|
9660
10416
|
}
|
|
@@ -9695,7 +10451,7 @@ let _wasm$1 = null;
|
|
|
9695
10451
|
async function initManifoldWasm() {
|
|
9696
10452
|
if (_wasm$1) return _wasm$1;
|
|
9697
10453
|
performance.mark("manifold:start");
|
|
9698
|
-
const Module = (await import("./manifold-
|
|
10454
|
+
const Module = (await import("./manifold-Cjk7WhRs.js")).default;
|
|
9699
10455
|
performance.mark("manifold:imported");
|
|
9700
10456
|
const wasm = await Module();
|
|
9701
10457
|
wasm.setup();
|
|
@@ -9965,8 +10721,8 @@ function stitchLoopAlongPath(loop, _path, frames, wasm) {
|
|
|
9965
10721
|
const v0 = baseIdx + j;
|
|
9966
10722
|
const v1 = nextIdx + j;
|
|
9967
10723
|
const v2 = nextIdx + j1;
|
|
9968
|
-
const
|
|
9969
|
-
triangles.push(v0,
|
|
10724
|
+
const v32 = baseIdx + j1;
|
|
10725
|
+
triangles.push(v0, v32, v2);
|
|
9970
10726
|
triangles.push(v0, v2, v1);
|
|
9971
10727
|
}
|
|
9972
10728
|
}
|
|
@@ -11312,8 +12068,16 @@ function lowerShapeCompilePlanToManifold(plan, wasm) {
|
|
|
11312
12068
|
case "importedMesh":
|
|
11313
12069
|
return lowerImportedMeshToManifold(plan.fileData, plan.format, plan.filePath, wasm);
|
|
11314
12070
|
case "sdf": {
|
|
11315
|
-
const
|
|
11316
|
-
return lowerSdfToManifold(
|
|
12071
|
+
const evaluator = compileSdfMaterializationEvaluator3(plan.tree);
|
|
12072
|
+
return lowerSdfToManifold(
|
|
12073
|
+
evaluator.fn,
|
|
12074
|
+
plan.bounds,
|
|
12075
|
+
plan.edgeLength,
|
|
12076
|
+
wasm,
|
|
12077
|
+
plan.meshing,
|
|
12078
|
+
evaluator.engine,
|
|
12079
|
+
evaluator.unsupportedReason
|
|
12080
|
+
);
|
|
11317
12081
|
}
|
|
11318
12082
|
case "fromSlices":
|
|
11319
12083
|
return lowerFromSlicesToManifold(plan, wasm);
|
|
@@ -11331,8 +12095,12 @@ function lowerShapeCompilePlanToManifold(plan, wasm) {
|
|
|
11331
12095
|
assertExhaustive(plan);
|
|
11332
12096
|
}
|
|
11333
12097
|
}
|
|
11334
|
-
function lowerSdfToManifold(evalFn, bounds, edgeLength2, wasm, meshing) {
|
|
12098
|
+
function lowerSdfToManifold(evalFn, bounds, edgeLength2, wasm, meshing, evaluatorEngine, evaluatorUnsupportedReason) {
|
|
11335
12099
|
const diagnostics = (meshing == null ? void 0 : meshing.diagnostics) ? { ...meshing.diagnostics } : void 0;
|
|
12100
|
+
if (diagnostics && evaluatorEngine) {
|
|
12101
|
+
diagnostics.evaluator = evaluatorEngine;
|
|
12102
|
+
if (evaluatorUnsupportedReason) diagnostics.evaluatorUnsupportedReason = evaluatorUnsupportedReason;
|
|
12103
|
+
}
|
|
11336
12104
|
const inset = edgeLength2;
|
|
11337
12105
|
const cappedEvalFn = (x2, y2, z2) => {
|
|
11338
12106
|
const bx = Math.max(bounds.min[0] + inset - x2, x2 - bounds.max[0] + inset);
|
|
@@ -16783,9 +17551,9 @@ function requireClipper() {
|
|
|
16783
17551
|
if (ClipperLib2.use_xyz) j.OffPt.Z = OffPt.Z;
|
|
16784
17552
|
this.m_Joins.push(j);
|
|
16785
17553
|
};
|
|
16786
|
-
ClipperLib2.Clipper.prototype.AddGhostJoin = function(
|
|
17554
|
+
ClipperLib2.Clipper.prototype.AddGhostJoin = function(Op2, OffPt) {
|
|
16787
17555
|
var j = new ClipperLib2.Join();
|
|
16788
|
-
j.OutPt1 =
|
|
17556
|
+
j.OutPt1 = Op2;
|
|
16789
17557
|
j.OffPt.X = OffPt.X;
|
|
16790
17558
|
j.OffPt.Y = OffPt.Y;
|
|
16791
17559
|
if (ClipperLib2.use_xyz) j.OffPt.Z = OffPt.Z;
|
|
@@ -19687,7 +20455,7 @@ function requireClipper() {
|
|
|
19687
20455
|
}
|
|
19688
20456
|
var clipperExports = requireClipper();
|
|
19689
20457
|
var ClipperLib = /* @__PURE__ */ getDefaultExportFromCjs(clipperExports);
|
|
19690
|
-
let f$
|
|
20458
|
+
let f$3 = class f {
|
|
19691
20459
|
constructor(t, e) {
|
|
19692
20460
|
this.next = null, this.key = t, this.data = e, this.left = null, this.right = null;
|
|
19693
20461
|
}
|
|
@@ -19696,7 +20464,7 @@ function d(n, t) {
|
|
|
19696
20464
|
return n > t ? 1 : n < t ? -1 : 0;
|
|
19697
20465
|
}
|
|
19698
20466
|
function u$1(n, t, e) {
|
|
19699
|
-
const r = new f$
|
|
20467
|
+
const r = new f$3(null, null);
|
|
19700
20468
|
let l = r, i = r;
|
|
19701
20469
|
for (; ; ) {
|
|
19702
20470
|
const o = e(n, t.key);
|
|
@@ -19719,7 +20487,7 @@ function u$1(n, t, e) {
|
|
|
19719
20487
|
return l.right = t.left, i.left = t.right, t.left = r.right, t.right = r.left, t;
|
|
19720
20488
|
}
|
|
19721
20489
|
function c(n, t, e, r) {
|
|
19722
|
-
const l = new f$
|
|
20490
|
+
const l = new f$3(n, t);
|
|
19723
20491
|
if (e === null)
|
|
19724
20492
|
return l.left = l.right = null, l;
|
|
19725
20493
|
e = u$1(n, e, r);
|
|
@@ -19760,7 +20528,7 @@ class z {
|
|
|
19760
20528
|
* Adds a key, if it is not present in the tree
|
|
19761
20529
|
*/
|
|
19762
20530
|
add(t, e) {
|
|
19763
|
-
const r = new f$
|
|
20531
|
+
const r = new f$3(t, e);
|
|
19764
20532
|
this._root === null && (r.left = r.right = null, this._size++, this._root = r);
|
|
19765
20533
|
const l = this._comparator, i = u$1(t, this._root, l), o = l(t, i.key);
|
|
19766
20534
|
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;
|
|
@@ -19973,23 +20741,23 @@ class z {
|
|
|
19973
20741
|
function a(n, t, e, r) {
|
|
19974
20742
|
const l = r - e;
|
|
19975
20743
|
if (l > 0) {
|
|
19976
|
-
const i = e + Math.floor(l / 2), o = n[i], s = t[i], h = new f$
|
|
20744
|
+
const i = e + Math.floor(l / 2), o = n[i], s = t[i], h = new f$3(o, s);
|
|
19977
20745
|
return h.left = a(n, t, e, i), h.right = a(n, t, i + 1, r), h;
|
|
19978
20746
|
}
|
|
19979
20747
|
return null;
|
|
19980
20748
|
}
|
|
19981
20749
|
function x(n, t) {
|
|
19982
|
-
const e = new f$
|
|
20750
|
+
const e = new f$3(null, null);
|
|
19983
20751
|
let r = e;
|
|
19984
20752
|
for (let l = 0; l < n.length; l++)
|
|
19985
|
-
r = r.next = new f$
|
|
20753
|
+
r = r.next = new f$3(n[l], t[l]);
|
|
19986
20754
|
return r.next = null, e.next;
|
|
19987
20755
|
}
|
|
19988
20756
|
function k(n) {
|
|
19989
20757
|
let t = n;
|
|
19990
20758
|
const e = [];
|
|
19991
20759
|
let r = false;
|
|
19992
|
-
const l = new f$
|
|
20760
|
+
const l = new f$3(null, null);
|
|
19993
20761
|
let i = l;
|
|
19994
20762
|
for (; !r; )
|
|
19995
20763
|
t ? (e.push(t), t = t.left) : e.length > 0 ? (t = i = i.next = e.pop(), t = t.right) : r = true;
|
|
@@ -20004,7 +20772,7 @@ function p(n, t, e) {
|
|
|
20004
20772
|
return null;
|
|
20005
20773
|
}
|
|
20006
20774
|
function y(n, t, e) {
|
|
20007
|
-
const r = new f$
|
|
20775
|
+
const r = new f$3(null, null);
|
|
20008
20776
|
let l = r, i = n, o = t;
|
|
20009
20777
|
for (; i !== null && o !== null; )
|
|
20010
20778
|
e(i.key, o.key) < 0 ? (l.next = i, i = i.next) : (l.next = o, o = o.next), l = l.next;
|
|
@@ -24992,7 +25760,13 @@ function normalizeTruckShapeForBooleanInput(shape) {
|
|
|
24992
25760
|
return normalized;
|
|
24993
25761
|
}
|
|
24994
25762
|
function lowerSdfPlan(plan) {
|
|
24995
|
-
|
|
25763
|
+
var _a3, _b3, _c2;
|
|
25764
|
+
const evaluator = compileSdfMaterializationEvaluator3(plan.tree);
|
|
25765
|
+
if ((_a3 = plan.meshing) == null ? void 0 : _a3.diagnostics) {
|
|
25766
|
+
plan.meshing.diagnostics.evaluator = evaluator.engine;
|
|
25767
|
+
if (evaluator.unsupportedReason) plan.meshing.diagnostics.evaluatorUnsupportedReason = evaluator.unsupportedReason;
|
|
25768
|
+
}
|
|
25769
|
+
const evalFn = evaluator.fn;
|
|
24996
25770
|
const inset = plan.edgeLength;
|
|
24997
25771
|
const cappedEvalFn = (x2, y2, z2) => {
|
|
24998
25772
|
const bx = Math.max(plan.bounds.min[0] + inset - x2, x2 - plan.bounds.max[0] + inset);
|
|
@@ -25004,14 +25778,18 @@ function lowerSdfPlan(plan) {
|
|
|
25004
25778
|
assertSdfMeshBudget(mesh, plan);
|
|
25005
25779
|
let surfaceNetsError;
|
|
25006
25780
|
try {
|
|
25007
|
-
|
|
25781
|
+
const shape = lowerExtractedSdfMesh(mesh, cappedEvalFn, true);
|
|
25782
|
+
if ((_b3 = plan.meshing) == null ? void 0 : _b3.diagnostics) logSdfMeshingDiagnostics("SDF meshing result", plan.meshing.diagnostics);
|
|
25783
|
+
return shape;
|
|
25008
25784
|
} catch (error) {
|
|
25009
25785
|
surfaceNetsError = error;
|
|
25010
25786
|
}
|
|
25011
25787
|
const tetraMesh = marchingTetrahedra(cappedEvalFn, plan.bounds, plan.edgeLength);
|
|
25012
25788
|
assertSdfMeshBudget(tetraMesh, plan);
|
|
25013
25789
|
try {
|
|
25014
|
-
|
|
25790
|
+
const shape = lowerExtractedSdfMesh(tetraMesh, cappedEvalFn, false);
|
|
25791
|
+
if ((_c2 = plan.meshing) == null ? void 0 : _c2.diagnostics) logSdfMeshingDiagnostics("SDF meshing result", plan.meshing.diagnostics);
|
|
25792
|
+
return shape;
|
|
25015
25793
|
} catch (error) {
|
|
25016
25794
|
throw new Error(
|
|
25017
25795
|
`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)}`
|
|
@@ -25375,7 +26153,9 @@ function lowerOffsetSolidPlan(plan) {
|
|
|
25375
26153
|
if (base.kind === "transform") {
|
|
25376
26154
|
return lowerTransformedOffsetSolidPlan(base, plan.thickness);
|
|
25377
26155
|
}
|
|
25378
|
-
return truckUnsupported(
|
|
26156
|
+
return truckUnsupported(
|
|
26157
|
+
`compile plan "${plan.kind}" for non-vertical-prism/non-revolved/non-loft/non-straight-sweep/non-straight-variable-sweep solids`
|
|
26158
|
+
);
|
|
25379
26159
|
}
|
|
25380
26160
|
function lowerLoftPlan(plan) {
|
|
25381
26161
|
return wrapTruckShapeBackend(
|
|
@@ -32677,6 +33457,37 @@ function mergeSketchPlacementModel(sketches) {
|
|
|
32677
33457
|
}
|
|
32678
33458
|
return first;
|
|
32679
33459
|
}
|
|
33460
|
+
function normalizeSceneTags(value, label = "tags") {
|
|
33461
|
+
if (value == null) return [];
|
|
33462
|
+
const rawTags = typeof value === "string" ? [value] : value;
|
|
33463
|
+
if (!Array.isArray(rawTags)) {
|
|
33464
|
+
throw new Error(`${label} must be a string or array of strings`);
|
|
33465
|
+
}
|
|
33466
|
+
const out = [];
|
|
33467
|
+
const seen = /* @__PURE__ */ new Set();
|
|
33468
|
+
rawTags.forEach((tag, index2) => {
|
|
33469
|
+
if (typeof tag !== "string") {
|
|
33470
|
+
throw new Error(`${label}[${index2}] must be a string`);
|
|
33471
|
+
}
|
|
33472
|
+
const trimmed = tag.trim();
|
|
33473
|
+
if (!trimmed || seen.has(trimmed)) return;
|
|
33474
|
+
seen.add(trimmed);
|
|
33475
|
+
out.push(trimmed);
|
|
33476
|
+
});
|
|
33477
|
+
return out;
|
|
33478
|
+
}
|
|
33479
|
+
function mergeSceneTags(...values) {
|
|
33480
|
+
const out = [];
|
|
33481
|
+
const seen = /* @__PURE__ */ new Set();
|
|
33482
|
+
values.forEach((value) => {
|
|
33483
|
+
normalizeSceneTags(value).forEach((tag) => {
|
|
33484
|
+
if (seen.has(tag)) return;
|
|
33485
|
+
seen.add(tag);
|
|
33486
|
+
out.push(tag);
|
|
33487
|
+
});
|
|
33488
|
+
});
|
|
33489
|
+
return out;
|
|
33490
|
+
}
|
|
32680
33491
|
const _groupPlacementRefs = /* @__PURE__ */ new WeakMap();
|
|
32681
33492
|
const _groupExplodeHint = /* @__PURE__ */ new WeakMap();
|
|
32682
33493
|
function getGroupRefs(g2) {
|
|
@@ -32700,7 +33511,7 @@ function transformGroupRefs(source, dest, matrix) {
|
|
|
32700
33511
|
}
|
|
32701
33512
|
return dest;
|
|
32702
33513
|
}
|
|
32703
|
-
function requireFiniteAngle(v, method) {
|
|
33514
|
+
function requireFiniteAngle$1(v, method) {
|
|
32704
33515
|
if (typeof v !== "number" || !Number.isFinite(v))
|
|
32705
33516
|
throw new Error(`${method} angleDeg must be a finite number, got ${typeof v === "number" ? v : typeof v}`);
|
|
32706
33517
|
}
|
|
@@ -32761,31 +33572,46 @@ function resolveNamedGroupChild(item) {
|
|
|
32761
33572
|
function normalizeGroupInputs(items) {
|
|
32762
33573
|
const children = [];
|
|
32763
33574
|
const childNames = [];
|
|
33575
|
+
const childTags = [];
|
|
32764
33576
|
items.forEach((item) => {
|
|
32765
33577
|
if (isNamedGroupChild(item)) {
|
|
32766
33578
|
children.push(resolveNamedGroupChild(item));
|
|
32767
33579
|
childNames.push(normalizeChildName(item.name));
|
|
33580
|
+
childTags.push(normalizeSceneTags(item.tags, `group(...) named item "${item.name}" tags`));
|
|
32768
33581
|
return;
|
|
32769
33582
|
}
|
|
32770
33583
|
children.push(item);
|
|
32771
33584
|
childNames.push(void 0);
|
|
33585
|
+
childTags.push([]);
|
|
32772
33586
|
});
|
|
32773
|
-
return { children, childNames };
|
|
33587
|
+
return { children, childNames, childTags };
|
|
32774
33588
|
}
|
|
32775
33589
|
class ShapeGroup {
|
|
32776
|
-
constructor(children, childNames) {
|
|
33590
|
+
constructor(children, childNames, childTags) {
|
|
32777
33591
|
__publicField(this, "children");
|
|
32778
33592
|
__publicField(this, "childNames");
|
|
33593
|
+
__publicField(this, "childTags");
|
|
32779
33594
|
if (childNames && childNames.length !== children.length) {
|
|
32780
33595
|
throw new Error("ShapeGroup childNames must match children length");
|
|
32781
33596
|
}
|
|
33597
|
+
if (childTags && childTags.length !== children.length) {
|
|
33598
|
+
throw new Error("ShapeGroup childTags must match children length");
|
|
33599
|
+
}
|
|
32782
33600
|
this.children = [...children];
|
|
32783
33601
|
this.childNames = this.children.map((_2, index2) => normalizeChildName(childNames == null ? void 0 : childNames[index2]));
|
|
33602
|
+
this.childTags = this.children.map((_2, index2) => normalizeSceneTags(childTags == null ? void 0 : childTags[index2], "ShapeGroup childTags"));
|
|
32784
33603
|
}
|
|
32785
33604
|
/** Return the optional name of the child at `index`. */
|
|
32786
33605
|
childName(index2) {
|
|
32787
33606
|
return this.childNames[index2];
|
|
32788
33607
|
}
|
|
33608
|
+
/**
|
|
33609
|
+
* Return tags attached to the child at `index`.
|
|
33610
|
+
* @internal
|
|
33611
|
+
*/
|
|
33612
|
+
tagsForChild(index2) {
|
|
33613
|
+
return [...this.childTags[index2] ?? []];
|
|
33614
|
+
}
|
|
32789
33615
|
/**
|
|
32790
33616
|
* Return the named child by name. Throws if not found.
|
|
32791
33617
|
* Useful when importing a multipart group and working on components individually.
|
|
@@ -32800,13 +33626,13 @@ class ShapeGroup {
|
|
|
32800
33626
|
}
|
|
32801
33627
|
/** Apply fn to all children, producing a new ShapeGroup that also copies placement refs. */
|
|
32802
33628
|
mapChildren(fn) {
|
|
32803
|
-
const next = new ShapeGroup(this.children.map(fn), this.childNames);
|
|
33629
|
+
const next = new ShapeGroup(this.children.map(fn), this.childNames, this.childTags);
|
|
32804
33630
|
copyGroupPorts(this, next);
|
|
32805
33631
|
return copyGroupRefs(this, next);
|
|
32806
33632
|
}
|
|
32807
33633
|
/** Apply fn to all children and also transform placement refs by the given matrix. */
|
|
32808
33634
|
mapChildrenTransform(fn, matrix) {
|
|
32809
|
-
const next = new ShapeGroup(this.children.map(fn), this.childNames);
|
|
33635
|
+
const next = new ShapeGroup(this.children.map(fn), this.childNames, this.childTags);
|
|
32810
33636
|
transformGroupPortsHelper(this, next, matrix);
|
|
32811
33637
|
return transformGroupRefs(this, next, matrix);
|
|
32812
33638
|
}
|
|
@@ -32933,25 +33759,25 @@ class ShapeGroup {
|
|
|
32933
33759
|
/** Rotate the group around an arbitrary axis through the origin. */
|
|
32934
33760
|
rotate(axis, angleDeg, options) {
|
|
32935
33761
|
requireRotateAxis(axis, "ShapeGroup.rotate()");
|
|
32936
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotate()");
|
|
33762
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotate()");
|
|
32937
33763
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotate()");
|
|
32938
33764
|
return this.rotateAroundAxis(axis, angleDeg, options == null ? void 0 : options.pivot);
|
|
32939
33765
|
}
|
|
32940
33766
|
/** Rotate the group around the X axis. */
|
|
32941
33767
|
rotateX(angleDeg, options) {
|
|
32942
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotateX()");
|
|
33768
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotateX()");
|
|
32943
33769
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotateX()");
|
|
32944
33770
|
return this.rotateAroundAxis([1, 0, 0], angleDeg, options == null ? void 0 : options.pivot);
|
|
32945
33771
|
}
|
|
32946
33772
|
/** Rotate the group around the Y axis. */
|
|
32947
33773
|
rotateY(angleDeg, options) {
|
|
32948
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotateY()");
|
|
33774
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotateY()");
|
|
32949
33775
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotateY()");
|
|
32950
33776
|
return this.rotateAroundAxis([0, 1, 0], angleDeg, options == null ? void 0 : options.pivot);
|
|
32951
33777
|
}
|
|
32952
33778
|
/** Rotate the group around the Z axis. */
|
|
32953
33779
|
rotateZ(angleDeg, options) {
|
|
32954
|
-
requireFiniteAngle(angleDeg, "ShapeGroup.rotateZ()");
|
|
33780
|
+
requireFiniteAngle$1(angleDeg, "ShapeGroup.rotateZ()");
|
|
32955
33781
|
if (options == null ? void 0 : options.pivot) requireVec3Pivot(options.pivot, "ShapeGroup.rotateZ()");
|
|
32956
33782
|
return this.rotateAroundAxis([0, 0, 1], angleDeg, options == null ? void 0 : options.pivot);
|
|
32957
33783
|
}
|
|
@@ -32994,7 +33820,8 @@ class ShapeGroup {
|
|
|
32994
33820
|
"ShapeGroup.transform only supports 3D children (Shape/ShapeGroup). For Sketch children, use 2D transforms (translate/rotate/scale/mirror)."
|
|
32995
33821
|
);
|
|
32996
33822
|
}),
|
|
32997
|
-
this.childNames
|
|
33823
|
+
this.childNames,
|
|
33824
|
+
this.childTags
|
|
32998
33825
|
);
|
|
32999
33826
|
transformGroupPortsHelper(this, next, matrix);
|
|
33000
33827
|
return transformGroupRefs(this, next, matrix);
|
|
@@ -33062,7 +33889,7 @@ class ShapeGroup {
|
|
|
33062
33889
|
* ```
|
|
33063
33890
|
*/
|
|
33064
33891
|
withReferences(refs) {
|
|
33065
|
-
const next = new ShapeGroup(this.children, this.childNames);
|
|
33892
|
+
const next = new ShapeGroup(this.children, this.childNames, this.childTags);
|
|
33066
33893
|
const merged = applyPlacementReferenceInput(getGroupRefs(this), refs);
|
|
33067
33894
|
return setGroupRefs(next, merged);
|
|
33068
33895
|
}
|
|
@@ -33130,7 +33957,7 @@ class ShapeGroup {
|
|
|
33130
33957
|
/** Attach named connectors — attachment points that survive transforms.
|
|
33131
33958
|
* Connectors can be bare (position + orientation) or typed (with connectorType/gender for compatibility matching). */
|
|
33132
33959
|
withConnectors(connectors) {
|
|
33133
|
-
const next = new ShapeGroup(this.children, this.childNames);
|
|
33960
|
+
const next = new ShapeGroup(this.children, this.childNames, this.childTags);
|
|
33134
33961
|
copyGroupRefs(this, next);
|
|
33135
33962
|
const existing = getGroupPorts(this);
|
|
33136
33963
|
const incoming = normalizeConnectorMapInput(connectors);
|
|
@@ -33180,7 +34007,7 @@ class ShapeGroup {
|
|
|
33180
34007
|
}
|
|
33181
34008
|
function group(...items) {
|
|
33182
34009
|
const normalized = normalizeGroupInputs(items);
|
|
33183
|
-
return new ShapeGroup(normalized.children, normalized.childNames);
|
|
34010
|
+
return new ShapeGroup(normalized.children, normalized.childNames, normalized.childTags);
|
|
33184
34011
|
}
|
|
33185
34012
|
function getTargetPortsForGroup(target) {
|
|
33186
34013
|
if (target instanceof Shape) {
|
|
@@ -35355,7 +36182,7 @@ function buildSdfFunctionDefinition(source, options) {
|
|
|
35355
36182
|
jsExpression: expression,
|
|
35356
36183
|
...shader.ok ? { shaderExpression: shader.expression } : { shaderUnsupportedReason: shader.reason },
|
|
35357
36184
|
raymarchStepLimit: resolveRaymarchStepLimit(options.bounds, options.maxStep),
|
|
35358
|
-
...options.lipschitz !== void 0 ? { raymarchLipschitz: requirePositiveFinite$
|
|
36185
|
+
...options.lipschitz !== void 0 ? { raymarchLipschitz: requirePositiveFinite$2(options.lipschitz, "sdf.fromFunction() lipschitz") } : {}
|
|
35359
36186
|
};
|
|
35360
36187
|
}
|
|
35361
36188
|
function extractSdfExpression(source) {
|
|
@@ -35523,7 +36350,7 @@ function formatNumericLiteralsForGlsl(source) {
|
|
|
35523
36350
|
return result;
|
|
35524
36351
|
}
|
|
35525
36352
|
function resolveRaymarchStepLimit(bounds, maxStep) {
|
|
35526
|
-
if (maxStep !== void 0) return requirePositiveFinite$
|
|
36353
|
+
if (maxStep !== void 0) return requirePositiveFinite$2(maxStep, "sdf.fromFunction() maxStep");
|
|
35527
36354
|
const dx = bounds.max[0] - bounds.min[0];
|
|
35528
36355
|
const dy = bounds.max[1] - bounds.min[1];
|
|
35529
36356
|
const dz = bounds.max[2] - bounds.min[2];
|
|
@@ -35531,7 +36358,7 @@ function resolveRaymarchStepLimit(bounds, maxStep) {
|
|
|
35531
36358
|
if (!Number.isFinite(diagonal) || diagonal <= 0) return 0.1;
|
|
35532
36359
|
return Math.max(0.025, Math.min(0.5, diagonal / 240));
|
|
35533
36360
|
}
|
|
35534
|
-
function requirePositiveFinite$
|
|
36361
|
+
function requirePositiveFinite$2(value, label) {
|
|
35535
36362
|
if (!Number.isFinite(value) || value <= 0) throw new Error(`${label} must be a positive finite number.`);
|
|
35536
36363
|
return value;
|
|
35537
36364
|
}
|
|
@@ -35558,6 +36385,199 @@ class SurfacePattern {
|
|
|
35558
36385
|
this.constants = constants;
|
|
35559
36386
|
}
|
|
35560
36387
|
}
|
|
36388
|
+
const typedSurfacePatterns = /* @__PURE__ */ new WeakMap();
|
|
36389
|
+
function getTypedSurfacePattern(pattern) {
|
|
36390
|
+
return typedSurfacePatterns.get(pattern);
|
|
36391
|
+
}
|
|
36392
|
+
class Pattern2D extends SurfacePattern {
|
|
36393
|
+
constructor(body) {
|
|
36394
|
+
super(body);
|
|
36395
|
+
}
|
|
36396
|
+
/** Add this pattern to one or more patterns or constant height offsets. */
|
|
36397
|
+
add(...patterns) {
|
|
36398
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36399
|
+
}
|
|
36400
|
+
/** Subtract another pattern or constant height offset from this pattern. */
|
|
36401
|
+
subtract(pattern) {
|
|
36402
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36403
|
+
}
|
|
36404
|
+
/** Multiply this pattern by one or more patterns or numeric scale factors. */
|
|
36405
|
+
multiply(...patterns) {
|
|
36406
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36407
|
+
}
|
|
36408
|
+
/** Keep the lower height between this pattern and one or more other patterns. */
|
|
36409
|
+
min(...patterns) {
|
|
36410
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36411
|
+
}
|
|
36412
|
+
/** Keep the higher height between this pattern and one or more other patterns. */
|
|
36413
|
+
max(...patterns) {
|
|
36414
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36415
|
+
}
|
|
36416
|
+
/** Limit pattern height to the inclusive `[min, max]` range in millimeters. */
|
|
36417
|
+
clamp(min2, max2) {
|
|
36418
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36419
|
+
}
|
|
36420
|
+
/** Convert negative heights to positive heights. */
|
|
36421
|
+
abs() {
|
|
36422
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36423
|
+
}
|
|
36424
|
+
/** Flip the pattern height sign. */
|
|
36425
|
+
negate() {
|
|
36426
|
+
throw new Error("Pattern2D values are created by sdf.pattern2d().");
|
|
36427
|
+
}
|
|
36428
|
+
}
|
|
36429
|
+
class Pattern2DImpl extends Pattern2D {
|
|
36430
|
+
constructor(node) {
|
|
36431
|
+
super(emitSurfacePatternJsExpression(node));
|
|
36432
|
+
__publicField(this, "node");
|
|
36433
|
+
this.node = node;
|
|
36434
|
+
typedSurfacePatterns.set(this, node);
|
|
36435
|
+
}
|
|
36436
|
+
add(...patterns) {
|
|
36437
|
+
return new Pattern2DImpl({ kind: "surfacePattern:add", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
36438
|
+
}
|
|
36439
|
+
subtract(pattern) {
|
|
36440
|
+
return this.add(new Pattern2DImpl({ kind: "surfacePattern:negate", child: patternNodeFromInput(pattern) }));
|
|
36441
|
+
}
|
|
36442
|
+
multiply(...patterns) {
|
|
36443
|
+
return new Pattern2DImpl({ kind: "surfacePattern:multiply", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
36444
|
+
}
|
|
36445
|
+
min(...patterns) {
|
|
36446
|
+
return new Pattern2DImpl({ kind: "surfacePattern:min", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
36447
|
+
}
|
|
36448
|
+
max(...patterns) {
|
|
36449
|
+
return new Pattern2DImpl({ kind: "surfacePattern:max", children: [this.node, ...patterns.map(patternNodeFromInput)] });
|
|
36450
|
+
}
|
|
36451
|
+
clamp(min2, max2) {
|
|
36452
|
+
const lo = requireFinite$8(min2, "Pattern2D.clamp() min");
|
|
36453
|
+
const hi = requireFinite$8(max2, "Pattern2D.clamp() max");
|
|
36454
|
+
if (lo > hi) throw new Error(`Pattern2D.clamp() min must be <= max. Received: ${lo} > ${hi}`);
|
|
36455
|
+
return new Pattern2DImpl({ kind: "surfacePattern:clamp", child: this.node, min: lo, max: hi });
|
|
36456
|
+
}
|
|
36457
|
+
abs() {
|
|
36458
|
+
return new Pattern2DImpl({ kind: "surfacePattern:abs", child: this.node });
|
|
36459
|
+
}
|
|
36460
|
+
negate() {
|
|
36461
|
+
return new Pattern2DImpl({ kind: "surfacePattern:negate", child: this.node });
|
|
36462
|
+
}
|
|
36463
|
+
}
|
|
36464
|
+
class Pattern2DBuilder {
|
|
36465
|
+
/** Create a constant-height pattern in millimeters. */
|
|
36466
|
+
constant(value = 0) {
|
|
36467
|
+
return new Pattern2DImpl({ kind: "surfacePattern:constant", value: requireFinite$8(value, "sdf.pattern2d().constant() value") });
|
|
36468
|
+
}
|
|
36469
|
+
/** Create a sinusoidal wave pattern in UV space. */
|
|
36470
|
+
sineWave(options) {
|
|
36471
|
+
return new Pattern2DImpl({
|
|
36472
|
+
kind: "surfacePattern:sineWave",
|
|
36473
|
+
direction: normalizeDirection$1(options.direction ?? [1, 0], "sdf.pattern2d().sineWave() direction"),
|
|
36474
|
+
wavelength: requirePositiveFinite$1(options.wavelength, "sdf.pattern2d().sineWave() wavelength"),
|
|
36475
|
+
amplitude: requireFinite$8(options.amplitude ?? 1, "sdf.pattern2d().sineWave() amplitude"),
|
|
36476
|
+
phase: requireFinite$8(options.phase ?? 0, "sdf.pattern2d().sineWave() phase"),
|
|
36477
|
+
bias: requireFinite$8(options.bias ?? 0, "sdf.pattern2d().sineWave() bias")
|
|
36478
|
+
});
|
|
36479
|
+
}
|
|
36480
|
+
/** Create recessed stripe bands in UV space. */
|
|
36481
|
+
stripes(options) {
|
|
36482
|
+
return new Pattern2DImpl({
|
|
36483
|
+
kind: "surfacePattern:stripes",
|
|
36484
|
+
direction: normalizeDirection$1(options.direction ?? [1, 0], "sdf.pattern2d().stripes() direction"),
|
|
36485
|
+
spacing: requirePositiveFinite$1(options.spacing, "sdf.pattern2d().stripes() spacing"),
|
|
36486
|
+
width: requirePositiveFinite$1(options.width, "sdf.pattern2d().stripes() width"),
|
|
36487
|
+
depth: requireNonNegativeFinite$1(options.depth ?? 1, "sdf.pattern2d().stripes() depth")
|
|
36488
|
+
});
|
|
36489
|
+
}
|
|
36490
|
+
/** Create an over-under woven relief pattern in UV space. */
|
|
36491
|
+
overUnderWeave(options) {
|
|
36492
|
+
return new Pattern2DImpl({
|
|
36493
|
+
kind: "surfacePattern:overUnderWeave",
|
|
36494
|
+
spacing: normalizeVec2(options.spacing, "sdf.pattern2d().overUnderWeave() spacing", requirePositiveFinite$1),
|
|
36495
|
+
threadWidth: normalizeVec2(options.threadWidth, "sdf.pattern2d().overUnderWeave() threadWidth", requirePositiveFinite$1),
|
|
36496
|
+
depth: requireNonNegativeFinite$1(options.depth ?? 0.8, "sdf.pattern2d().overUnderWeave() depth"),
|
|
36497
|
+
underScale: requireNonNegativeFinite$1(options.underScale ?? 0.15, "sdf.pattern2d().overUnderWeave() underScale")
|
|
36498
|
+
});
|
|
36499
|
+
}
|
|
36500
|
+
}
|
|
36501
|
+
function pattern2d() {
|
|
36502
|
+
return new Pattern2DBuilder();
|
|
36503
|
+
}
|
|
36504
|
+
function patternNodeFromInput(input) {
|
|
36505
|
+
if (input instanceof SurfacePattern) {
|
|
36506
|
+
const node = getTypedSurfacePattern(input);
|
|
36507
|
+
if (node) return node;
|
|
36508
|
+
}
|
|
36509
|
+
if (typeof input === "number") {
|
|
36510
|
+
return { kind: "surfacePattern:constant", value: requireFinite$8(input, "Pattern2D numeric input") };
|
|
36511
|
+
}
|
|
36512
|
+
throw new Error("Pattern2D composition expects another typed Pattern2D or a number.");
|
|
36513
|
+
}
|
|
36514
|
+
function requireFinite$8(value, label) {
|
|
36515
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
36516
|
+
throw new Error(`${label} must be a finite number. Received: ${String(value)}`);
|
|
36517
|
+
}
|
|
36518
|
+
return value;
|
|
36519
|
+
}
|
|
36520
|
+
function requirePositiveFinite$1(value, label) {
|
|
36521
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
36522
|
+
throw new Error(`${label} must be a positive finite number. Received: ${String(value)}`);
|
|
36523
|
+
}
|
|
36524
|
+
return value;
|
|
36525
|
+
}
|
|
36526
|
+
function requireNonNegativeFinite$1(value, label) {
|
|
36527
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
36528
|
+
throw new Error(`${label} must be a non-negative finite number. Received: ${String(value)}`);
|
|
36529
|
+
}
|
|
36530
|
+
return value;
|
|
36531
|
+
}
|
|
36532
|
+
function normalizeVec2(value, label, validate) {
|
|
36533
|
+
if (typeof value === "number") {
|
|
36534
|
+
const n = validate(value, label);
|
|
36535
|
+
return [n, n];
|
|
36536
|
+
}
|
|
36537
|
+
return [validate(value[0], `${label}[0]`), validate(value[1], `${label}[1]`)];
|
|
36538
|
+
}
|
|
36539
|
+
function normalizeDirection$1(value, label) {
|
|
36540
|
+
const x2 = requireFinite$8(value[0], `${label}[0]`);
|
|
36541
|
+
const y2 = requireFinite$8(value[1], `${label}[1]`);
|
|
36542
|
+
const length4 = Math.hypot(x2, y2);
|
|
36543
|
+
if (length4 <= 0) throw new Error(`${label} must not be the zero vector.`);
|
|
36544
|
+
return [x2 / length4, y2 / length4];
|
|
36545
|
+
}
|
|
36546
|
+
function f$2(value) {
|
|
36547
|
+
if (!Number.isFinite(value)) return "0";
|
|
36548
|
+
return Number(value.toPrecision(12)).toString();
|
|
36549
|
+
}
|
|
36550
|
+
function emitSurfacePatternJsExpression(node) {
|
|
36551
|
+
switch (node.kind) {
|
|
36552
|
+
case "surfacePattern:constant":
|
|
36553
|
+
return f$2(node.value);
|
|
36554
|
+
case "surfacePattern:sineWave": {
|
|
36555
|
+
const coord = `(u * ${f$2(node.direction[0])} + v * ${f$2(node.direction[1])})`;
|
|
36556
|
+
const phase = `(${coord} * ${f$2(2 * Math.PI / node.wavelength)} + ${f$2(node.phase)})`;
|
|
36557
|
+
return `(${f$2(node.bias)} + Math.sin(${phase}) * ${f$2(node.amplitude)})`;
|
|
36558
|
+
}
|
|
36559
|
+
case "surfacePattern:stripes": {
|
|
36560
|
+
const coord = `(u * ${f$2(node.direction[0])} + v * ${f$2(node.direction[1])})`;
|
|
36561
|
+
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)};})()`;
|
|
36562
|
+
}
|
|
36563
|
+
case "surfacePattern:overUnderWeave":
|
|
36564
|
+
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)};})()`;
|
|
36565
|
+
case "surfacePattern:abs":
|
|
36566
|
+
return `Math.abs(${emitSurfacePatternJsExpression(node.child)})`;
|
|
36567
|
+
case "surfacePattern:negate":
|
|
36568
|
+
return `(-(${emitSurfacePatternJsExpression(node.child)}))`;
|
|
36569
|
+
case "surfacePattern:add":
|
|
36570
|
+
return node.children.length === 0 ? "0" : `(${node.children.map(emitSurfacePatternJsExpression).join(" + ")})`;
|
|
36571
|
+
case "surfacePattern:multiply":
|
|
36572
|
+
return node.children.length === 0 ? "1" : `(${node.children.map(emitSurfacePatternJsExpression).join(" * ")})`;
|
|
36573
|
+
case "surfacePattern:min":
|
|
36574
|
+
return node.children.length === 0 ? "0" : `Math.min(${node.children.map(emitSurfacePatternJsExpression).join(", ")})`;
|
|
36575
|
+
case "surfacePattern:max":
|
|
36576
|
+
return node.children.length === 0 ? "0" : `Math.max(${node.children.map(emitSurfacePatternJsExpression).join(", ")})`;
|
|
36577
|
+
case "surfacePattern:clamp":
|
|
36578
|
+
return `Math.min(${f$2(node.max)}, Math.max(${f$2(node.min)}, ${emitSurfacePatternJsExpression(node.child)}))`;
|
|
36579
|
+
}
|
|
36580
|
+
}
|
|
35561
36581
|
const SCULPT_MATERIAL_PRESETS = {
|
|
35562
36582
|
ceramic: {
|
|
35563
36583
|
color: "#f4f0e6",
|
|
@@ -35627,6 +36647,18 @@ function requirePositiveFinite(value, label) {
|
|
|
35627
36647
|
}
|
|
35628
36648
|
return value;
|
|
35629
36649
|
}
|
|
36650
|
+
function requirePositiveInteger(value, label) {
|
|
36651
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value < 1) {
|
|
36652
|
+
throw new Error(`${label} must be a positive integer. Received: ${String(value)}`);
|
|
36653
|
+
}
|
|
36654
|
+
return value;
|
|
36655
|
+
}
|
|
36656
|
+
function requireNonNegativeFinite(value, label) {
|
|
36657
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
36658
|
+
throw new Error(`${label} must be a non-negative finite number. Received: ${String(value)}`);
|
|
36659
|
+
}
|
|
36660
|
+
return value;
|
|
36661
|
+
}
|
|
35630
36662
|
function resolveBlendRadius(input, label, fallback = 4) {
|
|
35631
36663
|
if (typeof input === "number") return requirePositiveFinite(input, `${label} radius`);
|
|
35632
36664
|
if ((input == null ? void 0 : input.radius) !== void 0) return requirePositiveFinite(input.radius, `${label} radius`);
|
|
@@ -35873,6 +36905,29 @@ class SdfShape {
|
|
|
35873
36905
|
clipBox(x2, y2, z2) {
|
|
35874
36906
|
return this.intersect(box$1(x2, y2, z2));
|
|
35875
36907
|
}
|
|
36908
|
+
/** Keep only the material where this shape overlaps another SDF pattern. */
|
|
36909
|
+
fillWith(pattern) {
|
|
36910
|
+
if (!(pattern instanceof SdfShape)) {
|
|
36911
|
+
throw new Error("SdfShape.fillWith() expects an SdfShape pattern, such as sdf.gyroid({ cellSize, wallThickness }).");
|
|
36912
|
+
}
|
|
36913
|
+
return this.intersect(pattern);
|
|
36914
|
+
}
|
|
36915
|
+
/** Keep only the gyroid lattice inside this shape. */
|
|
36916
|
+
fillWithGyroid(options) {
|
|
36917
|
+
return this.fillWith(gyroid(options));
|
|
36918
|
+
}
|
|
36919
|
+
/** Keep only the Schwarz-P lattice inside this shape. */
|
|
36920
|
+
fillWithSchwarzP(options) {
|
|
36921
|
+
return this.fillWith(schwarzP(options));
|
|
36922
|
+
}
|
|
36923
|
+
/** Keep only the diamond TPMS lattice inside this shape. */
|
|
36924
|
+
fillWithDiamond(options) {
|
|
36925
|
+
return this.fillWith(diamond(options));
|
|
36926
|
+
}
|
|
36927
|
+
/** Keep only the lidinoid TPMS lattice inside this shape. */
|
|
36928
|
+
fillWithLidinoid(options) {
|
|
36929
|
+
return this.fillWith(lidinoid(options));
|
|
36930
|
+
}
|
|
35876
36931
|
/** Smooth union — blends shapes together with a smooth radius. */
|
|
35877
36932
|
smoothUnion(other, radius) {
|
|
35878
36933
|
return this.withNode({ kind: "sdf:smoothUnion", children: [this._node, other._node], radius });
|
|
@@ -35933,6 +36988,21 @@ class SdfShape {
|
|
|
35933
36988
|
repeat(spacing, count) {
|
|
35934
36989
|
return this.withNode({ kind: "sdf:repeat", child: this._node, spacing, count: count ?? [0, 0, 0] });
|
|
35935
36990
|
}
|
|
36991
|
+
/**
|
|
36992
|
+
* Arrange this SDF in a circular array around the Z axis.
|
|
36993
|
+
*
|
|
36994
|
+
* The source shape is translated by `offset` in +X before arraying. This uses
|
|
36995
|
+
* angular domain folding, so evaluation stays O(1): the source SDF is sampled
|
|
36996
|
+
* twice no matter how many copies are requested.
|
|
36997
|
+
*/
|
|
36998
|
+
circularArray(count, offset2 = 0) {
|
|
36999
|
+
return this.withNode({
|
|
37000
|
+
kind: "sdf:circularArray",
|
|
37001
|
+
child: this._node,
|
|
37002
|
+
count: requirePositiveInteger(count, "SdfShape.circularArray() count"),
|
|
37003
|
+
offset: requireNonNegativeFinite(offset2, "SdfShape.circularArray() offset")
|
|
37004
|
+
});
|
|
37005
|
+
}
|
|
35936
37006
|
/** Hollow out, keeping only a shell of given thickness. */
|
|
35937
37007
|
shell(thickness) {
|
|
35938
37008
|
return this.withNode({ kind: "sdf:shell", child: this._node, thickness });
|
|
@@ -35944,8 +37014,8 @@ class SdfShape {
|
|
|
35944
37014
|
* // Function displacement
|
|
35945
37015
|
* shape.displace((x, y, z) => Math.sin(x) * 0.5)
|
|
35946
37016
|
*
|
|
35947
|
-
* // Pattern displacement
|
|
35948
|
-
* shape.displace(sdf.
|
|
37017
|
+
* // Pattern displacement from a 3D SDF field
|
|
37018
|
+
* shape.displace(sdf.knurl({ pitch: 2, depth: 0.3 }))
|
|
35949
37019
|
* ```
|
|
35950
37020
|
*/
|
|
35951
37021
|
displace(fn, constants) {
|
|
@@ -35969,10 +37039,18 @@ class SdfShape {
|
|
|
35969
37039
|
* UV coordinates are in **surface millimeters** — patterns defined with `spacing: 3`
|
|
35970
37040
|
* always produce 3mm spacing, regardless of shape size.
|
|
35971
37041
|
*
|
|
37042
|
+
* Prefer `sdf.pattern2d()` or built-in surface patterns when the relief should
|
|
37043
|
+
* stay on the native shader and meshing path. Callback functions are supported
|
|
37044
|
+
* for experimentation, but they are opaque to the typed pattern optimizer.
|
|
37045
|
+
*
|
|
35972
37046
|
* ```js
|
|
35973
|
-
* //
|
|
37047
|
+
* // Native typed pattern — auto-detects sphere UV
|
|
37048
|
+
* const p = sdf.pattern2d()
|
|
37049
|
+
* const ribs = p.stripes({ spacing: 3, width: 0.8, depth: 0.35 })
|
|
37050
|
+
* .add(p.sineWave({ direction: [0, 1], wavelength: 14, amplitude: 0.08 }))
|
|
37051
|
+
*
|
|
35974
37052
|
* sdf.sphere(27).shell(3)
|
|
35975
|
-
* .surfaceDisplace(
|
|
37053
|
+
* .surfaceDisplace(ribs)
|
|
35976
37054
|
* .toShape()
|
|
35977
37055
|
*
|
|
35978
37056
|
* // Custom 2D pattern via function
|
|
@@ -35982,15 +37060,18 @@ class SdfShape {
|
|
|
35982
37060
|
surfaceDisplace(pattern, options) {
|
|
35983
37061
|
let body;
|
|
35984
37062
|
let constants;
|
|
37063
|
+
let typedPattern;
|
|
35985
37064
|
if (pattern instanceof SurfacePattern) {
|
|
35986
37065
|
body = pattern.body;
|
|
35987
37066
|
constants = pattern.constants;
|
|
37067
|
+
typedPattern = getTypedSurfacePattern(pattern);
|
|
35988
37068
|
} else {
|
|
35989
37069
|
body = extractFunctionBody(pattern);
|
|
35990
37070
|
}
|
|
35991
37071
|
return this.withNode({
|
|
35992
37072
|
kind: "sdf:surfaceDisplace",
|
|
35993
37073
|
child: this._node,
|
|
37074
|
+
...typedPattern ? { pattern: typedPattern } : {},
|
|
35994
37075
|
patternBody: body,
|
|
35995
37076
|
constants,
|
|
35996
37077
|
...(options == null ? void 0 : options.uv) ? { uvMode: options.uv } : {},
|
|
@@ -36209,24 +37290,10 @@ function weave(options) {
|
|
|
36209
37290
|
});
|
|
36210
37291
|
}
|
|
36211
37292
|
function basketWeave(options) {
|
|
36212
|
-
const SP = (options == null ? void 0 : options.spacing) ?? 3;
|
|
36213
|
-
const TW = (options == null ? void 0 : options.threadWidth) ?? 1.5;
|
|
36214
|
-
const D2 = (options == null ? void 0 : options.depth) ?? 0.8;
|
|
36215
|
-
|
|
36216
|
-
const body = `(function() {
|
|
36217
|
-
var su = u / ${SP};
|
|
36218
|
-
var sv = v / ${SP};
|
|
36219
|
-
var du = Math.abs(su - Math.round(su)) * ${SP};
|
|
36220
|
-
var dv = Math.abs(sv - Math.round(sv)) * ${SP};
|
|
36221
|
-
var hw = ${hw};
|
|
36222
|
-
var pU = Math.max(0, 1 - du / hw); pU *= pU;
|
|
36223
|
-
var pV = Math.max(0, 1 - dv / hw); pV *= pV;
|
|
36224
|
-
var checker = ((Math.round(su) & 65535) + (Math.round(sv) & 65535)) & 1;
|
|
36225
|
-
var top = checker ? pV : pU;
|
|
36226
|
-
var bot = checker ? pU : pV;
|
|
36227
|
-
return -(top > bot * 0.15 ? top : bot * 0.15) * ${D2};
|
|
36228
|
-
})()`;
|
|
36229
|
-
return new SurfacePattern(body);
|
|
37293
|
+
const SP = requirePositiveFinite((options == null ? void 0 : options.spacing) ?? 3, "sdf.basketWeave() spacing");
|
|
37294
|
+
const TW = requirePositiveFinite((options == null ? void 0 : options.threadWidth) ?? 1.5, "sdf.basketWeave() threadWidth");
|
|
37295
|
+
const D2 = requireNonNegativeFinite((options == null ? void 0 : options.depth) ?? 0.8, "sdf.basketWeave() depth");
|
|
37296
|
+
return pattern2d().overUnderWeave({ spacing: SP, threadWidth: TW, depth: D2 });
|
|
36230
37297
|
}
|
|
36231
37298
|
function fromFunction(fn, options) {
|
|
36232
37299
|
if (!options || typeof options !== "object") {
|
|
@@ -36259,6 +37326,9 @@ function bend(shape, radius) {
|
|
|
36259
37326
|
function repeat(shape, spacing, count) {
|
|
36260
37327
|
return shape.repeat(spacing, count);
|
|
36261
37328
|
}
|
|
37329
|
+
function circularArray(shape, count, offset2 = 0) {
|
|
37330
|
+
return shape.circularArray(count, offset2);
|
|
37331
|
+
}
|
|
36262
37332
|
function resolveTpmsOptions(options) {
|
|
36263
37333
|
const wallThickness = options.wallThickness;
|
|
36264
37334
|
const thickness = wallThickness ?? options.thickness;
|
|
@@ -36699,12 +37769,16 @@ const sdf = {
|
|
|
36699
37769
|
weave,
|
|
36700
37770
|
/** Basket weave surface pattern — threads with over-under crossings in UV space. Returns a SurfacePattern for use with `.surfaceDisplace()`. */
|
|
36701
37771
|
basketWeave,
|
|
37772
|
+
/** Create typed, composable 2D surface patterns for `.surfaceDisplace()`. */
|
|
37773
|
+
pattern2d,
|
|
36702
37774
|
/** Twist an SDF shape around the Z axis. */
|
|
36703
37775
|
twist,
|
|
36704
37776
|
/** Bend an SDF shape around the Z axis. */
|
|
36705
37777
|
bend,
|
|
36706
37778
|
/** Repeat an SDF shape in space. */
|
|
36707
37779
|
repeat,
|
|
37780
|
+
/** Arrange an SDF shape in a circular array around the Z axis with O(1) folded-domain evaluation. */
|
|
37781
|
+
circularArray,
|
|
36708
37782
|
/** A 2D surface pattern — a heightmap function for use with `.surfaceDisplace()`. */
|
|
36709
37783
|
SurfacePattern,
|
|
36710
37784
|
/** Create a custom SDF from one expression; shader-safe expressions raymarch directly. */
|
|
@@ -41638,13 +42712,16 @@ class SolvedAssembly {
|
|
|
41638
42712
|
* @category Assembly
|
|
41639
42713
|
*/
|
|
41640
42714
|
toGroup() {
|
|
42715
|
+
var _a3;
|
|
41641
42716
|
const children = [];
|
|
41642
42717
|
const childNames = [];
|
|
41643
|
-
|
|
42718
|
+
const childTags = [];
|
|
42719
|
+
for (const [name, rec] of this.parts) {
|
|
41644
42720
|
children.push(this.getPart(name));
|
|
41645
42721
|
childNames.push(name);
|
|
42722
|
+
childTags.push(normalizeSceneTags((_a3 = rec.metadata) == null ? void 0 : _a3.tags, `Assembly part "${name}" metadata.tags`));
|
|
41646
42723
|
}
|
|
41647
|
-
return new ShapeGroup(children, childNames);
|
|
42724
|
+
return new ShapeGroup(children, childNames, childTags);
|
|
41648
42725
|
}
|
|
41649
42726
|
/**
|
|
41650
42727
|
* Return an array of named scene objects for the viewport renderer.
|
|
@@ -41678,17 +42755,18 @@ class SolvedAssembly {
|
|
|
41678
42755
|
const used = usedByPart.get(partName);
|
|
41679
42756
|
if (used && used.length > 0) markShapePortsUsed(shape, used);
|
|
41680
42757
|
};
|
|
41681
|
-
const appendGroupChildren = (grp, prefix, partName, out2) => {
|
|
42758
|
+
const appendGroupChildren = (grp, prefix, partName, out2, inheritedTags = []) => {
|
|
41682
42759
|
grp.children.forEach((child, index2) => {
|
|
41683
42760
|
const childName = grp.childName(index2);
|
|
41684
42761
|
const label = childName ? `${prefix}.${childName}` : `${prefix}.${index2 + 1}`;
|
|
42762
|
+
const tags = mergeSceneTags(inheritedTags, grp.tagsForChild(index2));
|
|
41685
42763
|
if (child instanceof ShapeGroup) {
|
|
41686
|
-
appendGroupChildren(child, label, partName, out2);
|
|
42764
|
+
appendGroupChildren(child, label, partName, out2, tags);
|
|
41687
42765
|
return;
|
|
41688
42766
|
}
|
|
41689
42767
|
if (child instanceof Shape) {
|
|
41690
42768
|
markUsedOnShape(child, partName);
|
|
41691
|
-
out2.push({ name: label, shape: child });
|
|
42769
|
+
out2.push({ name: label, shape: child, ...tags.length > 0 ? { tags } : {} });
|
|
41692
42770
|
}
|
|
41693
42771
|
});
|
|
41694
42772
|
};
|
|
@@ -42054,7 +43132,7 @@ class Assembly {
|
|
|
42054
43132
|
*
|
|
42055
43133
|
* @param name - Unique part name (must not already exist)
|
|
42056
43134
|
* @param part - The `Shape` or `ShapeGroup` geometry
|
|
42057
|
-
* @param options - Optional `{ transform, metadata }` (material, process, qty, etc.)
|
|
43135
|
+
* @param options - Optional `{ transform, metadata }` (material, process, qty, tags, etc.)
|
|
42058
43136
|
* @returns `this` for chaining
|
|
42059
43137
|
* @category Assembly
|
|
42060
43138
|
*/
|
|
@@ -43008,15 +44086,18 @@ class ImportedAssembly {
|
|
|
43008
44086
|
* Any stored placement offset and placement references are forwarded to the group.
|
|
43009
44087
|
*/
|
|
43010
44088
|
toGroup(state) {
|
|
44089
|
+
var _a3;
|
|
43011
44090
|
const solved = this._assembly.solve(state);
|
|
43012
44091
|
const def = this._assembly.describe();
|
|
43013
44092
|
const children = [];
|
|
43014
44093
|
const childNames = [];
|
|
44094
|
+
const childTags = [];
|
|
43015
44095
|
for (const p2 of def.parts) {
|
|
43016
44096
|
children.push(solved.getPart(p2.name));
|
|
43017
44097
|
childNames.push(p2.name);
|
|
44098
|
+
childTags.push(normalizeSceneTags((_a3 = p2.metadata) == null ? void 0 : _a3.tags, `Assembly part "${p2.name}" metadata.tags`));
|
|
43018
44099
|
}
|
|
43019
|
-
let result = new ShapeGroup(children, childNames);
|
|
44100
|
+
let result = new ShapeGroup(children, childNames, childTags);
|
|
43020
44101
|
const [dx, dy, dz] = this._offset;
|
|
43021
44102
|
if (dx !== 0 || dy !== 0 || dz !== 0) {
|
|
43022
44103
|
result = result.translate(dx, dy, dz);
|
|
@@ -43386,8 +44467,8 @@ function buildPure3mfBuffer(objects, options = {}) {
|
|
|
43386
44467
|
for (let t = 0; t < numTri; t++) {
|
|
43387
44468
|
const v1 = triVerts[t * 3];
|
|
43388
44469
|
const v2 = triVerts[t * 3 + 1];
|
|
43389
|
-
const
|
|
43390
|
-
xmlParts.push(` <triangle v1="${v1}" v2="${v2}" v3="${
|
|
44470
|
+
const v32 = triVerts[t * 3 + 2];
|
|
44471
|
+
xmlParts.push(` <triangle v1="${v1}" v2="${v2}" v3="${v32}" />`);
|
|
43391
44472
|
}
|
|
43392
44473
|
xmlParts.push(" </triangles>");
|
|
43393
44474
|
xmlParts.push(" </mesh>");
|
|
@@ -43813,7 +44894,7 @@ class GCodeBuilder {
|
|
|
43813
44894
|
this.lines.push("G1 E-0.8 F1800 ; retract");
|
|
43814
44895
|
this.lines.push("");
|
|
43815
44896
|
const safeZ = Math.min(maxZ + 5, p2.bedZ - 1);
|
|
43816
|
-
this.lines.push(`G1 Z${
|
|
44897
|
+
this.lines.push(`G1 Z${f$1(safeZ)} F900 ; lift nozzle above print`);
|
|
43817
44898
|
this.lines.push("");
|
|
43818
44899
|
this.lines.push("M140 S0 ; bed off");
|
|
43819
44900
|
this.lines.push("M104 S0 ; hotend off");
|
|
@@ -43857,7 +44938,7 @@ class GCodeBuilder {
|
|
|
43857
44938
|
travelTo(x2, y2, z2) {
|
|
43858
44939
|
this.retract();
|
|
43859
44940
|
const from = [...this.pos];
|
|
43860
|
-
this.lines.push(`G0 X${
|
|
44941
|
+
this.lines.push(`G0 X${f$1(x2)} Y${f$1(y2)} Z${f$1(z2)} F${Math.round(this.profile.travelSpeed)}`);
|
|
43861
44942
|
if (this.posInitialized) {
|
|
43862
44943
|
this._segments.push({ from, to: [x2, y2, z2], extrude: false, speed: this.profile.travelSpeed });
|
|
43863
44944
|
}
|
|
@@ -43889,7 +44970,7 @@ class GCodeBuilder {
|
|
|
43889
44970
|
const beadArea = this.profile.layerHeight * this.profile.nozzle;
|
|
43890
44971
|
const eIncrement = beadArea * dist4 / this.filamentArea;
|
|
43891
44972
|
this.e += eIncrement;
|
|
43892
|
-
this.lines.push(`G1 X${
|
|
44973
|
+
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)}`);
|
|
43893
44974
|
if (this.posInitialized) {
|
|
43894
44975
|
this._segments.push({ from, to: [x2, y2, z2], extrude: true, speed: this.currentSpeed });
|
|
43895
44976
|
}
|
|
@@ -43987,13 +45068,13 @@ class GCodeBuilder {
|
|
|
43987
45068
|
retract() {
|
|
43988
45069
|
if (this.retracted) return;
|
|
43989
45070
|
this.e -= this.profile.retractionDistance;
|
|
43990
|
-
this.lines.push(`G1 E${
|
|
45071
|
+
this.lines.push(`G1 E${f$1(this.e)} F${Math.round(this.profile.retractionSpeed)}`);
|
|
43991
45072
|
this.retracted = true;
|
|
43992
45073
|
}
|
|
43993
45074
|
unretract() {
|
|
43994
45075
|
if (!this.retracted) return;
|
|
43995
45076
|
this.e += this.profile.retractionDistance;
|
|
43996
|
-
this.lines.push(`G1 E${
|
|
45077
|
+
this.lines.push(`G1 E${f$1(this.e)} F${Math.round(this.profile.retractionSpeed)}`);
|
|
43997
45078
|
this.retracted = false;
|
|
43998
45079
|
}
|
|
43999
45080
|
// ---- Bounds tracking ----
|
|
@@ -44064,7 +45145,7 @@ class GCodeBuilder {
|
|
|
44064
45145
|
return this.lines.join("\n") + "\n";
|
|
44065
45146
|
}
|
|
44066
45147
|
}
|
|
44067
|
-
function
|
|
45148
|
+
function f$1(n) {
|
|
44068
45149
|
return n.toFixed(5).replace(/\.?0+$/, "");
|
|
44069
45150
|
}
|
|
44070
45151
|
function bambuModelName(preset) {
|
|
@@ -47575,7 +48656,8 @@ function explode(items, options = {}) {
|
|
|
47575
48656
|
if (child instanceof ShapeGroup) return explodeGroup(child, p2, depth + 1, total, groupCenter, motion.branchDirection);
|
|
47576
48657
|
return explodeLeaf(child, explodeAdd(total, leafMotion(child, p2, depth + 1, groupCenter, motion.branchDirection).offset));
|
|
47577
48658
|
}),
|
|
47578
|
-
grp.childNames
|
|
48659
|
+
grp.childNames,
|
|
48660
|
+
grp.children.map((_2, i) => grp.tagsForChild(i))
|
|
47579
48661
|
);
|
|
47580
48662
|
};
|
|
47581
48663
|
const explodeItemNode = (item, path2, depth, inherited, parentCenter, parentDirection) => {
|
|
@@ -47611,7 +48693,8 @@ function explode(items, options = {}) {
|
|
|
47611
48693
|
if (child instanceof ShapeGroup) return explodeGroup(child, p2, 1, [0, 0, 0], rootCenter, void 0);
|
|
47612
48694
|
return explodeLeaf(child, nodeMotion(child, p2, 1, rootCenter, void 0).offset);
|
|
47613
48695
|
}),
|
|
47614
|
-
items.childNames
|
|
48696
|
+
items.childNames,
|
|
48697
|
+
items.children.map((_2, i) => items.tagsForChild(i))
|
|
47615
48698
|
);
|
|
47616
48699
|
}
|
|
47617
48700
|
return items.map((item, i) => {
|
|
@@ -48380,6 +49463,398 @@ function spurGear(options) {
|
|
|
48380
49463
|
});
|
|
48381
49464
|
return attachGearMeta(shapeWithConnectors, meta2);
|
|
48382
49465
|
}
|
|
49466
|
+
function requirePositive$7(scope, name, value) {
|
|
49467
|
+
if (!isFinitePositive(value)) throw new Error(`${scope}: "${name}" must be > 0`);
|
|
49468
|
+
}
|
|
49469
|
+
function requireOptionalBore(scope, boreDiameter, maxDiameter) {
|
|
49470
|
+
const bore = boreDiameter ?? 0;
|
|
49471
|
+
if (!Number.isFinite(bore) || bore < 0) throw new Error(`${scope}: "boreDiameter" must be >= 0`);
|
|
49472
|
+
if (bore > 0 && bore >= maxDiameter) throw new Error(`${scope}: bore is too large for the body`);
|
|
49473
|
+
return bore;
|
|
49474
|
+
}
|
|
49475
|
+
function resolveSegments(segments) {
|
|
49476
|
+
if (segments === void 0) return void 0;
|
|
49477
|
+
if (!Number.isInteger(segments) || segments < 12) throw new Error('gear body: "segments" must be an integer >= 12');
|
|
49478
|
+
return segments;
|
|
49479
|
+
}
|
|
49480
|
+
function cutBore$1(shape, boreDiameter) {
|
|
49481
|
+
if (boreDiameter <= 0) return shape;
|
|
49482
|
+
const bounds = shape.boundingBox();
|
|
49483
|
+
const height = bounds.max[2] - bounds.min[2] + 2;
|
|
49484
|
+
const cutter = cylinder(height, boreDiameter * 0.5, void 0, 64).translate(0, 0, bounds.min[2] - 1);
|
|
49485
|
+
return shape.subtract(cutter);
|
|
49486
|
+
}
|
|
49487
|
+
function gearBodyDisk(options) {
|
|
49488
|
+
requirePositive$7("gearBodyDisk", "outerRadius", options.outerRadius);
|
|
49489
|
+
requirePositive$7("gearBodyDisk", "faceWidth", options.faceWidth);
|
|
49490
|
+
const bore = requireOptionalBore("gearBodyDisk", options.boreDiameter, options.outerRadius * 2);
|
|
49491
|
+
const segments = resolveSegments(options.segments);
|
|
49492
|
+
const outer = circle2d(options.outerRadius, segments);
|
|
49493
|
+
const profile = bore > 0 ? difference2d(outer, circle2d(bore * 0.5, segments)) : outer;
|
|
49494
|
+
return sketchExtrude(profile, options.faceWidth);
|
|
49495
|
+
}
|
|
49496
|
+
function gearBodyDiskWithHub(options) {
|
|
49497
|
+
requirePositive$7("gearBodyDiskWithHub", "hubDiameter", options.hubDiameter);
|
|
49498
|
+
if (options.hubDiameter >= options.outerRadius * 2) {
|
|
49499
|
+
throw new Error('gearBodyDiskWithHub: "hubDiameter" must be smaller than the outer diameter');
|
|
49500
|
+
}
|
|
49501
|
+
const bore = requireOptionalBore("gearBodyDiskWithHub", options.boreDiameter, options.hubDiameter);
|
|
49502
|
+
const base = gearBodyDisk({ ...options, boreDiameter: 0 });
|
|
49503
|
+
const hubFaceWidth = options.hubFaceWidth ?? options.faceWidth * 1.5;
|
|
49504
|
+
requirePositive$7("gearBodyDiskWithHub", "hubFaceWidth", hubFaceWidth);
|
|
49505
|
+
const hub = cylinder(hubFaceWidth, options.hubDiameter * 0.5, void 0, options.segments).translate(
|
|
49506
|
+
0,
|
|
49507
|
+
0,
|
|
49508
|
+
(options.faceWidth - hubFaceWidth) * 0.5
|
|
49509
|
+
);
|
|
49510
|
+
return cutBore$1(base.add(hub), bore);
|
|
49511
|
+
}
|
|
49512
|
+
function gearBodySpoked(options) {
|
|
49513
|
+
requirePositive$7("gearBodySpoked", "outerRadius", options.outerRadius);
|
|
49514
|
+
requirePositive$7("gearBodySpoked", "faceWidth", options.faceWidth);
|
|
49515
|
+
requirePositive$7("gearBodySpoked", "rimWidth", options.rimWidth);
|
|
49516
|
+
requirePositive$7("gearBodySpoked", "hubDiameter", options.hubDiameter);
|
|
49517
|
+
requirePositive$7("gearBodySpoked", "spokeWidth", options.spokeWidth);
|
|
49518
|
+
if (!Number.isInteger(options.spokeCount) || options.spokeCount < 2) {
|
|
49519
|
+
throw new Error('gearBodySpoked: "spokeCount" must be an integer >= 2');
|
|
49520
|
+
}
|
|
49521
|
+
const hubRadius = options.hubDiameter * 0.5;
|
|
49522
|
+
const rimInnerRadius = options.outerRadius - options.rimWidth;
|
|
49523
|
+
if (rimInnerRadius <= hubRadius) throw new Error("gearBodySpoked: rim overlaps the hub");
|
|
49524
|
+
const bore = requireOptionalBore("gearBodySpoked", options.boreDiameter, options.hubDiameter);
|
|
49525
|
+
const segments = resolveSegments(options.segments);
|
|
49526
|
+
const rim = difference2d(circle2d(options.outerRadius, segments), circle2d(rimInnerRadius, segments));
|
|
49527
|
+
const hub = circle2d(hubRadius, segments);
|
|
49528
|
+
const spokeLength = rimInnerRadius - hubRadius + options.spokeWidth;
|
|
49529
|
+
const spokeCenter = hubRadius + spokeLength * 0.5 - options.spokeWidth * 0.5;
|
|
49530
|
+
const spoke = sketchTranslate(rect(spokeLength, options.spokeWidth), spokeCenter, 0);
|
|
49531
|
+
const spokes = [];
|
|
49532
|
+
for (let i = 0; i < options.spokeCount; i++) {
|
|
49533
|
+
spokes.push(sketchRotateAround(spoke, 360 / options.spokeCount * i, [0, 0]));
|
|
49534
|
+
}
|
|
49535
|
+
const profile = bore > 0 ? difference2d(union2d(rim, hub, ...spokes), circle2d(bore * 0.5, segments)) : union2d(rim, hub, ...spokes);
|
|
49536
|
+
return sketchExtrude(profile, options.faceWidth);
|
|
49537
|
+
}
|
|
49538
|
+
function gearBodyFromProfile(profile, options) {
|
|
49539
|
+
if (!(profile instanceof Sketch)) throw new Error('gearBodyFromProfile: "profile" must be a Sketch');
|
|
49540
|
+
requirePositive$7("gearBodyFromProfile", "faceWidth", options.faceWidth);
|
|
49541
|
+
const bore = options.boreDiameter ?? 0;
|
|
49542
|
+
if (!Number.isFinite(bore) || bore < 0) throw new Error('gearBodyFromProfile: "boreDiameter" must be >= 0');
|
|
49543
|
+
return cutBore$1(sketchExtrude(profile, options.faceWidth), bore);
|
|
49544
|
+
}
|
|
49545
|
+
function requirePositive$6(scope, name, value) {
|
|
49546
|
+
if (!isFinitePositive(value)) throw new Error(`${scope}: "${name}" must be > 0`);
|
|
49547
|
+
}
|
|
49548
|
+
function requireFiniteAngle(scope, name, value) {
|
|
49549
|
+
if (value !== void 0 && !Number.isFinite(value)) throw new Error(`${scope}: "${name}" must be finite`);
|
|
49550
|
+
}
|
|
49551
|
+
function cutBore(shape, boreDiameter) {
|
|
49552
|
+
if (boreDiameter <= 0) return shape;
|
|
49553
|
+
const bounds = shape.boundingBox();
|
|
49554
|
+
const height = bounds.max[2] - bounds.min[2] + 2;
|
|
49555
|
+
const cutter = cylinder(height, boreDiameter * 0.5, void 0, 64).translate(0, 0, bounds.min[2] - 1);
|
|
49556
|
+
return shape.subtract(cutter);
|
|
49557
|
+
}
|
|
49558
|
+
function bodyOuterRadius(shape) {
|
|
49559
|
+
const bounds = shape.boundingBox();
|
|
49560
|
+
return Math.max(Math.abs(bounds.min[0]), Math.abs(bounds.max[0]), Math.abs(bounds.min[1]), Math.abs(bounds.max[1]));
|
|
49561
|
+
}
|
|
49562
|
+
function buildSpurTeethRegion(options, name, faceWidth) {
|
|
49563
|
+
const scope = "driveWheel.addSpurTeethBetween";
|
|
49564
|
+
const teethOnFullCircle = options.teethOnFullCircle;
|
|
49565
|
+
if (!Number.isInteger(teethOnFullCircle) || teethOnFullCircle < 6) {
|
|
49566
|
+
throw new Error(`${scope}: "teethOnFullCircle" must be an integer >= 6`);
|
|
49567
|
+
}
|
|
49568
|
+
const toothCount = options.toothCount;
|
|
49569
|
+
if (!Number.isInteger(toothCount) || toothCount < 1 || toothCount > teethOnFullCircle) {
|
|
49570
|
+
throw new Error(`${scope}: "toothCount" must be an integer in [1, teethOnFullCircle]`);
|
|
49571
|
+
}
|
|
49572
|
+
const firstTooth = options.firstTooth ?? 0;
|
|
49573
|
+
if (!Number.isInteger(firstTooth) || firstTooth < 0 || firstTooth >= teethOnFullCircle) {
|
|
49574
|
+
throw new Error(`${scope}: "firstTooth" must be an integer in [0, teethOnFullCircle)`);
|
|
49575
|
+
}
|
|
49576
|
+
let normalized;
|
|
49577
|
+
try {
|
|
49578
|
+
normalized = normalizeSpurGearOptions({ ...options, teeth: teethOnFullCircle, faceWidth, boreDiameter: 0 });
|
|
49579
|
+
} catch (error) {
|
|
49580
|
+
remapErrorPrefix(error, "spurGear", scope);
|
|
49581
|
+
}
|
|
49582
|
+
const gearMeta = buildSpurGearMeta(normalized);
|
|
49583
|
+
const pitchStepDeg = 360 / teethOnFullCircle;
|
|
49584
|
+
const fromAngleDeg = firstTooth * pitchStepDeg - pitchStepDeg * 0.5;
|
|
49585
|
+
const toAngleDeg = (firstTooth + toothCount - 1) * pitchStepDeg + pitchStepDeg * 0.5;
|
|
49586
|
+
const profile = buildSpurToothRegionProfile(gearMeta, firstTooth, toothCount, normalized.segmentsPerTooth);
|
|
49587
|
+
return {
|
|
49588
|
+
shape: sketchExtrude(profile, faceWidth),
|
|
49589
|
+
gearMeta,
|
|
49590
|
+
meta: {
|
|
49591
|
+
name,
|
|
49592
|
+
kind: "spurTeeth",
|
|
49593
|
+
fromAngleDeg,
|
|
49594
|
+
toAngleDeg,
|
|
49595
|
+
outerRadius: gearMeta.outerRadius,
|
|
49596
|
+
rootRadius: gearMeta.rootRadius,
|
|
49597
|
+
pitchRadius: gearMeta.pitchRadius,
|
|
49598
|
+
module: normalized.module,
|
|
49599
|
+
teethOnFullCircle,
|
|
49600
|
+
toothCount,
|
|
49601
|
+
faceWidth
|
|
49602
|
+
}
|
|
49603
|
+
};
|
|
49604
|
+
}
|
|
49605
|
+
function buildSolidArcRegion(options, name, faceWidth) {
|
|
49606
|
+
const scope = "driveWheel.addSolidArcBetween";
|
|
49607
|
+
requirePositive$6(scope, "outerRadius", options.outerRadius);
|
|
49608
|
+
const innerRadius = options.innerRadius ?? 0;
|
|
49609
|
+
if (!Number.isFinite(innerRadius) || innerRadius < 0) throw new Error(`${scope}: "innerRadius" must be >= 0`);
|
|
49610
|
+
if (innerRadius >= options.outerRadius) throw new Error(`${scope}: "innerRadius" must be smaller than "outerRadius"`);
|
|
49611
|
+
const sweepDeg = normalizedSweep(scope, options.fromAngleDeg, options.toAngleDeg);
|
|
49612
|
+
return {
|
|
49613
|
+
shape: sketchExtrude(buildSolidArcProfile(options, sweepDeg), faceWidth),
|
|
49614
|
+
meta: {
|
|
49615
|
+
name,
|
|
49616
|
+
kind: "solidArc",
|
|
49617
|
+
fromAngleDeg: options.fromAngleDeg,
|
|
49618
|
+
toAngleDeg: options.fromAngleDeg + sweepDeg,
|
|
49619
|
+
innerRadius,
|
|
49620
|
+
outerRadius: options.outerRadius,
|
|
49621
|
+
faceWidth
|
|
49622
|
+
}
|
|
49623
|
+
};
|
|
49624
|
+
}
|
|
49625
|
+
function normalizedSweep(scope, fromAngleDeg, toAngleDeg) {
|
|
49626
|
+
if (!Number.isFinite(fromAngleDeg)) throw new Error(`${scope}: "fromAngleDeg" must be finite`);
|
|
49627
|
+
if (!Number.isFinite(toAngleDeg)) throw new Error(`${scope}: "toAngleDeg" must be finite`);
|
|
49628
|
+
let sweep2 = toAngleDeg - fromAngleDeg;
|
|
49629
|
+
while (sweep2 <= 0) sweep2 += 360;
|
|
49630
|
+
if (sweep2 > 360 + EPSILON$1) throw new Error(`${scope}: angular sweep must be <= 360 degrees`);
|
|
49631
|
+
return Math.min(360, sweep2);
|
|
49632
|
+
}
|
|
49633
|
+
function buildSpurToothRegionProfile(meta2, firstTooth, toothCount, segmentsPerTooth) {
|
|
49634
|
+
const tooth = createSpurToothSketch(meta2, segmentsPerTooth);
|
|
49635
|
+
const teeth = [];
|
|
49636
|
+
for (let i = 0; i < toothCount; i++) {
|
|
49637
|
+
teeth.push(sketchRotateAround(tooth, 360 / meta2.teeth * (firstTooth + i), [0, 0]));
|
|
49638
|
+
}
|
|
49639
|
+
return union2d(...teeth);
|
|
49640
|
+
}
|
|
49641
|
+
function buildSolidArcProfile(options, sweepDeg) {
|
|
49642
|
+
const innerRadius = options.innerRadius ?? 0;
|
|
49643
|
+
const segments = options.segments ?? Math.max(16, Math.ceil(sweepDeg / 6));
|
|
49644
|
+
if (!Number.isInteger(segments) || segments < 4) throw new Error('driveWheel.addSolidArcBetween: "segments" must be an integer >= 4');
|
|
49645
|
+
if (Math.abs(sweepDeg - 360) < EPSILON$1) {
|
|
49646
|
+
const outer = circle2d(options.outerRadius, segments);
|
|
49647
|
+
return innerRadius > 0 ? difference2d(outer, circle2d(innerRadius, segments)) : outer;
|
|
49648
|
+
}
|
|
49649
|
+
const start = options.fromAngleDeg * Math.PI / 180;
|
|
49650
|
+
const end = start + sweepDeg * Math.PI / 180;
|
|
49651
|
+
const pts = [];
|
|
49652
|
+
if (innerRadius <= 0) pts.push([0, 0]);
|
|
49653
|
+
addArcPoints(pts, options.outerRadius, start, end, segments, true, true);
|
|
49654
|
+
if (innerRadius > 0) addArcPoints(pts, innerRadius, end, start, segments, true, true);
|
|
49655
|
+
return polygon(pts);
|
|
49656
|
+
}
|
|
49657
|
+
const DRIVE_WHEEL_META_KEY = Symbol.for("forgecad.library.driveWheelMeta");
|
|
49658
|
+
function attachDriveWheelMeta(shape, meta2) {
|
|
49659
|
+
shape[DRIVE_WHEEL_META_KEY] = meta2;
|
|
49660
|
+
return shape;
|
|
49661
|
+
}
|
|
49662
|
+
function readDriveWheelMeta(shape) {
|
|
49663
|
+
const meta2 = shape[DRIVE_WHEEL_META_KEY];
|
|
49664
|
+
return meta2 ?? null;
|
|
49665
|
+
}
|
|
49666
|
+
class DriveWheelBuilder {
|
|
49667
|
+
constructor(options = {}) {
|
|
49668
|
+
__publicField(this, "body");
|
|
49669
|
+
__publicField(this, "faceWidth");
|
|
49670
|
+
__publicField(this, "boreDiameter");
|
|
49671
|
+
__publicField(this, "regions", []);
|
|
49672
|
+
if (options.body !== void 0 && !(options.body instanceof Shape)) throw new Error('driveWheel: "body" must be a Shape');
|
|
49673
|
+
if (options.faceWidth !== void 0) requirePositive$6("driveWheel", "faceWidth", options.faceWidth);
|
|
49674
|
+
const boreDiameter = options.boreDiameter ?? 0;
|
|
49675
|
+
if (!Number.isFinite(boreDiameter) || boreDiameter < 0) throw new Error('driveWheel: "boreDiameter" must be >= 0');
|
|
49676
|
+
this.body = options.body;
|
|
49677
|
+
this.faceWidth = options.faceWidth;
|
|
49678
|
+
this.boreDiameter = boreDiameter;
|
|
49679
|
+
}
|
|
49680
|
+
/**
|
|
49681
|
+
* Add an involute spur-tooth window on part of the pitch circle.
|
|
49682
|
+
*/
|
|
49683
|
+
addSpurTeethBetween(options) {
|
|
49684
|
+
const faceWidth = this.resolveFaceWidth("driveWheel.addSpurTeethBetween", options.faceWidth);
|
|
49685
|
+
this.regions.push(buildSpurTeethRegion(options, this.resolveName("teeth", options.name), faceWidth));
|
|
49686
|
+
return this;
|
|
49687
|
+
}
|
|
49688
|
+
/**
|
|
49689
|
+
* Add a constant-radius solid arc region such as a dwell, stop, or pusher.
|
|
49690
|
+
*/
|
|
49691
|
+
addSolidArcBetween(options) {
|
|
49692
|
+
const faceWidth = this.resolveFaceWidth("driveWheel.addSolidArcBetween", options.faceWidth);
|
|
49693
|
+
this.regions.push(buildSolidArcRegion(options, this.resolveName("arc", options.name), faceWidth));
|
|
49694
|
+
return this;
|
|
49695
|
+
}
|
|
49696
|
+
/**
|
|
49697
|
+
* Add a fully custom region shape while preserving region metadata.
|
|
49698
|
+
*/
|
|
49699
|
+
addShapeRegion(name, shape, options = {}) {
|
|
49700
|
+
const scope = "driveWheel.addShapeRegion";
|
|
49701
|
+
if (typeof name !== "string" || name.trim().length === 0) throw new Error(`${scope}: "name" must be a non-empty string`);
|
|
49702
|
+
if (!(shape instanceof Shape)) throw new Error(`${scope}: "shape" must be a Shape`);
|
|
49703
|
+
requireFiniteAngle(scope, "fromAngleDeg", options.fromAngleDeg);
|
|
49704
|
+
requireFiniteAngle(scope, "toAngleDeg", options.toAngleDeg);
|
|
49705
|
+
if (options.innerRadius !== void 0 && (!Number.isFinite(options.innerRadius) || options.innerRadius < 0)) {
|
|
49706
|
+
throw new Error(`${scope}: "innerRadius" must be >= 0`);
|
|
49707
|
+
}
|
|
49708
|
+
if (options.outerRadius !== void 0) requirePositive$6(scope, "outerRadius", options.outerRadius);
|
|
49709
|
+
this.regions.push({
|
|
49710
|
+
shape: shape.clone(),
|
|
49711
|
+
meta: {
|
|
49712
|
+
name: this.resolveName("region", name),
|
|
49713
|
+
kind: "custom",
|
|
49714
|
+
...options
|
|
49715
|
+
}
|
|
49716
|
+
});
|
|
49717
|
+
return this;
|
|
49718
|
+
}
|
|
49719
|
+
/**
|
|
49720
|
+
* Build the final wheel shape with a bore connector and region metadata.
|
|
49721
|
+
*/
|
|
49722
|
+
build() {
|
|
49723
|
+
var _a3, _b3;
|
|
49724
|
+
if (this.regions.length === 0 && this.body === void 0) {
|
|
49725
|
+
throw new Error("driveWheel: add a body or at least one region before build()");
|
|
49726
|
+
}
|
|
49727
|
+
const faceWidth = this.resolveBuildFaceWidth();
|
|
49728
|
+
const firstGearRegion = (_a3 = this.regions.find((region) => region.gearMeta)) == null ? void 0 : _a3.gearMeta;
|
|
49729
|
+
if (firstGearRegion && this.boreDiameter * 0.5 >= firstGearRegion.rootRadius - EPSILON$1) {
|
|
49730
|
+
throw new Error("driveWheel: bore is too large for the first spur-tooth region");
|
|
49731
|
+
}
|
|
49732
|
+
const body = ((_b3 = this.body) == null ? void 0 : _b3.clone()) ?? gearBodyDisk({ outerRadius: (firstGearRegion == null ? void 0 : firstGearRegion.rootRadius) ?? this.defaultBodyRadius(), faceWidth });
|
|
49733
|
+
let combined = body;
|
|
49734
|
+
for (const region of this.regions) combined = combined.add(region.shape);
|
|
49735
|
+
combined = cutBore(combined, this.boreDiameter);
|
|
49736
|
+
const withConnectors = combined.withConnectors({
|
|
49737
|
+
bore: connectorFactory(
|
|
49738
|
+
"drive-wheel-bore",
|
|
49739
|
+
{ origin: [0, 0, faceWidth / 2], axis: [0, 0, 1], kind: "revolute" },
|
|
49740
|
+
this.measurements(faceWidth)
|
|
49741
|
+
)
|
|
49742
|
+
});
|
|
49743
|
+
return attachDriveWheelMeta(withConnectors, {
|
|
49744
|
+
kind: "driveWheel",
|
|
49745
|
+
faceWidth,
|
|
49746
|
+
boreDiameter: this.boreDiameter,
|
|
49747
|
+
regions: this.regionMetadata(body, faceWidth)
|
|
49748
|
+
});
|
|
49749
|
+
}
|
|
49750
|
+
measurements(faceWidth) {
|
|
49751
|
+
var _a3;
|
|
49752
|
+
const firstGearRegion = (_a3 = this.regions.find((region) => region.gearMeta)) == null ? void 0 : _a3.gearMeta;
|
|
49753
|
+
return {
|
|
49754
|
+
faceWidth,
|
|
49755
|
+
boreDiameter: this.boreDiameter,
|
|
49756
|
+
regionCount: this.regions.length,
|
|
49757
|
+
...firstGearRegion ? {
|
|
49758
|
+
module: firstGearRegion.module,
|
|
49759
|
+
teethOnFullCircle: firstGearRegion.teeth,
|
|
49760
|
+
pitchRadius: firstGearRegion.pitchRadius,
|
|
49761
|
+
outerRadius: firstGearRegion.outerRadius
|
|
49762
|
+
} : {}
|
|
49763
|
+
};
|
|
49764
|
+
}
|
|
49765
|
+
regionMetadata(body, faceWidth) {
|
|
49766
|
+
return [
|
|
49767
|
+
{ name: "body", kind: "body", outerRadius: bodyOuterRadius(body), faceWidth },
|
|
49768
|
+
...this.regions.map((region) => ({ ...region.meta }))
|
|
49769
|
+
];
|
|
49770
|
+
}
|
|
49771
|
+
resolveFaceWidth(scope, localFaceWidth) {
|
|
49772
|
+
const faceWidth = localFaceWidth ?? this.faceWidth;
|
|
49773
|
+
if (faceWidth === void 0) throw new Error(`${scope}: "faceWidth" is required unless driveWheel({ faceWidth }) was set`);
|
|
49774
|
+
requirePositive$6(scope, "faceWidth", faceWidth);
|
|
49775
|
+
if (this.faceWidth !== void 0 && localFaceWidth !== void 0 && Math.abs(this.faceWidth - localFaceWidth) > EPSILON$1) {
|
|
49776
|
+
throw new Error(`${scope}: region faceWidth must match driveWheel faceWidth`);
|
|
49777
|
+
}
|
|
49778
|
+
return faceWidth;
|
|
49779
|
+
}
|
|
49780
|
+
resolveBuildFaceWidth() {
|
|
49781
|
+
var _a3;
|
|
49782
|
+
const faceWidth = this.faceWidth ?? ((_a3 = this.regions.find((region) => region.meta.faceWidth !== void 0)) == null ? void 0 : _a3.meta.faceWidth);
|
|
49783
|
+
if (faceWidth === void 0) throw new Error('driveWheel: "faceWidth" is required before build()');
|
|
49784
|
+
return faceWidth;
|
|
49785
|
+
}
|
|
49786
|
+
defaultBodyRadius() {
|
|
49787
|
+
const outerRadius = this.regions.reduce((max2, region) => Math.max(max2, region.meta.outerRadius ?? 0), 0);
|
|
49788
|
+
if (outerRadius <= 0) throw new Error('driveWheel: "body" is required when regions do not define an outer radius');
|
|
49789
|
+
return outerRadius;
|
|
49790
|
+
}
|
|
49791
|
+
resolveName(prefix, requested) {
|
|
49792
|
+
const base = (requested == null ? void 0 : requested.trim()) || prefix;
|
|
49793
|
+
if (this.regions.every((region) => region.meta.name !== base)) return base;
|
|
49794
|
+
for (let i = 2; ; i++) {
|
|
49795
|
+
const candidate = `${base}${i}`;
|
|
49796
|
+
if (this.regions.every((region) => region.meta.name !== candidate)) return candidate;
|
|
49797
|
+
}
|
|
49798
|
+
}
|
|
49799
|
+
}
|
|
49800
|
+
function driveWheel(options = {}) {
|
|
49801
|
+
return new DriveWheelBuilder(options);
|
|
49802
|
+
}
|
|
49803
|
+
function normalizeSectorGearOptions(options) {
|
|
49804
|
+
const teethOnFullCircle = options.teethOnFullCircle;
|
|
49805
|
+
if (!Number.isInteger(teethOnFullCircle) || teethOnFullCircle < 6) {
|
|
49806
|
+
throw new Error('sectorGear: "teethOnFullCircle" must be an integer >= 6');
|
|
49807
|
+
}
|
|
49808
|
+
const toothCount = options.toothCount;
|
|
49809
|
+
if (!Number.isInteger(toothCount) || toothCount < 1 || toothCount > teethOnFullCircle) {
|
|
49810
|
+
throw new Error('sectorGear: "toothCount" must be an integer in [1, teethOnFullCircle]');
|
|
49811
|
+
}
|
|
49812
|
+
const firstTooth = options.firstTooth ?? 0;
|
|
49813
|
+
if (!Number.isInteger(firstTooth) || firstTooth < 0 || firstTooth >= teethOnFullCircle) {
|
|
49814
|
+
throw new Error('sectorGear: "firstTooth" must be an integer in [0, teethOnFullCircle)');
|
|
49815
|
+
}
|
|
49816
|
+
return {
|
|
49817
|
+
...normalizeSpurGearOptions({ ...options, teeth: teethOnFullCircle }),
|
|
49818
|
+
teethOnFullCircle,
|
|
49819
|
+
toothCount,
|
|
49820
|
+
firstTooth,
|
|
49821
|
+
boreDiameter: options.boreDiameter ?? 0
|
|
49822
|
+
};
|
|
49823
|
+
}
|
|
49824
|
+
function sectorGear(options) {
|
|
49825
|
+
const normalized = normalizeSectorGearOptions(options);
|
|
49826
|
+
if (options.body !== void 0 && !(options.body instanceof Shape)) {
|
|
49827
|
+
throw new Error('sectorGear: "body" must be a Shape');
|
|
49828
|
+
}
|
|
49829
|
+
const spurMeta = buildSpurGearMeta(normalized);
|
|
49830
|
+
const pitchStepDeg = 360 / normalized.teethOnFullCircle;
|
|
49831
|
+
const activeAngleStartDeg = normalized.firstTooth * pitchStepDeg - pitchStepDeg * 0.5;
|
|
49832
|
+
const activeAngleEndDeg = (normalized.firstTooth + normalized.toothCount - 1) * pitchStepDeg + pitchStepDeg * 0.5;
|
|
49833
|
+
const meta2 = {
|
|
49834
|
+
...spurMeta,
|
|
49835
|
+
kind: "sector",
|
|
49836
|
+
teethOnFullCircle: normalized.teethOnFullCircle,
|
|
49837
|
+
firstTooth: normalized.firstTooth,
|
|
49838
|
+
toothCount: normalized.toothCount,
|
|
49839
|
+
activeAngleStartDeg,
|
|
49840
|
+
activeAngleEndDeg
|
|
49841
|
+
};
|
|
49842
|
+
const wheel = driveWheel({ body: options.body, faceWidth: normalized.faceWidth, boreDiameter: normalized.boreDiameter }).addSpurTeethBetween({
|
|
49843
|
+
name: "teeth",
|
|
49844
|
+
module: normalized.module,
|
|
49845
|
+
teethOnFullCircle: normalized.teethOnFullCircle,
|
|
49846
|
+
toothCount: normalized.toothCount,
|
|
49847
|
+
firstTooth: normalized.firstTooth,
|
|
49848
|
+
pressureAngleDeg: normalized.pressureAngleDeg,
|
|
49849
|
+
faceWidth: normalized.faceWidth,
|
|
49850
|
+
backlash: normalized.backlash,
|
|
49851
|
+
clearance: normalized.clearance,
|
|
49852
|
+
addendum: normalized.addendum,
|
|
49853
|
+
dedendum: normalized.dedendum,
|
|
49854
|
+
segmentsPerTooth: normalized.segmentsPerTooth
|
|
49855
|
+
}).build();
|
|
49856
|
+
return attachGearMeta(wheel, meta2);
|
|
49857
|
+
}
|
|
48383
49858
|
function normalizeSideGearOptions(options) {
|
|
48384
49859
|
let normalizedSpur;
|
|
48385
49860
|
try {
|
|
@@ -49359,6 +50834,12 @@ function boltPattern(options) {
|
|
|
49359
50834
|
}
|
|
49360
50835
|
};
|
|
49361
50836
|
}
|
|
50837
|
+
const gearBodies = {
|
|
50838
|
+
disk: gearBodyDisk,
|
|
50839
|
+
diskWithHub: gearBodyDiskWithHub,
|
|
50840
|
+
spoked: gearBodySpoked,
|
|
50841
|
+
fromProfile: gearBodyFromProfile
|
|
50842
|
+
};
|
|
49362
50843
|
function thread(diameter, pitch, length4, options) {
|
|
49363
50844
|
const r = diameter / 2;
|
|
49364
50845
|
const depth = (options == null ? void 0 : options.depth) ?? pitch * 0.35;
|
|
@@ -49524,7 +51005,23 @@ const partLibrary = {
|
|
|
49524
51005
|
gearRatio,
|
|
49525
51006
|
rackRatio,
|
|
49526
51007
|
planetaryRatio,
|
|
49527
|
-
boltPattern
|
|
51008
|
+
boltPattern,
|
|
51009
|
+
/** Start a composable exceptional gear or drive wheel. */
|
|
51010
|
+
driveWheel,
|
|
51011
|
+
/** Read functional-region metadata from a drive wheel shape. */
|
|
51012
|
+
readDriveWheelMeta,
|
|
51013
|
+
/** Involute sector gear with teeth on only part of the pitch circle. */
|
|
51014
|
+
sectorGear,
|
|
51015
|
+
/** Gear body preset namespace: disk, diskWithHub, spoked, and fromProfile. */
|
|
51016
|
+
gearBodies,
|
|
51017
|
+
/** Solid disk/ring gear body, independent from any tooth geometry. */
|
|
51018
|
+
gearBodyDisk,
|
|
51019
|
+
/** Disk gear body with a raised center hub. */
|
|
51020
|
+
gearBodyDiskWithHub,
|
|
51021
|
+
/** Spoked gear body with an outer rim, center hub, and radial spokes. */
|
|
51022
|
+
gearBodySpoked,
|
|
51023
|
+
/** Extrude a custom 2D profile into a gear body. */
|
|
51024
|
+
gearBodyFromProfile
|
|
49528
51025
|
};
|
|
49529
51026
|
/**
|
|
49530
51027
|
* @license
|
|
@@ -51849,7 +53346,7 @@ class ProductStationBuilder {
|
|
|
51849
53346
|
this.profileValue = profileFromSketch(sketch, "custom", width, depth);
|
|
51850
53347
|
return this;
|
|
51851
53348
|
}
|
|
51852
|
-
/**
|
|
53349
|
+
/** Set the station crown amount for soft product-section intent. */
|
|
51853
53350
|
crown(amount) {
|
|
51854
53351
|
if (!Number.isFinite(amount)) throw new Error("station.crown(amount) requires a finite number");
|
|
51855
53352
|
this.crownValue = amount;
|
|
@@ -53180,7 +54677,7 @@ class ProductSkinBuilder {
|
|
|
53180
54677
|
this.stationsValue = stations.map(toStationSpec).sort((a2, b) => axisPosition(this.axisValue, a2.center) - axisPosition(this.axisValue, b.center));
|
|
53181
54678
|
return this;
|
|
53182
54679
|
}
|
|
53183
|
-
/** Attach guide rails
|
|
54680
|
+
/** Attach named guide rails for product-skin construction and downstream surface references. */
|
|
53184
54681
|
rails(rails) {
|
|
53185
54682
|
this.railsValue = { ...rails };
|
|
53186
54683
|
return this;
|
|
@@ -53214,7 +54711,7 @@ class ProductSkinBuilder {
|
|
|
53214
54711
|
this.edgeLengthValue = value;
|
|
53215
54712
|
return this;
|
|
53216
54713
|
}
|
|
53217
|
-
/**
|
|
54714
|
+
/** Record intended wall thickness for product design metadata. Use explicit shelling when the model needs real inner-wall geometry. */
|
|
53218
54715
|
wall(thickness) {
|
|
53219
54716
|
if (!Number.isFinite(thickness) || thickness <= 0) throw new Error("Product.skin().wall(thickness) requires a positive finite number");
|
|
53220
54717
|
this.wallValue = thickness;
|
|
@@ -56356,7 +57853,7 @@ class SurfaceMemberBuilder {
|
|
|
56356
57853
|
this.record.features.push({ ...normalizeFeature(name, feature), type: "counterbore" });
|
|
56357
57854
|
return this;
|
|
56358
57855
|
}
|
|
56359
|
-
/** Add a named anchor at a carrier surface coordinate for
|
|
57856
|
+
/** Add a named anchor at a carrier surface coordinate for explicit member joins. */
|
|
56360
57857
|
anchorAt(name, coordinate) {
|
|
56361
57858
|
if (!name.trim()) throw new Error("SurfaceMemberBuilder.anchorAt(name, coordinate) requires a non-empty name");
|
|
56362
57859
|
const explicitAnchors = this.record.spec.explicitAnchors ?? [];
|
|
@@ -65818,8 +67315,8 @@ tinf_build_bits_base(dist_bits, dist_base, 2, 1);
|
|
|
65818
67315
|
length_bits[28] = 0;
|
|
65819
67316
|
length_base[28] = 258;
|
|
65820
67317
|
var tinyInflate = tinf_uncompress;
|
|
65821
|
-
function derive(v0, v1, v2,
|
|
65822
|
-
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) *
|
|
67318
|
+
function derive(v0, v1, v2, v32, t) {
|
|
67319
|
+
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;
|
|
65823
67320
|
}
|
|
65824
67321
|
function BoundingBox() {
|
|
65825
67322
|
this.x1 = Number.NaN;
|
|
@@ -294630,6 +296127,7 @@ function classifySdfPreviewNode(node) {
|
|
|
294630
296127
|
case "sdf:twist":
|
|
294631
296128
|
case "sdf:bend":
|
|
294632
296129
|
case "sdf:repeat":
|
|
296130
|
+
case "sdf:circularArray":
|
|
294633
296131
|
case "sdf:shell":
|
|
294634
296132
|
case "sdf:onion":
|
|
294635
296133
|
return classifySdfPreviewNode(node.child);
|
|
@@ -294639,10 +296137,7 @@ function classifySdfPreviewNode(node) {
|
|
|
294639
296137
|
reason: "This SDF uses a custom JavaScript displacement function that cannot be compiled for raymarch preview."
|
|
294640
296138
|
};
|
|
294641
296139
|
case "sdf:surfaceDisplace":
|
|
294642
|
-
return
|
|
294643
|
-
mode: "unsupported",
|
|
294644
|
-
reason: "This SDF uses surface displacement that is not yet available in the raymarch shader."
|
|
294645
|
-
};
|
|
296140
|
+
return classifySurfaceDisplacePreviewNode(node);
|
|
294646
296141
|
case "sdf:spatialBlend":
|
|
294647
296142
|
return {
|
|
294648
296143
|
mode: "unsupported",
|
|
@@ -294668,6 +296163,79 @@ ${node.shaderUnsupportedReason}` : ""}`
|
|
|
294668
296163
|
};
|
|
294669
296164
|
}
|
|
294670
296165
|
}
|
|
296166
|
+
function classifySurfaceDisplacePreviewNode(node) {
|
|
296167
|
+
if (!node.pattern) {
|
|
296168
|
+
return {
|
|
296169
|
+
mode: "unsupported",
|
|
296170
|
+
reason: "This SDF uses a custom JavaScript surface pattern that cannot be compiled for raymarch preview."
|
|
296171
|
+
};
|
|
296172
|
+
}
|
|
296173
|
+
const childResult = classifySdfPreviewNode(node.child);
|
|
296174
|
+
if (childResult.mode !== "raymarch") return childResult;
|
|
296175
|
+
const uv = analyzeShaderSurfaceUv(node.child, "p", node.uvMode);
|
|
296176
|
+
if (uv.mode === "triplanar") {
|
|
296177
|
+
return {
|
|
296178
|
+
mode: "unsupported",
|
|
296179
|
+
reason: "Typed surface displacement raymarch preview currently supports sphere, cylinder, and torus UV mappings."
|
|
296180
|
+
};
|
|
296181
|
+
}
|
|
296182
|
+
return { mode: "raymarch" };
|
|
296183
|
+
}
|
|
296184
|
+
function f2(value) {
|
|
296185
|
+
if (!Number.isFinite(value)) return "0.0";
|
|
296186
|
+
const text = Number(value.toPrecision(9)).toString();
|
|
296187
|
+
return text.includes(".") || text.includes("e") ? text : `${text}.0`;
|
|
296188
|
+
}
|
|
296189
|
+
function v3(value) {
|
|
296190
|
+
return `vec3(${f2(value[0])}, ${f2(value[1])}, ${f2(value[2])})`;
|
|
296191
|
+
}
|
|
296192
|
+
function analyzeShaderSurfaceUv(node, p2, override) {
|
|
296193
|
+
const analysis = analyzeShaderSurfaceUvNode(node, p2);
|
|
296194
|
+
if (!override || override === "auto") return analysis;
|
|
296195
|
+
if (override === "triplanar") return { mode: "triplanar" };
|
|
296196
|
+
if (analysis.mode === "triplanar") return analysis;
|
|
296197
|
+
if (override === analysis.mode) return analysis;
|
|
296198
|
+
if (override === "sphere" || override === "cylinder") {
|
|
296199
|
+
return { mode: override, localPoint: analysis.localPoint, radius: analysis.radius };
|
|
296200
|
+
}
|
|
296201
|
+
return analysis.mode === "torus" ? analysis : { mode: "triplanar" };
|
|
296202
|
+
}
|
|
296203
|
+
function analyzeShaderSurfaceUvNode(node, p2) {
|
|
296204
|
+
switch (node.kind) {
|
|
296205
|
+
case "sdf:sphere":
|
|
296206
|
+
return { mode: "sphere", localPoint: p2, radius: node.radius };
|
|
296207
|
+
case "sdf:cylinder":
|
|
296208
|
+
return { mode: "cylinder", localPoint: p2, radius: node.radius };
|
|
296209
|
+
case "sdf:torus":
|
|
296210
|
+
return { mode: "torus", localPoint: p2, radius: node.minorRadius, majorRadius: node.majorRadius };
|
|
296211
|
+
case "sdf:translate":
|
|
296212
|
+
return analyzeShaderSurfaceUvNode(node.child, `(${p2} - ${v3(node.offset)})`);
|
|
296213
|
+
case "sdf:rotate":
|
|
296214
|
+
return analyzeShaderSurfaceUvNode(node.child, `rotateInvEuler(${p2}, ${v3(node.degrees)})`);
|
|
296215
|
+
case "sdf:scale": {
|
|
296216
|
+
const result = analyzeShaderSurfaceUvNode(node.child, `(${p2} / ${f2(node.factor)})`);
|
|
296217
|
+
if (result.mode === "triplanar") return result;
|
|
296218
|
+
return {
|
|
296219
|
+
...result,
|
|
296220
|
+
radius: result.radius * node.factor,
|
|
296221
|
+
...result.mode === "torus" ? { majorRadius: result.majorRadius * node.factor } : {}
|
|
296222
|
+
};
|
|
296223
|
+
}
|
|
296224
|
+
case "sdf:shell":
|
|
296225
|
+
return analyzeShaderSurfaceUvNode(node.child, p2);
|
|
296226
|
+
case "sdf:union":
|
|
296227
|
+
case "sdf:smoothUnion":
|
|
296228
|
+
case "sdf:intersection":
|
|
296229
|
+
case "sdf:smoothIntersection":
|
|
296230
|
+
case "sdf:difference":
|
|
296231
|
+
case "sdf:smoothDifference":
|
|
296232
|
+
return node.children.length > 0 ? analyzeShaderSurfaceUvNode(node.children[0], p2) : { mode: "triplanar" };
|
|
296233
|
+
case "sdf:morph":
|
|
296234
|
+
return analyzeShaderSurfaceUvNode(node.a, p2);
|
|
296235
|
+
default:
|
|
296236
|
+
return { mode: "triplanar" };
|
|
296237
|
+
}
|
|
296238
|
+
}
|
|
294671
296239
|
function describeScriptResultType(value) {
|
|
294672
296240
|
var _a3, _b3;
|
|
294673
296241
|
if (value == null) return String(value);
|
|
@@ -294728,7 +296296,7 @@ function mapScriptResultToScene(args) {
|
|
|
294728
296296
|
var _a3;
|
|
294729
296297
|
const objects = [];
|
|
294730
296298
|
const shapeDimensions = [];
|
|
294731
|
-
const pushShape = (shape, name, groupName, color, treePath) => {
|
|
296299
|
+
const pushShape = (shape, name, groupName, color, treePath, tags = []) => {
|
|
294732
296300
|
const objectId = `obj-${objects.length + 1}`;
|
|
294733
296301
|
objects.push({
|
|
294734
296302
|
id: objectId,
|
|
@@ -294739,7 +296307,8 @@ function mapScriptResultToScene(args) {
|
|
|
294739
296307
|
materialProps: shape.materialProps,
|
|
294740
296308
|
geometryInfo: shape.geometryInfo(),
|
|
294741
296309
|
groupName,
|
|
294742
|
-
treePath: treePath && treePath.length > 0 ? [...treePath] : [name]
|
|
296310
|
+
treePath: treePath && treePath.length > 0 ? [...treePath] : [name],
|
|
296311
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
294743
296312
|
});
|
|
294744
296313
|
const dims = getShapeDimensions(shape);
|
|
294745
296314
|
dims.forEach((dim2) => {
|
|
@@ -294763,7 +296332,7 @@ function mapScriptResultToScene(args) {
|
|
|
294763
296332
|
});
|
|
294764
296333
|
}
|
|
294765
296334
|
};
|
|
294766
|
-
const pushSketch = (sketch, name, groupName, treePath) => {
|
|
296335
|
+
const pushSketch = (sketch, name, groupName, treePath, tags = []) => {
|
|
294767
296336
|
const meta2 = sketch instanceof ConstraintSketch ? sketch.constraintMeta : void 0;
|
|
294768
296337
|
objects.push({
|
|
294769
296338
|
id: `obj-${objects.length + 1}`,
|
|
@@ -294774,10 +296343,11 @@ function mapScriptResultToScene(args) {
|
|
|
294774
296343
|
sketchMeta: meta2,
|
|
294775
296344
|
color: sketch.colorHex,
|
|
294776
296345
|
groupName,
|
|
294777
|
-
treePath: treePath && treePath.length > 0 ? [...treePath] : [name]
|
|
296346
|
+
treePath: treePath && treePath.length > 0 ? [...treePath] : [name],
|
|
296347
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
294778
296348
|
});
|
|
294779
296349
|
};
|
|
294780
|
-
const pushSdf = (sdfShape, name, groupName, treePath, color) => {
|
|
296350
|
+
const pushSdf = (sdfShape, name, groupName, treePath, color, tags = []) => {
|
|
294781
296351
|
const preview = classifySdfPreviewNode(sdfShape._node);
|
|
294782
296352
|
const displayColor = color || sdfShape.colorHex;
|
|
294783
296353
|
const data = {
|
|
@@ -294797,7 +296367,8 @@ function mapScriptResultToScene(args) {
|
|
|
294797
296367
|
materialProps: sdfShape.materialProps,
|
|
294798
296368
|
geometryInfo: null,
|
|
294799
296369
|
groupName,
|
|
294800
|
-
treePath: treePath && treePath.length > 0 ? [...treePath] : [name]
|
|
296370
|
+
treePath: treePath && treePath.length > 0 ? [...treePath] : [name],
|
|
296371
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
294801
296372
|
});
|
|
294802
296373
|
};
|
|
294803
296374
|
const isNamedObject = (item) => {
|
|
@@ -294814,18 +296385,24 @@ function mapScriptResultToScene(args) {
|
|
|
294814
296385
|
const rootGroupChildLabel = (grp, index2) => {
|
|
294815
296386
|
return shapeGroupChildSegment(grp, index2, true);
|
|
294816
296387
|
};
|
|
294817
|
-
const flattenGroupChild = (child, label, groupName, treePath) => {
|
|
296388
|
+
const flattenGroupChild = (child, label, groupName, treePath, tags = []) => {
|
|
294818
296389
|
const resolvedTreePath = treePath && treePath.length > 0 ? treePath : [label];
|
|
294819
296390
|
if (child instanceof ShapeGroup) {
|
|
294820
296391
|
child.children.forEach((nested, i) => {
|
|
294821
|
-
flattenGroupChild(
|
|
296392
|
+
flattenGroupChild(
|
|
296393
|
+
nested,
|
|
296394
|
+
groupChildLabel(child, label, i),
|
|
296395
|
+
groupName,
|
|
296396
|
+
[...resolvedTreePath, shapeGroupChildSegment(child, i)],
|
|
296397
|
+
mergeSceneTags(tags, child.tagsForChild(i))
|
|
296398
|
+
);
|
|
294822
296399
|
});
|
|
294823
296400
|
return;
|
|
294824
296401
|
}
|
|
294825
296402
|
if (child instanceof Shape) {
|
|
294826
|
-
pushShape(child, label, groupName, void 0, resolvedTreePath);
|
|
296403
|
+
pushShape(child, label, groupName, void 0, resolvedTreePath, tags);
|
|
294827
296404
|
} else if (child instanceof Sketch) {
|
|
294828
|
-
pushSketch(child, label, groupName, resolvedTreePath);
|
|
296405
|
+
pushSketch(child, label, groupName, resolvedTreePath, tags);
|
|
294829
296406
|
}
|
|
294830
296407
|
};
|
|
294831
296408
|
const isPlainObject2 = (value) => {
|
|
@@ -294834,34 +296411,40 @@ function mapScriptResultToScene(args) {
|
|
|
294834
296411
|
return proto2 === Object.prototype || proto2 === null;
|
|
294835
296412
|
};
|
|
294836
296413
|
const joinName = (path2) => path2.join(".");
|
|
294837
|
-
const processRenderableTree = (value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = [], seen = /* @__PURE__ */ new WeakSet()) => {
|
|
296414
|
+
const processRenderableTree = (value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = [], inheritedTags = [], seen = /* @__PURE__ */ new WeakSet()) => {
|
|
294838
296415
|
const segment = fallbackSegment.trim().length > 0 ? fallbackSegment : fallbackLabel;
|
|
294839
296416
|
const treePath = [...parentTreePath, segment];
|
|
294840
296417
|
const name = joinName(treePath) || fallbackLabel;
|
|
294841
296418
|
if (value instanceof Assembly) {
|
|
294842
|
-
value.solve().toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath));
|
|
296419
|
+
value.solve().toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath, inheritedTags));
|
|
294843
296420
|
return;
|
|
294844
296421
|
}
|
|
294845
296422
|
if (value instanceof SolvedAssembly) {
|
|
294846
|
-
value.toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath));
|
|
296423
|
+
value.toSceneObjects().forEach((item, index2) => processNamedItem(item, `${name}.${index2 + 1}`, `${index2 + 1}`, name, treePath, inheritedTags));
|
|
294847
296424
|
return;
|
|
294848
296425
|
}
|
|
294849
296426
|
if (value instanceof ShapeGroup) {
|
|
294850
296427
|
value.children.forEach((child, i) => {
|
|
294851
|
-
flattenGroupChild(
|
|
296428
|
+
flattenGroupChild(
|
|
296429
|
+
child,
|
|
296430
|
+
groupChildLabel(value, name, i),
|
|
296431
|
+
parentGroup,
|
|
296432
|
+
[...treePath, shapeGroupChildSegment(value, i)],
|
|
296433
|
+
mergeSceneTags(inheritedTags, value.tagsForChild(i))
|
|
296434
|
+
);
|
|
294852
296435
|
});
|
|
294853
296436
|
return;
|
|
294854
296437
|
}
|
|
294855
296438
|
if (value instanceof Shape) {
|
|
294856
|
-
pushShape(value, name, parentGroup, void 0, treePath);
|
|
296439
|
+
pushShape(value, name, parentGroup, void 0, treePath, inheritedTags);
|
|
294857
296440
|
return;
|
|
294858
296441
|
}
|
|
294859
296442
|
if (value instanceof Sketch) {
|
|
294860
|
-
pushSketch(value, name, parentGroup, treePath);
|
|
296443
|
+
pushSketch(value, name, parentGroup, treePath, inheritedTags);
|
|
294861
296444
|
return;
|
|
294862
296445
|
}
|
|
294863
296446
|
if (value instanceof SdfShape) {
|
|
294864
|
-
pushSdf(value, name, parentGroup, treePath);
|
|
296447
|
+
pushSdf(value, name, parentGroup, treePath, void 0, inheritedTags);
|
|
294865
296448
|
return;
|
|
294866
296449
|
}
|
|
294867
296450
|
if (value instanceof GCodeBuilder) {
|
|
@@ -294872,7 +296455,8 @@ function mapScriptResultToScene(args) {
|
|
|
294872
296455
|
sketch: null,
|
|
294873
296456
|
toolpath: value.build(),
|
|
294874
296457
|
geometryInfo: null,
|
|
294875
|
-
treePath
|
|
296458
|
+
treePath,
|
|
296459
|
+
...inheritedTags.length > 0 ? { tags: [...inheritedTags] } : {}
|
|
294876
296460
|
});
|
|
294877
296461
|
return;
|
|
294878
296462
|
}
|
|
@@ -294882,30 +296466,38 @@ function mapScriptResultToScene(args) {
|
|
|
294882
296466
|
value.forEach((item, index2) => {
|
|
294883
296467
|
const childSegment = `${index2 + 1}`;
|
|
294884
296468
|
const childLabel = `${name}.${childSegment}`;
|
|
294885
|
-
processRenderableTree(item, childLabel, childSegment, parentGroup, treePath, seen);
|
|
296469
|
+
processRenderableTree(item, childLabel, childSegment, parentGroup, treePath, inheritedTags, seen);
|
|
294886
296470
|
});
|
|
294887
296471
|
return;
|
|
294888
296472
|
}
|
|
294889
296473
|
if (isNamedObject(value)) {
|
|
294890
|
-
processNamedItem(value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath);
|
|
296474
|
+
processNamedItem(value, fallbackLabel, fallbackSegment, parentGroup, parentTreePath, inheritedTags);
|
|
294891
296475
|
return;
|
|
294892
296476
|
}
|
|
294893
296477
|
if (isPlainObject2(value)) {
|
|
294894
296478
|
if (seen.has(value)) return;
|
|
294895
296479
|
seen.add(value);
|
|
294896
296480
|
Object.entries(value).forEach(([key, entry]) => {
|
|
294897
|
-
processRenderableTree(entry, key, key, parentGroup, treePath, seen);
|
|
296481
|
+
processRenderableTree(entry, key, key, parentGroup, treePath, inheritedTags, seen);
|
|
294898
296482
|
});
|
|
294899
296483
|
}
|
|
294900
296484
|
};
|
|
294901
|
-
const processNamedItem = (item, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = []) => {
|
|
296485
|
+
const processNamedItem = (item, fallbackLabel, fallbackSegment, parentGroup, parentTreePath = [], inheritedTags = []) => {
|
|
296486
|
+
var _a4;
|
|
294902
296487
|
const name = typeof item.name === "string" && item.name.trim().length > 0 ? item.name : fallbackLabel;
|
|
294903
296488
|
const localSegment = typeof item.name === "string" && item.name.trim().length > 0 ? item.name : fallbackSegment;
|
|
294904
296489
|
const treePath = [...parentTreePath, localSegment];
|
|
294905
296490
|
const grp = parentGroup;
|
|
296491
|
+
const tags = mergeSceneTags(inheritedTags, (_a4 = item.metadata) == null ? void 0 : _a4.tags, item.tags);
|
|
294906
296492
|
if (item.group instanceof ShapeGroup) {
|
|
294907
296493
|
item.group.children.forEach((child, i) => {
|
|
294908
|
-
flattenGroupChild(
|
|
296494
|
+
flattenGroupChild(
|
|
296495
|
+
child,
|
|
296496
|
+
groupChildLabel(item.group, name, i),
|
|
296497
|
+
name,
|
|
296498
|
+
[...treePath, shapeGroupChildSegment(item.group, i)],
|
|
296499
|
+
mergeSceneTags(tags, item.group.tagsForChild(i))
|
|
296500
|
+
);
|
|
294909
296501
|
});
|
|
294910
296502
|
return;
|
|
294911
296503
|
}
|
|
@@ -294915,39 +296507,48 @@ function mapScriptResultToScene(args) {
|
|
|
294915
296507
|
const childTreePath = [...treePath, `${i + 1}`];
|
|
294916
296508
|
if (child instanceof ShapeGroup) {
|
|
294917
296509
|
child.children.forEach((nested, nestedIndex) => {
|
|
294918
|
-
flattenGroupChild(
|
|
294919
|
-
|
|
294920
|
-
|
|
294921
|
-
|
|
296510
|
+
flattenGroupChild(
|
|
296511
|
+
nested,
|
|
296512
|
+
groupChildLabel(child, name, nestedIndex),
|
|
296513
|
+
name,
|
|
296514
|
+
[...treePath, shapeGroupChildSegment(child, nestedIndex)],
|
|
296515
|
+
mergeSceneTags(tags, child.tagsForChild(nestedIndex))
|
|
296516
|
+
);
|
|
294922
296517
|
});
|
|
294923
296518
|
} else if (child instanceof Shape) {
|
|
294924
|
-
pushShape(child, childLabel, name, void 0, childTreePath);
|
|
296519
|
+
pushShape(child, childLabel, name, void 0, childTreePath, tags);
|
|
294925
296520
|
} else if (child instanceof Sketch) {
|
|
294926
|
-
pushSketch(child, childLabel, name, childTreePath);
|
|
296521
|
+
pushSketch(child, childLabel, name, childTreePath, tags);
|
|
294927
296522
|
} else if (child instanceof SdfShape) {
|
|
294928
|
-
pushSdf(child, childLabel, name, childTreePath);
|
|
296523
|
+
pushSdf(child, childLabel, name, childTreePath, void 0, tags);
|
|
294929
296524
|
} else if (isNamedObject(child)) {
|
|
294930
|
-
processNamedItem(child, childLabel, `${i + 1}`, name, treePath);
|
|
296525
|
+
processNamedItem(child, childLabel, `${i + 1}`, name, treePath, tags);
|
|
294931
296526
|
}
|
|
294932
296527
|
});
|
|
294933
296528
|
return;
|
|
294934
296529
|
}
|
|
294935
296530
|
if (item.shape instanceof ShapeGroup) {
|
|
294936
296531
|
item.shape.children.forEach(
|
|
294937
|
-
(child, i) => flattenGroupChild(
|
|
296532
|
+
(child, i) => flattenGroupChild(
|
|
296533
|
+
child,
|
|
296534
|
+
groupChildLabel(item.shape, name, i),
|
|
296535
|
+
name,
|
|
296536
|
+
[...treePath, shapeGroupChildSegment(item.shape, i)],
|
|
296537
|
+
mergeSceneTags(tags, item.shape.tagsForChild(i))
|
|
296538
|
+
)
|
|
294938
296539
|
);
|
|
294939
296540
|
return;
|
|
294940
296541
|
}
|
|
294941
296542
|
if (item.shape instanceof Shape) {
|
|
294942
|
-
pushShape(item.shape, name, grp, item.color, treePath);
|
|
296543
|
+
pushShape(item.shape, name, grp, item.color, treePath, tags);
|
|
294943
296544
|
return;
|
|
294944
296545
|
}
|
|
294945
296546
|
if (item.shape instanceof SdfShape) {
|
|
294946
|
-
pushSdf(item.shape, name, grp, treePath, item.color);
|
|
296547
|
+
pushSdf(item.shape, name, grp, treePath, item.color, tags);
|
|
294947
296548
|
return;
|
|
294948
296549
|
}
|
|
294949
296550
|
if (item.sdf instanceof SdfShape) {
|
|
294950
|
-
pushSdf(item.sdf, name, grp, treePath, item.color);
|
|
296551
|
+
pushSdf(item.sdf, name, grp, treePath, item.color, tags);
|
|
294951
296552
|
return;
|
|
294952
296553
|
}
|
|
294953
296554
|
if (item.sketch instanceof Sketch) {
|
|
@@ -294961,7 +296562,8 @@ function mapScriptResultToScene(args) {
|
|
|
294961
296562
|
sketchMeta: meta2,
|
|
294962
296563
|
color: item.color || item.sketch.colorHex,
|
|
294963
296564
|
groupName: grp,
|
|
294964
|
-
treePath
|
|
296565
|
+
treePath,
|
|
296566
|
+
...tags.length > 0 ? { tags: [...tags] } : {}
|
|
294965
296567
|
});
|
|
294966
296568
|
}
|
|
294967
296569
|
};
|
|
@@ -294975,14 +296577,20 @@ function mapScriptResultToScene(args) {
|
|
|
294975
296577
|
} else if (result instanceof ShapeGroup) {
|
|
294976
296578
|
result.children.forEach((child, i) => {
|
|
294977
296579
|
const label = rootGroupChildLabel(result, i);
|
|
294978
|
-
flattenGroupChild(child, label, void 0, [label]);
|
|
296580
|
+
flattenGroupChild(child, label, void 0, [label], result.tagsForChild(i));
|
|
294979
296581
|
});
|
|
294980
296582
|
} else if (Array.isArray(result)) {
|
|
294981
296583
|
result.forEach((item, index2) => {
|
|
294982
296584
|
const label = `Object ${index2 + 1}`;
|
|
294983
296585
|
if (item instanceof ShapeGroup) {
|
|
294984
296586
|
item.children.forEach((child, i) => {
|
|
294985
|
-
flattenGroupChild(
|
|
296587
|
+
flattenGroupChild(
|
|
296588
|
+
child,
|
|
296589
|
+
groupChildLabel(item, label, i),
|
|
296590
|
+
void 0,
|
|
296591
|
+
[label, shapeGroupChildSegment(item, i)],
|
|
296592
|
+
item.tagsForChild(i)
|
|
296593
|
+
);
|
|
294986
296594
|
});
|
|
294987
296595
|
return;
|
|
294988
296596
|
}
|
|
@@ -295015,7 +296623,7 @@ function mapScriptResultToScene(args) {
|
|
|
295015
296623
|
} else if (defaultValue instanceof ShapeGroup) {
|
|
295016
296624
|
defaultValue.children.forEach((child, i) => {
|
|
295017
296625
|
const label = rootGroupChildLabel(defaultValue, i);
|
|
295018
|
-
flattenGroupChild(child, label, void 0, [label]);
|
|
296626
|
+
flattenGroupChild(child, label, void 0, [label], defaultValue.tagsForChild(i));
|
|
295019
296627
|
});
|
|
295020
296628
|
} else if (defaultValue instanceof Shape) {
|
|
295021
296629
|
pushShape(defaultValue, args.fileName, void 0, void 0, [args.fileName]);
|
|
@@ -295061,7 +296669,8 @@ function mapScriptResultToScene(args) {
|
|
|
295061
296669
|
name: `${mock2.name} (mock)`,
|
|
295062
296670
|
shape: mock2.shape,
|
|
295063
296671
|
sketch: null,
|
|
295064
|
-
mock: true
|
|
296672
|
+
mock: true,
|
|
296673
|
+
tags: ["mock"]
|
|
295065
296674
|
});
|
|
295066
296675
|
}
|
|
295067
296676
|
const hasSdfLeaves = objects.some((obj) => obj.sdf);
|
|
@@ -296189,7 +297798,8 @@ function serializeRunResult(result, solverDebug = null) {
|
|
|
296189
297798
|
geometryInfo: obj.geometryInfo,
|
|
296190
297799
|
sketchMeta: obj.sketchMeta,
|
|
296191
297800
|
groupName: obj.groupName,
|
|
296192
|
-
treePath: obj.treePath
|
|
297801
|
+
treePath: obj.treePath,
|
|
297802
|
+
tags: obj.tags
|
|
296193
297803
|
};
|
|
296194
297804
|
if (serialized2.shapeData) {
|
|
296195
297805
|
transferables.push(
|
|
@@ -296235,6 +297845,7 @@ function serializeRunMetadata(result) {
|
|
|
296235
297845
|
sketchMeta: obj.sketchMeta,
|
|
296236
297846
|
groupName: obj.groupName,
|
|
296237
297847
|
treePath: obj.treePath,
|
|
297848
|
+
tags: obj.tags,
|
|
296238
297849
|
mock: obj.mock,
|
|
296239
297850
|
serverShapeRef: obj.serverShapeRef,
|
|
296240
297851
|
exactState: obj.exactState
|