brepjs 18.67.0 → 18.68.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 +218 -50
- package/dist/brepjs.js +216 -56
- package/dist/implicit/index.d.ts +11 -0
- package/dist/implicit/sdfFns.d.ts +59 -0
- package/dist/index.d.ts +2 -0
- package/dist/voxel/engine.d.ts +51 -0
- package/dist/voxel/fieldFns.d.ts +1 -0
- package/package.json +1 -1
package/dist/brepjs.cjs
CHANGED
|
@@ -182,7 +182,7 @@ function validateInputs(mesh, queries) {
|
|
|
182
182
|
return null;
|
|
183
183
|
}
|
|
184
184
|
/** Resolve a registered voxel engine, mapping an unregistered id to an error. */
|
|
185
|
-
function resolveEngine(id) {
|
|
185
|
+
function resolveEngine$1(id) {
|
|
186
186
|
try {
|
|
187
187
|
return require_errors.ok(getVoxel(id));
|
|
188
188
|
} catch (cause) {
|
|
@@ -199,7 +199,7 @@ function resolveEngine(id) {
|
|
|
199
199
|
function windingNumbers(mesh, queries, id) {
|
|
200
200
|
const invalid = validateInputs(mesh, queries);
|
|
201
201
|
if (invalid) return require_errors.err(invalid);
|
|
202
|
-
const engine = resolveEngine(id);
|
|
202
|
+
const engine = resolveEngine$1(id);
|
|
203
203
|
if (require_errors.isErr(engine)) return engine;
|
|
204
204
|
return require_errors.ok(engine.value.winding_numbers(mesh.vertices, mesh.triangles, queries));
|
|
205
205
|
}
|
|
@@ -211,15 +211,15 @@ function windingNumbers(mesh, queries, id) {
|
|
|
211
211
|
function pointsInside(mesh, queries, id) {
|
|
212
212
|
const invalid = validateInputs(mesh, queries);
|
|
213
213
|
if (invalid) return require_errors.err(invalid);
|
|
214
|
-
const engine = resolveEngine(id);
|
|
214
|
+
const engine = resolveEngine$1(id);
|
|
215
215
|
if (require_errors.isErr(engine)) return engine;
|
|
216
216
|
const flags = engine.value.points_inside(mesh.vertices, mesh.triangles, queries);
|
|
217
217
|
return require_errors.ok(Array.from(flags, (flag) => flag === 1));
|
|
218
218
|
}
|
|
219
219
|
//#endregion
|
|
220
220
|
//#region src/voxel/repairFns.ts
|
|
221
|
-
var DEFAULT_RESOLUTION$
|
|
222
|
-
var DEFAULT_PADDING$
|
|
221
|
+
var DEFAULT_RESOLUTION$4 = 48;
|
|
222
|
+
var DEFAULT_PADDING$4 = 2;
|
|
223
223
|
/**
|
|
224
224
|
* Repair a (possibly non-watertight) triangle-soup mesh into a closed surface:
|
|
225
225
|
* voxelize an FWN-signed SDF, then Surface-Nets contour it back to triangles.
|
|
@@ -232,11 +232,11 @@ function repairMesh(mesh, opts, id) {
|
|
|
232
232
|
const invalid = validateMesh(mesh);
|
|
233
233
|
if (invalid) return require_errors.err(invalid);
|
|
234
234
|
if (mesh.vertices.length === 0 || mesh.triangles.length === 0) return require_errors.err(require_errors.validationError("VOXEL_EMPTY_MESH", "repairMesh requires a non-empty triangle mesh."));
|
|
235
|
-
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$
|
|
236
|
-
const padding = opts?.padding ?? DEFAULT_PADDING$
|
|
235
|
+
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$4;
|
|
236
|
+
const padding = opts?.padding ?? DEFAULT_PADDING$4;
|
|
237
237
|
if (!Number.isInteger(resolution) || resolution < 1) return require_errors.err(require_errors.validationError("VOXEL_INVALID_RESOLUTION", "resolution must be an integer >= 1."));
|
|
238
238
|
if (!Number.isInteger(padding) || padding < 1) return require_errors.err(require_errors.validationError("VOXEL_INVALID_PADDING", "padding must be an integer >= 1."));
|
|
239
|
-
const engine = resolveEngine(id);
|
|
239
|
+
const engine = resolveEngine$1(id);
|
|
240
240
|
if (require_errors.isErr(engine)) return engine;
|
|
241
241
|
try {
|
|
242
242
|
try {
|
|
@@ -286,16 +286,16 @@ function shapeToMeshInput(shape, deflection = DEFAULT_DEFLECTION) {
|
|
|
286
286
|
}
|
|
287
287
|
//#endregion
|
|
288
288
|
//#region src/voxel/meshOpsFns.ts
|
|
289
|
-
var DEFAULT_RESOLUTION$
|
|
290
|
-
var DEFAULT_PADDING$
|
|
289
|
+
var DEFAULT_RESOLUTION$3 = 48;
|
|
290
|
+
var DEFAULT_PADDING$3 = 2;
|
|
291
291
|
var BOOLEAN_OP_CODES$1 = {
|
|
292
292
|
union: 0,
|
|
293
293
|
intersection: 1,
|
|
294
294
|
difference: 2
|
|
295
295
|
};
|
|
296
|
-
function resolveGridParams$
|
|
297
|
-
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$
|
|
298
|
-
const padding = opts?.padding ?? DEFAULT_PADDING$
|
|
296
|
+
function resolveGridParams$2(opts) {
|
|
297
|
+
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$3;
|
|
298
|
+
const padding = opts?.padding ?? DEFAULT_PADDING$3;
|
|
299
299
|
if (!Number.isInteger(resolution) || resolution < 1) return require_errors.err(require_errors.validationError("VOXEL_INVALID_RESOLUTION", "resolution must be an integer >= 1."));
|
|
300
300
|
if (!Number.isInteger(padding) || padding < 1) return require_errors.err(require_errors.validationError("VOXEL_INVALID_PADDING", "padding must be an integer >= 1."));
|
|
301
301
|
return require_errors.ok({
|
|
@@ -330,9 +330,9 @@ function offsetMesh(mesh, distance, opts, id) {
|
|
|
330
330
|
if (invalid) return require_errors.err(invalid);
|
|
331
331
|
if (mesh.vertices.length === 0 || mesh.triangles.length === 0) return require_errors.err(require_errors.validationError("VOXEL_EMPTY_MESH", "offsetMesh requires a non-empty triangle mesh."));
|
|
332
332
|
if (!Number.isFinite(distance)) return require_errors.err(require_errors.validationError("VOXEL_INVALID_DISTANCE", "distance must be a finite number."));
|
|
333
|
-
const params = resolveGridParams$
|
|
333
|
+
const params = resolveGridParams$2(opts);
|
|
334
334
|
if (require_errors.isErr(params)) return params;
|
|
335
|
-
const engine = resolveEngine(id);
|
|
335
|
+
const engine = resolveEngine$1(id);
|
|
336
336
|
if (require_errors.isErr(engine)) return engine;
|
|
337
337
|
try {
|
|
338
338
|
try {
|
|
@@ -359,9 +359,9 @@ function shellMesh(mesh, thickness, opts, id) {
|
|
|
359
359
|
if (invalid) return require_errors.err(invalid);
|
|
360
360
|
if (mesh.vertices.length === 0 || mesh.triangles.length === 0) return require_errors.err(require_errors.validationError("VOXEL_EMPTY_MESH", "shellMesh requires a non-empty triangle mesh."));
|
|
361
361
|
if (!Number.isFinite(thickness) || thickness <= 0) return require_errors.err(require_errors.validationError("VOXEL_INVALID_THICKNESS", "thickness must be a finite number > 0."));
|
|
362
|
-
const params = resolveGridParams$
|
|
362
|
+
const params = resolveGridParams$2(opts);
|
|
363
363
|
if (require_errors.isErr(params)) return params;
|
|
364
|
-
const engine = resolveEngine(id);
|
|
364
|
+
const engine = resolveEngine$1(id);
|
|
365
365
|
if (require_errors.isErr(engine)) return engine;
|
|
366
366
|
try {
|
|
367
367
|
try {
|
|
@@ -391,9 +391,9 @@ function voxelBoolean(a, b, op, opts, id) {
|
|
|
391
391
|
if (a.vertices.length === 0 || a.triangles.length === 0) return require_errors.err(require_errors.validationError("VOXEL_EMPTY_MESH", "voxelBoolean requires a non-empty mesh for operand A."));
|
|
392
392
|
if (b.vertices.length === 0 || b.triangles.length === 0) return require_errors.err(require_errors.validationError("VOXEL_EMPTY_MESH", "voxelBoolean requires a non-empty mesh for operand B."));
|
|
393
393
|
const opCode = BOOLEAN_OP_CODES$1[op];
|
|
394
|
-
const params = resolveGridParams$
|
|
394
|
+
const params = resolveGridParams$2(opts);
|
|
395
395
|
if (require_errors.isErr(params)) return params;
|
|
396
|
-
const engine = resolveEngine(id);
|
|
396
|
+
const engine = resolveEngine$1(id);
|
|
397
397
|
if (require_errors.isErr(engine)) return engine;
|
|
398
398
|
try {
|
|
399
399
|
try {
|
|
@@ -442,16 +442,16 @@ function voxelBooleanShapes(a, b, op, opts, id) {
|
|
|
442
442
|
}
|
|
443
443
|
//#endregion
|
|
444
444
|
//#region src/voxel/fieldFns.ts
|
|
445
|
-
var DEFAULT_RESOLUTION$
|
|
446
|
-
var DEFAULT_PADDING$
|
|
445
|
+
var DEFAULT_RESOLUTION$2 = 48;
|
|
446
|
+
var DEFAULT_PADDING$2 = 2;
|
|
447
447
|
var BOOLEAN_OP_CODES = {
|
|
448
448
|
union: 0,
|
|
449
449
|
intersection: 1,
|
|
450
450
|
difference: 2
|
|
451
451
|
};
|
|
452
|
-
function resolveGridParams(opts) {
|
|
453
|
-
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$
|
|
454
|
-
const padding = opts?.padding ?? DEFAULT_PADDING$
|
|
452
|
+
function resolveGridParams$1(opts) {
|
|
453
|
+
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$2;
|
|
454
|
+
const padding = opts?.padding ?? DEFAULT_PADDING$2;
|
|
455
455
|
if (!Number.isInteger(resolution) || resolution < 1) return require_errors.err(require_errors.validationError("VOXEL_INVALID_RESOLUTION", "resolution must be an integer >= 1."));
|
|
456
456
|
if (!Number.isInteger(padding) || padding < 1) return require_errors.err(require_errors.validationError("VOXEL_INVALID_PADDING", "padding must be an integer >= 1."));
|
|
457
457
|
return require_errors.ok({
|
|
@@ -501,6 +501,9 @@ function fieldDeletable(raw) {
|
|
|
501
501
|
}
|
|
502
502
|
};
|
|
503
503
|
}
|
|
504
|
+
function makeFieldHandle(raw) {
|
|
505
|
+
return makeHandle(raw);
|
|
506
|
+
}
|
|
504
507
|
function makeHandle(raw) {
|
|
505
508
|
const inner = require_shapeTypes.createKernelHandle(fieldDeletable(raw));
|
|
506
509
|
const handle = {
|
|
@@ -557,9 +560,9 @@ function voxelField(mesh, opts, id) {
|
|
|
557
560
|
const invalid = validateMesh(mesh);
|
|
558
561
|
if (invalid) return require_errors.err(invalid);
|
|
559
562
|
if (mesh.vertices.length === 0 || mesh.triangles.length === 0) return require_errors.err(require_errors.validationError("VOXEL_EMPTY_MESH", "voxelField requires a non-empty triangle mesh."));
|
|
560
|
-
const params = resolveGridParams(opts);
|
|
563
|
+
const params = resolveGridParams$1(opts);
|
|
561
564
|
if (require_errors.isErr(params)) return params;
|
|
562
|
-
const engine = resolveEngine(id);
|
|
565
|
+
const engine = resolveEngine$1(id);
|
|
563
566
|
if (require_errors.isErr(engine)) return engine;
|
|
564
567
|
try {
|
|
565
568
|
return require_errors.ok(makeHandle(new engine.value.VoxelField(mesh.vertices, mesh.triangles, params.value.resolution, params.value.padding)));
|
|
@@ -586,9 +589,9 @@ function voxelBooleanField(a, b, op, opts, id) {
|
|
|
586
589
|
if (invalidB) return require_errors.err(invalidB);
|
|
587
590
|
if (a.vertices.length === 0 || a.triangles.length === 0) return require_errors.err(require_errors.validationError("VOXEL_EMPTY_MESH", "voxelBooleanField requires a non-empty mesh for operand A."));
|
|
588
591
|
if (b.vertices.length === 0 || b.triangles.length === 0) return require_errors.err(require_errors.validationError("VOXEL_EMPTY_MESH", "voxelBooleanField requires a non-empty mesh for operand B."));
|
|
589
|
-
const params = resolveGridParams(opts);
|
|
592
|
+
const params = resolveGridParams$1(opts);
|
|
590
593
|
if (require_errors.isErr(params)) return params;
|
|
591
|
-
const engine = resolveEngine(id);
|
|
594
|
+
const engine = resolveEngine$1(id);
|
|
592
595
|
if (require_errors.isErr(engine)) return engine;
|
|
593
596
|
try {
|
|
594
597
|
return require_errors.ok(makeHandle(engine.value.VoxelField.boolean_of(a.vertices, a.triangles, b.vertices, b.triangles, BOOLEAN_OP_CODES[op], params.value.resolution, params.value.padding)));
|
|
@@ -698,6 +701,163 @@ function voxelBooleanFieldShapes(a, b, op, opts, id) {
|
|
|
698
701
|
return voxelBooleanField(meshA.value, meshB.value, op, opts, id);
|
|
699
702
|
}
|
|
700
703
|
//#endregion
|
|
704
|
+
//#region src/implicit/sdfFns.ts
|
|
705
|
+
var DEFAULT_RESOLUTION$1 = 48;
|
|
706
|
+
var DEFAULT_PADDING$1 = 2;
|
|
707
|
+
function resolveEngine(id) {
|
|
708
|
+
try {
|
|
709
|
+
return require_errors.ok(getVoxel(id));
|
|
710
|
+
} catch (cause) {
|
|
711
|
+
return require_errors.err(require_errors.moduleInitError("VOXEL_NOT_INITIALIZED", cause instanceof Error ? cause.message : "voxel engine not initialized", cause));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
function resolveGridParams(opts) {
|
|
715
|
+
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$1;
|
|
716
|
+
const padding = opts?.padding ?? DEFAULT_PADDING$1;
|
|
717
|
+
if (!Number.isInteger(resolution) || resolution < 1) return require_errors.err(require_errors.validationError("SDF_INVALID_RESOLUTION", "resolution must be an integer >= 1."));
|
|
718
|
+
if (!Number.isInteger(padding) || padding < 1) return require_errors.err(require_errors.validationError("SDF_INVALID_PADDING", "padding must be an integer >= 1."));
|
|
719
|
+
return require_errors.ok({
|
|
720
|
+
resolution,
|
|
721
|
+
padding
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
function sdfDeletable(raw) {
|
|
725
|
+
return {
|
|
726
|
+
raw,
|
|
727
|
+
delete() {
|
|
728
|
+
raw.free();
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
function makeSdfHandle(raw) {
|
|
733
|
+
const inner = require_shapeTypes.createKernelHandle(sdfDeletable(raw));
|
|
734
|
+
return {
|
|
735
|
+
get value() {
|
|
736
|
+
return inner.value.raw;
|
|
737
|
+
},
|
|
738
|
+
get disposed() {
|
|
739
|
+
return inner.disposed;
|
|
740
|
+
},
|
|
741
|
+
[Symbol.dispose]() {
|
|
742
|
+
inner[Symbol.dispose]();
|
|
743
|
+
},
|
|
744
|
+
union(other) {
|
|
745
|
+
return makeSdfHandle(this.value.union(other.value));
|
|
746
|
+
},
|
|
747
|
+
intersection(other) {
|
|
748
|
+
return makeSdfHandle(this.value.intersection(other.value));
|
|
749
|
+
},
|
|
750
|
+
difference(other) {
|
|
751
|
+
return makeSdfHandle(this.value.difference(other.value));
|
|
752
|
+
},
|
|
753
|
+
smoothUnion(other, k) {
|
|
754
|
+
return makeSdfHandle(this.value.smooth_union(other.value, k));
|
|
755
|
+
},
|
|
756
|
+
smoothIntersection(other, k) {
|
|
757
|
+
return makeSdfHandle(this.value.smooth_intersection(other.value, k));
|
|
758
|
+
},
|
|
759
|
+
smoothDifference(other, k) {
|
|
760
|
+
return makeSdfHandle(this.value.smooth_difference(other.value, k));
|
|
761
|
+
},
|
|
762
|
+
offset(distance) {
|
|
763
|
+
return makeSdfHandle(this.value.offset(distance));
|
|
764
|
+
},
|
|
765
|
+
round(radius) {
|
|
766
|
+
return makeSdfHandle(this.value.round(radius));
|
|
767
|
+
},
|
|
768
|
+
shell(thickness) {
|
|
769
|
+
return makeSdfHandle(this.value.shell(thickness));
|
|
770
|
+
},
|
|
771
|
+
onion(thickness) {
|
|
772
|
+
return makeSdfHandle(this.value.onion(thickness));
|
|
773
|
+
},
|
|
774
|
+
translate(x, y, z) {
|
|
775
|
+
return makeSdfHandle(this.value.translate(x, y, z));
|
|
776
|
+
},
|
|
777
|
+
rotate(ax, ay, az, angle) {
|
|
778
|
+
return makeSdfHandle(this.value.rotate(ax, ay, az, angle));
|
|
779
|
+
},
|
|
780
|
+
scale(s) {
|
|
781
|
+
return makeSdfHandle(this.value.scale(s));
|
|
782
|
+
},
|
|
783
|
+
rasterize(opts) {
|
|
784
|
+
return rasterizeField(this.value, opts);
|
|
785
|
+
},
|
|
786
|
+
rasterizeIn(bounds, opts) {
|
|
787
|
+
return rasterizeFieldIn(this.value, bounds, opts);
|
|
788
|
+
}
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
function rasterizeField(sdf, opts) {
|
|
792
|
+
const params = resolveGridParams(opts);
|
|
793
|
+
if (require_errors.isErr(params)) return params;
|
|
794
|
+
try {
|
|
795
|
+
return require_errors.ok(makeFieldHandle(sdf.rasterize(params.value.resolution, params.value.padding)));
|
|
796
|
+
} catch (cause) {
|
|
797
|
+
return rasterizeError(cause);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
function rasterizeFieldIn(sdf, bounds, opts) {
|
|
801
|
+
const params = resolveGridParams(opts);
|
|
802
|
+
if (require_errors.isErr(params)) return params;
|
|
803
|
+
const invalid = validateBounds(bounds);
|
|
804
|
+
if (invalid) return require_errors.err(invalid);
|
|
805
|
+
try {
|
|
806
|
+
return require_errors.ok(makeFieldHandle(sdf.rasterize_in(bounds.min[0], bounds.min[1], bounds.min[2], bounds.max[0], bounds.max[1], bounds.max[2], params.value.resolution, params.value.padding)));
|
|
807
|
+
} catch (cause) {
|
|
808
|
+
return rasterizeError(cause);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
function rasterizeError(cause) {
|
|
812
|
+
return require_errors.err(require_errors.computationError("SDF_RASTERIZE_FAILED", cause instanceof Error ? cause.message : "SDF rasterization failed (grid too large?).", cause));
|
|
813
|
+
}
|
|
814
|
+
function validateBounds(bounds) {
|
|
815
|
+
if (![...bounds.min, ...bounds.max].every((v) => Number.isFinite(v))) return require_errors.validationError("SDF_INVALID_BOUNDS", "bounds must be finite numbers.");
|
|
816
|
+
for (let axis = 0; axis < 3; axis++) if (bounds.max[axis] <= bounds.min[axis]) return require_errors.validationError("SDF_INVALID_BOUNDS", "bounds max must exceed min on every axis.");
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
function build(make, id) {
|
|
820
|
+
const engine = resolveEngine(id);
|
|
821
|
+
if (require_errors.isErr(engine)) return engine;
|
|
822
|
+
try {
|
|
823
|
+
return require_errors.ok(makeSdfHandle(make(engine.value)));
|
|
824
|
+
} catch (cause) {
|
|
825
|
+
return require_errors.err(require_errors.computationError("SDF_BUILD_FAILED", cause instanceof Error ? cause.message : "SDF primitive construction failed.", cause));
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
/** A sphere of radius `r`, centered at the origin. */
|
|
829
|
+
function sphere(r, id) {
|
|
830
|
+
return build((e) => e.Sdf.sphere(r), id);
|
|
831
|
+
}
|
|
832
|
+
/** An axis-aligned box of half-extents `(hx, hy, hz)`, centered at the origin. */
|
|
833
|
+
function box$1(hx, hy, hz, id) {
|
|
834
|
+
return build((e) => e.Sdf.box_(hx, hy, hz), id);
|
|
835
|
+
}
|
|
836
|
+
/** A box with rounded edges of radius `r`. */
|
|
837
|
+
function roundedBox(hx, hy, hz, r, id) {
|
|
838
|
+
return build((e) => e.Sdf.rounded_box(hx, hy, hz, r), id);
|
|
839
|
+
}
|
|
840
|
+
/** A capped cylinder, axis +Z, radius `r`, total height `h`, centered at origin. */
|
|
841
|
+
function cylinder$1(r, h, id) {
|
|
842
|
+
return build((e) => e.Sdf.cylinder(r, h), id);
|
|
843
|
+
}
|
|
844
|
+
/** A capped cone centered at the origin: base radius `r` at z = −h/2 tapering to an apex at z = +h/2. */
|
|
845
|
+
function cone$1(r, h, id) {
|
|
846
|
+
return build((e) => e.Sdf.cone(r, h), id);
|
|
847
|
+
}
|
|
848
|
+
/** A capsule: a line segment `a`→`b` of radius `r`. */
|
|
849
|
+
function capsule(a, b, r, id) {
|
|
850
|
+
return build((e) => e.Sdf.capsule(a[0], a[1], a[2], b[0], b[1], b[2], r), id);
|
|
851
|
+
}
|
|
852
|
+
/** A torus in the XY plane (axis +Z): a `minor`-radius tube on a `major` circle. */
|
|
853
|
+
function torus(major, minor, id) {
|
|
854
|
+
return build((e) => e.Sdf.torus(major, minor), id);
|
|
855
|
+
}
|
|
856
|
+
/** A half-space: the plane through `h·n` with outward normal `n` (normalized). */
|
|
857
|
+
function plane(n, h, id) {
|
|
858
|
+
return build((e) => e.Sdf.plane(n[0], n[1], n[2], h), id);
|
|
859
|
+
}
|
|
860
|
+
//#endregion
|
|
701
861
|
//#region src/lattice/latticeFns.ts
|
|
702
862
|
var LATTICE_TAGS = {
|
|
703
863
|
gyroid: 0,
|
|
@@ -751,7 +911,7 @@ function latticeInfill(mesh, opts, id) {
|
|
|
751
911
|
if (mesh.vertices.length === 0 || mesh.triangles.length === 0) return require_errors.err(require_errors.validationError("LATTICE_EMPTY_MESH", "latticeInfill requires a non-empty triangle mesh."));
|
|
752
912
|
const resolved = validateOptions(opts);
|
|
753
913
|
if (require_errors.isErr(resolved)) return resolved;
|
|
754
|
-
const engine = resolveEngine(id);
|
|
914
|
+
const engine = resolveEngine$1(id);
|
|
755
915
|
if (require_errors.isErr(engine)) return engine;
|
|
756
916
|
const { tag, period, thickness, resolution, padding } = resolved.value;
|
|
757
917
|
try {
|
|
@@ -792,7 +952,7 @@ function tpmsLattice(bounds, opts, id) {
|
|
|
792
952
|
}
|
|
793
953
|
const resolved = validateOptions(opts);
|
|
794
954
|
if (require_errors.isErr(resolved)) return resolved;
|
|
795
|
-
const engine = resolveEngine(id);
|
|
955
|
+
const engine = resolveEngine$1(id);
|
|
796
956
|
if (require_errors.isErr(engine)) return engine;
|
|
797
957
|
const { tag, period, thickness, resolution, padding } = resolved.value;
|
|
798
958
|
const [minX, minY, minZ] = bounds.min;
|
|
@@ -4461,7 +4621,7 @@ function depsOf(...sources) {
|
|
|
4461
4621
|
}
|
|
4462
4622
|
return acc.size === 0 ? EMPTY_DEPS : acc;
|
|
4463
4623
|
}
|
|
4464
|
-
function box$
|
|
4624
|
+
function box$2(x, y, z) {
|
|
4465
4625
|
const xe = asScalarExpr(x);
|
|
4466
4626
|
const ye = asScalarExpr(y);
|
|
4467
4627
|
const ze = asScalarExpr(z);
|
|
@@ -4476,7 +4636,7 @@ function box$1(x, y, z) {
|
|
|
4476
4636
|
freeParams: depsOf(xe, ye, ze)
|
|
4477
4637
|
};
|
|
4478
4638
|
}
|
|
4479
|
-
function sphere$
|
|
4639
|
+
function sphere$2(radius) {
|
|
4480
4640
|
const re = asScalarExpr(radius);
|
|
4481
4641
|
return {
|
|
4482
4642
|
kind: "Sphere",
|
|
@@ -4485,7 +4645,7 @@ function sphere$1(radius) {
|
|
|
4485
4645
|
freeParams: re.freeParams
|
|
4486
4646
|
};
|
|
4487
4647
|
}
|
|
4488
|
-
function cylinder$
|
|
4648
|
+
function cylinder$2(radius, height) {
|
|
4489
4649
|
const re = asScalarExpr(radius);
|
|
4490
4650
|
const he = asScalarExpr(height);
|
|
4491
4651
|
return {
|
|
@@ -4496,7 +4656,7 @@ function cylinder$1(radius, height) {
|
|
|
4496
4656
|
freeParams: depsOf(re, he)
|
|
4497
4657
|
};
|
|
4498
4658
|
}
|
|
4499
|
-
function cone$
|
|
4659
|
+
function cone$2(radius1, radius2, height) {
|
|
4500
4660
|
const r1 = asScalarExpr(radius1);
|
|
4501
4661
|
const r2 = asScalarExpr(radius2);
|
|
4502
4662
|
const he = asScalarExpr(height);
|
|
@@ -4511,7 +4671,7 @@ function cone$1(radius1, radius2, height) {
|
|
|
4511
4671
|
freeParams: depsOf(r1, r2, he)
|
|
4512
4672
|
};
|
|
4513
4673
|
}
|
|
4514
|
-
function torus$
|
|
4674
|
+
function torus$2(majorRadius, minorRadius) {
|
|
4515
4675
|
const ma = asScalarExpr(majorRadius);
|
|
4516
4676
|
const mi = asScalarExpr(minorRadius);
|
|
4517
4677
|
return {
|
|
@@ -5416,7 +5576,7 @@ function readSingleExpr(j, key, build) {
|
|
|
5416
5576
|
function readPrimitive(kind, j) {
|
|
5417
5577
|
switch (kind) {
|
|
5418
5578
|
case "Box": return readBox(j);
|
|
5419
|
-
case "Sphere": return readSingleExpr(j, "radius", sphere$
|
|
5579
|
+
case "Sphere": return readSingleExpr(j, "radius", sphere$2);
|
|
5420
5580
|
case "Cylinder": return readCylinder(j);
|
|
5421
5581
|
case "Cone": return readCone(j);
|
|
5422
5582
|
case "Torus": return readTorus(j);
|
|
@@ -5435,14 +5595,14 @@ function readBox(j) {
|
|
|
5435
5595
|
if (!y.ok) return y;
|
|
5436
5596
|
const z = readExpr(j["z"]);
|
|
5437
5597
|
if (!z.ok) return z;
|
|
5438
|
-
return require_errors.ok(box$
|
|
5598
|
+
return require_errors.ok(box$2(x.value, y.value, z.value));
|
|
5439
5599
|
}
|
|
5440
5600
|
function readCylinder(j) {
|
|
5441
5601
|
const r = readExpr(j["radius"]);
|
|
5442
5602
|
if (!r.ok) return r;
|
|
5443
5603
|
const h = readExpr(j["height"]);
|
|
5444
5604
|
if (!h.ok) return h;
|
|
5445
|
-
return require_errors.ok(cylinder$
|
|
5605
|
+
return require_errors.ok(cylinder$2(r.value, h.value));
|
|
5446
5606
|
}
|
|
5447
5607
|
function readCone(j) {
|
|
5448
5608
|
const r1 = readExpr(j["radius1"]);
|
|
@@ -5451,14 +5611,14 @@ function readCone(j) {
|
|
|
5451
5611
|
if (!r2.ok) return r2;
|
|
5452
5612
|
const h = readExpr(j["height"]);
|
|
5453
5613
|
if (!h.ok) return h;
|
|
5454
|
-
return require_errors.ok(cone$
|
|
5614
|
+
return require_errors.ok(cone$2(r1.value, r2.value, h.value));
|
|
5455
5615
|
}
|
|
5456
5616
|
function readTorus(j) {
|
|
5457
5617
|
const ma = readExpr(j["majorRadius"]);
|
|
5458
5618
|
if (!ma.ok) return ma;
|
|
5459
5619
|
const mi = readExpr(j["minorRadius"]);
|
|
5460
5620
|
if (!mi.ok) return mi;
|
|
5461
|
-
return require_errors.ok(torus$
|
|
5621
|
+
return require_errors.ok(torus$2(ma.value, mi.value));
|
|
5462
5622
|
}
|
|
5463
5623
|
function readPolygon(j) {
|
|
5464
5624
|
const pts = j["points"];
|
|
@@ -5634,11 +5794,11 @@ function foldBuildVec(dim, comps) {
|
|
|
5634
5794
|
}
|
|
5635
5795
|
function optimizeNode(n) {
|
|
5636
5796
|
switch (n.kind) {
|
|
5637
|
-
case "Box": return box$
|
|
5638
|
-
case "Sphere": return sphere$
|
|
5639
|
-
case "Cylinder": return cylinder$
|
|
5640
|
-
case "Cone": return cone$
|
|
5641
|
-
case "Torus": return torus$
|
|
5797
|
+
case "Box": return box$2(foldExpr(n.x), foldExpr(n.y), foldExpr(n.z));
|
|
5798
|
+
case "Sphere": return sphere$2(foldExpr(n.radius));
|
|
5799
|
+
case "Cylinder": return cylinder$2(foldExpr(n.radius), foldExpr(n.height));
|
|
5800
|
+
case "Cone": return cone$2(foldExpr(n.radius1), foldExpr(n.radius2), foldExpr(n.height));
|
|
5801
|
+
case "Torus": return torus$2(foldExpr(n.majorRadius), foldExpr(n.minorRadius));
|
|
5642
5802
|
case "Polygon": return polygon$1(n.points.map(foldExpr));
|
|
5643
5803
|
case "Circle": return circle$1(foldExpr(n.radius));
|
|
5644
5804
|
case "Line": return line$1(foldExpr(n.from), foldExpr(n.to));
|
|
@@ -5796,15 +5956,15 @@ var csg_exports = /* @__PURE__ */ require_textBlueprints.__exportAll({
|
|
|
5796
5956
|
asVec2Expr: () => asVec2Expr,
|
|
5797
5957
|
asVec3Expr: () => asVec3Expr,
|
|
5798
5958
|
binOp: () => binOp,
|
|
5799
|
-
box: () => box$
|
|
5959
|
+
box: () => box$2,
|
|
5800
5960
|
buildVec: () => buildVec,
|
|
5801
5961
|
circle: () => circle$1,
|
|
5802
5962
|
component: () => component,
|
|
5803
5963
|
compound: () => compound$1,
|
|
5804
|
-
cone: () => cone$
|
|
5964
|
+
cone: () => cone$2,
|
|
5805
5965
|
cut: () => cut$1,
|
|
5806
5966
|
cutAll: () => cutAll$1,
|
|
5807
|
-
cylinder: () => cylinder$
|
|
5967
|
+
cylinder: () => cylinder$2,
|
|
5808
5968
|
emptyFace: () => emptyFace,
|
|
5809
5969
|
emptySolid: () => emptySolid,
|
|
5810
5970
|
emptyWire: () => emptyWire,
|
|
@@ -5826,9 +5986,9 @@ var csg_exports = /* @__PURE__ */ require_textBlueprints.__exportAll({
|
|
|
5826
5986
|
replaceNode: () => replaceNode,
|
|
5827
5987
|
rotate: () => rotate$1,
|
|
5828
5988
|
scale: () => scale$1,
|
|
5829
|
-
sphere: () => sphere$
|
|
5989
|
+
sphere: () => sphere$2,
|
|
5830
5990
|
toJSON: () => toJSON,
|
|
5831
|
-
torus: () => torus$
|
|
5991
|
+
torus: () => torus$2,
|
|
5832
5992
|
translate: () => translate$1,
|
|
5833
5993
|
unaryOp: () => unaryOp,
|
|
5834
5994
|
vec2Lit: () => vec2Lit,
|
|
@@ -6308,6 +6468,14 @@ exports.roundedRectangleBlueprint = require_boolean2D.roundedRectangleBlueprint;
|
|
|
6308
6468
|
exports.scale = scale;
|
|
6309
6469
|
exports.scale2D = require_blueprintFns.scale2D;
|
|
6310
6470
|
exports.scaleDrawing = require_drawFns.scaleDrawing;
|
|
6471
|
+
exports.sdfBox = box$1;
|
|
6472
|
+
exports.sdfCapsule = capsule;
|
|
6473
|
+
exports.sdfCone = cone$1;
|
|
6474
|
+
exports.sdfCylinder = cylinder$1;
|
|
6475
|
+
exports.sdfPlane = plane;
|
|
6476
|
+
exports.sdfRoundedBox = roundedBox;
|
|
6477
|
+
exports.sdfSphere = sphere;
|
|
6478
|
+
exports.sdfTorus = torus;
|
|
6311
6479
|
exports.section = section;
|
|
6312
6480
|
exports.sectionToFace = sectionToFace;
|
|
6313
6481
|
exports.serializeHistory = require_historyFns.serializeHistory;
|
package/dist/brepjs.js
CHANGED
|
@@ -14,7 +14,7 @@ import { a as meshEdges$1, c as createMeshCache, i as mesh$1, n as exportSTEP, o
|
|
|
14
14
|
import { n as getAtOrThrow, r as lastOrThrow, t as firstOrThrow } from "./arrayAccess-DrUGPADn.js";
|
|
15
15
|
import { _ as makeThreePointArc, d as makeCircle, h as makeLine, l as makeBSplineInterpolation, n as fill, r as makeFace, s as assembleWire } from "./surfaceBuilders-jx81G_YJ.js";
|
|
16
16
|
import { a as fuseAll, c as sectionToFace$1, i as fuse$2, l as slice$1, n as cut$2, o as intersect$2, r as cutAll, s as section$1, t as booleanPipeline, u as split$1 } from "./booleanFns-CaKngiuu.js";
|
|
17
|
-
import { $ as fuseAllBisect, A as fixShape, B as offset$1, C as threePointArc, D as wireLoop, E as wire, F as isValid$1, G as chamferWithEvolution, H as thicken$1, I as solidFromShell, J as fuseWithEvolution, K as cutWithEvolution, L as chamfer$1, M as healFace, N as healSolid, O as autoHeal, P as healWire, Q as cutAllBisect, R as draft$1, S as tangentArc, T as vertex, U as variableFillet, V as shell$1, W as positionOnCurve, X as shellWithEvolution, Y as intersectWithEvolution, Z as checkBoolean, _ as polygon, a as circle, at as sharedEdges, b as sphere, c as cylinder, ct as chamferDistAngle, d as ellipsoid, dt as toLODGeometryData, et as getNurbsCurveData, f as face, ft as toLineGeometryData, g as offsetFace, h as line, i as bsplineApprox, it as facesOfEdge, j as heal$1, k as fixSelfIntersection, l as ellipse, lt as toBufferGeometryData, m as helix, n as bezier, nt as adjacentFaces, o as compound, ot as verticesOfEdge, p as filledFace, q as filletWithEvolution, r as box, rt as edgesOfFace, s as cone, st as wiresOfFace, t as addHoles, tt as getNurbsSurfaceData, u as ellipseArc, ut as toGroupedBufferGeometryData, v as sewShells, w as torus, x as subFace, y as solid, z as fillet$1 } from "./primitiveFns-ecKWNC5k.js";
|
|
17
|
+
import { $ as fuseAllBisect, A as fixShape, B as offset$1, C as threePointArc, D as wireLoop, E as wire, F as isValid$1, G as chamferWithEvolution, H as thicken$1, I as solidFromShell, J as fuseWithEvolution, K as cutWithEvolution, L as chamfer$1, M as healFace, N as healSolid, O as autoHeal, P as healWire, Q as cutAllBisect, R as draft$1, S as tangentArc, T as vertex, U as variableFillet, V as shell$1, W as positionOnCurve, X as shellWithEvolution, Y as intersectWithEvolution, Z as checkBoolean, _ as polygon, a as circle, at as sharedEdges, b as sphere$1, c as cylinder, ct as chamferDistAngle, d as ellipsoid, dt as toLODGeometryData, et as getNurbsCurveData, f as face, ft as toLineGeometryData, g as offsetFace, h as line, i as bsplineApprox, it as facesOfEdge, j as heal$1, k as fixSelfIntersection, l as ellipse, lt as toBufferGeometryData, m as helix, n as bezier, nt as adjacentFaces, o as compound, ot as verticesOfEdge, p as filledFace, q as filletWithEvolution, r as box, rt as edgesOfFace, s as cone, st as wiresOfFace, t as addHoles, tt as getNurbsSurfaceData, u as ellipseArc, ut as toGroupedBufferGeometryData, v as sewShells, w as torus$1, x as subFace, y as solid, z as fillet$1 } from "./primitiveFns-ecKWNC5k.js";
|
|
18
18
|
import { C as walkAssembly, D as exportAssemblySTEP, E as linearPattern, O as createAssembly, S as updateNode, _ as collectShapes, a as findStep, b as findNode, c as registerOperation, d as replayHistory, f as serializeHistory, g as addChild, h as undoLast, i as deserializeHistory, l as registerShape, m as stepsFrom, n as createHistory, o as getShape, p as stepCount, r as createRegistry, s as modifyStep, t as addStep, u as replayFrom, v as countNodes, w as circularPattern, x as removeChild, y as createAssemblyNode } from "./historyFns-CZ9oNL7j.js";
|
|
19
19
|
import { n as BaseSketcher2d, r as organiseBlueprints, t as BlueprintSketcher } from "./blueprintSketcher-0DeTMXwj.js";
|
|
20
20
|
import { a as createTypedFinder, i as wireFinder, n as edgeFinder, r as faceFinder, t as getSingleFace } from "./helpers-BX-0e71G.js";
|
|
@@ -193,7 +193,7 @@ function validateInputs(mesh, queries) {
|
|
|
193
193
|
return null;
|
|
194
194
|
}
|
|
195
195
|
/** Resolve a registered voxel engine, mapping an unregistered id to an error. */
|
|
196
|
-
function resolveEngine(id) {
|
|
196
|
+
function resolveEngine$1(id) {
|
|
197
197
|
try {
|
|
198
198
|
return ok(getVoxel(id));
|
|
199
199
|
} catch (cause) {
|
|
@@ -210,7 +210,7 @@ function resolveEngine(id) {
|
|
|
210
210
|
function windingNumbers(mesh, queries, id) {
|
|
211
211
|
const invalid = validateInputs(mesh, queries);
|
|
212
212
|
if (invalid) return err(invalid);
|
|
213
|
-
const engine = resolveEngine(id);
|
|
213
|
+
const engine = resolveEngine$1(id);
|
|
214
214
|
if (isErr(engine)) return engine;
|
|
215
215
|
return ok(engine.value.winding_numbers(mesh.vertices, mesh.triangles, queries));
|
|
216
216
|
}
|
|
@@ -222,15 +222,15 @@ function windingNumbers(mesh, queries, id) {
|
|
|
222
222
|
function pointsInside(mesh, queries, id) {
|
|
223
223
|
const invalid = validateInputs(mesh, queries);
|
|
224
224
|
if (invalid) return err(invalid);
|
|
225
|
-
const engine = resolveEngine(id);
|
|
225
|
+
const engine = resolveEngine$1(id);
|
|
226
226
|
if (isErr(engine)) return engine;
|
|
227
227
|
const flags = engine.value.points_inside(mesh.vertices, mesh.triangles, queries);
|
|
228
228
|
return ok(Array.from(flags, (flag) => flag === 1));
|
|
229
229
|
}
|
|
230
230
|
//#endregion
|
|
231
231
|
//#region src/voxel/repairFns.ts
|
|
232
|
-
var DEFAULT_RESOLUTION$
|
|
233
|
-
var DEFAULT_PADDING$
|
|
232
|
+
var DEFAULT_RESOLUTION$4 = 48;
|
|
233
|
+
var DEFAULT_PADDING$4 = 2;
|
|
234
234
|
/**
|
|
235
235
|
* Repair a (possibly non-watertight) triangle-soup mesh into a closed surface:
|
|
236
236
|
* voxelize an FWN-signed SDF, then Surface-Nets contour it back to triangles.
|
|
@@ -243,11 +243,11 @@ function repairMesh(mesh, opts, id) {
|
|
|
243
243
|
const invalid = validateMesh(mesh);
|
|
244
244
|
if (invalid) return err(invalid);
|
|
245
245
|
if (mesh.vertices.length === 0 || mesh.triangles.length === 0) return err(validationError("VOXEL_EMPTY_MESH", "repairMesh requires a non-empty triangle mesh."));
|
|
246
|
-
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$
|
|
247
|
-
const padding = opts?.padding ?? DEFAULT_PADDING$
|
|
246
|
+
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$4;
|
|
247
|
+
const padding = opts?.padding ?? DEFAULT_PADDING$4;
|
|
248
248
|
if (!Number.isInteger(resolution) || resolution < 1) return err(validationError("VOXEL_INVALID_RESOLUTION", "resolution must be an integer >= 1."));
|
|
249
249
|
if (!Number.isInteger(padding) || padding < 1) return err(validationError("VOXEL_INVALID_PADDING", "padding must be an integer >= 1."));
|
|
250
|
-
const engine = resolveEngine(id);
|
|
250
|
+
const engine = resolveEngine$1(id);
|
|
251
251
|
if (isErr(engine)) return engine;
|
|
252
252
|
try {
|
|
253
253
|
try {
|
|
@@ -297,16 +297,16 @@ function shapeToMeshInput(shape, deflection = DEFAULT_DEFLECTION) {
|
|
|
297
297
|
}
|
|
298
298
|
//#endregion
|
|
299
299
|
//#region src/voxel/meshOpsFns.ts
|
|
300
|
-
var DEFAULT_RESOLUTION$
|
|
301
|
-
var DEFAULT_PADDING$
|
|
300
|
+
var DEFAULT_RESOLUTION$3 = 48;
|
|
301
|
+
var DEFAULT_PADDING$3 = 2;
|
|
302
302
|
var BOOLEAN_OP_CODES$1 = {
|
|
303
303
|
union: 0,
|
|
304
304
|
intersection: 1,
|
|
305
305
|
difference: 2
|
|
306
306
|
};
|
|
307
|
-
function resolveGridParams$
|
|
308
|
-
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$
|
|
309
|
-
const padding = opts?.padding ?? DEFAULT_PADDING$
|
|
307
|
+
function resolveGridParams$2(opts) {
|
|
308
|
+
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$3;
|
|
309
|
+
const padding = opts?.padding ?? DEFAULT_PADDING$3;
|
|
310
310
|
if (!Number.isInteger(resolution) || resolution < 1) return err(validationError("VOXEL_INVALID_RESOLUTION", "resolution must be an integer >= 1."));
|
|
311
311
|
if (!Number.isInteger(padding) || padding < 1) return err(validationError("VOXEL_INVALID_PADDING", "padding must be an integer >= 1."));
|
|
312
312
|
return ok({
|
|
@@ -341,9 +341,9 @@ function offsetMesh(mesh, distance, opts, id) {
|
|
|
341
341
|
if (invalid) return err(invalid);
|
|
342
342
|
if (mesh.vertices.length === 0 || mesh.triangles.length === 0) return err(validationError("VOXEL_EMPTY_MESH", "offsetMesh requires a non-empty triangle mesh."));
|
|
343
343
|
if (!Number.isFinite(distance)) return err(validationError("VOXEL_INVALID_DISTANCE", "distance must be a finite number."));
|
|
344
|
-
const params = resolveGridParams$
|
|
344
|
+
const params = resolveGridParams$2(opts);
|
|
345
345
|
if (isErr(params)) return params;
|
|
346
|
-
const engine = resolveEngine(id);
|
|
346
|
+
const engine = resolveEngine$1(id);
|
|
347
347
|
if (isErr(engine)) return engine;
|
|
348
348
|
try {
|
|
349
349
|
try {
|
|
@@ -370,9 +370,9 @@ function shellMesh(mesh, thickness, opts, id) {
|
|
|
370
370
|
if (invalid) return err(invalid);
|
|
371
371
|
if (mesh.vertices.length === 0 || mesh.triangles.length === 0) return err(validationError("VOXEL_EMPTY_MESH", "shellMesh requires a non-empty triangle mesh."));
|
|
372
372
|
if (!Number.isFinite(thickness) || thickness <= 0) return err(validationError("VOXEL_INVALID_THICKNESS", "thickness must be a finite number > 0."));
|
|
373
|
-
const params = resolveGridParams$
|
|
373
|
+
const params = resolveGridParams$2(opts);
|
|
374
374
|
if (isErr(params)) return params;
|
|
375
|
-
const engine = resolveEngine(id);
|
|
375
|
+
const engine = resolveEngine$1(id);
|
|
376
376
|
if (isErr(engine)) return engine;
|
|
377
377
|
try {
|
|
378
378
|
try {
|
|
@@ -402,9 +402,9 @@ function voxelBoolean(a, b, op, opts, id) {
|
|
|
402
402
|
if (a.vertices.length === 0 || a.triangles.length === 0) return err(validationError("VOXEL_EMPTY_MESH", "voxelBoolean requires a non-empty mesh for operand A."));
|
|
403
403
|
if (b.vertices.length === 0 || b.triangles.length === 0) return err(validationError("VOXEL_EMPTY_MESH", "voxelBoolean requires a non-empty mesh for operand B."));
|
|
404
404
|
const opCode = BOOLEAN_OP_CODES$1[op];
|
|
405
|
-
const params = resolveGridParams$
|
|
405
|
+
const params = resolveGridParams$2(opts);
|
|
406
406
|
if (isErr(params)) return params;
|
|
407
|
-
const engine = resolveEngine(id);
|
|
407
|
+
const engine = resolveEngine$1(id);
|
|
408
408
|
if (isErr(engine)) return engine;
|
|
409
409
|
try {
|
|
410
410
|
try {
|
|
@@ -453,16 +453,16 @@ function voxelBooleanShapes(a, b, op, opts, id) {
|
|
|
453
453
|
}
|
|
454
454
|
//#endregion
|
|
455
455
|
//#region src/voxel/fieldFns.ts
|
|
456
|
-
var DEFAULT_RESOLUTION$
|
|
457
|
-
var DEFAULT_PADDING$
|
|
456
|
+
var DEFAULT_RESOLUTION$2 = 48;
|
|
457
|
+
var DEFAULT_PADDING$2 = 2;
|
|
458
458
|
var BOOLEAN_OP_CODES = {
|
|
459
459
|
union: 0,
|
|
460
460
|
intersection: 1,
|
|
461
461
|
difference: 2
|
|
462
462
|
};
|
|
463
|
-
function resolveGridParams(opts) {
|
|
464
|
-
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$
|
|
465
|
-
const padding = opts?.padding ?? DEFAULT_PADDING$
|
|
463
|
+
function resolveGridParams$1(opts) {
|
|
464
|
+
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$2;
|
|
465
|
+
const padding = opts?.padding ?? DEFAULT_PADDING$2;
|
|
466
466
|
if (!Number.isInteger(resolution) || resolution < 1) return err(validationError("VOXEL_INVALID_RESOLUTION", "resolution must be an integer >= 1."));
|
|
467
467
|
if (!Number.isInteger(padding) || padding < 1) return err(validationError("VOXEL_INVALID_PADDING", "padding must be an integer >= 1."));
|
|
468
468
|
return ok({
|
|
@@ -512,6 +512,9 @@ function fieldDeletable(raw) {
|
|
|
512
512
|
}
|
|
513
513
|
};
|
|
514
514
|
}
|
|
515
|
+
function makeFieldHandle(raw) {
|
|
516
|
+
return makeHandle(raw);
|
|
517
|
+
}
|
|
515
518
|
function makeHandle(raw) {
|
|
516
519
|
const inner = createKernelHandle(fieldDeletable(raw));
|
|
517
520
|
const handle = {
|
|
@@ -568,9 +571,9 @@ function voxelField(mesh, opts, id) {
|
|
|
568
571
|
const invalid = validateMesh(mesh);
|
|
569
572
|
if (invalid) return err(invalid);
|
|
570
573
|
if (mesh.vertices.length === 0 || mesh.triangles.length === 0) return err(validationError("VOXEL_EMPTY_MESH", "voxelField requires a non-empty triangle mesh."));
|
|
571
|
-
const params = resolveGridParams(opts);
|
|
574
|
+
const params = resolveGridParams$1(opts);
|
|
572
575
|
if (isErr(params)) return params;
|
|
573
|
-
const engine = resolveEngine(id);
|
|
576
|
+
const engine = resolveEngine$1(id);
|
|
574
577
|
if (isErr(engine)) return engine;
|
|
575
578
|
try {
|
|
576
579
|
return ok(makeHandle(new engine.value.VoxelField(mesh.vertices, mesh.triangles, params.value.resolution, params.value.padding)));
|
|
@@ -597,9 +600,9 @@ function voxelBooleanField(a, b, op, opts, id) {
|
|
|
597
600
|
if (invalidB) return err(invalidB);
|
|
598
601
|
if (a.vertices.length === 0 || a.triangles.length === 0) return err(validationError("VOXEL_EMPTY_MESH", "voxelBooleanField requires a non-empty mesh for operand A."));
|
|
599
602
|
if (b.vertices.length === 0 || b.triangles.length === 0) return err(validationError("VOXEL_EMPTY_MESH", "voxelBooleanField requires a non-empty mesh for operand B."));
|
|
600
|
-
const params = resolveGridParams(opts);
|
|
603
|
+
const params = resolveGridParams$1(opts);
|
|
601
604
|
if (isErr(params)) return params;
|
|
602
|
-
const engine = resolveEngine(id);
|
|
605
|
+
const engine = resolveEngine$1(id);
|
|
603
606
|
if (isErr(engine)) return engine;
|
|
604
607
|
try {
|
|
605
608
|
return ok(makeHandle(engine.value.VoxelField.boolean_of(a.vertices, a.triangles, b.vertices, b.triangles, BOOLEAN_OP_CODES[op], params.value.resolution, params.value.padding)));
|
|
@@ -709,6 +712,163 @@ function voxelBooleanFieldShapes(a, b, op, opts, id) {
|
|
|
709
712
|
return voxelBooleanField(meshA.value, meshB.value, op, opts, id);
|
|
710
713
|
}
|
|
711
714
|
//#endregion
|
|
715
|
+
//#region src/implicit/sdfFns.ts
|
|
716
|
+
var DEFAULT_RESOLUTION$1 = 48;
|
|
717
|
+
var DEFAULT_PADDING$1 = 2;
|
|
718
|
+
function resolveEngine(id) {
|
|
719
|
+
try {
|
|
720
|
+
return ok(getVoxel(id));
|
|
721
|
+
} catch (cause) {
|
|
722
|
+
return err(moduleInitError("VOXEL_NOT_INITIALIZED", cause instanceof Error ? cause.message : "voxel engine not initialized", cause));
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
function resolveGridParams(opts) {
|
|
726
|
+
const resolution = opts?.resolution ?? DEFAULT_RESOLUTION$1;
|
|
727
|
+
const padding = opts?.padding ?? DEFAULT_PADDING$1;
|
|
728
|
+
if (!Number.isInteger(resolution) || resolution < 1) return err(validationError("SDF_INVALID_RESOLUTION", "resolution must be an integer >= 1."));
|
|
729
|
+
if (!Number.isInteger(padding) || padding < 1) return err(validationError("SDF_INVALID_PADDING", "padding must be an integer >= 1."));
|
|
730
|
+
return ok({
|
|
731
|
+
resolution,
|
|
732
|
+
padding
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
function sdfDeletable(raw) {
|
|
736
|
+
return {
|
|
737
|
+
raw,
|
|
738
|
+
delete() {
|
|
739
|
+
raw.free();
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
function makeSdfHandle(raw) {
|
|
744
|
+
const inner = createKernelHandle(sdfDeletable(raw));
|
|
745
|
+
return {
|
|
746
|
+
get value() {
|
|
747
|
+
return inner.value.raw;
|
|
748
|
+
},
|
|
749
|
+
get disposed() {
|
|
750
|
+
return inner.disposed;
|
|
751
|
+
},
|
|
752
|
+
[Symbol.dispose]() {
|
|
753
|
+
inner[Symbol.dispose]();
|
|
754
|
+
},
|
|
755
|
+
union(other) {
|
|
756
|
+
return makeSdfHandle(this.value.union(other.value));
|
|
757
|
+
},
|
|
758
|
+
intersection(other) {
|
|
759
|
+
return makeSdfHandle(this.value.intersection(other.value));
|
|
760
|
+
},
|
|
761
|
+
difference(other) {
|
|
762
|
+
return makeSdfHandle(this.value.difference(other.value));
|
|
763
|
+
},
|
|
764
|
+
smoothUnion(other, k) {
|
|
765
|
+
return makeSdfHandle(this.value.smooth_union(other.value, k));
|
|
766
|
+
},
|
|
767
|
+
smoothIntersection(other, k) {
|
|
768
|
+
return makeSdfHandle(this.value.smooth_intersection(other.value, k));
|
|
769
|
+
},
|
|
770
|
+
smoothDifference(other, k) {
|
|
771
|
+
return makeSdfHandle(this.value.smooth_difference(other.value, k));
|
|
772
|
+
},
|
|
773
|
+
offset(distance) {
|
|
774
|
+
return makeSdfHandle(this.value.offset(distance));
|
|
775
|
+
},
|
|
776
|
+
round(radius) {
|
|
777
|
+
return makeSdfHandle(this.value.round(radius));
|
|
778
|
+
},
|
|
779
|
+
shell(thickness) {
|
|
780
|
+
return makeSdfHandle(this.value.shell(thickness));
|
|
781
|
+
},
|
|
782
|
+
onion(thickness) {
|
|
783
|
+
return makeSdfHandle(this.value.onion(thickness));
|
|
784
|
+
},
|
|
785
|
+
translate(x, y, z) {
|
|
786
|
+
return makeSdfHandle(this.value.translate(x, y, z));
|
|
787
|
+
},
|
|
788
|
+
rotate(ax, ay, az, angle) {
|
|
789
|
+
return makeSdfHandle(this.value.rotate(ax, ay, az, angle));
|
|
790
|
+
},
|
|
791
|
+
scale(s) {
|
|
792
|
+
return makeSdfHandle(this.value.scale(s));
|
|
793
|
+
},
|
|
794
|
+
rasterize(opts) {
|
|
795
|
+
return rasterizeField(this.value, opts);
|
|
796
|
+
},
|
|
797
|
+
rasterizeIn(bounds, opts) {
|
|
798
|
+
return rasterizeFieldIn(this.value, bounds, opts);
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
function rasterizeField(sdf, opts) {
|
|
803
|
+
const params = resolveGridParams(opts);
|
|
804
|
+
if (isErr(params)) return params;
|
|
805
|
+
try {
|
|
806
|
+
return ok(makeFieldHandle(sdf.rasterize(params.value.resolution, params.value.padding)));
|
|
807
|
+
} catch (cause) {
|
|
808
|
+
return rasterizeError(cause);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
function rasterizeFieldIn(sdf, bounds, opts) {
|
|
812
|
+
const params = resolveGridParams(opts);
|
|
813
|
+
if (isErr(params)) return params;
|
|
814
|
+
const invalid = validateBounds(bounds);
|
|
815
|
+
if (invalid) return err(invalid);
|
|
816
|
+
try {
|
|
817
|
+
return ok(makeFieldHandle(sdf.rasterize_in(bounds.min[0], bounds.min[1], bounds.min[2], bounds.max[0], bounds.max[1], bounds.max[2], params.value.resolution, params.value.padding)));
|
|
818
|
+
} catch (cause) {
|
|
819
|
+
return rasterizeError(cause);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
function rasterizeError(cause) {
|
|
823
|
+
return err(computationError("SDF_RASTERIZE_FAILED", cause instanceof Error ? cause.message : "SDF rasterization failed (grid too large?).", cause));
|
|
824
|
+
}
|
|
825
|
+
function validateBounds(bounds) {
|
|
826
|
+
if (![...bounds.min, ...bounds.max].every((v) => Number.isFinite(v))) return validationError("SDF_INVALID_BOUNDS", "bounds must be finite numbers.");
|
|
827
|
+
for (let axis = 0; axis < 3; axis++) if (bounds.max[axis] <= bounds.min[axis]) return validationError("SDF_INVALID_BOUNDS", "bounds max must exceed min on every axis.");
|
|
828
|
+
return null;
|
|
829
|
+
}
|
|
830
|
+
function build(make, id) {
|
|
831
|
+
const engine = resolveEngine(id);
|
|
832
|
+
if (isErr(engine)) return engine;
|
|
833
|
+
try {
|
|
834
|
+
return ok(makeSdfHandle(make(engine.value)));
|
|
835
|
+
} catch (cause) {
|
|
836
|
+
return err(computationError("SDF_BUILD_FAILED", cause instanceof Error ? cause.message : "SDF primitive construction failed.", cause));
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
/** A sphere of radius `r`, centered at the origin. */
|
|
840
|
+
function sphere(r, id) {
|
|
841
|
+
return build((e) => e.Sdf.sphere(r), id);
|
|
842
|
+
}
|
|
843
|
+
/** An axis-aligned box of half-extents `(hx, hy, hz)`, centered at the origin. */
|
|
844
|
+
function box$1(hx, hy, hz, id) {
|
|
845
|
+
return build((e) => e.Sdf.box_(hx, hy, hz), id);
|
|
846
|
+
}
|
|
847
|
+
/** A box with rounded edges of radius `r`. */
|
|
848
|
+
function roundedBox(hx, hy, hz, r, id) {
|
|
849
|
+
return build((e) => e.Sdf.rounded_box(hx, hy, hz, r), id);
|
|
850
|
+
}
|
|
851
|
+
/** A capped cylinder, axis +Z, radius `r`, total height `h`, centered at origin. */
|
|
852
|
+
function cylinder$1(r, h, id) {
|
|
853
|
+
return build((e) => e.Sdf.cylinder(r, h), id);
|
|
854
|
+
}
|
|
855
|
+
/** A capped cone centered at the origin: base radius `r` at z = −h/2 tapering to an apex at z = +h/2. */
|
|
856
|
+
function cone$1(r, h, id) {
|
|
857
|
+
return build((e) => e.Sdf.cone(r, h), id);
|
|
858
|
+
}
|
|
859
|
+
/** A capsule: a line segment `a`→`b` of radius `r`. */
|
|
860
|
+
function capsule(a, b, r, id) {
|
|
861
|
+
return build((e) => e.Sdf.capsule(a[0], a[1], a[2], b[0], b[1], b[2], r), id);
|
|
862
|
+
}
|
|
863
|
+
/** A torus in the XY plane (axis +Z): a `minor`-radius tube on a `major` circle. */
|
|
864
|
+
function torus(major, minor, id) {
|
|
865
|
+
return build((e) => e.Sdf.torus(major, minor), id);
|
|
866
|
+
}
|
|
867
|
+
/** A half-space: the plane through `h·n` with outward normal `n` (normalized). */
|
|
868
|
+
function plane(n, h, id) {
|
|
869
|
+
return build((e) => e.Sdf.plane(n[0], n[1], n[2], h), id);
|
|
870
|
+
}
|
|
871
|
+
//#endregion
|
|
712
872
|
//#region src/lattice/latticeFns.ts
|
|
713
873
|
var LATTICE_TAGS = {
|
|
714
874
|
gyroid: 0,
|
|
@@ -762,7 +922,7 @@ function latticeInfill(mesh, opts, id) {
|
|
|
762
922
|
if (mesh.vertices.length === 0 || mesh.triangles.length === 0) return err(validationError("LATTICE_EMPTY_MESH", "latticeInfill requires a non-empty triangle mesh."));
|
|
763
923
|
const resolved = validateOptions(opts);
|
|
764
924
|
if (isErr(resolved)) return resolved;
|
|
765
|
-
const engine = resolveEngine(id);
|
|
925
|
+
const engine = resolveEngine$1(id);
|
|
766
926
|
if (isErr(engine)) return engine;
|
|
767
927
|
const { tag, period, thickness, resolution, padding } = resolved.value;
|
|
768
928
|
try {
|
|
@@ -803,7 +963,7 @@ function tpmsLattice(bounds, opts, id) {
|
|
|
803
963
|
}
|
|
804
964
|
const resolved = validateOptions(opts);
|
|
805
965
|
if (isErr(resolved)) return resolved;
|
|
806
|
-
const engine = resolveEngine(id);
|
|
966
|
+
const engine = resolveEngine$1(id);
|
|
807
967
|
if (isErr(engine)) return engine;
|
|
808
968
|
const { tag, period, thickness, resolution, padding } = resolved.value;
|
|
809
969
|
const [minX, minY, minZ] = bounds.min;
|
|
@@ -4032,11 +4192,11 @@ var primitives_exports = /* @__PURE__ */ __exportAll({
|
|
|
4032
4192
|
polyhedron: () => polyhedron,
|
|
4033
4193
|
sewShells: () => sewShells,
|
|
4034
4194
|
solid: () => solid,
|
|
4035
|
-
sphere: () => sphere,
|
|
4195
|
+
sphere: () => sphere$1,
|
|
4036
4196
|
subFace: () => subFace,
|
|
4037
4197
|
tangentArc: () => tangentArc,
|
|
4038
4198
|
threePointArc: () => threePointArc,
|
|
4039
|
-
torus: () => torus,
|
|
4199
|
+
torus: () => torus$1,
|
|
4040
4200
|
vertex: () => vertex,
|
|
4041
4201
|
wire: () => wire,
|
|
4042
4202
|
wireLoop: () => wireLoop
|
|
@@ -4464,7 +4624,7 @@ function depsOf(...sources) {
|
|
|
4464
4624
|
}
|
|
4465
4625
|
return acc.size === 0 ? EMPTY_DEPS : acc;
|
|
4466
4626
|
}
|
|
4467
|
-
function box$
|
|
4627
|
+
function box$2(x, y, z) {
|
|
4468
4628
|
const xe = asScalarExpr(x);
|
|
4469
4629
|
const ye = asScalarExpr(y);
|
|
4470
4630
|
const ze = asScalarExpr(z);
|
|
@@ -4479,7 +4639,7 @@ function box$1(x, y, z) {
|
|
|
4479
4639
|
freeParams: depsOf(xe, ye, ze)
|
|
4480
4640
|
};
|
|
4481
4641
|
}
|
|
4482
|
-
function sphere$
|
|
4642
|
+
function sphere$2(radius) {
|
|
4483
4643
|
const re = asScalarExpr(radius);
|
|
4484
4644
|
return {
|
|
4485
4645
|
kind: "Sphere",
|
|
@@ -4488,7 +4648,7 @@ function sphere$1(radius) {
|
|
|
4488
4648
|
freeParams: re.freeParams
|
|
4489
4649
|
};
|
|
4490
4650
|
}
|
|
4491
|
-
function cylinder$
|
|
4651
|
+
function cylinder$2(radius, height) {
|
|
4492
4652
|
const re = asScalarExpr(radius);
|
|
4493
4653
|
const he = asScalarExpr(height);
|
|
4494
4654
|
return {
|
|
@@ -4499,7 +4659,7 @@ function cylinder$1(radius, height) {
|
|
|
4499
4659
|
freeParams: depsOf(re, he)
|
|
4500
4660
|
};
|
|
4501
4661
|
}
|
|
4502
|
-
function cone$
|
|
4662
|
+
function cone$2(radius1, radius2, height) {
|
|
4503
4663
|
const r1 = asScalarExpr(radius1);
|
|
4504
4664
|
const r2 = asScalarExpr(radius2);
|
|
4505
4665
|
const he = asScalarExpr(height);
|
|
@@ -4514,7 +4674,7 @@ function cone$1(radius1, radius2, height) {
|
|
|
4514
4674
|
freeParams: depsOf(r1, r2, he)
|
|
4515
4675
|
};
|
|
4516
4676
|
}
|
|
4517
|
-
function torus$
|
|
4677
|
+
function torus$2(majorRadius, minorRadius) {
|
|
4518
4678
|
const ma = asScalarExpr(majorRadius);
|
|
4519
4679
|
const mi = asScalarExpr(minorRadius);
|
|
4520
4680
|
return {
|
|
@@ -4750,7 +4910,7 @@ function evalBox(node, ctx) {
|
|
|
4750
4910
|
function evalSphere(node, ctx) {
|
|
4751
4911
|
const r = evalScalar(node.radius, ctx.env, "Sphere.radius");
|
|
4752
4912
|
if (!r.ok) return r;
|
|
4753
|
-
return ok(sphere(r.value));
|
|
4913
|
+
return ok(sphere$1(r.value));
|
|
4754
4914
|
}
|
|
4755
4915
|
function evalCylinder(node, ctx) {
|
|
4756
4916
|
const r = evalScalar(node.radius, ctx.env, "Cylinder.radius");
|
|
@@ -4773,7 +4933,7 @@ function evalTorus(node, ctx) {
|
|
|
4773
4933
|
if (!ma.ok) return ma;
|
|
4774
4934
|
const mi = evalScalar(node.minorRadius, ctx.env, "Torus.minorRadius");
|
|
4775
4935
|
if (!mi.ok) return mi;
|
|
4776
|
-
return ok(torus(ma.value, mi.value));
|
|
4936
|
+
return ok(torus$1(ma.value, mi.value));
|
|
4777
4937
|
}
|
|
4778
4938
|
function evalPolygon(node, ctx) {
|
|
4779
4939
|
const pts = [];
|
|
@@ -5419,7 +5579,7 @@ function readSingleExpr(j, key, build) {
|
|
|
5419
5579
|
function readPrimitive(kind, j) {
|
|
5420
5580
|
switch (kind) {
|
|
5421
5581
|
case "Box": return readBox(j);
|
|
5422
|
-
case "Sphere": return readSingleExpr(j, "radius", sphere$
|
|
5582
|
+
case "Sphere": return readSingleExpr(j, "radius", sphere$2);
|
|
5423
5583
|
case "Cylinder": return readCylinder(j);
|
|
5424
5584
|
case "Cone": return readCone(j);
|
|
5425
5585
|
case "Torus": return readTorus(j);
|
|
@@ -5438,14 +5598,14 @@ function readBox(j) {
|
|
|
5438
5598
|
if (!y.ok) return y;
|
|
5439
5599
|
const z = readExpr(j["z"]);
|
|
5440
5600
|
if (!z.ok) return z;
|
|
5441
|
-
return ok(box$
|
|
5601
|
+
return ok(box$2(x.value, y.value, z.value));
|
|
5442
5602
|
}
|
|
5443
5603
|
function readCylinder(j) {
|
|
5444
5604
|
const r = readExpr(j["radius"]);
|
|
5445
5605
|
if (!r.ok) return r;
|
|
5446
5606
|
const h = readExpr(j["height"]);
|
|
5447
5607
|
if (!h.ok) return h;
|
|
5448
|
-
return ok(cylinder$
|
|
5608
|
+
return ok(cylinder$2(r.value, h.value));
|
|
5449
5609
|
}
|
|
5450
5610
|
function readCone(j) {
|
|
5451
5611
|
const r1 = readExpr(j["radius1"]);
|
|
@@ -5454,14 +5614,14 @@ function readCone(j) {
|
|
|
5454
5614
|
if (!r2.ok) return r2;
|
|
5455
5615
|
const h = readExpr(j["height"]);
|
|
5456
5616
|
if (!h.ok) return h;
|
|
5457
|
-
return ok(cone$
|
|
5617
|
+
return ok(cone$2(r1.value, r2.value, h.value));
|
|
5458
5618
|
}
|
|
5459
5619
|
function readTorus(j) {
|
|
5460
5620
|
const ma = readExpr(j["majorRadius"]);
|
|
5461
5621
|
if (!ma.ok) return ma;
|
|
5462
5622
|
const mi = readExpr(j["minorRadius"]);
|
|
5463
5623
|
if (!mi.ok) return mi;
|
|
5464
|
-
return ok(torus$
|
|
5624
|
+
return ok(torus$2(ma.value, mi.value));
|
|
5465
5625
|
}
|
|
5466
5626
|
function readPolygon(j) {
|
|
5467
5627
|
const pts = j["points"];
|
|
@@ -5637,11 +5797,11 @@ function foldBuildVec(dim, comps) {
|
|
|
5637
5797
|
}
|
|
5638
5798
|
function optimizeNode(n) {
|
|
5639
5799
|
switch (n.kind) {
|
|
5640
|
-
case "Box": return box$
|
|
5641
|
-
case "Sphere": return sphere$
|
|
5642
|
-
case "Cylinder": return cylinder$
|
|
5643
|
-
case "Cone": return cone$
|
|
5644
|
-
case "Torus": return torus$
|
|
5800
|
+
case "Box": return box$2(foldExpr(n.x), foldExpr(n.y), foldExpr(n.z));
|
|
5801
|
+
case "Sphere": return sphere$2(foldExpr(n.radius));
|
|
5802
|
+
case "Cylinder": return cylinder$2(foldExpr(n.radius), foldExpr(n.height));
|
|
5803
|
+
case "Cone": return cone$2(foldExpr(n.radius1), foldExpr(n.radius2), foldExpr(n.height));
|
|
5804
|
+
case "Torus": return torus$2(foldExpr(n.majorRadius), foldExpr(n.minorRadius));
|
|
5645
5805
|
case "Polygon": return polygon$1(n.points.map(foldExpr));
|
|
5646
5806
|
case "Circle": return circle$1(foldExpr(n.radius));
|
|
5647
5807
|
case "Line": return line$1(foldExpr(n.from), foldExpr(n.to));
|
|
@@ -5799,15 +5959,15 @@ var csg_exports = /* @__PURE__ */ __exportAll({
|
|
|
5799
5959
|
asVec2Expr: () => asVec2Expr,
|
|
5800
5960
|
asVec3Expr: () => asVec3Expr,
|
|
5801
5961
|
binOp: () => binOp,
|
|
5802
|
-
box: () => box$
|
|
5962
|
+
box: () => box$2,
|
|
5803
5963
|
buildVec: () => buildVec,
|
|
5804
5964
|
circle: () => circle$1,
|
|
5805
5965
|
component: () => component,
|
|
5806
5966
|
compound: () => compound$1,
|
|
5807
|
-
cone: () => cone$
|
|
5967
|
+
cone: () => cone$2,
|
|
5808
5968
|
cut: () => cut$1,
|
|
5809
5969
|
cutAll: () => cutAll$1,
|
|
5810
|
-
cylinder: () => cylinder$
|
|
5970
|
+
cylinder: () => cylinder$2,
|
|
5811
5971
|
emptyFace: () => emptyFace,
|
|
5812
5972
|
emptySolid: () => emptySolid,
|
|
5813
5973
|
emptyWire: () => emptyWire,
|
|
@@ -5829,9 +5989,9 @@ var csg_exports = /* @__PURE__ */ __exportAll({
|
|
|
5829
5989
|
replaceNode: () => replaceNode,
|
|
5830
5990
|
rotate: () => rotate$1,
|
|
5831
5991
|
scale: () => scale$1,
|
|
5832
|
-
sphere: () => sphere$
|
|
5992
|
+
sphere: () => sphere$2,
|
|
5833
5993
|
toJSON: () => toJSON,
|
|
5834
|
-
torus: () => torus$
|
|
5994
|
+
torus: () => torus$2,
|
|
5835
5995
|
translate: () => translate$1,
|
|
5836
5996
|
unaryOp: () => unaryOp,
|
|
5837
5997
|
vec2Lit: () => vec2Lit,
|
|
@@ -5840,4 +6000,4 @@ var csg_exports = /* @__PURE__ */ __exportAll({
|
|
|
5840
6000
|
withEvaluator: () => withEvaluator
|
|
5841
6001
|
});
|
|
5842
6002
|
//#endregion
|
|
5843
|
-
export { BaseSketcher2d, BlueprintSketcher, BrepBugError, BrepErrorCode, BrepWrapperError, BrepkitAdapter, CompoundSketch, DEFAULT_CAPABILITIES, DEG2RAD, DisposalScope, EXACT_BREP_CAPABILITIES, FaceSketcher, HASH_CODE_MAX, OK, OcctWasmAdapter, RAD2DEG, Sketch, Sketcher, Sketches, addChild, addHoles, addMate, addStep, adjacentFaces, all, andThen, applyGlue, applyMatrix, approximateCurve, as2D, as3D, asTopo, assignRoles, autoHeal, bezier, blueprintToDXF, booleanPipeline, booleans_exports as booleans, boss, box, bsplineApprox, bug, cameraFromPlane, cameraLookAt, captureHint, cast, castShape, castShape3D, chamfer, chamferDistAngle as chamferDistAngleShape, chamferWithEvolution, checkAllInterferences, checkBoolean, checkInterference, circle, circularPattern, classifyPointOnFace, clearMeshCache, clone, closedWire, collect, collectShapes, colorFaces, colorShape, complexExtrude, composeTransforms, compound, compoundSketchExtrude, compoundSketchFace, compoundSketchLoft, compoundSketchRevolve, computationError, computeStraightSkeleton, cone, construction_exports as construction, convexHull, cornerFinder, countNodes, createAssembly, createAssemblyNode, createBlueprint, createCamera, createCompound, createCompoundBlueprint, createDistanceQuery, createEdge, createFace, createHandle, createHistory, createKernelHandle, createMeshCache, createNamedPlane, createOperationRegistry, createPlane, createRef, createRegistry, createShell, createSolid, createTaskQueue, createVertex, createWire, createWorkerClient, createWorkerHandler, csg_exports as csg, currentQuality, curve2dBoundingBox, curve2dDistanceFrom, curve2dFirstPoint, curve2dIsOnCurve, curve2dLastPoint, curve2dParameter, curve2dSplitAt, curve2dTangentAt, curveEndPoint, curveIsClosed, curveIsPeriodic, curveLength, curvePeriod, curvePointAt, curveStartPoint, curveTangentAt, cut, cut2D, cutAll, cutAllBisect, cutBlueprints, cutWithEvolution, cylinder, defaultScorer, dequeueTask, describe, deserializeDrawing, deserializeHistory, fromBREP as deserializeShape, downcast, draft, draw, drawCircle, drawEllipse, drawFaceOutline, drawParametricFunction, drawPointsInterpolation, drawPolysides, drawProjection, drawRectangle, drawRoundedRectangle, drawSingleCircle, drawSingleEllipse, drawText, drawingChamfer, drawingCut, drawingFillet, drawingFuse, drawingIntersect, drawingToSketchOnPlane, drill, edgeFinder, edgesOfFace, ellipse, ellipseArc, ellipsoid, enqueueTask, err, exportAssemblySTEP, exportDXF, exportGlb, exportGltf, exportIGES, exportOBJ, exportSTEP, exportSTEPConfigured, exportSTL, exportThreeMF, extrude, extrudeAll, face, faceCenter, faceFinder, faceGeomType, faceOrientation, facesOfEdge, fieldBoolean, fieldContour, fieldOffset, fieldReinit, fieldShell, fill, filledFace, fillet, filletWithEvolution, findFacesByTag, findNode, findStep, fixSelfIntersection, fixShape, flatMap, flatten, flipFaceOrientation, flipOrientation, fontMetrics, fromBREP$1 as fromBREP, fromKernelDir, fromKernelPnt, fromKernelVec, fromNullable, fuse, fuse2D, fuseAll, fuseAllBisect, fuseBlueprints, fuseWithEvolution, gearGeometry, getActiveVoxelId, getBounds, getBounds2D, getCompSolids, getCurveType, getDisposalStats, getEdges, getFaceColor, getFaceOrigins, getFaceTags, getFaces, getFont, getHashCode, getShape as getHistoryShape, getKernel, getKernelCapabilities, getKernelTier, getNurbsCurveData, getNurbsSurfaceData, getOrientation, getOrientation2D, getPerformanceStats, getShapeColor, getShapeKind, getShells, getSingleFace, getSolids, getSurfaceType, getTagMetadata, getVertices, getVoxel, getWires, guidedSweep, heal, healFace, healSolid, healWire, helix, hull, importDXF, importGLB, importIGES, importOBJ, importSTEP, importSTL, importSVG, importSVGPathD, importThreeMF, init, initFromManifold, initFromOC, initVoxel, innerWires, interpolateCurve, intersect, intersect2D, intersectBlueprints, intersectWithEvolution, invalidateShapeCache, ioNs_exports as io, ioError, is2D, is3D, isChamferRadius, isClosedWire, isCompSolid, isCompound, isDisposeRequest, isEdge, isEmpty, isEqualShape, isErr, isErrorResponse, isFace, isFilletRadius, isInitRequest, isInside2D, isLive, isManifoldShell, isNumber, isOk, isOperationRequest, isOrientedFace, isPlanarFace, isPlanarWire, isProjectionPlane, isEmpty$1 as isQueueEmpty, isSameShape, isShape1D, isShape3D, isShell, isSolid, isSuccessResponse, isValid, isValidSolid, isVertex, isWire, iterCompSolids, iterEdges, iterFaces, iterShells, iterSolids, iterTopo, iterVertices, iterWires, kernelCall, kernelCallRaw, kernelCallScoped, kernelError, latticeInfill, latticeInfillShape, line, linearPattern, loadFont, loft, loftAll, makeBaseBox, makeExternalGear, makeInternalGear, makePlane, makePlanetaryGear, makeProjectedEdges, manifoldShell, map, mapBoth, mapErr, match, measureArea, measureCurvatureAt, measureCurvatureAtMid, measureDistance, measureDistanceProps, measureLength, measureLinearProps, measureSurfaceProps, measureVolume, measureVolumeProps, measurement_exports as measurement, mesh, meshEdges, meshMultiLOD, minkowski, mirror, mirror2D, mirrorDrawing, mirrorJoin, modifiers_exports as modifiers, modifyStep, moduleInitError, multiSectionSweep, normalAt, offset, offsetFace, offsetMesh, offsetShape, offsetWire2D, ok, or, orElse, organiseBlueprints, orientedFace, outerWire, patterns_exports as patterns, pendingCount, pipeline, pivotPlane, planarFace, planarWire, planetPlacements, pocket, pointOnSurface, pointsInside, polygon, polyhedron, polysideInnerRadius, polysidesBlueprint, positionOnCurve, prewarm, primitives_exports as primitives, projectEdges, projectPointOnFace, query_exports as query, queryError, rectangularPattern, registerHandler, registerKernel, registerKernelTier, registerOperation, registerShape, registerVoxel, rejectAll, removeChild, removeHolesFromFace, repairMesh, replayFrom, replayHistory, resetDisposalStats, resetPerformanceStats, resize, resolve, resolve3D, resolveDirection, resolvePlane, resolveRef, reverseCurve, revolve, roof, rotate, rotate2D, rotateDrawing, roundedRectangleBlueprint, scale, scale2D, scaleDrawing, section, sectionToFace, serializeHistory, setShapeOrigin, setTagMetadata, sewShells, shape, shapeToMeshInput, shapeType, sharedEdges, shell, shellMesh, shellShape, shellWithEvolution, simplify, sketchCircle, sketchEllipse, sketchExtrude, sketchFace, sketchFaceOffset, sketchHelix, sketchLoft, sketchOnFace2D, sketchOnPlane2D, sketchParametricFunction, sketchPolysides, sketchRectangle, sketchRevolve, sketchRoundedRectangle, sketchSweep, sketchText, sketchWires, sketcherStateError, slice, solid, solidFromShell, solveAssembly, sphere, split, stepCount, stepsFrom, stretch2D, subFace, supportExtrude, supportsConstraintSketch, supportsProjection, surfaceFromGrid, surfaceFromImage, sweep, tagFaces, tangentArc, tap, tapErr, textBlueprints, textMetrics, thicken, threePointArc, toBREP, toBufferGeometryData, toGroupedBufferGeometryData, toKernelVec, toLODGeometryData, toLineGeometryData, toSVGPathD, toVec2, toVec3, torus, tpmsLattice, transformCopy, transforms_exports as transforms, translate, translate2D, translateDrawing, translatePlane, tryCatch, tryCatchAsync, twistExtrude, typeCastError, undoLast, unsupportedError, unwrap, unwrapErr, unwrapOr, unwrapOrElse, updateNode, updateRoles, uvBounds, uvCoordinates, validSolid, validatePlanetary, validationError, variableFillet, vecAdd, vecAngle, vecCross, vecDistance, vecDot, vecEquals, vecIsZero, vecLength, vecLengthSq, vecNegate, vecNormalize, vecProjectToPlane, vecRepr, vecRotate, vecScale, vecSub, vertex, vertexFinder, vertexPosition, verticesOfEdge, voxelBoolean, voxelBooleanField, voxelBooleanFieldShapes, voxelBooleanShapes, voxelField, voxelFieldFromShape, walkAssembly, windingNumbers, wire, wireFinder, wireLoop, wiresOfFace, withKernel, withKernelDir, withKernelPnt, withKernelVec, withQuality, withScope, withScopeResult, withScopeResultAsync, withTier, zip as zipResults };
|
|
6003
|
+
export { BaseSketcher2d, BlueprintSketcher, BrepBugError, BrepErrorCode, BrepWrapperError, BrepkitAdapter, CompoundSketch, DEFAULT_CAPABILITIES, DEG2RAD, DisposalScope, EXACT_BREP_CAPABILITIES, FaceSketcher, HASH_CODE_MAX, OK, OcctWasmAdapter, RAD2DEG, Sketch, Sketcher, Sketches, addChild, addHoles, addMate, addStep, adjacentFaces, all, andThen, applyGlue, applyMatrix, approximateCurve, as2D, as3D, asTopo, assignRoles, autoHeal, bezier, blueprintToDXF, booleanPipeline, booleans_exports as booleans, boss, box, bsplineApprox, bug, cameraFromPlane, cameraLookAt, captureHint, cast, castShape, castShape3D, chamfer, chamferDistAngle as chamferDistAngleShape, chamferWithEvolution, checkAllInterferences, checkBoolean, checkInterference, circle, circularPattern, classifyPointOnFace, clearMeshCache, clone, closedWire, collect, collectShapes, colorFaces, colorShape, complexExtrude, composeTransforms, compound, compoundSketchExtrude, compoundSketchFace, compoundSketchLoft, compoundSketchRevolve, computationError, computeStraightSkeleton, cone, construction_exports as construction, convexHull, cornerFinder, countNodes, createAssembly, createAssemblyNode, createBlueprint, createCamera, createCompound, createCompoundBlueprint, createDistanceQuery, createEdge, createFace, createHandle, createHistory, createKernelHandle, createMeshCache, createNamedPlane, createOperationRegistry, createPlane, createRef, createRegistry, createShell, createSolid, createTaskQueue, createVertex, createWire, createWorkerClient, createWorkerHandler, csg_exports as csg, currentQuality, curve2dBoundingBox, curve2dDistanceFrom, curve2dFirstPoint, curve2dIsOnCurve, curve2dLastPoint, curve2dParameter, curve2dSplitAt, curve2dTangentAt, curveEndPoint, curveIsClosed, curveIsPeriodic, curveLength, curvePeriod, curvePointAt, curveStartPoint, curveTangentAt, cut, cut2D, cutAll, cutAllBisect, cutBlueprints, cutWithEvolution, cylinder, defaultScorer, dequeueTask, describe, deserializeDrawing, deserializeHistory, fromBREP as deserializeShape, downcast, draft, draw, drawCircle, drawEllipse, drawFaceOutline, drawParametricFunction, drawPointsInterpolation, drawPolysides, drawProjection, drawRectangle, drawRoundedRectangle, drawSingleCircle, drawSingleEllipse, drawText, drawingChamfer, drawingCut, drawingFillet, drawingFuse, drawingIntersect, drawingToSketchOnPlane, drill, edgeFinder, edgesOfFace, ellipse, ellipseArc, ellipsoid, enqueueTask, err, exportAssemblySTEP, exportDXF, exportGlb, exportGltf, exportIGES, exportOBJ, exportSTEP, exportSTEPConfigured, exportSTL, exportThreeMF, extrude, extrudeAll, face, faceCenter, faceFinder, faceGeomType, faceOrientation, facesOfEdge, fieldBoolean, fieldContour, fieldOffset, fieldReinit, fieldShell, fill, filledFace, fillet, filletWithEvolution, findFacesByTag, findNode, findStep, fixSelfIntersection, fixShape, flatMap, flatten, flipFaceOrientation, flipOrientation, fontMetrics, fromBREP$1 as fromBREP, fromKernelDir, fromKernelPnt, fromKernelVec, fromNullable, fuse, fuse2D, fuseAll, fuseAllBisect, fuseBlueprints, fuseWithEvolution, gearGeometry, getActiveVoxelId, getBounds, getBounds2D, getCompSolids, getCurveType, getDisposalStats, getEdges, getFaceColor, getFaceOrigins, getFaceTags, getFaces, getFont, getHashCode, getShape as getHistoryShape, getKernel, getKernelCapabilities, getKernelTier, getNurbsCurveData, getNurbsSurfaceData, getOrientation, getOrientation2D, getPerformanceStats, getShapeColor, getShapeKind, getShells, getSingleFace, getSolids, getSurfaceType, getTagMetadata, getVertices, getVoxel, getWires, guidedSweep, heal, healFace, healSolid, healWire, helix, hull, importDXF, importGLB, importIGES, importOBJ, importSTEP, importSTL, importSVG, importSVGPathD, importThreeMF, init, initFromManifold, initFromOC, initVoxel, innerWires, interpolateCurve, intersect, intersect2D, intersectBlueprints, intersectWithEvolution, invalidateShapeCache, ioNs_exports as io, ioError, is2D, is3D, isChamferRadius, isClosedWire, isCompSolid, isCompound, isDisposeRequest, isEdge, isEmpty, isEqualShape, isErr, isErrorResponse, isFace, isFilletRadius, isInitRequest, isInside2D, isLive, isManifoldShell, isNumber, isOk, isOperationRequest, isOrientedFace, isPlanarFace, isPlanarWire, isProjectionPlane, isEmpty$1 as isQueueEmpty, isSameShape, isShape1D, isShape3D, isShell, isSolid, isSuccessResponse, isValid, isValidSolid, isVertex, isWire, iterCompSolids, iterEdges, iterFaces, iterShells, iterSolids, iterTopo, iterVertices, iterWires, kernelCall, kernelCallRaw, kernelCallScoped, kernelError, latticeInfill, latticeInfillShape, line, linearPattern, loadFont, loft, loftAll, makeBaseBox, makeExternalGear, makeInternalGear, makePlane, makePlanetaryGear, makeProjectedEdges, manifoldShell, map, mapBoth, mapErr, match, measureArea, measureCurvatureAt, measureCurvatureAtMid, measureDistance, measureDistanceProps, measureLength, measureLinearProps, measureSurfaceProps, measureVolume, measureVolumeProps, measurement_exports as measurement, mesh, meshEdges, meshMultiLOD, minkowski, mirror, mirror2D, mirrorDrawing, mirrorJoin, modifiers_exports as modifiers, modifyStep, moduleInitError, multiSectionSweep, normalAt, offset, offsetFace, offsetMesh, offsetShape, offsetWire2D, ok, or, orElse, organiseBlueprints, orientedFace, outerWire, patterns_exports as patterns, pendingCount, pipeline, pivotPlane, planarFace, planarWire, planetPlacements, pocket, pointOnSurface, pointsInside, polygon, polyhedron, polysideInnerRadius, polysidesBlueprint, positionOnCurve, prewarm, primitives_exports as primitives, projectEdges, projectPointOnFace, query_exports as query, queryError, rectangularPattern, registerHandler, registerKernel, registerKernelTier, registerOperation, registerShape, registerVoxel, rejectAll, removeChild, removeHolesFromFace, repairMesh, replayFrom, replayHistory, resetDisposalStats, resetPerformanceStats, resize, resolve, resolve3D, resolveDirection, resolvePlane, resolveRef, reverseCurve, revolve, roof, rotate, rotate2D, rotateDrawing, roundedRectangleBlueprint, scale, scale2D, scaleDrawing, box$1 as sdfBox, capsule as sdfCapsule, cone$1 as sdfCone, cylinder$1 as sdfCylinder, plane as sdfPlane, roundedBox as sdfRoundedBox, sphere as sdfSphere, torus as sdfTorus, section, sectionToFace, serializeHistory, setShapeOrigin, setTagMetadata, sewShells, shape, shapeToMeshInput, shapeType, sharedEdges, shell, shellMesh, shellShape, shellWithEvolution, simplify, sketchCircle, sketchEllipse, sketchExtrude, sketchFace, sketchFaceOffset, sketchHelix, sketchLoft, sketchOnFace2D, sketchOnPlane2D, sketchParametricFunction, sketchPolysides, sketchRectangle, sketchRevolve, sketchRoundedRectangle, sketchSweep, sketchText, sketchWires, sketcherStateError, slice, solid, solidFromShell, solveAssembly, sphere$1 as sphere, split, stepCount, stepsFrom, stretch2D, subFace, supportExtrude, supportsConstraintSketch, supportsProjection, surfaceFromGrid, surfaceFromImage, sweep, tagFaces, tangentArc, tap, tapErr, textBlueprints, textMetrics, thicken, threePointArc, toBREP, toBufferGeometryData, toGroupedBufferGeometryData, toKernelVec, toLODGeometryData, toLineGeometryData, toSVGPathD, toVec2, toVec3, torus$1 as torus, tpmsLattice, transformCopy, transforms_exports as transforms, translate, translate2D, translateDrawing, translatePlane, tryCatch, tryCatchAsync, twistExtrude, typeCastError, undoLast, unsupportedError, unwrap, unwrapErr, unwrapOr, unwrapOrElse, updateNode, updateRoles, uvBounds, uvCoordinates, validSolid, validatePlanetary, validationError, variableFillet, vecAdd, vecAngle, vecCross, vecDistance, vecDot, vecEquals, vecIsZero, vecLength, vecLengthSq, vecNegate, vecNormalize, vecProjectToPlane, vecRepr, vecRotate, vecScale, vecSub, vertex, vertexFinder, vertexPosition, verticesOfEdge, voxelBoolean, voxelBooleanField, voxelBooleanFieldShapes, voxelBooleanShapes, voxelField, voxelFieldFromShape, walkAssembly, windingNumbers, wire, wireFinder, wireLoop, wiresOfFace, withKernel, withKernelDir, withKernelPnt, withKernelVec, withQuality, withScope, withScopeResult, withScopeResultAsync, withTier, zip as zipResults };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field-first implicit CAD domain (ADR-0013, brepjs-implicit Phase 1).
|
|
3
|
+
*
|
|
4
|
+
* An analytic SDF expression tree that rasterizes DIRECTLY into the voxel
|
|
5
|
+
* substrate's dense grid with no input mesh — the field-first twin of the
|
|
6
|
+
* mesh-first voxel path. Primitives compose through CSG / smooth / domain
|
|
7
|
+
* combinators into an {@link SdfHandle}, which rasterizes to a banded-SDF
|
|
8
|
+
* {@link VoxelFieldHandle} for contour / offset / shell.
|
|
9
|
+
*/
|
|
10
|
+
export type { SdfHandle, SdfBounds } from './sdfFns.js';
|
|
11
|
+
export { sphere, box, roundedBox, cylinder, cone, capsule, torus, plane } from './sdfFns.js';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Result } from '../core/result.js';
|
|
2
|
+
import { WasmSdf } from '../voxel/engine.js';
|
|
3
|
+
import { VoxelFieldHandle, VoxelFieldOptions } from '../voxel/fieldFns.js';
|
|
4
|
+
/** Explicit world bounds `[min..max]` for {@link SdfHandle.rasterizeIn}. */
|
|
5
|
+
export interface SdfBounds {
|
|
6
|
+
min: [number, number, number];
|
|
7
|
+
max: [number, number, number];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A disposable handle around an analytic SDF expression. Every combinator clones
|
|
11
|
+
* into a NEW wasm node and returns a NEW handle (the wasm `Sdf` is a value, not a
|
|
12
|
+
* mutable builder), so an `SdfHandle` is immutable — the receiver stays valid and
|
|
13
|
+
* must be disposed independently. `rasterize` produces a banded-SDF
|
|
14
|
+
* {@link VoxelFieldHandle} you can boolean / offset / shell / contour.
|
|
15
|
+
*
|
|
16
|
+
* Dispose is mandatory: use `using`, or call `[Symbol.dispose]()`, to free the
|
|
17
|
+
* WASM expression tree. Intermediate handles in a chain (`a.union(b).shell(t)`)
|
|
18
|
+
* each own a wasm allocation; bind them to `using` or dispose them explicitly.
|
|
19
|
+
*/
|
|
20
|
+
export interface SdfHandle {
|
|
21
|
+
/** The wrapped WASM expression. Throws if the handle has been disposed. */
|
|
22
|
+
readonly value: WasmSdf;
|
|
23
|
+
/** Whether the backing WASM expression has been freed. */
|
|
24
|
+
readonly disposed: boolean;
|
|
25
|
+
[Symbol.dispose](): void;
|
|
26
|
+
union(other: SdfHandle): SdfHandle;
|
|
27
|
+
intersection(other: SdfHandle): SdfHandle;
|
|
28
|
+
difference(other: SdfHandle): SdfHandle;
|
|
29
|
+
smoothUnion(other: SdfHandle, k: number): SdfHandle;
|
|
30
|
+
smoothIntersection(other: SdfHandle, k: number): SdfHandle;
|
|
31
|
+
smoothDifference(other: SdfHandle, k: number): SdfHandle;
|
|
32
|
+
offset(distance: number): SdfHandle;
|
|
33
|
+
round(radius: number): SdfHandle;
|
|
34
|
+
shell(thickness: number): SdfHandle;
|
|
35
|
+
onion(thickness: number): SdfHandle;
|
|
36
|
+
translate(x: number, y: number, z: number): SdfHandle;
|
|
37
|
+
rotate(ax: number, ay: number, az: number, angle: number): SdfHandle;
|
|
38
|
+
scale(s: number): SdfHandle;
|
|
39
|
+
/** Rasterize into a banded-SDF field over the expression's analytic bounds. */
|
|
40
|
+
rasterize(opts?: VoxelFieldOptions): Result<VoxelFieldHandle>;
|
|
41
|
+
/** Rasterize over explicit world bounds (clips unbounded primitives). */
|
|
42
|
+
rasterizeIn(bounds: SdfBounds, opts?: VoxelFieldOptions): Result<VoxelFieldHandle>;
|
|
43
|
+
}
|
|
44
|
+
/** A sphere of radius `r`, centered at the origin. */
|
|
45
|
+
export declare function sphere(r: number, id?: string): Result<SdfHandle>;
|
|
46
|
+
/** An axis-aligned box of half-extents `(hx, hy, hz)`, centered at the origin. */
|
|
47
|
+
export declare function box(hx: number, hy: number, hz: number, id?: string): Result<SdfHandle>;
|
|
48
|
+
/** A box with rounded edges of radius `r`. */
|
|
49
|
+
export declare function roundedBox(hx: number, hy: number, hz: number, r: number, id?: string): Result<SdfHandle>;
|
|
50
|
+
/** A capped cylinder, axis +Z, radius `r`, total height `h`, centered at origin. */
|
|
51
|
+
export declare function cylinder(r: number, h: number, id?: string): Result<SdfHandle>;
|
|
52
|
+
/** A capped cone centered at the origin: base radius `r` at z = −h/2 tapering to an apex at z = +h/2. */
|
|
53
|
+
export declare function cone(r: number, h: number, id?: string): Result<SdfHandle>;
|
|
54
|
+
/** A capsule: a line segment `a`→`b` of radius `r`. */
|
|
55
|
+
export declare function capsule(a: [number, number, number], b: [number, number, number], r: number, id?: string): Result<SdfHandle>;
|
|
56
|
+
/** A torus in the XY plane (axis +Z): a `minor`-radius tube on a `major` circle. */
|
|
57
|
+
export declare function torus(major: number, minor: number, id?: string): Result<SdfHandle>;
|
|
58
|
+
/** A half-space: the plane through `h·n` with outward normal `n` (normalized). */
|
|
59
|
+
export declare function plane(n: [number, number, number], h: number, id?: string): Result<SdfHandle>;
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export { importSVGPathD, importSVG, type SVGImportOptions } from './io/svgImport
|
|
|
40
40
|
export { exportSTEPConfigured, type StepExportOptions, type StepExportPart, } from './io/stepConfigFns.js';
|
|
41
41
|
export { initVoxel, registerVoxel, getVoxel, getActiveVoxelId, windingNumbers, pointsInside, repairMesh, offsetMesh, shellMesh, voxelBoolean, offsetShape, shellShape, voxelBooleanShapes, voxelField, voxelBooleanField, fieldBoolean, fieldOffset, fieldShell, fieldReinit, fieldContour, voxelFieldFromShape, voxelBooleanFieldShapes, shapeToMeshInput, } from './voxel/index.js';
|
|
42
42
|
export type { VoxelEngine, VoxelMeshInput, VoxelRepairResult, RepairOptions, VoxelOpOptions, VoxelFieldHandle, VoxelFieldOptions, VoxelBooleanOp, } from './voxel/index.js';
|
|
43
|
+
export { sphere as sdfSphere, box as sdfBox, roundedBox as sdfRoundedBox, cylinder as sdfCylinder, cone as sdfCone, capsule as sdfCapsule, torus as sdfTorus, plane as sdfPlane, } from './implicit/index.js';
|
|
44
|
+
export type { SdfHandle, SdfBounds } from './implicit/index.js';
|
|
43
45
|
export { latticeInfill, latticeInfillShape, tpmsLattice } from './lattice/index.js';
|
|
44
46
|
export type { LatticeType, LatticeOptions, LatticeBounds } from './lattice/index.js';
|
|
45
47
|
export { default as Sketcher } from './sketching/sketcher.js';
|
package/dist/voxel/engine.d.ts
CHANGED
|
@@ -29,9 +29,60 @@ export interface VoxelEngine {
|
|
|
29
29
|
* satisfied by the generated `VoxelField` wasm-bindgen class.
|
|
30
30
|
*/
|
|
31
31
|
VoxelField: WasmVoxelFieldConstructor;
|
|
32
|
+
/**
|
|
33
|
+
* Field-first analytic SDF builder (ADR-0013). Static primitive constructors
|
|
34
|
+
* and combinator methods compose an opaque expression tree that rasterizes
|
|
35
|
+
* directly into a {@link WasmVoxelField} with no input mesh. Structurally
|
|
36
|
+
* satisfied by the generated `Sdf` wasm-bindgen class.
|
|
37
|
+
*/
|
|
38
|
+
Sdf: WasmSdfConstructor;
|
|
32
39
|
/** Engine artifact version, for loader/artifact compatibility checks. */
|
|
33
40
|
version(): string;
|
|
34
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Static surface of the wasm `Sdf` class: the primitive constructors that seed an
|
|
44
|
+
* expression tree (centered at the origin unless noted). Each returns a fresh
|
|
45
|
+
* {@link WasmSdf}. Structurally satisfied by the generated `Sdf` class.
|
|
46
|
+
*/
|
|
47
|
+
export interface WasmSdfConstructor {
|
|
48
|
+
sphere(r: number): WasmSdf;
|
|
49
|
+
box_(hx: number, hy: number, hz: number): WasmSdf;
|
|
50
|
+
rounded_box(hx: number, hy: number, hz: number, r: number): WasmSdf;
|
|
51
|
+
cylinder(r: number, h: number): WasmSdf;
|
|
52
|
+
cone(r: number, h: number): WasmSdf;
|
|
53
|
+
capsule(ax: number, ay: number, az: number, bx: number, by: number, bz: number, r: number): WasmSdf;
|
|
54
|
+
torus(major: number, minor: number): WasmSdf;
|
|
55
|
+
plane(nx: number, ny: number, nz: number, h: number): WasmSdf;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* An opaque analytic SDF expression. Every combinator CLONES into a new node and
|
|
59
|
+
* returns a fresh `WasmSdf` (wasm-bindgen has no shared borrow across calls), so an
|
|
60
|
+
* `Sdf` is a value, not a mutable builder. `rasterize` builds a banded-SDF
|
|
61
|
+
* {@link WasmVoxelField}; `free()` releases the backing WASM expression tree.
|
|
62
|
+
* Structurally satisfied by the generated `Sdf` wasm-bindgen class.
|
|
63
|
+
*/
|
|
64
|
+
export interface WasmSdf {
|
|
65
|
+
union(other: WasmSdf): WasmSdf;
|
|
66
|
+
intersection(other: WasmSdf): WasmSdf;
|
|
67
|
+
difference(other: WasmSdf): WasmSdf;
|
|
68
|
+
smooth_union(other: WasmSdf, k: number): WasmSdf;
|
|
69
|
+
smooth_intersection(other: WasmSdf, k: number): WasmSdf;
|
|
70
|
+
smooth_difference(other: WasmSdf, k: number): WasmSdf;
|
|
71
|
+
offset(d: number): WasmSdf;
|
|
72
|
+
round(r: number): WasmSdf;
|
|
73
|
+
shell(t: number): WasmSdf;
|
|
74
|
+
onion(t: number): WasmSdf;
|
|
75
|
+
translate(x: number, y: number, z: number): WasmSdf;
|
|
76
|
+
rotate(ax: number, ay: number, az: number, angle: number): WasmSdf;
|
|
77
|
+
scale(s: number): WasmSdf;
|
|
78
|
+
/** Rasterize into a banded-SDF dense field over the expression's analytic bounds. */
|
|
79
|
+
rasterize(resolution: number, padding: number): WasmVoxelField;
|
|
80
|
+
/** Rasterize over explicit `[min..max]` bounds (clips unbounded primitives). */
|
|
81
|
+
rasterize_in(min_x: number, min_y: number, min_z: number, max_x: number, max_y: number, max_z: number, resolution: number, padding: number): WasmVoxelField;
|
|
82
|
+
/** Release the backing WASM expression-tree allocation (wasm-bindgen lifecycle). */
|
|
83
|
+
free(): void;
|
|
84
|
+
[Symbol.dispose](): void;
|
|
85
|
+
}
|
|
35
86
|
/**
|
|
36
87
|
* Constructor of the wasm `VoxelField` class. `new VoxelField(verts, tris, res,
|
|
37
88
|
* padding)` voxelizes a mesh into a persistent dense field. Throws (as a JS
|
package/dist/voxel/fieldFns.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ export interface VoxelFieldHandle {
|
|
|
45
45
|
/** Surface-Nets contour the current field to a mesh (the field stays alive). */
|
|
46
46
|
contour(): KernelMeshResult;
|
|
47
47
|
}
|
|
48
|
+
export declare function makeFieldHandle(raw: WasmVoxelField): VoxelFieldHandle;
|
|
48
49
|
/**
|
|
49
50
|
* Voxelize a mesh into a persistent dense {@link VoxelFieldHandle}: one grid you
|
|
50
51
|
* can boolean / offset / shell / reinit in place, then contour once. The handle
|