@meshioplusplus/wasm 9.22.0 → 9.25.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
@@ -294,6 +294,49 @@ export type OpSpec =
294
294
  location?: 'point' | 'cell';
295
295
  output?: string;
296
296
  component?: number;
297
+ }
298
+ | {
299
+ /**
300
+ * A regular grid around the mesh. One of the two steps that replace their
301
+ * input's geometry rather than transforming it: what comes out is a
302
+ * lattice, not the mesh that went in. Give exactly one of `resolution` and
303
+ * `cellSize`.
304
+ */
305
+ op: 'voxelize';
306
+ resolution?: number[];
307
+ cellSize?: number;
308
+ bounds?: number[];
309
+ padding?: number;
310
+ paddingRelative?: number;
311
+ fill?: VoxelFill;
312
+ attachOccupancy?: boolean;
313
+ maxCells?: number;
314
+ sign?: SdfSign;
315
+ }
316
+ | {
317
+ /**
318
+ * A signed distance field: a grid over the mesh's surface, filled. Like
319
+ * `voxelize` it replaces the geometry — what comes out is the grid,
320
+ * carrying `sdf:distance`. `structure: 'octree'` refines only near the
321
+ * surface and sizes itself from `rootResolution`/`maxDepth`, so passing
322
+ * `resolution` or `cellSize` with it is an error; its output is
323
+ * 1-irregular (it has hanging nodes).
324
+ */
325
+ op: 'computeSdf';
326
+ structure?: SdfStructure;
327
+ resolution?: number[];
328
+ cellSize?: number;
329
+ bounds?: number[];
330
+ padding?: number;
331
+ paddingRelative?: number;
332
+ rootResolution?: number;
333
+ maxDepth?: number;
334
+ bandCells?: number;
335
+ recordLevels?: boolean;
336
+ maxCells?: number;
337
+ sign?: SdfSign;
338
+ location?: SdfLocation;
339
+ band?: number;
297
340
  };
298
341
 
299
342
  /** Per-operation counters and caveats from a pipeline run. */
@@ -305,6 +348,18 @@ export interface OpReport {
305
348
  /** `gradient`'s differential operator. See doc/gradient.md. */
306
349
  export type GradientOperator = 'gradient' | 'divergence' | 'curl';
307
350
 
351
+ /** Which cells `voxelize` keeps. See doc/voxelize.md. */
352
+ export type VoxelFill = 'all' | 'surface' | 'inside';
353
+
354
+ /** How a signed distance decides which side of the surface a point is on. */
355
+ export type SdfSign = 'unsigned' | 'pseudonormal' | 'winding-number';
356
+
357
+ /** Where a distance is evaluated on a mesh. */
358
+ export type SdfLocation = 'corner' | 'center';
359
+
360
+ /** What to do about a surface that is not watertight. */
361
+ export type SdfWatertightCheck = 'off' | 'warn' | 'error';
362
+
308
363
  /** `gradient`'s reconstruction method. See doc/gradient.md. */
309
364
  export type GradientMethod = 'green-gauss' | 'least-squares';
310
365
 
@@ -327,6 +382,12 @@ export type NanPolicy = 'ignore' | 'replace' | 'fail';
327
382
  /** Cell-keeping rule for the crop operations: every node inside, or any. */
328
383
  export type CropMode = 'all' | 'any';
329
384
 
385
+ /** Comparison for `cropPredicate` — the same vocabulary `refine`'s selector uses. */
386
+ export type CropCompare = '<' | '<=' | '>' | '>=' | '==' | '!=';
387
+
388
+ /** What `computeSdf` generates to carry the field. */
389
+ export type SdfStructure = 'voxel' | 'octree';
390
+
330
391
  /** Partitioning criterion for `split`. */
331
392
  export type SplitBy = 'type' | 'component' | 'region' | 'tag';
332
393
 
@@ -924,6 +985,34 @@ export interface MeshioPlusPlusModule {
924
985
  recordIds?: boolean,
925
986
  ): Mesh;
926
987
 
988
+ /**
989
+ * Subset a mesh to the cells whose value in a scalar `cell_data` array
990
+ * satisfies a comparison.
991
+ *
992
+ * Deliberately general rather than inside/outside-a-surface specific:
993
+ * inside/outside composes as `distanceToSurface(m, skin, 'pseudonormal',
994
+ * 'center')` then `cropPredicate(field.mesh, 'sdf:distance', '<', 0)`, and the
995
+ * same one mode also crops by `quality:*`, by a material id, or by anything
996
+ * `dataCalc` can produce.
997
+ *
998
+ * There is **no `mode`**: `cropBbox`/`cropPlane` test *points* and then need
999
+ * an all/any rule, whereas a `cell_data` predicate is already one value per
1000
+ * cell and has nothing to reduce.
1001
+ *
1002
+ * **A non-finite cell value never matches**, whatever the comparison —
1003
+ * `attachQuality` reports NaN where a metric does not apply.
1004
+ * @throws {Error} when `array` is not a scalar `cell_data` array covering
1005
+ * every block, or the comparison is not one of `<`, `<=`, `>`, `>=`, `==`,
1006
+ * `!=`.
1007
+ */
1008
+ cropPredicate(
1009
+ mesh: Mesh,
1010
+ array: string,
1011
+ compare?: CropCompare,
1012
+ value?: number,
1013
+ recordIds?: boolean,
1014
+ ): Mesh;
1015
+
927
1016
  /**
928
1017
  * Planar cross-section of a mesh (marching tetrahedra on a simplexified
929
1018
  * input): a volume mesh yields a triangle/quad surface, a 2D surface mesh a
@@ -953,6 +1042,120 @@ export interface MeshioPlusPlusModule {
953
1042
  recordParentIds?: boolean,
954
1043
  ): Mesh;
955
1044
 
1045
+ /**
1046
+ * A regular hexahedron lattice from nothing — the only entry point here that
1047
+ * creates a mesh rather than transforming one. Points run x fastest, then y,
1048
+ * then z; every cell is a right parallelepiped.
1049
+ * @throws {Error} on a negative cell count, a non-positive spacing, or a grid
1050
+ * above `maxCells`.
1051
+ */
1052
+ grid(dims: number[], origin?: number[] | null, spacing?: number[] | null,
1053
+ maxCells?: number): Mesh;
1054
+
1055
+ /**
1056
+ * Build a regular grid around a mesh. Give exactly one of `resolution` and
1057
+ * `cellSize`; `fill` selects the whole bounding box, only the cells a triangle
1058
+ * passes through, or only the cells inside the surface.
1059
+ * @throws {Error} when neither or both size options are given, on an unknown
1060
+ * `fill`/`sign`, or when the grid exceeds `maxCells`.
1061
+ */
1062
+ voxelize(
1063
+ mesh: Mesh,
1064
+ resolution?: number[] | null,
1065
+ cellSize?: number,
1066
+ bounds?: number[] | null,
1067
+ padding?: number,
1068
+ paddingRelative?: number,
1069
+ fill?: VoxelFill,
1070
+ sign?: SdfSign,
1071
+ attachOccupancy?: boolean,
1072
+ maxCells?: number,
1073
+ watertightCheck?: SdfWatertightCheck,
1074
+ ): {
1075
+ mesh: Mesh;
1076
+ dims: number[];
1077
+ origin: number[];
1078
+ spacing: number[];
1079
+ numOccupied: number;
1080
+ };
1081
+
1082
+ /** What is wrong with a surface, in numbers rather than a bare flag. */
1083
+ surfaceWatertightCheck(mesh: Mesh): {
1084
+ boundaryEdges: number;
1085
+ nonManifoldEdges: number;
1086
+ inconsistentPairs: number;
1087
+ degenerateTriangles: number;
1088
+ watertight: boolean;
1089
+ };
1090
+
1091
+ /**
1092
+ * Signed distances from a flat `[x0,y0,z0, x1,y1,z1, …]` array of query points
1093
+ * to a surface. Negative is inside.
1094
+ * @throws {Error} when the array length is not a multiple of three, or the
1095
+ * surface has no triangles.
1096
+ */
1097
+ sampleDistance(surface: Mesh, points: number[], sign?: SdfSign, band?: number,
1098
+ watertightCheck?: SdfWatertightCheck): Float64Array;
1099
+
1100
+ /**
1101
+ * Attach the signed distance from a query mesh's points (or cell centres) to a
1102
+ * surface, as `sdf:distance`.
1103
+ */
1104
+ distanceToSurface(
1105
+ query: Mesh,
1106
+ surface: Mesh,
1107
+ sign?: SdfSign,
1108
+ location?: SdfLocation,
1109
+ band?: number,
1110
+ recordInside?: boolean,
1111
+ watertightCheck?: SdfWatertightCheck,
1112
+ ): { mesh: Mesh; numBanded: number; quality: object };
1113
+
1114
+ /**
1115
+ * Generate a grid over a surface and fill it with signed distances — the one
1116
+ * call that turns a surface into a field.
1117
+ *
1118
+ * `structure` is `'voxel'` (a dense lattice) or `'octree'` (refined near the
1119
+ * surface, and therefore **1-irregular**: it has hanging nodes, like
1120
+ * `refine`'s `'balanced'` closure). `resolution`/`cellSize` size a voxel grid
1121
+ * and are an **error** with `'octree'`, whose finest cell is
1122
+ * `rootResolution / 2 ** maxDepth` and is therefore already determined.
1123
+ *
1124
+ * `dims` reports the ROOT cell counts and `spacing` the FINEST cell size. The
1125
+ * mesh also carries the numeric `sdf:*` `field_data` header describing itself;
1126
+ * no file format persists arbitrary `field_data`, so write it as `.vti`, whose
1127
+ * `Origin`/`Spacing`/`WholeExtent` attributes are the same information.
1128
+ * @throws {Error} when neither or both size options are given for a voxel
1129
+ * grid, when either is given for an octree, on a non-positive
1130
+ * `rootResolution`/`bandCells`, or when the grid exceeds `maxCells`.
1131
+ */
1132
+ computeSdf(
1133
+ surface: Mesh,
1134
+ structure?: SdfStructure,
1135
+ resolution?: number[] | null,
1136
+ cellSize?: number,
1137
+ bounds?: number[] | null,
1138
+ padding?: number,
1139
+ paddingRelative?: number,
1140
+ rootResolution?: number,
1141
+ maxDepth?: number,
1142
+ bandCells?: number,
1143
+ recordLevels?: boolean,
1144
+ maxCells?: number,
1145
+ sign?: SdfSign,
1146
+ location?: SdfLocation,
1147
+ band?: number,
1148
+ watertightCheck?: SdfWatertightCheck,
1149
+ ): {
1150
+ mesh: Mesh;
1151
+ dims: number[];
1152
+ origin: number[];
1153
+ spacing: number[];
1154
+ maxDepth: number;
1155
+ numBanded: number;
1156
+ quality: object;
1157
+ };
1158
+
956
1159
  /**
957
1160
  * Field differential operators: the gradient, divergence or curl of a
958
1161
  * `point_data` field. `"green-gauss"` applies the divergence theorem over the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshioplusplus/wasm",
3
- "version": "9.22.0",
3
+ "version": "9.25.0",
4
4
  "description": "meshio++ mesh I/O compiled to WebAssembly: read/write 41 mesh formats (incl. MED, CGNS, Exodus) in the browser or Node.js",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
package/src/index.mjs CHANGED
@@ -150,8 +150,15 @@ function resolveVariant(variant) {
150
150
  * smooth: (mesh: Mesh, method?: string, iterations?: number, lambda?: number, mu?: number, fixBoundary?: boolean, preserveFeatures?: boolean, featureAngle?: number, guardInversion?: boolean) => {mesh: Mesh, numNodesMoved: number, maxDisplacement: number, numSkippedInversion: number},
151
151
  * cropBbox: (mesh: Mesh, lo: number[], hi: number[], mode?: string, recordIds?: boolean) => Mesh,
152
152
  * cropPlane: (mesh: Mesh, point: number[], normal: number[], mode?: string, recordIds?: boolean) => Mesh,
153
+ * cropPredicate: (mesh: Mesh, array: string, compare?: string, value?: number, recordIds?: boolean) => Mesh,
153
154
  * slice: (mesh: Mesh, origin: number[], normal: number[], recordParentIds?: boolean) => Mesh,
154
155
  * isosurface: (mesh: Mesh, array: string, isovalues: number|number[], component?: number, recordParentIds?: boolean) => Mesh,
156
+ * grid: (dims: number[], origin?: number[], spacing?: number[], maxCells?: number) => Mesh,
157
+ * 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},
158
+ * surfaceWatertightCheck: (mesh: Mesh) => {boundaryEdges: number, nonManifoldEdges: number, inconsistentPairs: number, degenerateTriangles: number, watertight: boolean},
159
+ * sampleDistance: (surface: Mesh, points: number[], sign?: string, band?: number, watertightCheck?: string) => Float64Array,
160
+ * distanceToSurface: (query: Mesh, surface: Mesh, sign?: string, location?: string, band?: number, recordInside?: boolean, watertightCheck?: string) => {mesh: Mesh, numBanded: number, quality: object},
161
+ * computeSdf: (surface: Mesh, structure?: string, resolution?: number[], cellSize?: number, bounds?: number[], padding?: number, paddingRelative?: number, rootResolution?: number, maxDepth?: number, bandCells?: number, recordLevels?: boolean, maxCells?: number, sign?: string, location?: string, band?: number, watertightCheck?: string) => {mesh: Mesh, dims: number[], origin: number[], spacing: number[], maxDepth: number, numBanded: number, quality: object},
155
162
  * gradient: (mesh: Mesh, array: string, operator?: string, method?: string, location?: string, output?: string, component?: number, overwrite?: boolean) => {mesh: Mesh, numSkipped: number, numFallback: number},
156
163
  * split: (mesh: Mesh, by: string, tagName?: string) => {key: string, mesh: Mesh}[],
157
164
  * convertCells: (mesh: Mesh, mode?: string, recordParentIds?: boolean) => Mesh,
@@ -349,8 +356,62 @@ export async function loadMeshioPlusPlus(moduleOverrides = {}, { variant = 'auto
349
356
  Module.cropBbox(mesh, lo, hi, mode, recordIds),
350
357
  cropPlane: (mesh, point, normal, mode = 'all', recordIds = false) =>
351
358
  Module.cropPlane(mesh, point, normal, mode, recordIds),
359
+ cropPredicate: (mesh, array, compare = '<', value = 0, recordIds = false) =>
360
+ Module.cropPredicate(mesh, array, compare, value, recordIds),
352
361
  slice: (mesh, origin, normal, recordParentIds = false) =>
353
362
  Module.slice(mesh, origin, normal, recordParentIds),
363
+ grid: (dims, origin = null, spacing = null, maxCells = 20000000) =>
364
+ Module.grid(dims, origin, spacing, maxCells),
365
+ voxelize: (
366
+ mesh,
367
+ resolution = null,
368
+ cellSize = 0,
369
+ bounds = null,
370
+ padding = 0,
371
+ paddingRelative = 0,
372
+ fill = 'all',
373
+ sign = 'pseudonormal',
374
+ attachOccupancy = false,
375
+ maxCells = 20000000,
376
+ watertightCheck = 'warn',
377
+ ) =>
378
+ Module.voxelize(mesh, resolution, cellSize, bounds, padding, paddingRelative,
379
+ fill, sign, attachOccupancy, maxCells, watertightCheck),
380
+ surfaceWatertightCheck: (mesh) => Module.surfaceWatertightCheck(mesh),
381
+ sampleDistance: (surface, points, sign = 'pseudonormal', band = 0, watertightCheck = 'warn') =>
382
+ Module.sampleDistance(surface, points, sign, band, watertightCheck),
383
+ distanceToSurface: (
384
+ query,
385
+ surface,
386
+ sign = 'pseudonormal',
387
+ location = 'corner',
388
+ band = 0,
389
+ recordInside = false,
390
+ watertightCheck = 'warn',
391
+ ) =>
392
+ Module.distanceToSurface(query, surface, sign, location, band, recordInside,
393
+ watertightCheck),
394
+ computeSdf: (
395
+ surface,
396
+ structure = 'voxel',
397
+ resolution = null,
398
+ cellSize = 0,
399
+ bounds = null,
400
+ padding = 0,
401
+ paddingRelative = 0.1,
402
+ rootResolution = 8,
403
+ maxDepth = 4,
404
+ bandCells = 1,
405
+ recordLevels = true,
406
+ maxCells = 20000000,
407
+ sign = 'pseudonormal',
408
+ location = 'corner',
409
+ band = 0,
410
+ watertightCheck = 'warn',
411
+ ) =>
412
+ Module.computeSdf(surface, structure, resolution, cellSize, bounds, padding,
413
+ paddingRelative, rootResolution, maxDepth, bandCells, recordLevels, maxCells,
414
+ sign, location, band, watertightCheck),
354
415
  isosurface: (mesh, array, isovalues, component = -1, recordParentIds = false) =>
355
416
  Module.isosurface(
356
417
  mesh,