brepjs 18.102.0 → 18.103.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 +43 -0
- package/dist/brepjs.js +43 -0
- package/dist/csg/builders.d.ts +3 -1
- package/dist/csg/evaluators/instance.d.ts +5 -0
- package/dist/csg/index.d.ts +2 -2
- package/dist/csg/types.d.ts +10 -1
- package/package.json +1 -1
package/dist/brepjs.cjs
CHANGED
|
@@ -5471,6 +5471,19 @@ function compound$1(children) {
|
|
|
5471
5471
|
freeParams: depsOf(...children)
|
|
5472
5472
|
};
|
|
5473
5473
|
}
|
|
5474
|
+
function instance$1(source, placements, fuse = false) {
|
|
5475
|
+
const copied = placements.map((m) => m.map((row) => [...row]));
|
|
5476
|
+
let h = fnvMixInt32(fnvMixBool(mix(startHash("Instance"), source), fuse), copied.length);
|
|
5477
|
+
for (const m of copied) for (const v of m.flat()) h = fnvMixNumber(h, v);
|
|
5478
|
+
return {
|
|
5479
|
+
kind: "Instance",
|
|
5480
|
+
source,
|
|
5481
|
+
placements: copied,
|
|
5482
|
+
fuse,
|
|
5483
|
+
structuralHash: h,
|
|
5484
|
+
freeParams: depsOf(source)
|
|
5485
|
+
};
|
|
5486
|
+
}
|
|
5474
5487
|
//#endregion
|
|
5475
5488
|
//#region src/csg/types.ts
|
|
5476
5489
|
function outputKindOf(node) {
|
|
@@ -5495,6 +5508,7 @@ function outputKindOf(node) {
|
|
|
5495
5508
|
case "Scale":
|
|
5496
5509
|
case "Mirror": return outputKindOf(node.target);
|
|
5497
5510
|
case "Compound": return "Compound";
|
|
5511
|
+
case "Instance": return node.fuse ? "Solid" : "Compound";
|
|
5498
5512
|
}
|
|
5499
5513
|
}
|
|
5500
5514
|
//#endregion
|
|
@@ -5728,6 +5742,13 @@ function evalEmpty() {
|
|
|
5728
5742
|
return require_errors.err(require_errors.computationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, "Empty: cannot materialize an Empty node directly — only valid as boolean/transform operand"));
|
|
5729
5743
|
}
|
|
5730
5744
|
//#endregion
|
|
5745
|
+
//#region src/csg/evaluators/instance.ts
|
|
5746
|
+
function evalInstance(node, ctx) {
|
|
5747
|
+
const r = ctx.evalNode(node.source);
|
|
5748
|
+
if (!r.ok) return r;
|
|
5749
|
+
return materialize(instance(r.value, node.placements), { fuse: node.fuse });
|
|
5750
|
+
}
|
|
5751
|
+
//#endregion
|
|
5731
5752
|
//#region src/csg/evaluate.ts
|
|
5732
5753
|
function dispatch(node, ctx) {
|
|
5733
5754
|
switch (node.kind) {
|
|
@@ -5751,6 +5772,7 @@ function dispatch(node, ctx) {
|
|
|
5751
5772
|
case "Scale": return evalScale(node, ctx);
|
|
5752
5773
|
case "Mirror": return evalMirror(node, ctx);
|
|
5753
5774
|
case "Compound": return evalCompound(node, ctx);
|
|
5775
|
+
case "Instance": return evalInstance(node, ctx);
|
|
5754
5776
|
}
|
|
5755
5777
|
}
|
|
5756
5778
|
function hashExprValue(h, v) {
|
|
@@ -6085,6 +6107,12 @@ function nodeToJson(n) {
|
|
|
6085
6107
|
kind: "Compound",
|
|
6086
6108
|
children: n.children.map(nodeToJson)
|
|
6087
6109
|
};
|
|
6110
|
+
if (n.kind === "Instance") return {
|
|
6111
|
+
kind: "Instance",
|
|
6112
|
+
source: nodeToJson(n.source),
|
|
6113
|
+
placements: n.placements,
|
|
6114
|
+
fuse: n.fuse
|
|
6115
|
+
};
|
|
6088
6116
|
return primitiveToJson(n) ?? booleanToJson(n) ?? transformToJson(n);
|
|
6089
6117
|
}
|
|
6090
6118
|
function bad(msg) {
|
|
@@ -6225,6 +6253,7 @@ function readNode(j) {
|
|
|
6225
6253
|
case "Scale":
|
|
6226
6254
|
case "Mirror": return readTransform(kind, j);
|
|
6227
6255
|
case "Compound": return readCompound(j);
|
|
6256
|
+
case "Instance": return readInstance(j);
|
|
6228
6257
|
default: return bad(`unknown node kind: ${String(kind)}`);
|
|
6229
6258
|
}
|
|
6230
6259
|
}
|
|
@@ -6383,6 +6412,16 @@ function readCompound(j) {
|
|
|
6383
6412
|
const children = readNodeArray(j["children"], "Compound.children");
|
|
6384
6413
|
return children.ok ? require_errors.ok(compound$1(children.value)) : children;
|
|
6385
6414
|
}
|
|
6415
|
+
function isMatrix4x4(v) {
|
|
6416
|
+
return Array.isArray(v) && v.length === 4 && v.every((row) => Array.isArray(row) && row.length === 4 && row.every(isNumber$1));
|
|
6417
|
+
}
|
|
6418
|
+
function readInstance(j) {
|
|
6419
|
+
const source = readNode(j["source"]);
|
|
6420
|
+
if (!source.ok) return source;
|
|
6421
|
+
const placements = j["placements"];
|
|
6422
|
+
if (!Array.isArray(placements) || !placements.every(isMatrix4x4)) return bad("Instance.placements must be an array of 4x4 number matrices");
|
|
6423
|
+
return require_errors.ok(instance$1(source.value, placements, j["fuse"] === true));
|
|
6424
|
+
}
|
|
6386
6425
|
//#endregion
|
|
6387
6426
|
//#region src/csg/optimize.ts
|
|
6388
6427
|
function optimize(node) {
|
|
@@ -6479,6 +6518,7 @@ function optimizeNode(n) {
|
|
|
6479
6518
|
at: n.at ? foldExpr(n.at) : void 0
|
|
6480
6519
|
});
|
|
6481
6520
|
case "Compound": return compound$1(n.children.map(optimizeNode).filter((c) => c.kind !== "Empty"));
|
|
6521
|
+
case "Instance": return instance$1(optimizeNode(n.source), n.placements, n.fuse);
|
|
6482
6522
|
}
|
|
6483
6523
|
}
|
|
6484
6524
|
function optimizeFuse(a, b, tol) {
|
|
@@ -6568,6 +6608,7 @@ function rebuildChildren(n, pred, repl) {
|
|
|
6568
6608
|
at: n.at
|
|
6569
6609
|
});
|
|
6570
6610
|
case "Compound": return compound$1(n.children.map((c) => walk(c, pred, repl)));
|
|
6611
|
+
case "Instance": return instance$1(walk(n.source, pred, repl), n.placements, n.fuse);
|
|
6571
6612
|
}
|
|
6572
6613
|
}
|
|
6573
6614
|
function forEachNode(root, fn) {
|
|
@@ -6596,6 +6637,7 @@ function childrenOf(n) {
|
|
|
6596
6637
|
case "Scale":
|
|
6597
6638
|
case "Mirror": return [n.target];
|
|
6598
6639
|
case "Compound": return n.children;
|
|
6640
|
+
case "Instance": return [n.source];
|
|
6599
6641
|
}
|
|
6600
6642
|
}
|
|
6601
6643
|
function nodeCount(root) {
|
|
@@ -6632,6 +6674,7 @@ var csg_exports = /* @__PURE__ */ require_textBlueprints.__exportAll({
|
|
|
6632
6674
|
fromJSON: () => fromJSON,
|
|
6633
6675
|
fuse: () => fuse$1,
|
|
6634
6676
|
fuseAll: () => fuseAll$1,
|
|
6677
|
+
instance: () => instance$1,
|
|
6635
6678
|
intersect: () => intersect$1,
|
|
6636
6679
|
line: () => line$1,
|
|
6637
6680
|
mirror: () => mirror$1,
|
package/dist/brepjs.js
CHANGED
|
@@ -5474,6 +5474,19 @@ function compound$1(children) {
|
|
|
5474
5474
|
freeParams: depsOf(...children)
|
|
5475
5475
|
};
|
|
5476
5476
|
}
|
|
5477
|
+
function instance$1(source, placements, fuse = false) {
|
|
5478
|
+
const copied = placements.map((m) => m.map((row) => [...row]));
|
|
5479
|
+
let h = fnvMixInt32(fnvMixBool(mix(startHash("Instance"), source), fuse), copied.length);
|
|
5480
|
+
for (const m of copied) for (const v of m.flat()) h = fnvMixNumber(h, v);
|
|
5481
|
+
return {
|
|
5482
|
+
kind: "Instance",
|
|
5483
|
+
source,
|
|
5484
|
+
placements: copied,
|
|
5485
|
+
fuse,
|
|
5486
|
+
structuralHash: h,
|
|
5487
|
+
freeParams: depsOf(source)
|
|
5488
|
+
};
|
|
5489
|
+
}
|
|
5477
5490
|
//#endregion
|
|
5478
5491
|
//#region src/csg/types.ts
|
|
5479
5492
|
function outputKindOf(node) {
|
|
@@ -5498,6 +5511,7 @@ function outputKindOf(node) {
|
|
|
5498
5511
|
case "Scale":
|
|
5499
5512
|
case "Mirror": return outputKindOf(node.target);
|
|
5500
5513
|
case "Compound": return "Compound";
|
|
5514
|
+
case "Instance": return node.fuse ? "Solid" : "Compound";
|
|
5501
5515
|
}
|
|
5502
5516
|
}
|
|
5503
5517
|
//#endregion
|
|
@@ -5731,6 +5745,13 @@ function evalEmpty() {
|
|
|
5731
5745
|
return err(computationError(BrepErrorCode.NULL_SHAPE_INPUT, "Empty: cannot materialize an Empty node directly — only valid as boolean/transform operand"));
|
|
5732
5746
|
}
|
|
5733
5747
|
//#endregion
|
|
5748
|
+
//#region src/csg/evaluators/instance.ts
|
|
5749
|
+
function evalInstance(node, ctx) {
|
|
5750
|
+
const r = ctx.evalNode(node.source);
|
|
5751
|
+
if (!r.ok) return r;
|
|
5752
|
+
return materialize(instance(r.value, node.placements), { fuse: node.fuse });
|
|
5753
|
+
}
|
|
5754
|
+
//#endregion
|
|
5734
5755
|
//#region src/csg/evaluate.ts
|
|
5735
5756
|
function dispatch(node, ctx) {
|
|
5736
5757
|
switch (node.kind) {
|
|
@@ -5754,6 +5775,7 @@ function dispatch(node, ctx) {
|
|
|
5754
5775
|
case "Scale": return evalScale(node, ctx);
|
|
5755
5776
|
case "Mirror": return evalMirror(node, ctx);
|
|
5756
5777
|
case "Compound": return evalCompound(node, ctx);
|
|
5778
|
+
case "Instance": return evalInstance(node, ctx);
|
|
5757
5779
|
}
|
|
5758
5780
|
}
|
|
5759
5781
|
function hashExprValue(h, v) {
|
|
@@ -6088,6 +6110,12 @@ function nodeToJson(n) {
|
|
|
6088
6110
|
kind: "Compound",
|
|
6089
6111
|
children: n.children.map(nodeToJson)
|
|
6090
6112
|
};
|
|
6113
|
+
if (n.kind === "Instance") return {
|
|
6114
|
+
kind: "Instance",
|
|
6115
|
+
source: nodeToJson(n.source),
|
|
6116
|
+
placements: n.placements,
|
|
6117
|
+
fuse: n.fuse
|
|
6118
|
+
};
|
|
6091
6119
|
return primitiveToJson(n) ?? booleanToJson(n) ?? transformToJson(n);
|
|
6092
6120
|
}
|
|
6093
6121
|
function bad(msg) {
|
|
@@ -6228,6 +6256,7 @@ function readNode(j) {
|
|
|
6228
6256
|
case "Scale":
|
|
6229
6257
|
case "Mirror": return readTransform(kind, j);
|
|
6230
6258
|
case "Compound": return readCompound(j);
|
|
6259
|
+
case "Instance": return readInstance(j);
|
|
6231
6260
|
default: return bad(`unknown node kind: ${String(kind)}`);
|
|
6232
6261
|
}
|
|
6233
6262
|
}
|
|
@@ -6386,6 +6415,16 @@ function readCompound(j) {
|
|
|
6386
6415
|
const children = readNodeArray(j["children"], "Compound.children");
|
|
6387
6416
|
return children.ok ? ok(compound$1(children.value)) : children;
|
|
6388
6417
|
}
|
|
6418
|
+
function isMatrix4x4(v) {
|
|
6419
|
+
return Array.isArray(v) && v.length === 4 && v.every((row) => Array.isArray(row) && row.length === 4 && row.every(isNumber$1));
|
|
6420
|
+
}
|
|
6421
|
+
function readInstance(j) {
|
|
6422
|
+
const source = readNode(j["source"]);
|
|
6423
|
+
if (!source.ok) return source;
|
|
6424
|
+
const placements = j["placements"];
|
|
6425
|
+
if (!Array.isArray(placements) || !placements.every(isMatrix4x4)) return bad("Instance.placements must be an array of 4x4 number matrices");
|
|
6426
|
+
return ok(instance$1(source.value, placements, j["fuse"] === true));
|
|
6427
|
+
}
|
|
6389
6428
|
//#endregion
|
|
6390
6429
|
//#region src/csg/optimize.ts
|
|
6391
6430
|
function optimize(node) {
|
|
@@ -6482,6 +6521,7 @@ function optimizeNode(n) {
|
|
|
6482
6521
|
at: n.at ? foldExpr(n.at) : void 0
|
|
6483
6522
|
});
|
|
6484
6523
|
case "Compound": return compound$1(n.children.map(optimizeNode).filter((c) => c.kind !== "Empty"));
|
|
6524
|
+
case "Instance": return instance$1(optimizeNode(n.source), n.placements, n.fuse);
|
|
6485
6525
|
}
|
|
6486
6526
|
}
|
|
6487
6527
|
function optimizeFuse(a, b, tol) {
|
|
@@ -6571,6 +6611,7 @@ function rebuildChildren(n, pred, repl) {
|
|
|
6571
6611
|
at: n.at
|
|
6572
6612
|
});
|
|
6573
6613
|
case "Compound": return compound$1(n.children.map((c) => walk(c, pred, repl)));
|
|
6614
|
+
case "Instance": return instance$1(walk(n.source, pred, repl), n.placements, n.fuse);
|
|
6574
6615
|
}
|
|
6575
6616
|
}
|
|
6576
6617
|
function forEachNode(root, fn) {
|
|
@@ -6599,6 +6640,7 @@ function childrenOf(n) {
|
|
|
6599
6640
|
case "Scale":
|
|
6600
6641
|
case "Mirror": return [n.target];
|
|
6601
6642
|
case "Compound": return n.children;
|
|
6643
|
+
case "Instance": return [n.source];
|
|
6602
6644
|
}
|
|
6603
6645
|
}
|
|
6604
6646
|
function nodeCount(root) {
|
|
@@ -6635,6 +6677,7 @@ var csg_exports = /* @__PURE__ */ __exportAll({
|
|
|
6635
6677
|
fromJSON: () => fromJSON,
|
|
6636
6678
|
fuse: () => fuse$1,
|
|
6637
6679
|
fuseAll: () => fuseAll$1,
|
|
6680
|
+
instance: () => instance$1,
|
|
6638
6681
|
intersect: () => intersect$1,
|
|
6639
6682
|
line: () => line$1,
|
|
6640
6683
|
mirror: () => mirror$1,
|
package/dist/csg/builders.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ScalarInput, Vec3Input } from './expressions.js';
|
|
2
|
-
import {
|
|
2
|
+
import { Matrix4x4 } from '../core/types.js';
|
|
3
|
+
import { BoxNode, SphereNode, CylinderNode, ConeNode, TorusNode, PolygonNode, CircleNode, LineNode, VertexLitNode, EmptyNode, FuseNode, CutNode, IntersectNode, FuseAllNode, CutAllNode, TranslateNode, RotateNode, ScaleNode, MirrorNode, CompoundNode, InstanceNode, IRNode, SolidNode, FaceNode, EdgeNode, VertexNode } from './types.js';
|
|
3
4
|
export declare function box(x: ScalarInput, y: ScalarInput, z: ScalarInput): BoxNode;
|
|
4
5
|
export declare function sphere(radius: ScalarInput): SphereNode;
|
|
5
6
|
export declare function cylinder(radius: ScalarInput, height: ScalarInput): CylinderNode;
|
|
@@ -33,4 +34,5 @@ export interface MirrorOptions {
|
|
|
33
34
|
}
|
|
34
35
|
export declare function mirror(target: IRNode, options?: MirrorOptions): MirrorNode;
|
|
35
36
|
export declare function compound(children: ReadonlyArray<IRNode>): CompoundNode;
|
|
37
|
+
export declare function instance(source: IRNode, placements: ReadonlyArray<Matrix4x4>, fuse?: boolean): InstanceNode;
|
|
36
38
|
export type { FaceNode, EdgeNode, VertexNode, SolidNode };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Result } from '../../core/result.js';
|
|
2
|
+
import { AnyShape, Dimension } from '../../core/shapeTypes.js';
|
|
3
|
+
import { InstanceNode } from '../types.js';
|
|
4
|
+
import { EvalContext } from './context.js';
|
|
5
|
+
export declare function evalInstance(node: InstanceNode, ctx: EvalContext): Result<AnyShape<Dimension>>;
|
package/dist/csg/index.d.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* parameterize via named expression bindings; evaluate against the active
|
|
6
6
|
* kernel with subtree-level cache reuse for incremental parametric edits.
|
|
7
7
|
*/
|
|
8
|
-
export { box, sphere, cylinder, cone, torus, polygon, circle, line, vertex, emptySolid, emptyFace, emptyWire, fuse, cut, intersect, fuseAll, cutAll, translate, rotate, scale, mirror, compound, type RotateOptions, type ScaleOptions, type MirrorOptions, } from './builders.js';
|
|
8
|
+
export { box, sphere, cylinder, cone, torus, polygon, circle, line, vertex, emptySolid, emptyFace, emptyWire, fuse, cut, intersect, fuseAll, cutAll, translate, rotate, scale, mirror, compound, instance, type RotateOptions, type ScaleOptions, type MirrorOptions, } from './builders.js';
|
|
9
9
|
export { numLit, vec3Lit, vec2Lit, param, binOp, unaryOp, component, buildVec, add, mul, asScalarExpr, asVec3Expr, asVec2Expr, type Expr, type ExprValue, type Env, type ScalarInput, type Vec3Input, type Vec2Input, type BinaryOp, type UnaryOp, } from './expressions.js';
|
|
10
|
-
export type { IRNode, NodeKind, OutputKind, PrimitiveNode, BooleanNode, TransformIRNode, SolidNode, FaceNode, EdgeNode, VertexNode, AnyNode, } from './types.js';
|
|
10
|
+
export type { IRNode, NodeKind, OutputKind, PrimitiveNode, BooleanNode, TransformIRNode, InstanceNode, SolidNode, FaceNode, EdgeNode, VertexNode, AnyNode, } from './types.js';
|
|
11
11
|
export { outputKindOf } from './types.js';
|
|
12
12
|
export { Evaluator, withEvaluator, type EvaluatorOptions, type StepInfo, type CacheStats, } from './evaluate.js';
|
|
13
13
|
export { toJSON, fromJSON, CSG_VERSION, type CsgEnvelope } from './serialize.js';
|
package/dist/csg/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Expr } from './expressions.js';
|
|
2
|
+
import { Matrix4x4 } from '../core/types.js';
|
|
2
3
|
export type OutputKind = 'Solid' | 'Face' | 'Wire' | 'Edge' | 'Vertex' | 'Compound';
|
|
3
4
|
/** Output kinds that have a corresponding empty-shape builder + serializer. */
|
|
4
5
|
export type EmptyOutputKind = 'Solid' | 'Face' | 'Wire';
|
|
@@ -111,10 +112,18 @@ export interface CompoundNode extends IRNodeBase {
|
|
|
111
112
|
readonly kind: 'Compound';
|
|
112
113
|
readonly children: readonly IRNode[];
|
|
113
114
|
}
|
|
115
|
+
export interface InstanceNode extends IRNodeBase {
|
|
116
|
+
readonly kind: 'Instance';
|
|
117
|
+
readonly source: IRNode;
|
|
118
|
+
/** Per-instance world transforms (row-major 4x4 literals). */
|
|
119
|
+
readonly placements: readonly Matrix4x4[];
|
|
120
|
+
/** Fuse the placed copies into one solid; otherwise a Compound. */
|
|
121
|
+
readonly fuse: boolean;
|
|
122
|
+
}
|
|
114
123
|
export type PrimitiveNode = BoxNode | SphereNode | CylinderNode | ConeNode | TorusNode | PolygonNode | CircleNode | LineNode | VertexLitNode | EmptyNode;
|
|
115
124
|
export type BooleanNode = FuseNode | CutNode | IntersectNode | FuseAllNode | CutAllNode;
|
|
116
125
|
export type TransformIRNode = TranslateNode | RotateNode | ScaleNode | MirrorNode;
|
|
117
|
-
export type IRNode = PrimitiveNode | BooleanNode | TransformIRNode | CompoundNode;
|
|
126
|
+
export type IRNode = PrimitiveNode | BooleanNode | TransformIRNode | CompoundNode | InstanceNode;
|
|
118
127
|
export type NodeKind = IRNode['kind'];
|
|
119
128
|
export type AnyNode = IRNode;
|
|
120
129
|
/** Nodes that produce a 3D solid. */
|