@meshioplusplus/wasm 10.21.1 → 12.0.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
@@ -7,6 +7,53 @@
7
7
  * A rectangular (uniform node count) group of cells, all the same meshio++
8
8
  * cell type.
9
9
  */
10
+ /**
11
+ * What is wrong with a surface, in numbers rather than a bare flag -- the four
12
+ * counts `surfaceWatertightCheck`, `computeCurvature`, `repair` and
13
+ * `shrinkwrap` all report.
14
+ */
15
+ export interface SurfaceQualityInfo {
16
+ boundaryEdges: number;
17
+ nonManifoldEdges: number;
18
+ inconsistentPairs: number;
19
+ degenerateTriangles: number;
20
+ watertight: boolean;
21
+ }
22
+
23
+ /**
24
+ * A `point_data`/`cell_data`/`field_data` array's JS type: it carries its
25
+ * source dtype crossing the WASM boundary instead of always widening to
26
+ * `Float64Array` (roadmap §1 "WASM parity": dtype carry). `BigInt64Array`/
27
+ * `BigUint64Array` elements are JS `bigint`, not `number` -- see
28
+ * {@link XdmfTimeSeriesWriter.writeDataArrays} if you need to feed one to an
29
+ * API that still expects `number`s.
30
+ */
31
+ export type DataArray =
32
+ | Float32Array
33
+ | Float64Array
34
+ | Int8Array
35
+ | Int16Array
36
+ | Int32Array
37
+ | BigInt64Array
38
+ | Uint8Array
39
+ | Uint16Array
40
+ | Uint32Array
41
+ | BigUint64Array;
42
+
43
+ /**
44
+ * The index maps an op that prunes/renumbers points and cells returns when
45
+ * called with `returnMaps: true`, alongside its `mesh`: `pointMap` is input
46
+ * point index -> output point index (-1 if pruned), `cellMaps` is one array
47
+ * per **input** cell block, input cell -> output index within the
48
+ * corresponding output block (-1 if dropped). See doc/wasm.md's "Index maps"
49
+ * section for the per-op semantics (e.g. what a collapsed/welded point's
50
+ * -1-or-survivor value means).
51
+ */
52
+ export interface PointCellMaps {
53
+ pointMap: Int32Array;
54
+ cellMaps: Int32Array[];
55
+ }
56
+
10
57
  export interface RectangularCellBlock {
11
58
  /** meshio++ cell type name, e.g. "triangle", "tetra10", "hexahedron". */
12
59
  type: string;
@@ -37,10 +84,11 @@ export interface PolygonCellBlock {
37
84
  * start index into the face list (length numCells + 1, so cell `c`'s faces
38
85
  * are `faceOffsets[cellOffsets[c]] .. faceOffsets[cellOffsets[c + 1]]`).
39
86
  *
40
- * No C++ format writer accepts a polyhedron block yet (a documented,
41
- * pre-existing gap) -- this shape crosses the JS boundary correctly (e.g.
42
- * through {@link MeshioPlusPlusModule.clean} or any other operation) but
43
- * `writeMesh` will throw naming the format when asked to write one.
87
+ * `writeMesh` accepts a polyhedron block for the formats that can hold one
88
+ * (`vtu`, `ensight` nfaced, `cgns` NFACE_n, `med` POE, `openfoam`); a format
89
+ * that cannot (legacy `vtk`, `vtp`, ...) throws naming the format. The shape
90
+ * also crosses the JS boundary unchanged through operations such as
91
+ * {@link MeshioPlusPlusModule.clean}.
44
92
  */
45
93
  export interface PolyhedronCellBlock {
46
94
  type: string;
@@ -68,9 +116,10 @@ export interface Mesh {
68
116
  /**
69
117
  * name -> flat, row-major per-point data. A multi-component (vector/tensor)
70
118
  * array is stored interleaved, `numPoints * components` long, with its width
71
- * declared in {@link Mesh.point_data_components}.
119
+ * declared in {@link Mesh.point_data_components}. Each array's JS type is
120
+ * its source dtype (see {@link DataArray}), not always `Float64Array`.
72
121
  */
73
- point_data?: Record<string, Float64Array>;
122
+ point_data?: Record<string, DataArray>;
74
123
  /**
75
124
  * Per-entity width of any `point_data` array that is not a scalar, since a
76
125
  * flat typed array carries no shape. A name absent here has one component.
@@ -78,8 +127,13 @@ export interface Mesh {
78
127
  * scalar-only mesh gets an empty object.
79
128
  */
80
129
  point_data_components?: Record<string, number>;
81
- /** name -> one flat array per cell block, same order as `cells`. */
82
- cell_data?: Record<string, Float64Array[]>;
130
+ /**
131
+ * name -> one flat array per cell block, same order as `cells`. Every
132
+ * block of one named array shares the same {@link DataArray} class --
133
+ * `writeMesh`/`convert`-side callers that mix classes across blocks of the
134
+ * same name get a thrown Error naming the array.
135
+ */
136
+ cell_data?: Record<string, DataArray[]>;
83
137
  /**
84
138
  * Per-entity width of any `cell_data` array that is not a scalar. One value
85
139
  * per *array*, not per block: every block of a named cell_data array must
@@ -87,11 +141,141 @@ export interface Mesh {
87
141
  */
88
142
  cell_data_components?: Record<string, number>;
89
143
  /** name -> scalar/small metadata arrays (e.g. material ids). */
90
- field_data?: Record<string, Float64Array>;
144
+ field_data?: Record<string, DataArray>;
91
145
  /** Per-entity width of any `field_data` array that is not a scalar. */
92
146
  field_data_components?: Record<string, number>;
93
147
  /** Named groups of points / cells / cell facets (see {@link Region}). */
94
148
  regions?: Region[];
149
+ /** `Begin Properties` blocks -- Kratos material data (currently MDPA only). See {@link PropertySet}. */
150
+ propertySets?: PropertySet[];
151
+ /**
152
+ * Format-specific side-channel metadata a generic `Mesh` cannot represent,
153
+ * attached by `readMeshSelective(path, {info: true})`. Present only for
154
+ * formats with one (openfoam/med/mdpa/ansysinp/unv/gmsh/exodus); absent
155
+ * otherwise, even when `info: true` was requested. Its own `format` field
156
+ * is what `writeMesh` checks before reusing it on a write with no explicit
157
+ * `options.info`. See doc/wasm.md's "Side channel (info)" section.
158
+ */
159
+ info?: MeshInfo;
160
+ }
161
+
162
+ /** The union of every format's side-channel `info` shape. Discriminate on `format`. */
163
+ export type MeshInfo =
164
+ | OpenFoamInfo
165
+ | MedInfo
166
+ | MdpaInfo
167
+ | AnsysInfo
168
+ | UnvInfo
169
+ | GmshInfo
170
+ | ExodusInfo;
171
+
172
+ /** OpenFOAM's side channel: `readMeshSelective`'s cell_tags/patch-type map, reshaped per patch. */
173
+ export interface OpenFoamInfo {
174
+ format: 'openfoam';
175
+ patches: Array<{
176
+ /** The negative, MED-style family id `cell_tags` uses for this patch. */
177
+ familyId: number;
178
+ /** Names this family id is known by (usually one; more than one on a collision). */
179
+ names: string[];
180
+ /** The patch `type` (`patch`/`wall`/`symmetry`/...), when known. */
181
+ type?: string;
182
+ }>;
183
+ }
184
+
185
+ /** MED's side channel: family/group names, units, and per-field step/time metadata. */
186
+ export interface MedInfo {
187
+ format: 'med';
188
+ /** Point family id -> subset name(s), as `point_tags`/`cell_tags` key them. */
189
+ pointTags: Record<string, string[]>;
190
+ cellTags: Record<string, string[]>;
191
+ meshName: string;
192
+ description: string;
193
+ unitTime: string;
194
+ unitCoords: string;
195
+ /** Family id -> its `FAM_<id>...` group link name. */
196
+ pointTagGroups: Record<string, string>;
197
+ cellTagGroups: Record<string, string>;
198
+ /** Lenient-mode only: constructs this read could not represent, verbatim. */
199
+ skippedConstructs: string[];
200
+ /** Lenient-mode only: field name -> `[UNI, UNT]` unit strings. */
201
+ fieldUnits: Record<string, [string, string]>;
202
+ /** Lenient-mode only: field name -> `{ndt, nor, pdt}` (MED's own step/order/time triple). */
203
+ stepMeta: Record<string, { ndt: number; nor: number; pdt: number }>;
204
+ /** Field name -> every step's time value (always filled, not lenient-only). */
205
+ fieldTimeValues: Record<string, number[]>;
206
+ }
207
+
208
+ /** MDPA's side channel: per-block entity names. Properties ride on `mesh.propertySets` instead (see {@link PropertySet}), not here. */
209
+ export interface MdpaInfo {
210
+ format: 'mdpa';
211
+ /** One entry per cell block, mesh block order. */
212
+ entityNames: Array<{ name: string; isCondition: boolean }>;
213
+ /** Lenient-mode only: constructs this read could not represent, verbatim. */
214
+ skippedConstructs: string[];
215
+ }
216
+
217
+ /**
218
+ * The shared shape of Ansys (`.cdb`/`.inp`, MAPDL) and UNV's side channel:
219
+ * named point/cell sets the generic {@link Region} shape does not carry.
220
+ */
221
+ export interface AnsysUnvInfoShape {
222
+ /** Set name -> 0-based point/node indices. */
223
+ pointSets: Record<string, number[]>;
224
+ /** Set name -> one array of 0-based local indices per cell block. */
225
+ cellSets: Record<string, number[][]>;
226
+ }
227
+
228
+ export interface AnsysInfo extends AnsysUnvInfoShape {
229
+ format: 'ansysinp';
230
+ }
231
+
232
+ export interface UnvInfo extends AnsysUnvInfoShape {
233
+ format: 'unv';
234
+ }
235
+
236
+ /** Gmsh's side channel: `$Entities` bounding-entity tags, one array per cell block. */
237
+ export interface GmshInfo {
238
+ format: 'gmsh';
239
+ boundingEntities: number[][];
240
+ }
241
+
242
+ /** Exodus's side channel: info/QA records. Read-only -- there is no Info-bearing Exodus writer. */
243
+ export interface ExodusInfo {
244
+ format: 'exodus';
245
+ infoRecords: string[];
246
+ }
247
+
248
+ /**
249
+ * One `Begin Properties <id>` block: an id plus its entries, in file order.
250
+ * Carried on the {@link Mesh} object itself (like {@link Region}), keyed by
251
+ * id rather than entity index, so operations that renumber cells/points
252
+ * cannot invalidate them. Shape-preserving operations (`clean`, `smooth`,
253
+ * `transform`, `attachQuality`, the `data*` ops) carry them through;
254
+ * restructuring and multi-input ones (`merge`, `cropBbox`/`cropPlane`/
255
+ * `cropPredicate`, `split`, `partition`, `diff`) do not.
256
+ */
257
+ export interface PropertySet {
258
+ id: number;
259
+ values: PropertyValue[];
260
+ }
261
+
262
+ /**
263
+ * One `KEY value` entry of a properties block. Exactly one of `values` and
264
+ * `text` carries the value: a plain number is a one-element `values`; an
265
+ * inline `Begin Table` is an `(n, k)` `values` (flat, row-major -- `k` given
266
+ * by `components` when `k > 1`) with `isTable` set and `key` holding the
267
+ * table header's arguments verbatim; anything else (a constitutive-law name,
268
+ * a bracketed vector/matrix) is kept verbatim in `text`, which is what makes
269
+ * an unrecognized value lossless.
270
+ */
271
+ export interface PropertyValue {
272
+ key: string;
273
+ values: Float64Array;
274
+ /** Per-entity width of `values` when `isTable` and `k > 1`. Absent means 1. */
275
+ components?: number;
276
+ /** The value verbatim, when it is not numeric (`values` is then empty). */
277
+ text: string;
278
+ isTable: boolean;
95
279
  }
96
280
 
97
281
  /**
@@ -137,7 +321,34 @@ export interface RegionSummary {
137
321
  numEntries: number;
138
322
  }
139
323
 
140
- export interface ConvertOptions {
324
+ /**
325
+ * Parameterized-write options for `writeMesh`/`convert`, all optional --
326
+ * unset/empty reproduces the exact write from before v11.2.0. There is
327
+ * deliberately no gzip level or VTK 4.2/5.1 selector: neither exists as a
328
+ * `WriteOptions` field on the C++ side (gzip level 4 is a fixed registry
329
+ * default; `vtk42`/`vtk51` are separate format keys, not a `vtk` option).
330
+ */
331
+ export interface MeshWriteOptions {
332
+ /** ASCII vs binary. Errors for a format with only one variant. */
333
+ encoding?: "ascii" | "binary";
334
+ /** Block-compression codec, for the VTK-XML formats (vtu/vtp) only. */
335
+ codec?: "none" | "zlib" | "lz4" | "zstd";
336
+ /** `printf`-style float format for ASCII writers that take one (e.g. `".16e"`, the default). */
337
+ floatFormat?: string;
338
+ }
339
+
340
+ /**
341
+ * `writeMesh`'s own options: `MeshWriteOptions` plus `info`, a format's
342
+ * side-channel metadata to write (see {@link MeshInfo}) -- wins over a
343
+ * `mesh.info` whose own `format` matches this write's. Given for a format
344
+ * with no side-channel writer (openfoam/mdpa/ansysinp/unv/gmsh/med are the
345
+ * writable ones; exodus is read-only) throws naming it.
346
+ */
347
+ export interface MeshWriteOptionsWithInfo extends MeshWriteOptions {
348
+ info?: MeshInfo;
349
+ }
350
+
351
+ export interface ConvertOptions extends MeshWriteOptions {
141
352
  /** Explicit input format key, or omit to infer from inPath's extension. */
142
353
  inFormat?: string;
143
354
  /** Explicit output format key, or omit to infer from outPath's extension. */
@@ -667,13 +878,16 @@ export interface XdmfTimeSeriesWriter {
667
878
  * Append one step from raw arrays instead of a mesh -- the granularity a
668
879
  * solver has once `writePointsCells` has fixed the geometry. Arrays are
669
880
  * emitted in key order; `components` gives the per-entity width of any array
670
- * that is not a scalar, since a flat typed array carries no shape.
881
+ * that is not a scalar, since a flat typed array carries no shape. A
882
+ * `BigInt64Array`/`BigUint64Array` value (e.g. taken from a mesh's
883
+ * `cell_data` unchanged) is widened to `number`s internally -- the XDMF
884
+ * data path is double-precision regardless of the source dtype.
671
885
  * @throws {Error} if an array's length does not match the static grid.
672
886
  */
673
887
  writeDataArrays(
674
888
  time: number,
675
- pointData: Record<string, Float64Array | number[]>,
676
- cellData?: Record<string, Float64Array | number[]>,
889
+ pointData: Record<string, DataArray | number[]>,
890
+ cellData?: Record<string, DataArray | number[]>,
677
891
  components?: Record<string, number>
678
892
  ): void;
679
893
 
@@ -706,6 +920,41 @@ export interface XdmfTimeSeriesWriter {
706
920
  close(): void;
707
921
  }
708
922
 
923
+ /** One entry of a sequence plan: one step of one file. See {@link MeshioPlusPlusModule.sequenceEntries} and {@link SequenceReader}. */
924
+ export interface SequenceEntry {
925
+ path: string;
926
+ step: number;
927
+ time: number;
928
+ timeSource: 'explicit' | 'file' | 'filename' | 'index';
929
+ }
930
+
931
+ /**
932
+ * A stateful sequence reader, opened by {@link MeshioPlusPlusModule.openSequence}.
933
+ * Plans the sequence once (no heavy data read) and reads one step's mesh at a
934
+ * time -- at most one mesh alive, whatever the step count. See
935
+ * `doc/sequences.md`.
936
+ */
937
+ export interface SequenceReader {
938
+ /** How many entries this sequence has. */
939
+ count: number;
940
+ path(i: number): string;
941
+ step(i: number): number;
942
+ time(i: number): number;
943
+ timeSource(i: number): 'explicit' | 'file' | 'filename' | 'index';
944
+ entry(i: number): SequenceEntry;
945
+ entries(): SequenceEntry[];
946
+ /**
947
+ * Read entry `i`'s mesh. `pointsOnly`/`arrays`/`lenient` are `readMeshSelective`'s.
948
+ * @throws {Error} if `i` is out of `[0, count)`.
949
+ */
950
+ read(
951
+ i: number,
952
+ options?: { pointsOnly?: boolean; arrays?: string[] | null; lenient?: boolean },
953
+ ): Mesh;
954
+ /** Release the handle. Safe to call twice; after this every other method throws. */
955
+ close(): void;
956
+ }
957
+
709
958
  /**
710
959
  * The instantiated module returned by `loadMeshioPlusPlus()`. `FS` is
711
960
  * Emscripten's virtual filesystem (MEMFS by default) -- write the bytes of a
@@ -751,6 +1000,13 @@ export interface MeshioPlusPlusModule {
751
1000
  * truncated block or a bad node reference still throws, because continuing
752
1001
  * past those would return a mesh that is quietly wrong.
753
1002
  *
1003
+ * `info: true` attaches the format's side channel as the result's `.info`
1004
+ * (see {@link MeshInfo}) for the formats that have one
1005
+ * (openfoam/med/mdpa/ansysinp/unv/gmsh/exodus); silently has no effect for
1006
+ * any other format, so a caller can always pass it and check `.info`
1007
+ * itself. `pointsOnly`/`arrays` reach the read only for the formats whose
1008
+ * info-bearing reader takes selective-read options (med/mdpa/gmsh/exodus).
1009
+ *
754
1010
  * @throws {Error} on an out-of-range `timeStep`.
755
1011
  */
756
1012
  readMeshSelective(
@@ -761,6 +1017,7 @@ export interface MeshioPlusPlusModule {
761
1017
  arrays?: string[] | null;
762
1018
  timeStep?: number;
763
1019
  lenient?: boolean;
1020
+ info?: boolean;
764
1021
  }
765
1022
  ): Mesh;
766
1023
 
@@ -778,18 +1035,26 @@ export interface MeshioPlusPlusModule {
778
1035
  readerSupportsOptions(format: string): boolean;
779
1036
 
780
1037
  /**
781
- * Write a mesh to the virtual filesystem.
782
- * @throws {Error} on an unknown/write-unsupported format or malformed input
783
- * (e.g. a points/connectivity array length not divisible by its
784
- * declared dim/nodesPerCell).
1038
+ * Write a mesh to the virtual filesystem. See {@link MeshWriteOptionsWithInfo.info}
1039
+ * for writing a format's side channel.
1040
+ * @returns every virtual-FS path this write touched (new or changed),
1041
+ * sorted -- more than one for a multi-file writer (`.xdmf` + its `.h5`
1042
+ * companion, an OpenFOAM `polyMesh` directory's files, ...).
1043
+ * @throws {Error} on an unknown/write-unsupported format, an `options`
1044
+ * field the format cannot honour, `info` given for a format with no
1045
+ * side-channel writer, or malformed input (e.g. a points/connectivity
1046
+ * array length not divisible by its declared dim/nodesPerCell).
785
1047
  */
786
- writeMesh(path: string, mesh: Mesh, format?: string): void;
1048
+ writeMesh(
1049
+ path: string, mesh: Mesh, format?: string, options?: MeshWriteOptionsWithInfo
1050
+ ): string[];
787
1051
 
788
1052
  /**
789
1053
  * Read `inPath` and write it to `outPath` directly (no intermediate JS
790
1054
  * mesh object). Mirrors the CLI's `convert` subcommand.
1055
+ * @returns every virtual-FS path the write touched (new or changed), sorted.
791
1056
  */
792
- convert(inPath: string, outPath: string, options?: ConvertOptions): void;
1057
+ convert(inPath: string, outPath: string, options?: ConvertOptions): string[];
793
1058
 
794
1059
  /**
795
1060
  * Like {@link convert}, but writes a *renderable surface*: a mesh with
@@ -885,12 +1150,24 @@ export interface MeshioPlusPlusModule {
885
1150
  timeFrom?: 'auto' | 'file' | 'filename' | 'index';
886
1151
  sort?: boolean;
887
1152
  },
888
- ): Array<{
889
- path: string;
890
- step: number;
891
- time: number;
892
- timeSource: 'explicit' | 'file' | 'filename' | 'index';
893
- }>;
1153
+ ): SequenceEntry[];
1154
+
1155
+ /**
1156
+ * Open a **stateful** sequence reader: plans the sequence once (`source`/
1157
+ * `options` exactly as {@link sequenceEntries}), then lets you read one
1158
+ * step's mesh at a time via {@link SequenceReader.read} without holding
1159
+ * more than one mesh alive -- the lazy-read counterpart to
1160
+ * `sequenceEntries` + `readMesh` in a loop.
1161
+ */
1162
+ openSequence(
1163
+ source: string | string[],
1164
+ options?: {
1165
+ format?: string;
1166
+ times?: number[];
1167
+ timeFrom?: 'auto' | 'file' | 'filename' | 'index';
1168
+ sort?: boolean;
1169
+ },
1170
+ ): SequenceReader;
894
1171
 
895
1172
  /**
896
1173
  * **Fan-in**: write every step of `source` into one multi-step file.
@@ -997,7 +1274,13 @@ export interface MeshioPlusPlusModule {
997
1274
  /** Whether two meshes are equal within tolerance. */
998
1275
  meshesEqual(a: Mesh, b: Mesh, atol?: number, rtol?: number, unordered?: boolean): boolean;
999
1276
 
1000
- /** Combine several meshes into one, optionally welding coincident points. */
1277
+ /**
1278
+ * Combine several meshes into one, optionally welding coincident points.
1279
+ * With `returnMaps: true`, also returns `pointMaps`/`cellMaps`: one array
1280
+ * per INPUT MESH (not per input block, unlike every other op's maps), each
1281
+ * input's local point/cell index -> the output index (cellMaps: -1 if
1282
+ * dropped as a duplicate).
1283
+ */
1001
1284
  merge(
1002
1285
  meshes: Mesh[],
1003
1286
  weld?: boolean,
@@ -1005,12 +1288,23 @@ export interface MeshioPlusPlusModule {
1005
1288
  sourceTag?: boolean,
1006
1289
  dataPolicy?: MergeDataPolicy,
1007
1290
  dropDuplicateCells?: boolean,
1291
+ returnMaps?: false,
1008
1292
  ): Mesh;
1293
+ merge(
1294
+ meshes: Mesh[],
1295
+ weld?: boolean,
1296
+ atol?: number,
1297
+ sourceTag?: boolean,
1298
+ dataPolicy?: MergeDataPolicy,
1299
+ dropDuplicateCells?: boolean,
1300
+ returnMaps?: true,
1301
+ ): { mesh: Mesh; pointMaps: Int32Array[]; cellMaps: Int32Array[] };
1009
1302
 
1010
1303
  /** Apply a row-major 4x4 affine transform to the point coordinates. */
1011
1304
  transform(mesh: Mesh, matrix: number[], rotateVectorData?: boolean): Mesh;
1012
1305
 
1013
- /** Weld / prune / de-duplicate in one pass. */
1306
+ /** Weld / prune / de-duplicate in one pass. With `returnMaps: true`, the
1307
+ * result also carries `pointMap`/`cellMaps` (see {@link PointCellMaps}). */
1014
1308
  clean(
1015
1309
  mesh: Mesh,
1016
1310
  weld?: boolean,
@@ -1018,12 +1312,15 @@ export interface MeshioPlusPlusModule {
1018
1312
  removeOrphans?: boolean,
1019
1313
  dropDegenerate?: boolean,
1020
1314
  dropDuplicateCells?: boolean,
1315
+ returnMaps?: boolean,
1021
1316
  ): {
1022
1317
  mesh: Mesh;
1023
1318
  pointsWelded: number;
1024
1319
  pointsRemovedOrphan: number;
1025
1320
  cellsDroppedDegenerate: number;
1026
1321
  cellsDroppedDuplicate: number;
1322
+ pointMap?: Int32Array;
1323
+ cellMaps?: Int32Array[];
1027
1324
  };
1028
1325
 
1029
1326
  /**
@@ -1033,9 +1330,12 @@ export interface MeshioPlusPlusModule {
1033
1330
  * `"laplacian"` is stronger per pass but contracts the mesh. A **negative**
1034
1331
  * `lambda` means "this method's own default" (0.5 Laplacian, 0.33 Taubin).
1035
1332
  * Boundary and feature nodes are pinned by default, and `guardInversion`
1036
- * rejects any move that would flip an incident cell.
1333
+ * rejects any move that would flip an incident cell. `frozen` is an
1334
+ * optional array of 0-based point ids to pin outright, unioned with any
1335
+ * boundary/feature pins.
1037
1336
  * @throws {Error} on an unknown `method`, a non-negative `lambda` outside
1038
- * `(0, 1)`, or a `"taubin"` `mu` that does not satisfy `mu < -lambda < 0`.
1337
+ * `(0, 1)`, a `"taubin"` `mu` that does not satisfy `mu < -lambda < 0`, or
1338
+ * a `frozen` id outside `[0, numPoints)`.
1039
1339
  */
1040
1340
  smooth(
1041
1341
  mesh: Mesh,
@@ -1047,6 +1347,7 @@ export interface MeshioPlusPlusModule {
1047
1347
  preserveFeatures?: boolean,
1048
1348
  featureAngle?: number,
1049
1349
  guardInversion?: boolean,
1350
+ frozen?: number[] | Int32Array | null,
1050
1351
  ): { mesh: Mesh; numNodesMoved: number; maxDisplacement: number; numSkippedInversion: number };
1051
1352
 
1052
1353
  /**
@@ -1114,17 +1415,37 @@ export interface MeshioPlusPlusModule {
1114
1415
  fine: Mesh,
1115
1416
  ): { mesh: Mesh; numGroupsUndone: number; numCellsRemoved: number };
1116
1417
 
1117
- /** Subset a mesh to an axis-aligned bounding box. */
1118
- cropBbox(mesh: Mesh, lo: number[], hi: number[], mode?: CropMode, recordIds?: boolean): Mesh;
1119
-
1120
- /** Subset a mesh to the half-space `(p - point) . normal >= 0`. */
1418
+ /** Subset a mesh to an axis-aligned bounding box. With `returnMaps: true`,
1419
+ * returns `{mesh, pointMap, cellMaps}` (see {@link PointCellMaps}) instead
1420
+ * of a bare mesh. */
1421
+ cropBbox(
1422
+ mesh: Mesh, lo: number[], hi: number[], mode?: CropMode, recordIds?: boolean,
1423
+ returnMaps?: false,
1424
+ ): Mesh;
1425
+ cropBbox(
1426
+ mesh: Mesh, lo: number[], hi: number[], mode?: CropMode, recordIds?: boolean,
1427
+ returnMaps?: true,
1428
+ ): { mesh: Mesh } & PointCellMaps;
1429
+
1430
+ /** Subset a mesh to the half-space `(p - point) . normal >= 0`. With
1431
+ * `returnMaps: true`, returns `{mesh, pointMap, cellMaps}` instead of a
1432
+ * bare mesh. */
1121
1433
  cropPlane(
1122
1434
  mesh: Mesh,
1123
1435
  point: number[],
1124
1436
  normal: number[],
1125
1437
  mode?: CropMode,
1126
1438
  recordIds?: boolean,
1439
+ returnMaps?: false,
1127
1440
  ): Mesh;
1441
+ cropPlane(
1442
+ mesh: Mesh,
1443
+ point: number[],
1444
+ normal: number[],
1445
+ mode?: CropMode,
1446
+ recordIds?: boolean,
1447
+ returnMaps?: true,
1448
+ ): { mesh: Mesh } & PointCellMaps;
1128
1449
 
1129
1450
  /**
1130
1451
  * Subset a mesh to the cells whose value in a scalar `cell_data` array
@@ -1145,6 +1466,9 @@ export interface MeshioPlusPlusModule {
1145
1466
  * @throws {Error} when `array` is not a scalar `cell_data` array covering
1146
1467
  * every block, or the comparison is not one of `<`, `<=`, `>`, `>=`, `==`,
1147
1468
  * `!=`.
1469
+ *
1470
+ * With `returnMaps: true`, returns `{mesh, pointMap, cellMaps}` instead of
1471
+ * a bare mesh.
1148
1472
  */
1149
1473
  cropPredicate(
1150
1474
  mesh: Mesh,
@@ -1152,7 +1476,16 @@ export interface MeshioPlusPlusModule {
1152
1476
  compare?: CropCompare,
1153
1477
  value?: number,
1154
1478
  recordIds?: boolean,
1479
+ returnMaps?: false,
1155
1480
  ): Mesh;
1481
+ cropPredicate(
1482
+ mesh: Mesh,
1483
+ array: string,
1484
+ compare?: CropCompare,
1485
+ value?: number,
1486
+ recordIds?: boolean,
1487
+ returnMaps?: true,
1488
+ ): { mesh: Mesh } & PointCellMaps;
1156
1489
 
1157
1490
  /**
1158
1491
  * Planar cross-section of a mesh (marching tetrahedra on a simplexified
@@ -1527,8 +1860,143 @@ export interface MeshioPlusPlusModule {
1527
1860
  minQualityAfter: number;
1528
1861
  };
1529
1862
 
1530
- /** Partition a mesh into submeshes by type, connected component, or tag. */
1531
- split(mesh: Mesh, by: SplitBy, tagName?: string): { key: string; mesh: Mesh }[];
1863
+ /**
1864
+ * Per-vertex mean (H) and Gaussian (K) curvature of a surface mesh -- the
1865
+ * signed distance's natural companion as a node feature. K is the angle
1866
+ * defect, H the cotangent Laplace-Beltrami operator. Writes
1867
+ * `curvature:mean`/`curvature:gaussian` point data, optionally
1868
+ * `curvature:area` and `curvature:principal`. `totalAngleDefect` is the
1869
+ * Gauss-Bonnet oracle: `2*pi*chi` exactly for a CLOSED surface (`4*pi` for
1870
+ * anything sphere-like), whatever the tessellation and whichever
1871
+ * `dualArea`. H's sign is orientation-dependent and K's is not, so check
1872
+ * `quality.inconsistentPairs` before trusting a sign. Never repairs its
1873
+ * input. See doc/curvature.md.
1874
+ * @throws {Error} on a non-surface input or an unknown region.
1875
+ */
1876
+ computeCurvature(
1877
+ mesh: Mesh,
1878
+ mean?: boolean,
1879
+ gaussian?: boolean,
1880
+ dualArea?: 'mixed-voronoi' | 'barycentric',
1881
+ includeBoundary?: boolean,
1882
+ recordArea?: boolean,
1883
+ recordPrincipal?: boolean,
1884
+ region?: string,
1885
+ ): {
1886
+ mesh: Mesh;
1887
+ numBoundary: number;
1888
+ numIsolated: number;
1889
+ numDegenerate: number;
1890
+ totalAngleDefect: number;
1891
+ quality: {
1892
+ boundaryEdges: number;
1893
+ nonManifoldEdges: number;
1894
+ inconsistentPairs: number;
1895
+ degenerateTriangles: number;
1896
+ watertight: boolean;
1897
+ };
1898
+ };
1899
+
1900
+ /**
1901
+ * Surface repair beyond `clean`: weld (opt-in) -> triangulate -> split
1902
+ * bowties -> orient by the topological half-edge rule per connected
1903
+ * component -> fan-fill boundary loops of at most `maxHoleEdges` edges,
1904
+ * wound to agree with the surrounding surface -> orient closed components
1905
+ * outward. Lower-dimensional blocks ride along; fill triangles land in one
1906
+ * trailing `triangle` block. Non-manifold EDGES are counted, never split.
1907
+ * See doc/repair.md.
1908
+ * @throws {Error} on a volume or higher-order input (naming the fix).
1909
+ */
1910
+ repair(
1911
+ mesh: Mesh,
1912
+ fixOrientation?: boolean,
1913
+ orientOutward?: boolean,
1914
+ fillHoles?: boolean,
1915
+ splitNonManifold?: boolean,
1916
+ maxHoleEdges?: number,
1917
+ weldTolerance?: number,
1918
+ recordProvenance?: boolean,
1919
+ ): {
1920
+ mesh: Mesh;
1921
+ qualityBefore: SurfaceQualityInfo;
1922
+ qualityAfter: SurfaceQualityInfo;
1923
+ numFlipped: number;
1924
+ numComponents: number;
1925
+ largestComponent: number;
1926
+ numOrientedOutward: number;
1927
+ numUnorientable: number;
1928
+ numVerticesSplit: number;
1929
+ numHolesDetected: number;
1930
+ numHolesFilled: number;
1931
+ numHolesSkipped: number;
1932
+ numFacesAdded: number;
1933
+ numPointsAdded: number;
1934
+ pointsWelded: number;
1935
+ };
1936
+
1937
+ /**
1938
+ * Project every (selected) point of `mesh` onto the surface of `target`:
1939
+ * `x' = x + w (p + offset n - x)`, one projection, no iteration. Every
1940
+ * point of the source moves whatever cells it carries; only the target must
1941
+ * be a surface. The offset goes along the hit FEATURE's pseudonormal (the
1942
+ * bisector at a crease), not the selected triangle's normal. `weights`
1943
+ * names a point-data array on the source. See doc/shrinkwrap.md.
1944
+ * @throws {Error} on an unusable target, region or weights array.
1945
+ */
1946
+ shrinkwrap(
1947
+ mesh: Mesh,
1948
+ target: Mesh,
1949
+ offset?: number,
1950
+ maxDistance?: number,
1951
+ weights?: string,
1952
+ targetRegion?: string,
1953
+ normalWeight?: 'angle' | 'area',
1954
+ recordDistance?: boolean,
1955
+ recordClosestCell?: boolean,
1956
+ ): {
1957
+ mesh: Mesh;
1958
+ quality: SurfaceQualityInfo;
1959
+ numProjected: number;
1960
+ numMissed: number;
1961
+ numSkipped: number;
1962
+ maxDisplacement: number;
1963
+ };
1964
+
1965
+ /**
1966
+ * Sobolev (Helmholtz-filtered) deformation: solve `(M + l^2 K) u = M d`
1967
+ * over the mesh's own P1 operators and move the points by `u` -- a
1968
+ * screened-Poisson low-pass filter of the raw displacement whose cutoff
1969
+ * wavelength is `lengthScale`. Every top-dimensional block must be a linear
1970
+ * simplex; lower-dimensional blocks ride along. Nothing is pinned by
1971
+ * default. Non-convergence sets `converged` false and returns the last
1972
+ * iterate. See doc/sobolev_deform.md.
1973
+ * @throws {Error} on a missing array or a non-simplex block (naming the fix).
1974
+ */
1975
+ sobolevDeform(
1976
+ mesh: Mesh,
1977
+ array: string,
1978
+ lengthScale: number,
1979
+ fixedPointsArray?: string,
1980
+ fixBoundary?: boolean,
1981
+ recordFiltered?: boolean,
1982
+ maxIterations?: number,
1983
+ tolerance?: number,
1984
+ ): {
1985
+ mesh: Mesh;
1986
+ numIterations: number;
1987
+ residual: number;
1988
+ converged: boolean;
1989
+ numFixed: number;
1990
+ numIsolated: number;
1991
+ maxDisplacement: number;
1992
+ };
1993
+
1994
+ /** Partition a mesh into submeshes by type, connected component, or tag.
1995
+ * With `returnMaps: true`, each piece also carries `pointMap`/`cellMaps`
1996
+ * (see {@link PointCellMaps}). */
1997
+ split(
1998
+ mesh: Mesh, by: SplitBy, tagName?: string, returnMaps?: boolean,
1999
+ ): ({ key: string; mesh: Mesh } & Partial<PointCellMaps>)[];
1532
2000
 
1533
2001
  /**
1534
2002
  * Convert the element representation: drop higher-order nodes
@@ -1536,8 +2004,16 @@ export interface MeshioPlusPlusModule {
1536
2004
  * or promote linear cells to serendipity quadratic (`"elevate"`).
1537
2005
  * @throws {Error} on a polyhedron block under `"simplexify"`, or a
1538
2006
  * full-Lagrange target (quad9/hexahedron27) under `"elevate"`.
2007
+ *
2008
+ * With `returnMaps: true`, returns `{mesh, pointMap, cellMaps}` instead of
2009
+ * a bare mesh.
1539
2010
  */
1540
- convertCells(mesh: Mesh, mode?: ConvertCellsMode, recordParentIds?: boolean): Mesh;
2011
+ convertCells(
2012
+ mesh: Mesh, mode?: ConvertCellsMode, recordParentIds?: boolean, returnMaps?: false,
2013
+ ): Mesh;
2014
+ convertCells(
2015
+ mesh: Mesh, mode?: ConvertCellsMode, recordParentIds?: boolean, returnMaps?: true,
2016
+ ): { mesh: Mesh } & PointCellMaps;
1541
2017
 
1542
2018
  /**
1543
2019
  * Polyhedrally refine a mesh: one polyhedral child per face of every
@@ -1549,8 +2025,11 @@ export interface MeshioPlusPlusModule {
1549
2025
  * `convertCells`, there is no point map -- subdivide never prunes or
1550
2026
  * renumbers an original point.
1551
2027
  * @throws {Error} when a cell's faces are not a closed orientable surface.
2028
+ *
2029
+ * With `returnMaps: true`, returns `{mesh, cellMaps}` instead of a bare mesh.
1552
2030
  */
1553
- subdivide(mesh: Mesh, recordParentIds?: boolean): Mesh;
2031
+ subdivide(mesh: Mesh, recordParentIds?: boolean, returnMaps?: false): Mesh;
2032
+ subdivide(mesh: Mesh, recordParentIds?: boolean, returnMaps?: true): { mesh: Mesh; cellMaps: Int32Array[] };
1554
2033
 
1555
2034
  /**
1556
2035
  * Polyhedrally coarsen a mesh: merge groups of cells into single larger
@@ -1563,8 +2042,13 @@ export interface MeshioPlusPlusModule {
1563
2042
  * for a minimal point set).
1564
2043
  * @throws {Error} when targetGroupSize is 0, or the mesh contains a face
1565
2044
  * shared by three or more cells (non-manifold).
2045
+ *
2046
+ * With `returnMaps: true`, returns `{mesh, cellMap}` instead of a bare
2047
+ * mesh -- a single FLAT array (global input cell index -> global output
2048
+ * cell index), unlike the other ops' per-block `cellMaps`.
1566
2049
  */
1567
- agglomerate(mesh: Mesh, targetGroupSize?: number): Mesh;
2050
+ agglomerate(mesh: Mesh, targetGroupSize?: number, returnMaps?: false): Mesh;
2051
+ agglomerate(mesh: Mesh, targetGroupSize?: number, returnMaps?: true): { mesh: Mesh; cellMap: Int32Array };
1568
2052
 
1569
2053
  /**
1570
2054
  * Refine a mesh, subdividing cells into same-type children (`line` → 2,
@@ -1579,13 +2063,24 @@ export interface MeshioPlusPlusModule {
1579
2063
  * @throws {Error} on a higher-order cell, a `pyramid`, or a ragged
1580
2064
  * polygon/polyhedron block — none has a same-type subdivision — and on more
1581
2065
  * than one selector, an unknown region, or an unusable predicate array.
2066
+ *
2067
+ * With `returnMaps: true`, returns `{mesh, pointMap, cellMaps}` instead of
2068
+ * a bare mesh.
1582
2069
  */
1583
2070
  refine(
1584
2071
  mesh: Mesh,
1585
2072
  levels?: number,
1586
2073
  recordParentIds?: boolean,
1587
- options?: RefineOptions
2074
+ options?: RefineOptions,
2075
+ returnMaps?: false,
1588
2076
  ): Mesh;
2077
+ refine(
2078
+ mesh: Mesh,
2079
+ levels?: number,
2080
+ recordParentIds?: boolean,
2081
+ options?: RefineOptions,
2082
+ returnMaps?: true,
2083
+ ): { mesh: Mesh } & PointCellMaps;
1589
2084
 
1590
2085
  /**
1591
2086
  * Decimate a SURFACE mesh by quadric-error-metric (Garland-Heckbert) edge
@@ -1596,11 +2091,13 @@ export interface MeshioPlusPlusModule {
1596
2091
  * (once-used-edge test) and feature vertices (face normals differing by
1597
2092
  * more than `featureAngle` degrees) are pinned by default, and the link
1598
2093
  * condition plus a normal-flip guard reject any collapse that would change
1599
- * topology or fold the surface. The index maps and the frozen mask are not
1600
- * carried across the JS boundary, as on the other flat bindings.
2094
+ * topology or fold the surface. `frozen` is an optional array of 0-based
2095
+ * point ids to pin outright. With `returnMaps: true`, the result also
2096
+ * carries `pointMap`/`cellMaps`.
1601
2097
  * @throws {Error} on a 3D volume mesh (extract the surface first),
1602
2098
  * higher-order or ragged blocks, `line`/`vertex` blocks, an unknown
1603
- * `placement`, or a criterion count other than one.
2099
+ * `placement`, a criterion count other than one, or a `frozen` id outside
2100
+ * `[0, numPoints)`.
1604
2101
  */
1605
2102
  decimate(
1606
2103
  mesh: Mesh,
@@ -1611,24 +2108,66 @@ export interface MeshioPlusPlusModule {
1611
2108
  preserveBoundary?: boolean,
1612
2109
  preserveFeatures?: boolean,
1613
2110
  featureAngle?: number,
2111
+ frozen?: number[] | Int32Array | null,
2112
+ returnMaps?: boolean,
1614
2113
  ): {
1615
2114
  mesh: Mesh;
1616
2115
  facesRemoved: number;
1617
2116
  pointsRemoved: number;
1618
2117
  collapsesRejected: number;
1619
2118
  maxErrorApplied: number;
2119
+ pointMap?: Int32Array;
2120
+ cellMaps?: Int32Array[];
2121
+ };
2122
+
2123
+ /**
2124
+ * Decimate a tetrahedral VOLUME mesh by quadric-error-metric tet-edge
2125
+ * collapse — `decimate`'s volume sibling. Exactly one of `ratio` (fraction
2126
+ * of tets to KEEP, in (0, 1]), `targetCells` and `maxError` must be
2127
+ * non-negative. The output is all-tetra with the block structure kept 1:1.
2128
+ * `preserveBoundary` defaults to `false` here (unlike `decimate`): the
2129
+ * mesh's outer surface is usually interior geometry a solver still wants
2130
+ * simplified, not a boundary to protect. `frozen` is an optional array of
2131
+ * 0-based point ids to pin outright, unioned with any boundary/feature
2132
+ * pins. With `returnMaps: true`, the result also carries
2133
+ * `pointMap`/`cellMaps`.
2134
+ * @throws {Error} on a non-manifold boundary face, a non-tetra 3D cell,
2135
+ * higher-order tets, ragged/polyhedron blocks, a non-3D block, an unknown
2136
+ * `placement`, a criterion count other than one, or a `frozen` id outside
2137
+ * `[0, numPoints)`.
2138
+ */
2139
+ decimateVolume(
2140
+ mesh: Mesh,
2141
+ ratio?: number,
2142
+ targetCells?: number,
2143
+ maxError?: number,
2144
+ placement?: DecimatePlacement,
2145
+ preserveBoundary?: boolean,
2146
+ preserveFeatures?: boolean,
2147
+ featureAngle?: number,
2148
+ frozen?: number[] | Int32Array | null,
2149
+ returnMaps?: boolean,
2150
+ ): {
2151
+ mesh: Mesh;
2152
+ tetsRemoved: number;
2153
+ pointsRemoved: number;
2154
+ collapsesRejected: number;
2155
+ maxErrorApplied: number;
2156
+ pointMap?: Int32Array;
2157
+ cellMaps?: Int32Array[];
1620
2158
  };
1621
2159
 
1622
2160
  /**
1623
2161
  * Decompose a mesh into exactly `nparts` balanced pieces for domain
1624
2162
  * decomposition (the count-driven complement to `split`). Pieces keep the
1625
2163
  * input's cell-block structure 1:1 (empty blocks included, unlike `split`),
1626
- * so concatenating them reproduces the input. The index maps are not
1627
- * carried across the JS boundary — use `recordIds` for the
2164
+ * so concatenating them reproduces the input. Use `recordIds` for the
1628
2165
  * `partition:original_*_id` arrays, or `partitionLabels` for the raw
1629
- * assignment. `weightsKey` names a scalar `cell_data` array of per-cell
1630
- * weights. `ghostLayers > 0` grows each piece by that many shared-node BFS
1631
- * layers of other parts' cells (a halo), tagged `partition:ghost`.
2166
+ * assignment; with `returnMaps: true`, each piece also carries
2167
+ * `pointMap`/`cellMaps` (see {@link PointCellMaps}). `weightsKey` names a
2168
+ * scalar `cell_data` array of per-cell weights. `ghostLayers > 0` grows
2169
+ * each piece by that many shared-node BFS layers of other parts' cells (a
2170
+ * halo), tagged `partition:ghost`.
1632
2171
  * @throws {Error} on `method: 'kahip'` (KaHIP is never part of the WASM
1633
2172
  * build; the message names `MESHIOPLUSPLUS_WITH_KAHIP`), `nparts < 1`,
1634
2173
  * `ghostLayers < 0`, or a bad weights array.
@@ -1643,7 +2182,8 @@ export interface MeshioPlusPlusModule {
1643
2182
  recordIds?: boolean,
1644
2183
  ghostLayers?: number,
1645
2184
  weightsKey?: string,
1646
- ): { partId: number; mesh: Mesh }[];
2185
+ returnMaps?: boolean,
2186
+ ): ({ partId: number; mesh: Mesh } & Partial<PointCellMaps>)[];
1647
2187
 
1648
2188
  /**
1649
2189
  * The per-cell part assignment only: one array per cell block
@@ -1792,16 +2332,54 @@ export interface MeshioPlusPlusModule {
1792
2332
  * instantiation otherwise. `variant: 'auto'` (default) picks the threaded build
1793
2333
  * under Node and in a cross-origin-isolated browser, else the sequential one.
1794
2334
  *
1795
- * @param moduleOverrides forwarded as-is to the Emscripten module factory
1796
- * (e.g. `{ locateFile }` to relocate the `.wasm` binary for a bundler/CDN).
1797
- * `locateFile` receives the requested filename, so return the URL matching the
1798
- * loaded variant (`meshioplusplus_wasm.wasm` or `meshioplusplus_wasm_mt.wasm`).
2335
+ * @param moduleOverrides forwarded to the Emscripten module factory, with
2336
+ * `locateFile`/`onAbort` wrapped for diagnostics (your own overrides still
2337
+ * run first) -- see {@link MeshioPlusPlusLoadError}. `locateFile` receives
2338
+ * the requested filename, so return the URL matching the loaded variant
2339
+ * (`meshioplusplus_wasm.wasm` or `meshioplusplus_wasm_mt.wasm`).
1799
2340
  * @param options.variant which native artifact to load: `'auto'` (default),
1800
2341
  * `'mt'` (force threaded), or `'seq'` (force sequential).
2342
+ * @throws {MeshioPlusPlusLoadError} if the WASM module fails to instantiate.
1801
2343
  */
1802
2344
  export function loadMeshioPlusPlus(
1803
- moduleOverrides?: object,
2345
+ moduleOverrides?: ModuleOverrides,
1804
2346
  options?: { variant?: 'auto' | 'mt' | 'seq' },
1805
2347
  ): Promise<MeshioPlusPlusModule>;
1806
2348
 
2349
+ /** Overrides forwarded to the underlying Emscripten module factory. */
2350
+ export interface ModuleOverrides {
2351
+ /**
2352
+ * Resolve the URL for a native artifact Emscripten wants to fetch (the
2353
+ * `.wasm` binary, and under a threaded build its worker script). Receives
2354
+ * the requested filename and Emscripten's own default prefix; return the
2355
+ * URL to actually load. Must return the file matching the loaded variant
2356
+ * (`meshioplusplus_wasm.wasm` vs `meshioplusplus_wasm_mt.wasm`) -- a
2357
+ * mismatch either fails instantiation or, in the case of the sequential
2358
+ * binary handed to the threaded glue, loads successfully but reports the
2359
+ * wrong {@link MeshioPlusPlusModule.parallelBackend}, which
2360
+ * `loadMeshioPlusPlus` detects and rejects with a {@link MeshioPlusPlusLoadError}.
2361
+ */
2362
+ locateFile?(path: string, prefix: string): string;
2363
+ /** Called by Emscripten when the module aborts during instantiation. */
2364
+ onAbort?(reason: unknown): void;
2365
+ [key: string]: unknown;
2366
+ }
2367
+
2368
+ /**
2369
+ * Thrown by `loadMeshioPlusPlus()` when a WASM module fails to instantiate.
2370
+ * `cause` is the underlying error (or abort reason) that triggered it.
2371
+ */
2372
+ export interface MeshioPlusPlusLoadError extends Error {
2373
+ name: 'MeshioPlusPlusLoadError';
2374
+ /** Which native artifact was being loaded. */
2375
+ variant: 'mt' | 'seq';
2376
+ /** The glue module specifier (e.g. '../dist/meshioplusplus_wasm_mt.mjs'). */
2377
+ glue: string;
2378
+ /** The filename Emscripten asked `locateFile` to resolve, if it got that far. */
2379
+ requestedFile?: string;
2380
+ /** What `locateFile` returned for `requestedFile`. */
2381
+ resolvedUrl?: string;
2382
+ cause?: unknown;
2383
+ }
2384
+
1807
2385
  export default loadMeshioPlusPlus;