@meshioplusplus/wasm 16.31.0 → 16.39.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
@@ -394,10 +394,124 @@ export interface RegionSummary {
394
394
  * `WriteOptions` field on the C++ side (gzip level 4 is a fixed registry
395
395
  * default; `vtk42`/`vtk51` are separate format keys, not a `vtk` option).
396
396
  */
397
+ /** A built-in colormap (shared with the SVG and TikZ writers). */
398
+ export type ColormapBase = "viridis" | "coolwarm" | "turbo" | "magma" | "inferno" | "plasma" | "grey" | "synthwave";
399
+ /** A built-in colormap or its reversed `_r` variant. */
400
+ export type ColormapName = ColormapBase | `${ColormapBase}_r`;
401
+
402
+ /** A colour: `0xRRGGBBAA` as a number (alpha 0 is transparent), or `[r, g, b, a?]` in 0-255. */
403
+ export type RenderColor = number | [number, number, number] | [number, number, number, number];
404
+
405
+ /**
406
+ * Options of the software rasterizer (`render`, `renderText`, `renderPng`); every
407
+ * field is optional and an unknown key is an error. See doc/tui.md.
408
+ */
409
+ export interface RenderOptions {
410
+ width?: number;
411
+ height?: number;
412
+ pixelAspect?: number;
413
+ /** 1, 2 or 4 samples per pixel along each axis. */
414
+ supersample?: number;
415
+ azimuth?: number;
416
+ elevation?: number;
417
+ roll?: number;
418
+ /** `"iso"`, `"+x"`, `"-x"`, `"+y"`, `"-y"`, `"+z"` or `"-z"`: the side the camera sits on. */
419
+ view?: string;
420
+ projection?: "orthographic" | "perspective";
421
+ fov?: number;
422
+ zoom?: number;
423
+ pan?: [number, number];
424
+ shading?: "none" | "flat" | "smooth";
425
+ twoSided?: boolean;
426
+ ambient?: number;
427
+ lightDir?: [number, number, number];
428
+ splitAngle?: number;
429
+ edges?: "none" | "all" | "feature";
430
+ featureAngle?: number;
431
+ edgeColor?: RenderColor;
432
+ fillColor?: RenderColor;
433
+ lineColor?: RenderColor;
434
+ background?: RenderColor;
435
+ pointRadius?: number;
436
+ colorBy?: string;
437
+ component?: number;
438
+ cmap?: ColormapName;
439
+ vmin?: number;
440
+ vmax?: number;
441
+ nanColor?: RenderColor;
442
+ colorbar?: boolean;
443
+ axes?: boolean;
444
+ scaleBar?: boolean;
445
+ /** `"mises"`, `"hydrostatic"` or `"principal"` reduction of the `colorBy` tensor array. */
446
+ reduce?: "mises" | "hydrostatic" | "principal";
447
+ /** A `dataCalc` expression to colour by instead of `colorBy`. */
448
+ expr?: string;
449
+ /** Percentiles bounding the automatic range; `null` leaves an end alone. */
450
+ clip?: [number | null, number | null];
451
+ symmetric?: boolean;
452
+ scale?: "linear" | "log" | "symlog";
453
+ scaleThreshold?: number;
454
+ categorical?: boolean;
455
+ colorRegions?: boolean;
456
+ categoryEdges?: boolean;
457
+ isolines?: number;
458
+ isoLevels?: number[];
459
+ isoColor?: RenderColor;
460
+ vectors?: string;
461
+ vectorCount?: number;
462
+ vectorLength?: number;
463
+ vectorColor?: RenderColor;
464
+ warp?: string;
465
+ warpScale?: number;
466
+ warpOutline?: boolean;
467
+ outlineColor?: RenderColor;
468
+ diagnostic?: "none" | "quality" | "inverted" | "degenerate" | "orientation" | "free_edges" | "edge_length";
469
+ qualityMetric?: string;
470
+ /**
471
+ * One or two cut-away planes that clip the geometry away: each is six numbers,
472
+ * a point and then the normal of the side kept (`[0.5, 0, 0, 1, 0, 0]` keeps `x >= 0.5`).
473
+ * The back faces then in view, the inside of the cut, are drawn in `cutawayTint`.
474
+ */
475
+ cutaway?: number[] | number[][];
476
+ cutawayTint?: RenderColor;
477
+ /** A vector point array to follow with streamlines, drawn over the mesh's own cells. */
478
+ streamlines?: string;
479
+ /** About this many seeds (default 40). */
480
+ streamSeeds?: number;
481
+ /** The longest a line grows each way from its seed, in model diagonals (default 0.5). */
482
+ streamLength?: number;
483
+ streamColor?: RenderColor;
484
+ }
485
+
486
+ /** Options of `renderText`: the cell encodings only (the graphics protocols are CLI features). */
487
+ export interface RenderTextOptions {
488
+ encoding?: "halfblock" | "quadrant" | "sextant" | "braille" | "ascii";
489
+ colorDepth?: "truecolor" | "256" | "16" | "mono";
490
+ format?: "ansi" | "plain" | "html";
491
+ cols?: number;
492
+ rows?: number;
493
+ cellAspect?: number;
494
+ notes?: boolean;
495
+ }
496
+
497
+ /** A rendered image. */
498
+ export interface RenderedFrame {
499
+ width: number;
500
+ height: number;
501
+ /** RGBA, rows top to bottom, straight alpha: `new ImageData(frame.rgba, frame.width, frame.height)`. */
502
+ rgba: Uint8ClampedArray;
503
+ /** The input cell (global, block-major) drawn at each pixel; -1 for none. */
504
+ cellIds: Float64Array;
505
+ /** The mapped `[vmin, vmax]`, or `null` when no field is mapped. */
506
+ range: [number, number] | null;
507
+ /** The colour range, ticks and keys, as text. */
508
+ notes: string[];
509
+ }
510
+
397
511
  /** glTF writer parameters. Components are 0-based; omitted selects magnitude. */
398
512
  export interface GltfWriteOptions {
399
513
  colorBy?: string;
400
- cmap?: "viridis" | "coolwarm" | "turbo";
514
+ cmap?: ColormapName;
401
515
  component?: number;
402
516
  vmin?: number;
403
517
  vmax?: number;
@@ -677,6 +791,37 @@ export interface OpReport {
677
791
  warnings: string[];
678
792
  }
679
793
 
794
+ /** One named point- or cell-data array of a {@link SurfaceBuffers}. */
795
+ export interface SurfaceArray {
796
+ name: string;
797
+ /**
798
+ * `components` values per point or cell, in the array's own dtype, except
799
+ * that a 64-bit integer array arrives as `Int32Array`/`Uint32Array` when
800
+ * every value fits and as `Float64Array` when one does not: never a
801
+ * `BigInt64Array`, which vtk.js cannot hold.
802
+ */
803
+ values: Exclude<DataArray, BigInt64Array | BigUint64Array>;
804
+ /** Values per tuple: a vector has 3, a 3x3 tensor 9, a scalar 1. */
805
+ components: number;
806
+ }
807
+
808
+ /**
809
+ * A renderable surface as the arrays a vtk.js `vtkPolyData` is built from,
810
+ * numbered exactly as the VTP file of the same surface would be.
811
+ */
812
+ export interface SurfaceBuffers {
813
+ /** x, y, z per point (2-D meshes padded with z = 0). */
814
+ points: Float32Array | Float64Array;
815
+ /** VTK legacy cell layout, `[n, id0, …, idn-1, n, …]`, per PolyData section. */
816
+ verts: Uint32Array;
817
+ lines: Uint32Array;
818
+ polys: Uint32Array;
819
+ /** Sorted by name. */
820
+ pointData: SurfaceArray[];
821
+ /** Sorted by name; values in Verts, then Lines, then Polys order. */
822
+ cellData: SurfaceArray[];
823
+ }
824
+
680
825
  /** `gradient`'s differential operator. See doc/gradient.md. */
681
826
  export type GradientOperator = 'gradient' | 'divergence' | 'curl';
682
827
 
@@ -1180,9 +1325,8 @@ export interface MeshioPlusPlusModule {
1180
1325
  * node, so `triangle6` connectivity drawn verbatim is visible garbage).
1181
1326
  *
1182
1327
  * Prefer this over `readMesh` -> `extractSkin` -> `writeMesh` for anything
1183
- * headed to a renderer. It never materializes a JS {@link Mesh}, so
1184
- * multi-component (vector/tensor) arrays survive -- the flat JS
1185
- * representation cannot carry them.
1328
+ * headed to a renderer. It never materializes a JS {@link Mesh}, so the
1329
+ * mesh is not copied across the boundary and back.
1186
1330
  */
1187
1331
  convertSurface(inPath: string, outPath: string, options?: ConvertOptions): void;
1188
1332
 
@@ -1191,8 +1335,8 @@ export interface MeshioPlusPlusModule {
1191
1335
  * first — all inside C++.
1192
1336
  *
1193
1337
  * Chaining the individual operation bindings (`smooth`, `clean`, …) would
1194
- * route the mesh through the flat JS {@link Mesh} on every step and so
1195
- * destroy every multi-component array; nothing crosses the boundary here.
1338
+ * copy the mesh into a JS {@link Mesh} and back on every step; here nothing
1339
+ * crosses the boundary until the result is written.
1196
1340
  *
1197
1341
  * An **empty** pipeline is exactly {@link convertSurface}. That is
1198
1342
  * deliberate: one call serves both the plain and the post-operation display,
@@ -1227,6 +1371,29 @@ export interface MeshioPlusPlusModule {
1227
1371
  }
1228
1372
  ): OpReport;
1229
1373
 
1374
+ /**
1375
+ * {@link convertSurfaceOps} without the file: the same pipeline and surface,
1376
+ * returned as typed arrays ready for a vtk.js `vtkPolyData` instead of being
1377
+ * written, base64-encoded and compressed for a VTP reader to undo. The
1378
+ * browser viewer renders through this.
1379
+ *
1380
+ * Cells are numbered as the VTP file of the surface numbers them (Verts,
1381
+ * Lines, then Polys, each in block order), so `surface:parent_cell` and a
1382
+ * picked cell id mean the same in both.
1383
+ *
1384
+ * @throws {Error} on an unknown operation name, an unreadable file, or a
1385
+ * surface PolyData cannot hold (a polyhedron block left by an operation).
1386
+ */
1387
+ surfaceBuffersOps(
1388
+ inPath: string,
1389
+ ops?: OpSpec[],
1390
+ options?: {
1391
+ inFormat?: string;
1392
+ /** Keep `surface:parent_cell` (the picker needs it). */
1393
+ keepProvenance?: boolean;
1394
+ }
1395
+ ): OpReport & { surface: SurfaceBuffers };
1396
+
1230
1397
  /**
1231
1398
  * Run a whole settings pipeline: read `Input.Path`, apply `Operations` in
1232
1399
  * order, write `Output.Path` — the `settings.json` engine (see
@@ -1397,7 +1564,7 @@ export interface MeshioPlusPlusModule {
1397
1564
  *
1398
1565
  * Prefer this over a hardcoded table when building a file-picker filter or a
1399
1566
  * "convert to" menu: the two lists genuinely differ (`openfoam` is
1400
- * read-only, `svg`, `tikz` and `gltf` are write-only), and the set depends on how
1567
+ * read-only, `gltf` and `step` are write-only), and the set depends on how
1401
1568
  * the artifact was built -- an official build carries the HDF5/netCDF-backed
1402
1569
  * formats, one built with `--without-hdf5` does not.
1403
1570
  */
@@ -2131,6 +2298,20 @@ export interface MeshioPlusPlusModule {
2131
2298
  * cover the whole surface, selected or not. See doc/feature_edges.md.
2132
2299
  * @throws {Error} on an angle outside [0, 180] or an unknown region.
2133
2300
  */
2301
+ /**
2302
+ * Render a mesh into an RGBA frame with a deterministic software rasterizer: no
2303
+ * WebGL, so it works in a Node script or a server-side preview. Volume cells
2304
+ * are drawn through their boundary skin. See doc/tui.md.
2305
+ * @throws {Error} on an unknown option, an invalid value or an unknown array.
2306
+ */
2307
+ render(mesh: Mesh, options?: RenderOptions): RenderedFrame;
2308
+ /**
2309
+ * Render a mesh as terminal-cell text sized `cols` x `rows` (default 80 x 24).
2310
+ * The Kitty, iTerm2 and Sixel encodings are not exported here.
2311
+ */
2312
+ renderText(mesh: Mesh, options?: RenderOptions, text?: RenderTextOptions): string;
2313
+ /** Render a mesh and encode it as an RGBA PNG; `compress` 0 stores it uncompressed (default). */
2314
+ renderPng(mesh: Mesh, options?: RenderOptions, compress?: number): Uint8Array;
2134
2315
  featureEdges(
2135
2316
  mesh: Mesh,
2136
2317
  featureAngle?: number,
@@ -2147,6 +2328,58 @@ export interface MeshioPlusPlusModule {
2147
2328
  numInconsistent: number;
2148
2329
  };
2149
2330
 
2331
+ /**
2332
+ * Split a surface into smooth patches by region growing, bounded by its
2333
+ * feature edges. The mesh comes back unchanged plus cell data
2334
+ * `segment:patch` (-1 off the surface), field data `segment:adjacency`
2335
+ * (rows `[a, b, sharedEdges]`) and one cell region per patch,
2336
+ * `<prefix>:<k>`. See doc/segment.md.
2337
+ * @throws {Error} on an option out of range, an unknown region or a volume block.
2338
+ */
2339
+ segment(
2340
+ mesh: Mesh,
2341
+ featureAngle?: number,
2342
+ normalTolerance?: number,
2343
+ curvatureTolerance?: number,
2344
+ minPatchCells?: number,
2345
+ region?: string,
2346
+ prefix?: string,
2347
+ ): {
2348
+ mesh: Mesh;
2349
+ numPatches: number;
2350
+ numMerged: number;
2351
+ numFeatureEdges: number;
2352
+ numBoundaryEdges: number;
2353
+ numNonManifoldEdges: number;
2354
+ };
2355
+
2356
+ /**
2357
+ * Fit a plane, sphere, cylinder, cone or torus to each patch of a surface
2358
+ * (the first accepted in that order, or none). The mesh comes back unchanged
2359
+ * plus cell data `fit:type`, `fit:rms`, `fit:max` and per-patch field data
2360
+ * `fit:patch_*`; `patchData = ''` fits the whole surface. See
2361
+ * doc/fit_primitives.md.
2362
+ * @throws {Error} on a bad option, an unknown type or a missing label array.
2363
+ */
2364
+ fitPrimitives(
2365
+ mesh: Mesh,
2366
+ patchData?: string,
2367
+ tolerance?: number,
2368
+ relative?: boolean,
2369
+ minInlierFraction?: number,
2370
+ types?: Array<'plane' | 'sphere' | 'cylinder' | 'cone' | 'torus'>,
2371
+ maxIterations?: number,
2372
+ ): {
2373
+ mesh: Mesh;
2374
+ numPatches: number;
2375
+ numPlane: number;
2376
+ numSphere: number;
2377
+ numCylinder: number;
2378
+ numCone: number;
2379
+ numTorus: number;
2380
+ numUnfitted: number;
2381
+ };
2382
+
2150
2383
  /**
2151
2384
  * The (sampled) Hausdorff distance between the surfaces of two meshes; a
2152
2385
  * volume mesh contributes its skin. `faceSamples = s > 0` also samples the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshioplusplus/wasm",
3
- "version": "16.31.0",
3
+ "version": "16.39.0",
4
4
  "description": "meshio++ mesh I/O compiled to WebAssembly: read 76 and write 68 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
@@ -206,6 +206,7 @@ export class MeshioPlusPlusLoadError extends Error {
206
206
  * convert: (inPath: string, outPath: string, options?: {inFormat?: string, outFormat?: string, encoding?: string, codec?: string, floatFormat?: string}) => string[],
207
207
  * convertSurface: (inPath: string, outPath: string, options?: {inFormat?: string, outFormat?: string}) => void,
208
208
  * convertSurfaceOps: (inPath: string, outPath: string, ops?: object[], options?: {inFormat?: string, outFormat?: string, keepProvenance?: boolean, compressVtp?: boolean}) => {steps: object[], warnings: string[]},
209
+ * surfaceBuffersOps: (inPath: string, ops?: object[], options?: {inFormat?: string, keepProvenance?: boolean}) => {surface: object, steps: object[], warnings: string[]},
209
210
  * runPipeline: (settings: object|string) => {steps: object[], warnings: string[]},
210
211
  * sequenceEntries: (source: string|string[], options?: object) => object[],
211
212
  * sequenceToTimeseries: (source: string|string[], outPath: string, outFormat?: string, options?: object) => number,
@@ -254,6 +255,11 @@ export class MeshioPlusPlusLoadError extends Error {
254
255
  * 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}},
255
256
  * checkQuality: (mesh: Mesh, require?: string, maxInverted?: number, maxDegenerate?: number) => {passed: boolean, numCells: number, numInverted: number, numDegenerate: number, checks: Array<object>, summary: string},
256
257
  * 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},
258
+ * 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},
259
+ * 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},
260
+ * render: (mesh: Mesh, options?: RenderOptions) => RenderedFrame,
261
+ * renderText: (mesh: Mesh, options?: RenderOptions, text?: RenderTextOptions) => string,
262
+ * renderPng: (mesh: Mesh, options?: RenderOptions, compress?: number) => Uint8Array,
257
263
  * hausdorffDistance: (a: Mesh, b: Mesh, faceSamples?: number, regionA?: string, regionB?: string) => {distance: number, aToB: number, bToA: number, meanAToB: number, rmsAToB: number, meanBToA: number, rmsBToA: number, numSamplesA: number, numSamplesB: number, worstPointA: Float64Array, worstPointB: Float64Array},
258
264
  * editRegions: (mesh: Mesh, edits: Array<{op: string, inputs: Array<string | {name: string, kind?: string, dim?: number, tag?: number}>, output?: string, dim?: number, tag?: number, keepInputs?: boolean}>) => Mesh,
259
265
  * regionAdjacency: (mesh: Mesh, regions?: Array<string | {name: string, kind?: string, dim?: number, tag?: number}>) => Mesh,
@@ -443,12 +449,12 @@ export async function loadMeshioPlusPlus(moduleOverrides = {}, { variant = 'auto
443
449
  // Like `convert`, but writes a renderable *surface*: a volume mesh
444
450
  // becomes its boundary, everything else passes through, and the result
445
451
  // is linearized. Prefer this over readMesh -> extractSkin -> writeMesh
446
- // for anything headed to a renderer: it stays inside C++, so
447
- // multi-component data survives, which the flat JS mesh cannot carry.
452
+ // for anything headed to a renderer: it stays inside C++, so the mesh
453
+ // is never copied into a JS object and back.
448
454
  convertSurface: (inPath, outPath, { inFormat = '', outFormat = '' } = {}) =>
449
455
  Module.convertSurface(inPath, inFormat, outPath, outFormat),
450
456
  // Like `convertSurface`, but applies a pipeline of mesh operations
451
- // first -- entirely inside C++, so multi-component data survives them.
457
+ // first -- entirely inside C++, with no JS mesh between the steps.
452
458
  // An empty pipeline is exactly `convertSurface`, which is what lets a
453
459
  // caller use one code path for both the plain and the post-operation
454
460
  // display, and what makes undo a replay rather than an inverse.
@@ -467,6 +473,10 @@ export async function loadMeshioPlusPlus(moduleOverrides = {}, { variant = 'auto
467
473
  keepProvenance,
468
474
  compressVtp
469
475
  ),
476
+ // `convertSurfaceOps` without the file: the surface comes back as the
477
+ // typed arrays a vtk.js vtkPolyData is built from (see index.d.ts).
478
+ surfaceBuffersOps: (inPath, ops = [], { inFormat = '', keepProvenance = false } = {}) =>
479
+ Module.surfaceBuffersOps(inPath, inFormat, ops, keepProvenance),
470
480
  // A whole settings.json pipeline (PascalCase vocabulary, see
471
481
  // doc/pipeline.md). Accepts the parsed object, the JSON text, or a
472
482
  // MEMFS path ending in ".json" -- the wasm binary carries no JSON
@@ -511,7 +521,7 @@ export async function loadMeshioPlusPlus(moduleOverrides = {}, { variant = 'auto
511
521
  hasCgnslib: () => Module.hasCgnslib(),
512
522
  // What this build can actually read/write, both sorted. Prefer this
513
523
  // over a hardcoded table: a few formats are read-only (openfoam) or
514
- // write-only (svg/tikz/gltf), and the HDF5/netCDF-backed ones are present
524
+ // write-only (gltf), and the HDF5/netCDF-backed ones are present
515
525
  // only in a build that linked them (the official artifact does).
516
526
  availableFormats: () => Module.availableFormats(),
517
527
  // Mesh operations (see doc/*.md per operation): computations ON a mesh,
@@ -826,6 +836,31 @@ export async function loadMeshioPlusPlus(moduleOverrides = {}, { variant = 'auto
826
836
  ) =>
827
837
  Module.featureEdges(mesh, featureAngle, feature, boundary, nonManifold,
828
838
  inconsistent, region),
839
+ segment: (
840
+ mesh,
841
+ featureAngle = 30,
842
+ normalTolerance = 0,
843
+ curvatureTolerance = 0,
844
+ minPatchCells = 1,
845
+ region = '',
846
+ prefix = 'patch',
847
+ ) =>
848
+ Module.segment(mesh, featureAngle, normalTolerance, curvatureTolerance,
849
+ minPatchCells, region, prefix),
850
+ fitPrimitives: (
851
+ mesh,
852
+ patchData = 'segment:patch',
853
+ tolerance = 1e-3,
854
+ relative = true,
855
+ minInlierFraction = 0.9,
856
+ types = ['plane', 'sphere', 'cylinder', 'cone', 'torus'],
857
+ maxIterations = 50,
858
+ ) =>
859
+ Module.fitPrimitives(mesh, patchData, tolerance, relative, minInlierFraction,
860
+ Array.isArray(types) ? types : [types], maxIterations),
861
+ render: (mesh, options = {}) => Module.render(mesh, options),
862
+ renderText: (mesh, options = {}, text = {}) => Module.renderText(mesh, options, text),
863
+ renderPng: (mesh, options = {}, compress = 0) => Module.renderPng(mesh, options, compress),
829
864
  hausdorffDistance: (a, b, faceSamples = 0, regionA = '', regionB = '') =>
830
865
  Module.hausdorffDistance(a, b, faceSamples, regionA, regionB),
831
866
  editRegions: (mesh, edits) =>