@meshioplusplus/wasm 16.32.0 → 16.40.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
@@ -185,7 +185,7 @@ export interface Mesh {
185
185
  /**
186
186
  * Format-specific side-channel metadata a generic `Mesh` cannot represent,
187
187
  * attached by `readMeshSelective(path, {info: true})`. Present only for
188
- * formats with one (openfoam/med/mdpa/ansysinp/unv/gmsh/exodus); absent
188
+ * formats with one (openfoam/med/mdpa/ansysinp/unv/gmsh/exodus/mfem); absent
189
189
  * otherwise, even when `info: true` was requested. Its own `format` field
190
190
  * is what `writeMesh` checks before reusing it on a write with no explicit
191
191
  * `options.info`. See doc/wasm.md's "Side channel (info)" section.
@@ -201,7 +201,8 @@ export type MeshInfo =
201
201
  | AnsysInfo
202
202
  | UnvInfo
203
203
  | GmshInfo
204
- | ExodusInfo;
204
+ | ExodusInfo
205
+ | MfemInfo;
205
206
 
206
207
  /** OpenFOAM's side channel: `readMeshSelective`'s cell_tags/patch-type map, reshaped per patch. */
207
208
  export interface OpenFoamInfo {
@@ -305,6 +306,54 @@ export interface GmshInfo {
305
306
  periodic?: { entity: number[]; affine: number[]; nodePairs: BigInt64Array | number[] }[];
306
307
  }
307
308
 
309
+ /**
310
+ * MFEM's side channel (v16.40.0): the NURBS patches an `MFEM NURBS mesh` was
311
+ * sampled from (C++ `NurbsInfo`). Arrays are flat, their widths given beside
312
+ * them; every index is 0-based. `writeMesh` writes the patches back as an
313
+ * `MFEM NURBS mesh` while the mesh still is their sampling (it refuses a mesh
314
+ * moved or edited since). A mesh that is not NURBS has no patches.
315
+ */
316
+ export interface MfemInfo {
317
+ format: 'mfem';
318
+ patches: {
319
+ /** Degree per parametric direction. */
320
+ degrees: number[];
321
+ /** One knot vector per parametric direction. */
322
+ knots: number[][];
323
+ /** Components of each control point. */
324
+ spaceDim: number;
325
+ /** (points, spaceDim) Cartesian control points, direction 0 fastest. */
326
+ controlPoints: Float64Array;
327
+ /** One weight per control point. */
328
+ weights: Float64Array;
329
+ /** Per field (see `fieldNames`): (points, fieldComponents[k]) control values. */
330
+ fields: Float64Array[];
331
+ }[];
332
+ /** The point-data name of each field the patches carry. */
333
+ fieldNames: string[];
334
+ /** Components of each field. */
335
+ fieldComponents: number[];
336
+ /** The file's patch topology, or null when the source states none. */
337
+ topology: {
338
+ dimension: number;
339
+ numVertices: number;
340
+ /** (patches, 2^dimension) corner vertices. */
341
+ patchVertices: BigInt64Array | number[];
342
+ patchAttributes: BigInt64Array | number[];
343
+ /** (boundary patches, 2^(dimension-1)) corner vertices. */
344
+ boundaryVertices: BigInt64Array | number[];
345
+ boundaryAttributes: BigInt64Array | number[];
346
+ /** (edges, 3): knot vector, vertex, vertex. */
347
+ edges: BigInt64Array | number[];
348
+ } | null;
349
+ /** The patch of each element cell (the first block). */
350
+ cellPatch: BigInt64Array | number[];
351
+ /** (element cells, 3): each one's knot span per direction. */
352
+ cellSpan: BigInt64Array | number[];
353
+ /** The boundary patch of each boundary cell. */
354
+ boundaryCellPatch: BigInt64Array | number[];
355
+ }
356
+
308
357
  /** Exodus's side channel: info/QA records. Read-only -- there is no Info-bearing Exodus writer. */
309
358
  export interface ExodusInfo {
310
359
  format: 'exodus';
@@ -394,10 +443,124 @@ export interface RegionSummary {
394
443
  * `WriteOptions` field on the C++ side (gzip level 4 is a fixed registry
395
444
  * default; `vtk42`/`vtk51` are separate format keys, not a `vtk` option).
396
445
  */
446
+ /** A built-in colormap (shared with the SVG and TikZ writers). */
447
+ export type ColormapBase = "viridis" | "coolwarm" | "turbo" | "magma" | "inferno" | "plasma" | "grey" | "synthwave";
448
+ /** A built-in colormap or its reversed `_r` variant. */
449
+ export type ColormapName = ColormapBase | `${ColormapBase}_r`;
450
+
451
+ /** A colour: `0xRRGGBBAA` as a number (alpha 0 is transparent), or `[r, g, b, a?]` in 0-255. */
452
+ export type RenderColor = number | [number, number, number] | [number, number, number, number];
453
+
454
+ /**
455
+ * Options of the software rasterizer (`render`, `renderText`, `renderPng`); every
456
+ * field is optional and an unknown key is an error. See doc/tui.md.
457
+ */
458
+ export interface RenderOptions {
459
+ width?: number;
460
+ height?: number;
461
+ pixelAspect?: number;
462
+ /** 1, 2 or 4 samples per pixel along each axis. */
463
+ supersample?: number;
464
+ azimuth?: number;
465
+ elevation?: number;
466
+ roll?: number;
467
+ /** `"iso"`, `"+x"`, `"-x"`, `"+y"`, `"-y"`, `"+z"` or `"-z"`: the side the camera sits on. */
468
+ view?: string;
469
+ projection?: "orthographic" | "perspective";
470
+ fov?: number;
471
+ zoom?: number;
472
+ pan?: [number, number];
473
+ shading?: "none" | "flat" | "smooth";
474
+ twoSided?: boolean;
475
+ ambient?: number;
476
+ lightDir?: [number, number, number];
477
+ splitAngle?: number;
478
+ edges?: "none" | "all" | "feature";
479
+ featureAngle?: number;
480
+ edgeColor?: RenderColor;
481
+ fillColor?: RenderColor;
482
+ lineColor?: RenderColor;
483
+ background?: RenderColor;
484
+ pointRadius?: number;
485
+ colorBy?: string;
486
+ component?: number;
487
+ cmap?: ColormapName;
488
+ vmin?: number;
489
+ vmax?: number;
490
+ nanColor?: RenderColor;
491
+ colorbar?: boolean;
492
+ axes?: boolean;
493
+ scaleBar?: boolean;
494
+ /** `"mises"`, `"hydrostatic"` or `"principal"` reduction of the `colorBy` tensor array. */
495
+ reduce?: "mises" | "hydrostatic" | "principal";
496
+ /** A `dataCalc` expression to colour by instead of `colorBy`. */
497
+ expr?: string;
498
+ /** Percentiles bounding the automatic range; `null` leaves an end alone. */
499
+ clip?: [number | null, number | null];
500
+ symmetric?: boolean;
501
+ scale?: "linear" | "log" | "symlog";
502
+ scaleThreshold?: number;
503
+ categorical?: boolean;
504
+ colorRegions?: boolean;
505
+ categoryEdges?: boolean;
506
+ isolines?: number;
507
+ isoLevels?: number[];
508
+ isoColor?: RenderColor;
509
+ vectors?: string;
510
+ vectorCount?: number;
511
+ vectorLength?: number;
512
+ vectorColor?: RenderColor;
513
+ warp?: string;
514
+ warpScale?: number;
515
+ warpOutline?: boolean;
516
+ outlineColor?: RenderColor;
517
+ diagnostic?: "none" | "quality" | "inverted" | "degenerate" | "orientation" | "free_edges" | "edge_length";
518
+ qualityMetric?: string;
519
+ /**
520
+ * One or two cut-away planes that clip the geometry away: each is six numbers,
521
+ * a point and then the normal of the side kept (`[0.5, 0, 0, 1, 0, 0]` keeps `x >= 0.5`).
522
+ * The back faces then in view, the inside of the cut, are drawn in `cutawayTint`.
523
+ */
524
+ cutaway?: number[] | number[][];
525
+ cutawayTint?: RenderColor;
526
+ /** A vector point array to follow with streamlines, drawn over the mesh's own cells. */
527
+ streamlines?: string;
528
+ /** About this many seeds (default 40). */
529
+ streamSeeds?: number;
530
+ /** The longest a line grows each way from its seed, in model diagonals (default 0.5). */
531
+ streamLength?: number;
532
+ streamColor?: RenderColor;
533
+ }
534
+
535
+ /** Options of `renderText`: the cell encodings only (the graphics protocols are CLI features). */
536
+ export interface RenderTextOptions {
537
+ encoding?: "halfblock" | "quadrant" | "sextant" | "braille" | "ascii";
538
+ colorDepth?: "truecolor" | "256" | "16" | "mono";
539
+ format?: "ansi" | "plain" | "html";
540
+ cols?: number;
541
+ rows?: number;
542
+ cellAspect?: number;
543
+ notes?: boolean;
544
+ }
545
+
546
+ /** A rendered image. */
547
+ export interface RenderedFrame {
548
+ width: number;
549
+ height: number;
550
+ /** RGBA, rows top to bottom, straight alpha: `new ImageData(frame.rgba, frame.width, frame.height)`. */
551
+ rgba: Uint8ClampedArray;
552
+ /** The input cell (global, block-major) drawn at each pixel; -1 for none. */
553
+ cellIds: Float64Array;
554
+ /** The mapped `[vmin, vmax]`, or `null` when no field is mapped. */
555
+ range: [number, number] | null;
556
+ /** The colour range, ticks and keys, as text. */
557
+ notes: string[];
558
+ }
559
+
397
560
  /** glTF writer parameters. Components are 0-based; omitted selects magnitude. */
398
561
  export interface GltfWriteOptions {
399
562
  colorBy?: string;
400
- cmap?: "viridis" | "coolwarm" | "turbo";
563
+ cmap?: ColormapName;
401
564
  component?: number;
402
565
  vmin?: number;
403
566
  vmax?: number;
@@ -1450,7 +1613,7 @@ export interface MeshioPlusPlusModule {
1450
1613
  *
1451
1614
  * Prefer this over a hardcoded table when building a file-picker filter or a
1452
1615
  * "convert to" menu: the two lists genuinely differ (`openfoam` is
1453
- * read-only, `svg`, `tikz` and `gltf` are write-only), and the set depends on how
1616
+ * read-only, `gltf` and `step` are write-only), and the set depends on how
1454
1617
  * the artifact was built -- an official build carries the HDF5/netCDF-backed
1455
1618
  * formats, one built with `--without-hdf5` does not.
1456
1619
  */
@@ -2184,6 +2347,20 @@ export interface MeshioPlusPlusModule {
2184
2347
  * cover the whole surface, selected or not. See doc/feature_edges.md.
2185
2348
  * @throws {Error} on an angle outside [0, 180] or an unknown region.
2186
2349
  */
2350
+ /**
2351
+ * Render a mesh into an RGBA frame with a deterministic software rasterizer: no
2352
+ * WebGL, so it works in a Node script or a server-side preview. Volume cells
2353
+ * are drawn through their boundary skin. See doc/tui.md.
2354
+ * @throws {Error} on an unknown option, an invalid value or an unknown array.
2355
+ */
2356
+ render(mesh: Mesh, options?: RenderOptions): RenderedFrame;
2357
+ /**
2358
+ * Render a mesh as terminal-cell text sized `cols` x `rows` (default 80 x 24).
2359
+ * The Kitty, iTerm2 and Sixel encodings are not exported here.
2360
+ */
2361
+ renderText(mesh: Mesh, options?: RenderOptions, text?: RenderTextOptions): string;
2362
+ /** Render a mesh and encode it as an RGBA PNG; `compress` 0 stores it uncompressed (default). */
2363
+ renderPng(mesh: Mesh, options?: RenderOptions, compress?: number): Uint8Array;
2187
2364
  featureEdges(
2188
2365
  mesh: Mesh,
2189
2366
  featureAngle?: number,
@@ -2200,6 +2377,58 @@ export interface MeshioPlusPlusModule {
2200
2377
  numInconsistent: number;
2201
2378
  };
2202
2379
 
2380
+ /**
2381
+ * Split a surface into smooth patches by region growing, bounded by its
2382
+ * feature edges. The mesh comes back unchanged plus cell data
2383
+ * `segment:patch` (-1 off the surface), field data `segment:adjacency`
2384
+ * (rows `[a, b, sharedEdges]`) and one cell region per patch,
2385
+ * `<prefix>:<k>`. See doc/segment.md.
2386
+ * @throws {Error} on an option out of range, an unknown region or a volume block.
2387
+ */
2388
+ segment(
2389
+ mesh: Mesh,
2390
+ featureAngle?: number,
2391
+ normalTolerance?: number,
2392
+ curvatureTolerance?: number,
2393
+ minPatchCells?: number,
2394
+ region?: string,
2395
+ prefix?: string,
2396
+ ): {
2397
+ mesh: Mesh;
2398
+ numPatches: number;
2399
+ numMerged: number;
2400
+ numFeatureEdges: number;
2401
+ numBoundaryEdges: number;
2402
+ numNonManifoldEdges: number;
2403
+ };
2404
+
2405
+ /**
2406
+ * Fit a plane, sphere, cylinder, cone or torus to each patch of a surface
2407
+ * (the first accepted in that order, or none). The mesh comes back unchanged
2408
+ * plus cell data `fit:type`, `fit:rms`, `fit:max` and per-patch field data
2409
+ * `fit:patch_*`; `patchData = ''` fits the whole surface. See
2410
+ * doc/fit_primitives.md.
2411
+ * @throws {Error} on a bad option, an unknown type or a missing label array.
2412
+ */
2413
+ fitPrimitives(
2414
+ mesh: Mesh,
2415
+ patchData?: string,
2416
+ tolerance?: number,
2417
+ relative?: boolean,
2418
+ minInlierFraction?: number,
2419
+ types?: Array<'plane' | 'sphere' | 'cylinder' | 'cone' | 'torus'>,
2420
+ maxIterations?: number,
2421
+ ): {
2422
+ mesh: Mesh;
2423
+ numPatches: number;
2424
+ numPlane: number;
2425
+ numSphere: number;
2426
+ numCylinder: number;
2427
+ numCone: number;
2428
+ numTorus: number;
2429
+ numUnfitted: number;
2430
+ };
2431
+
2203
2432
  /**
2204
2433
  * The (sampled) Hausdorff distance between the surfaces of two meshes; a
2205
2434
  * 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.32.0",
3
+ "version": "16.40.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
@@ -255,6 +255,11 @@ export class MeshioPlusPlusLoadError extends Error {
255
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}},
256
256
  * checkQuality: (mesh: Mesh, require?: string, maxInverted?: number, maxDegenerate?: number) => {passed: boolean, numCells: number, numInverted: number, numDegenerate: number, checks: Array<object>, summary: string},
257
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,
258
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},
259
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,
260
265
  * regionAdjacency: (mesh: Mesh, regions?: Array<string | {name: string, kind?: string, dim?: number, tag?: number}>) => Mesh,
@@ -516,7 +521,7 @@ export async function loadMeshioPlusPlus(moduleOverrides = {}, { variant = 'auto
516
521
  hasCgnslib: () => Module.hasCgnslib(),
517
522
  // What this build can actually read/write, both sorted. Prefer this
518
523
  // over a hardcoded table: a few formats are read-only (openfoam) or
519
- // 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
520
525
  // only in a build that linked them (the official artifact does).
521
526
  availableFormats: () => Module.availableFormats(),
522
527
  // Mesh operations (see doc/*.md per operation): computations ON a mesh,
@@ -831,6 +836,31 @@ export async function loadMeshioPlusPlus(moduleOverrides = {}, { variant = 'auto
831
836
  ) =>
832
837
  Module.featureEdges(mesh, featureAngle, feature, boundary, nonManifold,
833
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),
834
864
  hausdorffDistance: (a, b, faceSamples = 0, regionA = '', regionB = '') =>
835
865
  Module.hausdorffDistance(a, b, faceSamples, regionA, regionB),
836
866
  editRegions: (mesh, edits) =>