brepjs 18.154.0 → 18.155.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/brepjs.cjs +278 -227
- package/dist/brepjs.js +278 -227
- package/dist/csg/edit.d.ts +1 -0
- package/dist/csg/serialize.d.ts +2 -1
- package/package.json +1 -1
package/dist/brepjs.js
CHANGED
|
@@ -3616,12 +3616,164 @@ function withEvaluator(options, fn) {
|
|
|
3616
3616
|
_usingCtx$4.d();
|
|
3617
3617
|
}
|
|
3618
3618
|
}
|
|
3619
|
+
//#endregion
|
|
3620
|
+
//#region src/csg/edit.ts
|
|
3621
|
+
function replaceNode(root, pred, replacement) {
|
|
3622
|
+
return walk(root, pred, replacement, /* @__PURE__ */ new Map());
|
|
3623
|
+
}
|
|
3624
|
+
function walk(node, pred, repl, memo) {
|
|
3625
|
+
const cached = memo.get(node);
|
|
3626
|
+
if (cached !== void 0) return cached;
|
|
3627
|
+
const out = pred(node) ? repl : rebuildChildren(node, pred, repl, memo);
|
|
3628
|
+
memo.set(node, out);
|
|
3629
|
+
return out;
|
|
3630
|
+
}
|
|
3631
|
+
function rebuildChildren(n, pred, repl, memo) {
|
|
3632
|
+
switch (n.kind) {
|
|
3633
|
+
case "Box":
|
|
3634
|
+
case "Sphere":
|
|
3635
|
+
case "Cylinder":
|
|
3636
|
+
case "Cone":
|
|
3637
|
+
case "Torus":
|
|
3638
|
+
case "Polygon":
|
|
3639
|
+
case "Circle":
|
|
3640
|
+
case "Line":
|
|
3641
|
+
case "Vertex":
|
|
3642
|
+
case "Empty":
|
|
3643
|
+
case "Path":
|
|
3644
|
+
case "Profile": return n;
|
|
3645
|
+
case "Fuse": return fuse$1(walk(n.a, pred, repl, memo), walk(n.b, pred, repl, memo), n.tolerance);
|
|
3646
|
+
case "Cut": return cut$1(walk(n.a, pred, repl, memo), walk(n.b, pred, repl, memo), n.tolerance);
|
|
3647
|
+
case "Intersect": return intersect$1(walk(n.a, pred, repl, memo), walk(n.b, pred, repl, memo), n.tolerance);
|
|
3648
|
+
case "FuseAll": return fuseAll$1(n.shapes.map((c) => walk(c, pred, repl, memo)), n.tolerance);
|
|
3649
|
+
case "CutAll": return cutAll$1(walk(n.base, pred, repl, memo), n.tools.map((c) => walk(c, pred, repl, memo)), n.tolerance);
|
|
3650
|
+
case "Translate": return translate$1(walk(n.target, pred, repl, memo), n.vector);
|
|
3651
|
+
case "Rotate": return rotate$1(walk(n.target, pred, repl, memo), n.angle, {
|
|
3652
|
+
axis: n.axis,
|
|
3653
|
+
at: n.at
|
|
3654
|
+
});
|
|
3655
|
+
case "Scale": return scale$2(walk(n.target, pred, repl, memo), n.factor, { center: n.center });
|
|
3656
|
+
case "Mirror": return mirror$1(walk(n.target, pred, repl, memo), {
|
|
3657
|
+
normal: n.normal,
|
|
3658
|
+
at: n.at
|
|
3659
|
+
});
|
|
3660
|
+
case "Compound": return compound$1(n.children.map((c) => walk(c, pred, repl, memo)));
|
|
3661
|
+
case "Instance": return instance$1(walk(n.source, pred, repl, memo), n.placements, n.fuse);
|
|
3662
|
+
case "Extrude":
|
|
3663
|
+
case "Revolve":
|
|
3664
|
+
case "Loft":
|
|
3665
|
+
case "Sweep":
|
|
3666
|
+
case "Color":
|
|
3667
|
+
case "Fillet":
|
|
3668
|
+
case "Chamfer":
|
|
3669
|
+
case "Shell": return rebuildFeature(n, pred, repl, memo);
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3672
|
+
function rebuildFeature(n, pred, repl, memo) {
|
|
3673
|
+
switch (n.kind) {
|
|
3674
|
+
case "Extrude": return extrude$1(walk(n.profile, pred, repl, memo), n.vector);
|
|
3675
|
+
case "Revolve": return revolve$1(walk(n.profile, pred, repl, memo), n.angle, {
|
|
3676
|
+
axis: n.axis,
|
|
3677
|
+
at: n.at
|
|
3678
|
+
});
|
|
3679
|
+
case "Loft": return loft$1(n.sections.map((s) => walk(s, pred, repl, memo)), { ruled: n.ruled });
|
|
3680
|
+
case "Sweep": return sweep$2(walk(n.profile, pred, repl, memo), walk(n.spine, pred, repl, memo), { frenet: n.frenet });
|
|
3681
|
+
case "Color": return color(walk(n.target, pred, repl, memo), [...n.color]);
|
|
3682
|
+
case "Fillet": return fillet$1(walk(n.target, pred, repl, memo), n.ref, n.radius);
|
|
3683
|
+
case "Chamfer": return chamfer$1(walk(n.target, pred, repl, memo), n.ref, n.distance);
|
|
3684
|
+
case "Shell": return shell$1(walk(n.target, pred, repl, memo), n.refs, n.thickness);
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
/** Visits each DISTINCT node once (identity-deduplicated), so a shared
|
|
3688
|
+
* subtree is reported once and a self-referencing DAG walks in linear time. */
|
|
3689
|
+
function forEachNode(root, fn) {
|
|
3690
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3691
|
+
const visit = (node) => {
|
|
3692
|
+
if (seen.has(node)) return;
|
|
3693
|
+
seen.add(node);
|
|
3694
|
+
fn(node);
|
|
3695
|
+
for (const child of childrenOf(node)) visit(child);
|
|
3696
|
+
};
|
|
3697
|
+
visit(root);
|
|
3698
|
+
}
|
|
3699
|
+
function childrenOf(n) {
|
|
3700
|
+
switch (n.kind) {
|
|
3701
|
+
case "Box":
|
|
3702
|
+
case "Sphere":
|
|
3703
|
+
case "Cylinder":
|
|
3704
|
+
case "Cone":
|
|
3705
|
+
case "Torus":
|
|
3706
|
+
case "Polygon":
|
|
3707
|
+
case "Circle":
|
|
3708
|
+
case "Line":
|
|
3709
|
+
case "Vertex":
|
|
3710
|
+
case "Empty":
|
|
3711
|
+
case "Path":
|
|
3712
|
+
case "Profile": return [];
|
|
3713
|
+
case "Fuse":
|
|
3714
|
+
case "Cut":
|
|
3715
|
+
case "Intersect": return [n.a, n.b];
|
|
3716
|
+
case "FuseAll": return n.shapes;
|
|
3717
|
+
case "CutAll": return [n.base, ...n.tools];
|
|
3718
|
+
case "Translate":
|
|
3719
|
+
case "Rotate":
|
|
3720
|
+
case "Scale":
|
|
3721
|
+
case "Mirror":
|
|
3722
|
+
case "Color":
|
|
3723
|
+
case "Fillet":
|
|
3724
|
+
case "Chamfer":
|
|
3725
|
+
case "Shell": return [n.target];
|
|
3726
|
+
case "Compound": return n.children;
|
|
3727
|
+
case "Instance": return [n.source];
|
|
3728
|
+
case "Extrude":
|
|
3729
|
+
case "Revolve": return [n.profile];
|
|
3730
|
+
case "Loft": return n.sections;
|
|
3731
|
+
case "Sweep": return [n.profile, n.spine];
|
|
3732
|
+
}
|
|
3733
|
+
}
|
|
3734
|
+
function nodeCount(root) {
|
|
3735
|
+
let n = 0;
|
|
3736
|
+
forEachNode(root, () => {
|
|
3737
|
+
n++;
|
|
3738
|
+
});
|
|
3739
|
+
return n;
|
|
3740
|
+
}
|
|
3619
3741
|
var MIN_CSG_VERSION = 1;
|
|
3620
3742
|
function toJSON(node) {
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3743
|
+
const ctx = {
|
|
3744
|
+
counts: countRefs(node),
|
|
3745
|
+
ids: /* @__PURE__ */ new Map(),
|
|
3746
|
+
defs: []
|
|
3624
3747
|
};
|
|
3748
|
+
const root = emitNode(node, ctx);
|
|
3749
|
+
return ctx.defs.length > 0 ? {
|
|
3750
|
+
csgVersion: 8,
|
|
3751
|
+
defs: ctx.defs,
|
|
3752
|
+
root
|
|
3753
|
+
} : {
|
|
3754
|
+
csgVersion: 8,
|
|
3755
|
+
root
|
|
3756
|
+
};
|
|
3757
|
+
}
|
|
3758
|
+
function countRefs(root) {
|
|
3759
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3760
|
+
const visit = (n) => {
|
|
3761
|
+
const seen = counts.get(n) ?? 0;
|
|
3762
|
+
counts.set(n, seen + 1);
|
|
3763
|
+
if (seen === 0) for (const child of childrenOf(n)) visit(child);
|
|
3764
|
+
};
|
|
3765
|
+
visit(root);
|
|
3766
|
+
return counts;
|
|
3767
|
+
}
|
|
3768
|
+
function emitNode(n, ctx) {
|
|
3769
|
+
if ((ctx.counts.get(n) ?? 0) < 2) return nodeToJson(n, ctx);
|
|
3770
|
+
const existing = ctx.ids.get(n);
|
|
3771
|
+
if (existing !== void 0) return { $ref: existing };
|
|
3772
|
+
const body = nodeToJson(n, ctx);
|
|
3773
|
+
const id = ctx.defs.length;
|
|
3774
|
+
ctx.defs.push(body);
|
|
3775
|
+
ctx.ids.set(n, id);
|
|
3776
|
+
return { $ref: id };
|
|
3625
3777
|
}
|
|
3626
3778
|
function exprToJson(e) {
|
|
3627
3779
|
switch (e.kind) {
|
|
@@ -3720,25 +3872,25 @@ function primitiveToJson(n) {
|
|
|
3720
3872
|
default: return;
|
|
3721
3873
|
}
|
|
3722
3874
|
}
|
|
3723
|
-
function booleanToJson(n) {
|
|
3875
|
+
function booleanToJson(n, ctx) {
|
|
3724
3876
|
switch (n.kind) {
|
|
3725
3877
|
case "Fuse":
|
|
3726
3878
|
case "Cut":
|
|
3727
3879
|
case "Intersect": return {
|
|
3728
3880
|
kind: n.kind,
|
|
3729
|
-
a:
|
|
3730
|
-
b:
|
|
3881
|
+
a: emitNode(n.a, ctx),
|
|
3882
|
+
b: emitNode(n.b, ctx),
|
|
3731
3883
|
tolerance: n.tolerance
|
|
3732
3884
|
};
|
|
3733
3885
|
case "FuseAll": return {
|
|
3734
3886
|
kind: "FuseAll",
|
|
3735
|
-
shapes: n.shapes.map(
|
|
3887
|
+
shapes: n.shapes.map((s) => emitNode(s, ctx)),
|
|
3736
3888
|
tolerance: n.tolerance
|
|
3737
3889
|
};
|
|
3738
3890
|
case "CutAll": return {
|
|
3739
3891
|
kind: "CutAll",
|
|
3740
|
-
base:
|
|
3741
|
-
tools: n.tools.map(
|
|
3892
|
+
base: emitNode(n.base, ctx),
|
|
3893
|
+
tools: n.tools.map((t) => emitNode(t, ctx)),
|
|
3742
3894
|
tolerance: n.tolerance
|
|
3743
3895
|
};
|
|
3744
3896
|
default: return;
|
|
@@ -3805,103 +3957,108 @@ function contourToJson(c) {
|
|
|
3805
3957
|
segments: c.segments.map(segmentToJson)
|
|
3806
3958
|
};
|
|
3807
3959
|
}
|
|
3808
|
-
function transformToJson(n) {
|
|
3960
|
+
function transformToJson(n, ctx) {
|
|
3809
3961
|
switch (n.kind) {
|
|
3810
3962
|
case "Translate": return {
|
|
3811
3963
|
kind: "Translate",
|
|
3812
|
-
target:
|
|
3964
|
+
target: emitNode(n.target, ctx),
|
|
3813
3965
|
vector: exprToJson(n.vector)
|
|
3814
3966
|
};
|
|
3815
3967
|
case "Rotate": return {
|
|
3816
3968
|
kind: "Rotate",
|
|
3817
|
-
target:
|
|
3969
|
+
target: emitNode(n.target, ctx),
|
|
3818
3970
|
angle: exprToJson(n.angle),
|
|
3819
3971
|
axis: optExprToJson(n.axis),
|
|
3820
3972
|
at: optExprToJson(n.at)
|
|
3821
3973
|
};
|
|
3822
3974
|
case "Scale": return {
|
|
3823
3975
|
kind: "Scale",
|
|
3824
|
-
target:
|
|
3976
|
+
target: emitNode(n.target, ctx),
|
|
3825
3977
|
factor: exprToJson(n.factor),
|
|
3826
3978
|
center: optExprToJson(n.center)
|
|
3827
3979
|
};
|
|
3828
3980
|
case "Mirror": return {
|
|
3829
3981
|
kind: "Mirror",
|
|
3830
|
-
target:
|
|
3982
|
+
target: emitNode(n.target, ctx),
|
|
3831
3983
|
normal: optExprToJson(n.normal),
|
|
3832
3984
|
at: optExprToJson(n.at)
|
|
3833
3985
|
};
|
|
3834
3986
|
default: return;
|
|
3835
3987
|
}
|
|
3836
3988
|
}
|
|
3837
|
-
function
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3989
|
+
function featureToJson(n, ctx) {
|
|
3990
|
+
switch (n.kind) {
|
|
3991
|
+
case "Extrude": return {
|
|
3992
|
+
kind: "Extrude",
|
|
3993
|
+
profile: emitNode(n.profile, ctx),
|
|
3994
|
+
vector: exprToJson(n.vector)
|
|
3995
|
+
};
|
|
3996
|
+
case "Revolve": return {
|
|
3997
|
+
kind: "Revolve",
|
|
3998
|
+
profile: emitNode(n.profile, ctx),
|
|
3999
|
+
angle: exprToJson(n.angle),
|
|
4000
|
+
axis: optExprToJson(n.axis),
|
|
4001
|
+
at: optExprToJson(n.at)
|
|
4002
|
+
};
|
|
4003
|
+
case "Loft": return {
|
|
4004
|
+
kind: "Loft",
|
|
4005
|
+
sections: n.sections.map((s) => emitNode(s, ctx)),
|
|
4006
|
+
ruled: n.ruled
|
|
4007
|
+
};
|
|
4008
|
+
case "Path": return {
|
|
4009
|
+
kind: "Path",
|
|
4010
|
+
start: exprToJson(n.start),
|
|
4011
|
+
segments: n.segments.map(segmentToJson)
|
|
4012
|
+
};
|
|
4013
|
+
case "Sweep": return {
|
|
4014
|
+
kind: "Sweep",
|
|
4015
|
+
profile: emitNode(n.profile, ctx),
|
|
4016
|
+
spine: emitNode(n.spine, ctx),
|
|
4017
|
+
frenet: n.frenet
|
|
4018
|
+
};
|
|
4019
|
+
case "Profile": return {
|
|
4020
|
+
kind: "Profile",
|
|
4021
|
+
outline: contourToJson(n.outline),
|
|
4022
|
+
holes: n.holes.map(contourToJson)
|
|
4023
|
+
};
|
|
4024
|
+
default: return;
|
|
4025
|
+
}
|
|
4026
|
+
}
|
|
4027
|
+
function nodeToJson(n, ctx) {
|
|
3871
4028
|
if (n.kind === "Color") return {
|
|
3872
4029
|
kind: "Color",
|
|
3873
|
-
target:
|
|
4030
|
+
target: emitNode(n.target, ctx),
|
|
3874
4031
|
color: [...n.color]
|
|
3875
4032
|
};
|
|
3876
4033
|
if (n.kind === "Fillet") return {
|
|
3877
4034
|
kind: "Fillet",
|
|
3878
|
-
target:
|
|
4035
|
+
target: emitNode(n.target, ctx),
|
|
3879
4036
|
ref: edgeRefToJson(n.ref),
|
|
3880
4037
|
radius: exprToJson(n.radius)
|
|
3881
4038
|
};
|
|
3882
4039
|
if (n.kind === "Chamfer") return {
|
|
3883
4040
|
kind: "Chamfer",
|
|
3884
|
-
target:
|
|
4041
|
+
target: emitNode(n.target, ctx),
|
|
3885
4042
|
ref: edgeRefToJson(n.ref),
|
|
3886
4043
|
distance: exprToJson(n.distance)
|
|
3887
4044
|
};
|
|
3888
4045
|
if (n.kind === "Shell") return {
|
|
3889
4046
|
kind: "Shell",
|
|
3890
|
-
target:
|
|
4047
|
+
target: emitNode(n.target, ctx),
|
|
3891
4048
|
refs: n.refs.map(shapeRefToJson),
|
|
3892
4049
|
thickness: exprToJson(n.thickness)
|
|
3893
4050
|
};
|
|
3894
4051
|
if (n.kind === "Compound") return {
|
|
3895
4052
|
kind: "Compound",
|
|
3896
|
-
children: n.children.map(
|
|
4053
|
+
children: n.children.map((c) => emitNode(c, ctx))
|
|
3897
4054
|
};
|
|
3898
4055
|
if (n.kind === "Instance") return {
|
|
3899
4056
|
kind: "Instance",
|
|
3900
|
-
source:
|
|
4057
|
+
source: emitNode(n.source, ctx),
|
|
3901
4058
|
placements: n.placements,
|
|
3902
4059
|
fuse: n.fuse
|
|
3903
4060
|
};
|
|
3904
|
-
return primitiveToJson(n) ?? booleanToJson(n) ?? transformToJson(n);
|
|
4061
|
+
return featureToJson(n, ctx) ?? primitiveToJson(n) ?? booleanToJson(n, ctx) ?? transformToJson(n, ctx);
|
|
3905
4062
|
}
|
|
3906
4063
|
function bad(msg) {
|
|
3907
4064
|
return err(validationError(BrepErrorCode.NULL_SHAPE_INPUT, `csg.fromJSON: ${msg}`));
|
|
@@ -3934,9 +4091,18 @@ function readVec2(v, where) {
|
|
|
3934
4091
|
function fromJSON(envelope) {
|
|
3935
4092
|
if (!isObj(envelope)) return bad("input is not an object");
|
|
3936
4093
|
const v = envelope["csgVersion"];
|
|
3937
|
-
if (typeof v !== "number" || !Number.isInteger(v) || v < MIN_CSG_VERSION || v >
|
|
3938
|
-
const
|
|
3939
|
-
|
|
4094
|
+
if (typeof v !== "number" || !Number.isInteger(v) || v < MIN_CSG_VERSION || v > 8) return bad(`unsupported csgVersion ${String(v)} (expected ${MIN_CSG_VERSION}..8)`);
|
|
4095
|
+
const rawDefs = envelope["defs"];
|
|
4096
|
+
const defs = [];
|
|
4097
|
+
if (rawDefs !== void 0) {
|
|
4098
|
+
if (!Array.isArray(rawDefs)) return bad("defs: not an array");
|
|
4099
|
+
for (const raw of rawDefs) {
|
|
4100
|
+
const r = readNode(raw, defs);
|
|
4101
|
+
if (!r.ok) return r;
|
|
4102
|
+
defs.push(r.value);
|
|
4103
|
+
}
|
|
4104
|
+
}
|
|
4105
|
+
return readNode(envelope["root"], defs);
|
|
3940
4106
|
}
|
|
3941
4107
|
function readExpr(j) {
|
|
3942
4108
|
if (!isObj(j)) return bad("expression: not an object");
|
|
@@ -4002,11 +4168,11 @@ function readBuildVec(j) {
|
|
|
4002
4168
|
}
|
|
4003
4169
|
return ok(buildVec(dim, out));
|
|
4004
4170
|
}
|
|
4005
|
-
function readNodeArray(j, where) {
|
|
4171
|
+
function readNodeArray(j, where, defs) {
|
|
4006
4172
|
if (!Array.isArray(j)) return bad(`${where}: not array`);
|
|
4007
4173
|
const out = [];
|
|
4008
4174
|
for (const c of j) {
|
|
4009
|
-
const r = readNode(c);
|
|
4175
|
+
const r = readNode(c, defs);
|
|
4010
4176
|
if (!r.ok) return r;
|
|
4011
4177
|
out.push(r.value);
|
|
4012
4178
|
}
|
|
@@ -4017,8 +4183,15 @@ function readOptTolerance(j) {
|
|
|
4017
4183
|
if (t === void 0 || t === null) return ok(void 0);
|
|
4018
4184
|
return isNumber$1(t) ? ok(t) : bad("tolerance: not a finite number");
|
|
4019
4185
|
}
|
|
4020
|
-
function readNode(j) {
|
|
4186
|
+
function readNode(j, defs) {
|
|
4021
4187
|
if (!isObj(j)) return bad("node: not an object");
|
|
4188
|
+
const ref = j["$ref"];
|
|
4189
|
+
if (ref !== void 0) {
|
|
4190
|
+
if (!isNumber$1(ref) || !Number.isInteger(ref) || ref < 0) return bad("$ref: expected a non-negative integer def index");
|
|
4191
|
+
const node = defs[ref];
|
|
4192
|
+
if (node === void 0) return bad(`$ref: ${ref} is out of range (forward refs are rejected)`);
|
|
4193
|
+
return ok(node);
|
|
4194
|
+
}
|
|
4022
4195
|
const kind = j["kind"];
|
|
4023
4196
|
switch (kind) {
|
|
4024
4197
|
case "Box":
|
|
@@ -4033,25 +4206,25 @@ function readNode(j) {
|
|
|
4033
4206
|
case "Empty": return readPrimitive(kind, j);
|
|
4034
4207
|
case "Fuse":
|
|
4035
4208
|
case "Cut":
|
|
4036
|
-
case "Intersect": return readBinaryBool(kind, j);
|
|
4209
|
+
case "Intersect": return readBinaryBool(kind, j, defs);
|
|
4037
4210
|
case "FuseAll":
|
|
4038
|
-
case "CutAll": return readNaryBool(kind, j);
|
|
4211
|
+
case "CutAll": return readNaryBool(kind, j, defs);
|
|
4039
4212
|
case "Translate":
|
|
4040
4213
|
case "Rotate":
|
|
4041
4214
|
case "Scale":
|
|
4042
|
-
case "Mirror": return readTransform(kind, j);
|
|
4043
|
-
case "Compound": return readCompound(j);
|
|
4044
|
-
case "Instance": return readInstance(j);
|
|
4045
|
-
case "Extrude": return readExtrude(j);
|
|
4046
|
-
case "Revolve": return readRevolve(j);
|
|
4047
|
-
case "Loft": return readLoft(j);
|
|
4215
|
+
case "Mirror": return readTransform(kind, j, defs);
|
|
4216
|
+
case "Compound": return readCompound(j, defs);
|
|
4217
|
+
case "Instance": return readInstance(j, defs);
|
|
4218
|
+
case "Extrude": return readExtrude(j, defs);
|
|
4219
|
+
case "Revolve": return readRevolve(j, defs);
|
|
4220
|
+
case "Loft": return readLoft(j, defs);
|
|
4048
4221
|
case "Path": return readPath(j);
|
|
4049
|
-
case "Sweep": return readSweep(j);
|
|
4222
|
+
case "Sweep": return readSweep(j, defs);
|
|
4050
4223
|
case "Profile": return readProfile(j);
|
|
4051
|
-
case "Color": return readColor(j);
|
|
4052
|
-
case "Fillet": return readFillet(j);
|
|
4053
|
-
case "Chamfer": return readChamfer(j);
|
|
4054
|
-
case "Shell": return readShell(j);
|
|
4224
|
+
case "Color": return readColor(j, defs);
|
|
4225
|
+
case "Fillet": return readFillet(j, defs);
|
|
4226
|
+
case "Chamfer": return readChamfer(j, defs);
|
|
4227
|
+
case "Shell": return readShell(j, defs);
|
|
4055
4228
|
default: return bad(`unknown node kind: ${String(kind)}`);
|
|
4056
4229
|
}
|
|
4057
4230
|
}
|
|
@@ -4133,10 +4306,10 @@ function readEmpty(j) {
|
|
|
4133
4306
|
default: return bad(`Empty.output: ${String(out)}`);
|
|
4134
4307
|
}
|
|
4135
4308
|
}
|
|
4136
|
-
function readBinaryBool(kind, j) {
|
|
4137
|
-
const a = readNode(j["a"]);
|
|
4309
|
+
function readBinaryBool(kind, j, defs) {
|
|
4310
|
+
const a = readNode(j["a"], defs);
|
|
4138
4311
|
if (!a.ok) return a;
|
|
4139
|
-
const b = readNode(j["b"]);
|
|
4312
|
+
const b = readNode(j["b"], defs);
|
|
4140
4313
|
if (!b.ok) return b;
|
|
4141
4314
|
const t = readOptTolerance(j);
|
|
4142
4315
|
if (!t.ok) return t;
|
|
@@ -4146,20 +4319,20 @@ function readBinaryBool(kind, j) {
|
|
|
4146
4319
|
case "Intersect": return ok(intersect$1(a.value, b.value, t.value));
|
|
4147
4320
|
}
|
|
4148
4321
|
}
|
|
4149
|
-
function readNaryBool(kind, j) {
|
|
4322
|
+
function readNaryBool(kind, j, defs) {
|
|
4150
4323
|
const t = readOptTolerance(j);
|
|
4151
4324
|
if (!t.ok) return t;
|
|
4152
4325
|
if (kind === "FuseAll") {
|
|
4153
|
-
const shapes = readNodeArray(j["shapes"], "FuseAll.shapes");
|
|
4326
|
+
const shapes = readNodeArray(j["shapes"], "FuseAll.shapes", defs);
|
|
4154
4327
|
return shapes.ok ? ok(fuseAll$1(shapes.value, t.value)) : shapes;
|
|
4155
4328
|
}
|
|
4156
|
-
const base = readNode(j["base"]);
|
|
4329
|
+
const base = readNode(j["base"], defs);
|
|
4157
4330
|
if (!base.ok) return base;
|
|
4158
|
-
const tools = readNodeArray(j["tools"], "CutAll.tools");
|
|
4331
|
+
const tools = readNodeArray(j["tools"], "CutAll.tools", defs);
|
|
4159
4332
|
return tools.ok ? ok(cutAll$1(base.value, tools.value, t.value)) : tools;
|
|
4160
4333
|
}
|
|
4161
|
-
function readTransform(kind, j) {
|
|
4162
|
-
const tgt = readNode(j["target"]);
|
|
4334
|
+
function readTransform(kind, j, defs) {
|
|
4335
|
+
const tgt = readNode(j["target"], defs);
|
|
4163
4336
|
if (!tgt.ok) return tgt;
|
|
4164
4337
|
switch (kind) {
|
|
4165
4338
|
case "Translate": return readTranslate(j, tgt.value);
|
|
@@ -4206,15 +4379,15 @@ function readMirror(j, target) {
|
|
|
4206
4379
|
at: at.value
|
|
4207
4380
|
}));
|
|
4208
4381
|
}
|
|
4209
|
-
function readExtrude(j) {
|
|
4210
|
-
const profile = readNode(j["profile"]);
|
|
4382
|
+
function readExtrude(j, defs) {
|
|
4383
|
+
const profile = readNode(j["profile"], defs);
|
|
4211
4384
|
if (!profile.ok) return profile;
|
|
4212
4385
|
const vector = readExpr(j["vector"]);
|
|
4213
4386
|
if (!vector.ok) return vector;
|
|
4214
4387
|
return ok(extrude$1(profile.value, vector.value));
|
|
4215
4388
|
}
|
|
4216
|
-
function readRevolve(j) {
|
|
4217
|
-
const profile = readNode(j["profile"]);
|
|
4389
|
+
function readRevolve(j, defs) {
|
|
4390
|
+
const profile = readNode(j["profile"], defs);
|
|
4218
4391
|
if (!profile.ok) return profile;
|
|
4219
4392
|
const angle = readExpr(j["angle"]);
|
|
4220
4393
|
if (!angle.ok) return angle;
|
|
@@ -4227,8 +4400,8 @@ function readRevolve(j) {
|
|
|
4227
4400
|
at: at.value
|
|
4228
4401
|
}));
|
|
4229
4402
|
}
|
|
4230
|
-
function readLoft(j) {
|
|
4231
|
-
const sections = readNodeArray(j["sections"], "Loft.sections");
|
|
4403
|
+
function readLoft(j, defs) {
|
|
4404
|
+
const sections = readNodeArray(j["sections"], "Loft.sections", defs);
|
|
4232
4405
|
if (!sections.ok) return sections;
|
|
4233
4406
|
const ruled = j["ruled"];
|
|
4234
4407
|
if (ruled !== void 0 && typeof ruled !== "boolean") return bad("Loft.ruled: not a boolean");
|
|
@@ -4376,8 +4549,8 @@ function readShapeRef(j, where) {
|
|
|
4376
4549
|
}
|
|
4377
4550
|
});
|
|
4378
4551
|
}
|
|
4379
|
-
function readShell(j) {
|
|
4380
|
-
const target = readNode(j["target"]);
|
|
4552
|
+
function readShell(j, defs) {
|
|
4553
|
+
const target = readNode(j["target"], defs);
|
|
4381
4554
|
if (!target.ok) return target;
|
|
4382
4555
|
const thickness = readExpr(j["thickness"]);
|
|
4383
4556
|
if (!thickness.ok) return thickness;
|
|
@@ -4391,8 +4564,8 @@ function readShell(j) {
|
|
|
4391
4564
|
}
|
|
4392
4565
|
return ok(shell$1(target.value, refs, thickness.value));
|
|
4393
4566
|
}
|
|
4394
|
-
function readFillet(j) {
|
|
4395
|
-
const target = readNode(j["target"]);
|
|
4567
|
+
function readFillet(j, defs) {
|
|
4568
|
+
const target = readNode(j["target"], defs);
|
|
4396
4569
|
if (!target.ok) return target;
|
|
4397
4570
|
const radius = readExpr(j["radius"]);
|
|
4398
4571
|
if (!radius.ok) return radius;
|
|
@@ -4400,8 +4573,8 @@ function readFillet(j) {
|
|
|
4400
4573
|
if (!ref.ok) return ref;
|
|
4401
4574
|
return ok(fillet$1(target.value, ref.value, radius.value));
|
|
4402
4575
|
}
|
|
4403
|
-
function readChamfer(j) {
|
|
4404
|
-
const target = readNode(j["target"]);
|
|
4576
|
+
function readChamfer(j, defs) {
|
|
4577
|
+
const target = readNode(j["target"], defs);
|
|
4405
4578
|
if (!target.ok) return target;
|
|
4406
4579
|
const distance = readExpr(j["distance"]);
|
|
4407
4580
|
if (!distance.ok) return distance;
|
|
@@ -4409,8 +4582,8 @@ function readChamfer(j) {
|
|
|
4409
4582
|
if (!ref.ok) return ref;
|
|
4410
4583
|
return ok(chamfer$1(target.value, ref.value, distance.value));
|
|
4411
4584
|
}
|
|
4412
|
-
function readColor(j) {
|
|
4413
|
-
const target = readNode(j["target"]);
|
|
4585
|
+
function readColor(j, defs) {
|
|
4586
|
+
const target = readNode(j["target"], defs);
|
|
4414
4587
|
if (!target.ok) return target;
|
|
4415
4588
|
const c = j["color"];
|
|
4416
4589
|
if (!Array.isArray(c) || c.length !== 4 || !c.every((v) => isNumber$1(v) && v >= 0 && v <= 1)) return bad("Color.color: expected an RGBA array of 4 numbers in [0, 1]");
|
|
@@ -4434,10 +4607,10 @@ function readProfile(j) {
|
|
|
4434
4607
|
}
|
|
4435
4608
|
return ok(profile(outline.value, holes));
|
|
4436
4609
|
}
|
|
4437
|
-
function readSweep(j) {
|
|
4438
|
-
const profile = readNode(j["profile"]);
|
|
4610
|
+
function readSweep(j, defs) {
|
|
4611
|
+
const profile = readNode(j["profile"], defs);
|
|
4439
4612
|
if (!profile.ok) return profile;
|
|
4440
|
-
const spine = readNode(j["spine"]);
|
|
4613
|
+
const spine = readNode(j["spine"], defs);
|
|
4441
4614
|
if (!spine.ok) return spine;
|
|
4442
4615
|
const frenet = readFlag(j, "frenet");
|
|
4443
4616
|
if (!frenet.ok) return frenet;
|
|
@@ -4456,15 +4629,15 @@ function readPath(j) {
|
|
|
4456
4629
|
}
|
|
4457
4630
|
return ok(path(start.value, segments));
|
|
4458
4631
|
}
|
|
4459
|
-
function readCompound(j) {
|
|
4460
|
-
const children = readNodeArray(j["children"], "Compound.children");
|
|
4632
|
+
function readCompound(j, defs) {
|
|
4633
|
+
const children = readNodeArray(j["children"], "Compound.children", defs);
|
|
4461
4634
|
return children.ok ? ok(compound$1(children.value)) : children;
|
|
4462
4635
|
}
|
|
4463
4636
|
function isMatrix4x4(v) {
|
|
4464
4637
|
return Array.isArray(v) && v.length === 4 && v.every((row) => Array.isArray(row) && row.length === 4 && row.every(isNumber$1));
|
|
4465
4638
|
}
|
|
4466
|
-
function readInstance(j) {
|
|
4467
|
-
const source = readNode(j["source"]);
|
|
4639
|
+
function readInstance(j, defs) {
|
|
4640
|
+
const source = readNode(j["source"], defs);
|
|
4468
4641
|
if (!source.ok) return source;
|
|
4469
4642
|
const placements = j["placements"];
|
|
4470
4643
|
if (!Array.isArray(placements) || !placements.every(isMatrix4x4)) return bad("Instance.placements must be an array of 4x4 number matrices");
|
|
@@ -4662,128 +4835,6 @@ function optimizeTranslate(target, vector) {
|
|
|
4662
4835
|
return translate$1(ot, ov);
|
|
4663
4836
|
}
|
|
4664
4837
|
//#endregion
|
|
4665
|
-
//#region src/csg/edit.ts
|
|
4666
|
-
function replaceNode(root, pred, replacement) {
|
|
4667
|
-
return walk(root, pred, replacement, /* @__PURE__ */ new Map());
|
|
4668
|
-
}
|
|
4669
|
-
function walk(node, pred, repl, memo) {
|
|
4670
|
-
const cached = memo.get(node);
|
|
4671
|
-
if (cached !== void 0) return cached;
|
|
4672
|
-
const out = pred(node) ? repl : rebuildChildren(node, pred, repl, memo);
|
|
4673
|
-
memo.set(node, out);
|
|
4674
|
-
return out;
|
|
4675
|
-
}
|
|
4676
|
-
function rebuildChildren(n, pred, repl, memo) {
|
|
4677
|
-
switch (n.kind) {
|
|
4678
|
-
case "Box":
|
|
4679
|
-
case "Sphere":
|
|
4680
|
-
case "Cylinder":
|
|
4681
|
-
case "Cone":
|
|
4682
|
-
case "Torus":
|
|
4683
|
-
case "Polygon":
|
|
4684
|
-
case "Circle":
|
|
4685
|
-
case "Line":
|
|
4686
|
-
case "Vertex":
|
|
4687
|
-
case "Empty":
|
|
4688
|
-
case "Path":
|
|
4689
|
-
case "Profile": return n;
|
|
4690
|
-
case "Fuse": return fuse$1(walk(n.a, pred, repl, memo), walk(n.b, pred, repl, memo), n.tolerance);
|
|
4691
|
-
case "Cut": return cut$1(walk(n.a, pred, repl, memo), walk(n.b, pred, repl, memo), n.tolerance);
|
|
4692
|
-
case "Intersect": return intersect$1(walk(n.a, pred, repl, memo), walk(n.b, pred, repl, memo), n.tolerance);
|
|
4693
|
-
case "FuseAll": return fuseAll$1(n.shapes.map((c) => walk(c, pred, repl, memo)), n.tolerance);
|
|
4694
|
-
case "CutAll": return cutAll$1(walk(n.base, pred, repl, memo), n.tools.map((c) => walk(c, pred, repl, memo)), n.tolerance);
|
|
4695
|
-
case "Translate": return translate$1(walk(n.target, pred, repl, memo), n.vector);
|
|
4696
|
-
case "Rotate": return rotate$1(walk(n.target, pred, repl, memo), n.angle, {
|
|
4697
|
-
axis: n.axis,
|
|
4698
|
-
at: n.at
|
|
4699
|
-
});
|
|
4700
|
-
case "Scale": return scale$2(walk(n.target, pred, repl, memo), n.factor, { center: n.center });
|
|
4701
|
-
case "Mirror": return mirror$1(walk(n.target, pred, repl, memo), {
|
|
4702
|
-
normal: n.normal,
|
|
4703
|
-
at: n.at
|
|
4704
|
-
});
|
|
4705
|
-
case "Compound": return compound$1(n.children.map((c) => walk(c, pred, repl, memo)));
|
|
4706
|
-
case "Instance": return instance$1(walk(n.source, pred, repl, memo), n.placements, n.fuse);
|
|
4707
|
-
case "Extrude":
|
|
4708
|
-
case "Revolve":
|
|
4709
|
-
case "Loft":
|
|
4710
|
-
case "Sweep":
|
|
4711
|
-
case "Color":
|
|
4712
|
-
case "Fillet":
|
|
4713
|
-
case "Chamfer":
|
|
4714
|
-
case "Shell": return rebuildFeature(n, pred, repl, memo);
|
|
4715
|
-
}
|
|
4716
|
-
}
|
|
4717
|
-
function rebuildFeature(n, pred, repl, memo) {
|
|
4718
|
-
switch (n.kind) {
|
|
4719
|
-
case "Extrude": return extrude$1(walk(n.profile, pred, repl, memo), n.vector);
|
|
4720
|
-
case "Revolve": return revolve$1(walk(n.profile, pred, repl, memo), n.angle, {
|
|
4721
|
-
axis: n.axis,
|
|
4722
|
-
at: n.at
|
|
4723
|
-
});
|
|
4724
|
-
case "Loft": return loft$1(n.sections.map((s) => walk(s, pred, repl, memo)), { ruled: n.ruled });
|
|
4725
|
-
case "Sweep": return sweep$2(walk(n.profile, pred, repl, memo), walk(n.spine, pred, repl, memo), { frenet: n.frenet });
|
|
4726
|
-
case "Color": return color(walk(n.target, pred, repl, memo), [...n.color]);
|
|
4727
|
-
case "Fillet": return fillet$1(walk(n.target, pred, repl, memo), n.ref, n.radius);
|
|
4728
|
-
case "Chamfer": return chamfer$1(walk(n.target, pred, repl, memo), n.ref, n.distance);
|
|
4729
|
-
case "Shell": return shell$1(walk(n.target, pred, repl, memo), n.refs, n.thickness);
|
|
4730
|
-
}
|
|
4731
|
-
}
|
|
4732
|
-
/** Visits each DISTINCT node once (identity-deduplicated), so a shared
|
|
4733
|
-
* subtree is reported once and a self-referencing DAG walks in linear time. */
|
|
4734
|
-
function forEachNode(root, fn) {
|
|
4735
|
-
const seen = /* @__PURE__ */ new Set();
|
|
4736
|
-
const visit = (node) => {
|
|
4737
|
-
if (seen.has(node)) return;
|
|
4738
|
-
seen.add(node);
|
|
4739
|
-
fn(node);
|
|
4740
|
-
for (const child of childrenOf(node)) visit(child);
|
|
4741
|
-
};
|
|
4742
|
-
visit(root);
|
|
4743
|
-
}
|
|
4744
|
-
function childrenOf(n) {
|
|
4745
|
-
switch (n.kind) {
|
|
4746
|
-
case "Box":
|
|
4747
|
-
case "Sphere":
|
|
4748
|
-
case "Cylinder":
|
|
4749
|
-
case "Cone":
|
|
4750
|
-
case "Torus":
|
|
4751
|
-
case "Polygon":
|
|
4752
|
-
case "Circle":
|
|
4753
|
-
case "Line":
|
|
4754
|
-
case "Vertex":
|
|
4755
|
-
case "Empty":
|
|
4756
|
-
case "Path":
|
|
4757
|
-
case "Profile": return [];
|
|
4758
|
-
case "Fuse":
|
|
4759
|
-
case "Cut":
|
|
4760
|
-
case "Intersect": return [n.a, n.b];
|
|
4761
|
-
case "FuseAll": return n.shapes;
|
|
4762
|
-
case "CutAll": return [n.base, ...n.tools];
|
|
4763
|
-
case "Translate":
|
|
4764
|
-
case "Rotate":
|
|
4765
|
-
case "Scale":
|
|
4766
|
-
case "Mirror":
|
|
4767
|
-
case "Color":
|
|
4768
|
-
case "Fillet":
|
|
4769
|
-
case "Chamfer":
|
|
4770
|
-
case "Shell": return [n.target];
|
|
4771
|
-
case "Compound": return n.children;
|
|
4772
|
-
case "Instance": return [n.source];
|
|
4773
|
-
case "Extrude":
|
|
4774
|
-
case "Revolve": return [n.profile];
|
|
4775
|
-
case "Loft": return n.sections;
|
|
4776
|
-
case "Sweep": return [n.profile, n.spine];
|
|
4777
|
-
}
|
|
4778
|
-
}
|
|
4779
|
-
function nodeCount(root) {
|
|
4780
|
-
let n = 0;
|
|
4781
|
-
forEachNode(root, () => {
|
|
4782
|
-
n++;
|
|
4783
|
-
});
|
|
4784
|
-
return n;
|
|
4785
|
-
}
|
|
4786
|
-
//#endregion
|
|
4787
4838
|
//#region src/sketching/blueprintContourFns.ts
|
|
4788
4839
|
var EPS$1 = 1e-6;
|
|
4789
4840
|
function p2(p) {
|
|
@@ -8741,7 +8792,7 @@ var patterns_exports = /* @__PURE__ */ __exportAll({
|
|
|
8741
8792
|
//#endregion
|
|
8742
8793
|
//#region src/ns/csg.ts
|
|
8743
8794
|
var csg_exports = /* @__PURE__ */ __exportAll({
|
|
8744
|
-
CSG_VERSION: () =>
|
|
8795
|
+
CSG_VERSION: () => 8,
|
|
8745
8796
|
Evaluator: () => Evaluator,
|
|
8746
8797
|
add: () => add$1,
|
|
8747
8798
|
arbitraryClosedProfile: () => arbitraryClosedProfile,
|