@meshioplusplus/wasm 17.7.0 → 17.9.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/index.d.ts CHANGED
@@ -902,6 +902,36 @@ export type OpSpec =
902
902
  maxCells?: number;
903
903
  sign?: SdfSign;
904
904
  }
905
+ | {
906
+ /**
907
+ * An octree (quadtree for a planar `line` skin) around the mesh: leaves
908
+ * are fine only where the skin is. Like `voxelize` it replaces the
909
+ * geometry; the result carries `octree:level`/`octree:cut` cell data and
910
+ * `octree:hanging` point data.
911
+ */
912
+ op: 'octree';
913
+ rootCells?: number[];
914
+ minLevel?: number;
915
+ maxLevel?: number;
916
+ bounds?: number[];
917
+ padding?: number;
918
+ paddingRelative?: number;
919
+ dimension?: number;
920
+ sampleDistance?: number;
921
+ balance?: OctreeBalance;
922
+ fill?: VoxelFill;
923
+ attachDistance?: boolean;
924
+ evenOdd?: boolean;
925
+ maxCells?: number;
926
+ sign?: SdfSign;
927
+ transition?: OctreeTransition;
928
+ snap?: boolean;
929
+ surfaceLevel?: number;
930
+ curvatureThreshold?: number;
931
+ featureAngle?: number;
932
+ sizeArray?: string;
933
+ plane?: PlanarPlane;
934
+ }
905
935
  | {
906
936
  /**
907
937
  * A signed distance field: a grid over the mesh's surface, filled. Like
@@ -971,6 +1001,15 @@ export type GradientOperator = 'gradient' | 'divergence' | 'curl';
971
1001
  /** Which cells `voxelize` keeps. See doc/voxelize.md. */
972
1002
  export type VoxelFill = 'all' | 'surface' | 'inside';
973
1003
 
1004
+ /** How strictly `octree` keeps neighbouring leaves the same size. See doc/octree.md. */
1005
+ export type OctreeBalance = 'none' | 'face' | 'full';
1006
+
1007
+ /** What `octree` emits where a fine leaf meets a coarse one. See doc/octree.md. */
1008
+ export type OctreeTransition = 'hanging' | 'polyhedra' | 'templates';
1009
+
1010
+ /** The plane of a 2-D skin. */
1011
+ export type PlanarPlane = 'auto' | 'xy' | 'xz' | 'yz';
1012
+
974
1013
  /** How a signed distance decides which side of the surface a point is on. */
975
1014
  export type SdfSign = 'unsigned' | 'pseudonormal' | 'winding-number';
976
1015
 
@@ -1105,8 +1144,9 @@ export type InterpolateOnConflict = 'error' | 'overwrite' | 'suffix';
1105
1144
  * exists on the target: throw, replace, or write to `name + '_interp'`. */
1106
1145
  export type ConservativeInterpolateOnConflict = 'error' | 'overwrite' | 'suffix';
1107
1146
 
1108
- /** Partitioning backend: SFC is always available; KaHIP is never compiled
1109
- * into the WASM build, so `'kahip'` always throws and `'auto'` = `'sfc'`. */
1147
+ /** Partitioning backend: SFC is always available; KaHIP is linked only in
1148
+ * the full artifact, so `'kahip'` throws there outside it and `'auto'`
1149
+ * resolves to SFC. */
1110
1150
  export type PartitionMethod = 'sfc' | 'kahip' | 'auto';
1111
1151
 
1112
1152
  /** KaHIP preconfiguration (ignored by the SFC method). */
@@ -1704,10 +1744,18 @@ export interface MeshioPlusPlusModule {
1704
1744
 
1705
1745
  /**
1706
1746
  * Whether OpenCASCADE is linked in, so `step` and `iges` read and `fitCad`
1707
- * runs: true in the full artifact (`{full: true}`), false in the lean one.
1747
+ * has its OpenCASCADE backend: true in the full artifact (`{full: true}`),
1748
+ * false in the lean one (where `fitCad` runs the native backend).
1708
1749
  */
1709
1750
  hasOcct(): boolean;
1710
1751
 
1752
+ /**
1753
+ * Whether the KaHIP kaffpa partitioner is linked in, so `partition` with
1754
+ * `method: 'kahip'` runs: true in the full artifact (`{full: true}`),
1755
+ * false in the lean one.
1756
+ */
1757
+ hasKahip(): boolean;
1758
+
1711
1759
  /** Whether the VTK XML zstd block codec is linked in (the full artifact). */
1712
1760
  hasZstd(): boolean;
1713
1761
 
@@ -2046,6 +2094,51 @@ export interface MeshioPlusPlusModule {
2046
2094
  numOccupied: number;
2047
2095
  };
2048
2096
 
2097
+ /**
2098
+ * Build an octree (a quadtree for a planar `line` skin) around a mesh: leaves
2099
+ * are fine only where the skin is. `balance` keeps neighbours within 2:1;
2100
+ * `fill` is as for `voxelize`. Pass `null` for `rootCells`/`bounds` to take the
2101
+ * defaults.
2102
+ * @throws {Error} on an empty or oversized level range, an unknown
2103
+ * `balance`/`fill`/`sign`, an open polyline with `fill: 'inside'`, or when
2104
+ * the tree exceeds `maxCells`.
2105
+ */
2106
+ octree(
2107
+ mesh: Mesh,
2108
+ rootCells?: number[] | null,
2109
+ minLevel?: number,
2110
+ maxLevel?: number,
2111
+ bounds?: number[] | null,
2112
+ padding?: number,
2113
+ paddingRelative?: number,
2114
+ dimension?: number,
2115
+ sampleDistance?: number,
2116
+ balance?: OctreeBalance,
2117
+ fill?: VoxelFill,
2118
+ sign?: SdfSign,
2119
+ attachDistance?: boolean,
2120
+ evenOdd?: boolean,
2121
+ maxCells?: number,
2122
+ watertightCheck?: SdfWatertightCheck,
2123
+ transition?: OctreeTransition,
2124
+ snap?: boolean,
2125
+ surfaceLevel?: number,
2126
+ curvatureThreshold?: number,
2127
+ featureAngle?: number,
2128
+ sizeArray?: string,
2129
+ plane?: PlanarPlane,
2130
+ ): {
2131
+ mesh: Mesh;
2132
+ dimension: number;
2133
+ numLeaves: number;
2134
+ numHanging: number;
2135
+ finestLevel: number;
2136
+ origin: number[];
2137
+ rootSize: number;
2138
+ numSnapped: number;
2139
+ numRefused: number;
2140
+ };
2141
+
2049
2142
  /** What is wrong with a surface, in numbers rather than a bare flag. */
2050
2143
  surfaceWatertightCheck(mesh: Mesh): {
2051
2144
  boundaryEdges: number;
@@ -2499,7 +2592,10 @@ export interface MeshioPlusPlusModule {
2499
2592
  * feature edges. The mesh comes back unchanged plus cell data
2500
2593
  * `segment:patch` (-1 off the surface), field data `segment:adjacency`
2501
2594
  * (rows `[a, b, sharedEdges]`) and one cell region per patch,
2502
- * `<prefix>:<k>`. See doc/segment.md.
2595
+ * `<prefix>:<k>`. `method: 'primitive'` (v17.9.0) ends a patch where the
2596
+ * surface its facets lie on changes, at `tolerance` (relative to the
2597
+ * diagonal), so a fillet comes apart from its tangent planes. See
2598
+ * doc/segment.md.
2503
2599
  * @throws {Error} on an option out of range, an unknown region or a volume block.
2504
2600
  */
2505
2601
  segment(
@@ -2510,6 +2606,8 @@ export interface MeshioPlusPlusModule {
2510
2606
  minPatchCells?: number,
2511
2607
  region?: string,
2512
2608
  prefix?: string,
2609
+ method?: 'angle' | 'primitive',
2610
+ tolerance?: number,
2513
2611
  ): {
2514
2612
  mesh: Mesh;
2515
2613
  numPatches: number;
@@ -2551,10 +2649,12 @@ export interface MeshioPlusPlusModule {
2551
2649
  * output of `segment` then `fitPrimitives`): planes, spheres, cylinders,
2552
2650
  * cones and tori, fillets and blends, threads and freeform B-spline faces,
2553
2651
  * sewn and checked by OpenCASCADE, optionally written as STEP to
2554
- * `stepPath` on the virtual FS. Needs OpenCASCADE: the full artifact only.
2555
- * See doc/fit_cad.md.
2556
- * @throws {Error} in the lean artifact (naming `{full: true}`), on a bad
2557
- * option, or on a skin that is not closed.
2652
+ * `stepPath` on the virtual FS. The lean artifact (and `backend: 'native'`)
2653
+ * runs the kernel-free backend instead (v17.9.0): the fitted patches become
2654
+ * analytic STEP faces, the rest coplanar polygons, and `mesh` is the skin
2655
+ * itself. See doc/fit_cad.md.
2656
+ * @throws {Error} with `backend: 'occt'` in the lean artifact (naming
2657
+ * `{full: true}`), on a bad option, or on a skin that is not closed.
2558
2658
  */
2559
2659
  fitCad(mesh: Mesh, options?: FitCadOptions): FitCadResult;
2560
2660
 
@@ -3045,9 +3145,9 @@ export interface MeshioPlusPlusModule {
3045
3145
  * scalar `cell_data` array of per-cell weights. `ghostLayers > 0` grows
3046
3146
  * each piece by that many shared-node BFS layers of other parts' cells (a
3047
3147
  * halo), tagged `partition:ghost`.
3048
- * @throws {Error} on `method: 'kahip'` (KaHIP is never part of the WASM
3049
- * build; the message names `MESHIOPLUSPLUS_WITH_KAHIP`), `nparts < 1`,
3050
- * `ghostLayers < 0`, or a bad weights array.
3148
+ * @throws {Error} on `method: 'kahip'` outside the full artifact (KaHIP
3149
+ * is linked only there; the message names `MESHIOPLUSPLUS_WITH_KAHIP`),
3150
+ * `nparts < 1`, `ghostLayers < 0`, or a bad weights array.
3051
3151
  */
3052
3152
  partition(
3053
3153
  mesh: Mesh,
@@ -3290,6 +3390,10 @@ export interface FitCadOptions {
3290
3390
  fillets?: boolean;
3291
3391
  /** Try thread faces, tapered and of varying pitch included (default true). */
3292
3392
  threads?: boolean;
3393
+ /** Merge faces on one surface once the solid is built (default true; v17.9.0). */
3394
+ mergeFaces?: boolean;
3395
+ /** The engine: OpenCASCADE when linked in (`'auto'`, the default), or none (v17.9.0). */
3396
+ backend?: 'auto' | 'occt' | 'native';
3293
3397
  }
3294
3398
 
3295
3399
  /** What {@link MeshioPlusPlusModule.fitCad} built. */
@@ -3333,6 +3437,8 @@ export interface FitCadResult {
3333
3437
  numTaperedThread: number;
3334
3438
  /** Thread flanks whose pitch varies along the axis. */
3335
3439
  numVariablePitchThread: number;
3440
+ /** The engine that built the solid (v17.9.0). */
3441
+ backend: 'occt' | 'native';
3336
3442
  /** The solid's B-rep, for `writeMesh(path, mesh, 'cad_json', {info})`. */
3337
3443
  info: CadJsonInfo;
3338
3444
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshioplusplus/wasm",
3
- "version": "17.7.0",
3
+ "version": "17.9.0",
4
4
  "description": "meshio++ mesh I/O compiled to WebAssembly: read 80 and write 75 mesh formats (incl. MED, CGNS, Exodus; STEP and IGES in the full build) in the browser or Node.js",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
package/src/index.mjs CHANGED
@@ -32,7 +32,7 @@
32
32
  //
33
33
  // Beside that lean pair the package ships the FULL pair (roadmap 6.2),
34
34
  // meshioplusplus_wasm_full and meshioplusplus_wasm_full_mt: the same API, with
35
- // OpenCASCADE (STEP/IGES reading, fitCad), zstd, lz4 and bzip2 linked in, and
35
+ // OpenCASCADE (STEP/IGES reading, fitCad's OpenCASCADE backend), zstd, lz4 and bzip2 linked in, and
36
36
  // a mixed licence (OpenCASCADE is LGPL-2.1 with its exception; see
37
37
  // THIRD_PARTY_NOTICES.md). `{ full: true }` loads it, with the same variant
38
38
  // choice. Its import() is deliberately NOT literal: a bundler that saw it would
@@ -249,6 +249,7 @@ export class MeshioPlusPlusLoadError extends Error {
249
249
  * parallelBackend: () => string,
250
250
  * hasCgnslib: () => boolean,
251
251
  * hasOcct: () => boolean,
252
+ * hasKahip: () => boolean,
252
253
  * hasZstd: () => boolean,
253
254
  * hasLz4: () => boolean,
254
255
  * hasBzip2: () => boolean,
@@ -276,6 +277,7 @@ export class MeshioPlusPlusLoadError extends Error {
276
277
  * isosurface: (mesh: Mesh, array: string, isovalues: number|number[], component?: number, recordParentIds?: boolean) => Mesh,
277
278
  * grid: (dims: number[], origin?: number[], spacing?: number[], maxCells?: number) => Mesh,
278
279
  * voxelize: (mesh: Mesh, resolution?: number[], cellSize?: number, bounds?: number[], padding?: number, paddingRelative?: number, fill?: string, sign?: string, attachOccupancy?: boolean, maxCells?: number, watertightCheck?: string) => {mesh: Mesh, dims: number[], origin: number[], spacing: number[], numOccupied: number},
280
+ * octree: (mesh: Mesh, rootCells?: number[], minLevel?: number, maxLevel?: number, bounds?: number[], padding?: number, paddingRelative?: number, dimension?: number, sampleDistance?: number, balance?: string, fill?: string, sign?: string, attachDistance?: boolean, evenOdd?: boolean, maxCells?: number, watertightCheck?: string, transition?: string, snap?: boolean, surfaceLevel?: number, curvatureThreshold?: number, featureAngle?: number, sizeArray?: string, plane?: string) => {mesh: Mesh, dimension: number, numLeaves: number, numHanging: number, finestLevel: number, origin: number[], rootSize: number, numSnapped: number, numRefused: number},
279
281
  * surfaceWatertightCheck: (mesh: Mesh) => {boundaryEdges: number, nonManifoldEdges: number, inconsistentPairs: number, degenerateTriangles: number, watertight: boolean},
280
282
  * sampleDistance: (surface: Mesh, points: number[], sign?: string, band?: number, watertightCheck?: string) => Float64Array,
281
283
  * distanceToSurface: (query: Mesh, surface: Mesh, sign?: string, location?: string, band?: number, recordInside?: boolean, watertightCheck?: string) => {mesh: Mesh, numBanded: number, quality: object},
@@ -290,12 +292,12 @@ export class MeshioPlusPlusLoadError extends Error {
290
292
  * computeNormals: (mesh: Mesh, pointNormals?: boolean, cellNormals?: boolean, weight?: string, splitAngle?: number, recordParentIds?: boolean, region?: string) => {mesh: Mesh, numIsolated: number, numUndefined: number, numDegenerate: number, numSplitPoints: number, numAddedPoints: number, quality: {boundaryEdges: number, nonManifoldEdges: number, inconsistentPairs: number, degenerateTriangles: number, watertight: boolean}},
291
293
  * checkQuality: (mesh: Mesh, require?: string, maxInverted?: number, maxDegenerate?: number) => {passed: boolean, numCells: number, numInverted: number, numDegenerate: number, checks: Array<object>, summary: string},
292
294
  * featureEdges: (mesh: Mesh, featureAngle?: number, feature?: boolean, boundary?: boolean, nonManifold?: boolean, inconsistent?: boolean, region?: string) => {mesh: Mesh, numFeature: number, numBoundary: number, numNonManifold: number, numInconsistent: number},
293
- * segment: (mesh: Mesh, featureAngle?: number, normalTolerance?: number, curvatureTolerance?: number, minPatchCells?: number, region?: string, prefix?: string) => {mesh: Mesh, numPatches: number, numMerged: number, numFeatureEdges: number, numBoundaryEdges: number, numNonManifoldEdges: number},
295
+ * segment: (mesh: Mesh, featureAngle?: number, normalTolerance?: number, curvatureTolerance?: number, minPatchCells?: number, region?: string, prefix?: string, method?: 'angle' | 'primitive', tolerance?: number) => {mesh: Mesh, numPatches: number, numMerged: number, numFeatureEdges: number, numBoundaryEdges: number, numNonManifoldEdges: number},
294
296
  * igaRefine: (info: object, options?: {subdivisions?: number | number[], elevate?: number | number[], sampleSubdivisions?: number, trimSamples?: number, edges?: boolean, trim?: boolean}) => {mesh: Mesh, info: object},
295
297
  * igaSample: (info: object, options?: {sampleSubdivisions?: number, trimSamples?: number, edges?: boolean, trim?: boolean}) => {mesh: Mesh, info: object},
296
298
  * igaEvaluate: (info: object, patch: number, params: ArrayLike<number>, options?: {derivatives?: 0 | 1, trimSamples?: number}) => object,
297
299
  * fitPrimitives: (mesh: Mesh, patchData?: string, tolerance?: number, relative?: boolean, minInlierFraction?: number, types?: string[], maxIterations?: number) => {mesh: Mesh, numPatches: number, numPlane: number, numSphere: number, numCylinder: number, numCone: number, numTorus: number, numUnfitted: number},
298
- * fitCad: (mesh: Mesh, options?: {stepPath?: string, tolerance?: number, exactEdges?: boolean, types?: string[], meshDeflection?: number, maxDemotionRounds?: number, freeform?: boolean, freeformDegree?: number, freeformMaxControl?: number, freeformSplit?: boolean, fillets?: boolean, threads?: boolean}) => object,
300
+ * fitCad: (mesh: Mesh, options?: {stepPath?: string, tolerance?: number, exactEdges?: boolean, types?: string[], meshDeflection?: number, maxDemotionRounds?: number, freeform?: boolean, freeformDegree?: number, freeformMaxControl?: number, freeformSplit?: boolean, fillets?: boolean, threads?: boolean, mergeFaces?: boolean, backend?: 'auto' | 'occt' | 'native'}) => object,
299
301
  * tessellate: (mesh: Mesh, levels?: number, curved?: boolean, fields?: boolean, recordStencil?: boolean) => {mesh: Mesh, numSourcePoints: number, numSourceCells: number, numCurvedSourceCells: number, numPassThroughSourceCells: number, numPoints: number, numCells: number, numBoundaryFacets: number, numInteriorFacets: number, numFacetsWithBadCount: number},
300
302
  * render: (mesh: Mesh, options?: RenderOptions) => RenderedFrame,
301
303
  * renderText: (mesh: Mesh, options?: RenderOptions, text?: RenderTextOptions) => string,
@@ -600,9 +602,10 @@ export async function loadMeshioPlusPlus(
600
602
  // meshioplusplus_wasm_mt one -- which of the two this instance loaded.
601
603
  parallelBackend: () => Module.parallelBackend(),
602
604
  hasCgnslib: () => Module.hasCgnslib(),
603
- // The full artifact's libraries (roadmap 6.2): all four are true there
605
+ // The full artifact's libraries (roadmap 6.2): all five are true there
604
606
  // and false in the lean one. buildFlavour() names which loaded.
605
607
  hasOcct: () => Module.hasOcct(),
608
+ hasKahip: () => Module.hasKahip(),
606
609
  hasZstd: () => Module.hasZstd(),
607
610
  hasLz4: () => Module.hasLz4(),
608
611
  hasBzip2: () => Module.hasBzip2(),
@@ -755,6 +758,35 @@ export async function loadMeshioPlusPlus(
755
758
  ) =>
756
759
  Module.voxelize(mesh, resolution, cellSize, bounds, padding, paddingRelative,
757
760
  fill, sign, attachOccupancy, maxCells, watertightCheck),
761
+ octree: (
762
+ mesh,
763
+ rootCells = null,
764
+ minLevel = 0,
765
+ maxLevel = 4,
766
+ bounds = null,
767
+ padding = 0,
768
+ paddingRelative = 0,
769
+ dimension = 0,
770
+ sampleDistance = 0,
771
+ balance = 'face',
772
+ fill = 'all',
773
+ sign = 'pseudonormal',
774
+ attachDistance = false,
775
+ evenOdd = false,
776
+ maxCells = 20000000,
777
+ watertightCheck = 'warn',
778
+ transition = 'hanging',
779
+ snap = false,
780
+ surfaceLevel = -1,
781
+ curvatureThreshold = 0,
782
+ featureAngle = 0,
783
+ sizeArray = '',
784
+ plane = 'auto',
785
+ ) =>
786
+ Module.octree(mesh, rootCells, minLevel, maxLevel, bounds, padding, paddingRelative,
787
+ dimension, sampleDistance, balance, fill, sign, attachDistance, evenOdd, maxCells,
788
+ watertightCheck, transition, snap, surfaceLevel, curvatureThreshold, featureAngle,
789
+ sizeArray, plane),
758
790
  surfaceWatertightCheck: (mesh) => Module.surfaceWatertightCheck(mesh),
759
791
  sampleDistance: (surface, points, sign = 'pseudonormal', band = 0, watertightCheck = 'warn') =>
760
792
  Module.sampleDistance(surface, points, sign, band, watertightCheck),
@@ -932,9 +964,11 @@ export async function loadMeshioPlusPlus(
932
964
  minPatchCells = 1,
933
965
  region = '',
934
966
  prefix = 'patch',
967
+ method = 'angle',
968
+ tolerance = 1e-3,
935
969
  ) =>
936
970
  Module.segment(mesh, featureAngle, normalTolerance, curvatureTolerance,
937
- minPatchCells, region, prefix),
971
+ minPatchCells, region, prefix, method, tolerance),
938
972
  fitPrimitives: (
939
973
  mesh,
940
974
  patchData = 'segment:patch',