@meshioplusplus/wasm 10.20.2 → 11.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,19 @@
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
+
10
23
  export interface RectangularCellBlock {
11
24
  /** meshio++ cell type name, e.g. "triangle", "tetra10", "hexahedron". */
12
25
  type: string;
@@ -1527,6 +1540,137 @@ export interface MeshioPlusPlusModule {
1527
1540
  minQualityAfter: number;
1528
1541
  };
1529
1542
 
1543
+ /**
1544
+ * Per-vertex mean (H) and Gaussian (K) curvature of a surface mesh -- the
1545
+ * signed distance's natural companion as a node feature. K is the angle
1546
+ * defect, H the cotangent Laplace-Beltrami operator. Writes
1547
+ * `curvature:mean`/`curvature:gaussian` point data, optionally
1548
+ * `curvature:area` and `curvature:principal`. `totalAngleDefect` is the
1549
+ * Gauss-Bonnet oracle: `2*pi*chi` exactly for a CLOSED surface (`4*pi` for
1550
+ * anything sphere-like), whatever the tessellation and whichever
1551
+ * `dualArea`. H's sign is orientation-dependent and K's is not, so check
1552
+ * `quality.inconsistentPairs` before trusting a sign. Never repairs its
1553
+ * input. See doc/curvature.md.
1554
+ * @throws {Error} on a non-surface input or an unknown region.
1555
+ */
1556
+ computeCurvature(
1557
+ mesh: Mesh,
1558
+ mean?: boolean,
1559
+ gaussian?: boolean,
1560
+ dualArea?: 'mixed-voronoi' | 'barycentric',
1561
+ includeBoundary?: boolean,
1562
+ recordArea?: boolean,
1563
+ recordPrincipal?: boolean,
1564
+ region?: string,
1565
+ ): {
1566
+ mesh: Mesh;
1567
+ numBoundary: number;
1568
+ numIsolated: number;
1569
+ numDegenerate: number;
1570
+ totalAngleDefect: number;
1571
+ quality: {
1572
+ boundaryEdges: number;
1573
+ nonManifoldEdges: number;
1574
+ inconsistentPairs: number;
1575
+ degenerateTriangles: number;
1576
+ watertight: boolean;
1577
+ };
1578
+ };
1579
+
1580
+ /**
1581
+ * Surface repair beyond `clean`: weld (opt-in) -> triangulate -> split
1582
+ * bowties -> orient by the topological half-edge rule per connected
1583
+ * component -> fan-fill boundary loops of at most `maxHoleEdges` edges,
1584
+ * wound to agree with the surrounding surface -> orient closed components
1585
+ * outward. Lower-dimensional blocks ride along; fill triangles land in one
1586
+ * trailing `triangle` block. Non-manifold EDGES are counted, never split.
1587
+ * See doc/repair.md.
1588
+ * @throws {Error} on a volume or higher-order input (naming the fix).
1589
+ */
1590
+ repair(
1591
+ mesh: Mesh,
1592
+ fixOrientation?: boolean,
1593
+ orientOutward?: boolean,
1594
+ fillHoles?: boolean,
1595
+ splitNonManifold?: boolean,
1596
+ maxHoleEdges?: number,
1597
+ weldTolerance?: number,
1598
+ recordProvenance?: boolean,
1599
+ ): {
1600
+ mesh: Mesh;
1601
+ qualityBefore: SurfaceQualityInfo;
1602
+ qualityAfter: SurfaceQualityInfo;
1603
+ numFlipped: number;
1604
+ numComponents: number;
1605
+ largestComponent: number;
1606
+ numOrientedOutward: number;
1607
+ numUnorientable: number;
1608
+ numVerticesSplit: number;
1609
+ numHolesDetected: number;
1610
+ numHolesFilled: number;
1611
+ numHolesSkipped: number;
1612
+ numFacesAdded: number;
1613
+ numPointsAdded: number;
1614
+ pointsWelded: number;
1615
+ };
1616
+
1617
+ /**
1618
+ * Project every (selected) point of `mesh` onto the surface of `target`:
1619
+ * `x' = x + w (p + offset n - x)`, one projection, no iteration. Every
1620
+ * point of the source moves whatever cells it carries; only the target must
1621
+ * be a surface. The offset goes along the hit FEATURE's pseudonormal (the
1622
+ * bisector at a crease), not the selected triangle's normal. `weights`
1623
+ * names a point-data array on the source. See doc/shrinkwrap.md.
1624
+ * @throws {Error} on an unusable target, region or weights array.
1625
+ */
1626
+ shrinkwrap(
1627
+ mesh: Mesh,
1628
+ target: Mesh,
1629
+ offset?: number,
1630
+ maxDistance?: number,
1631
+ weights?: string,
1632
+ targetRegion?: string,
1633
+ normalWeight?: 'angle' | 'area',
1634
+ recordDistance?: boolean,
1635
+ recordClosestCell?: boolean,
1636
+ ): {
1637
+ mesh: Mesh;
1638
+ quality: SurfaceQualityInfo;
1639
+ numProjected: number;
1640
+ numMissed: number;
1641
+ numSkipped: number;
1642
+ maxDisplacement: number;
1643
+ };
1644
+
1645
+ /**
1646
+ * Sobolev (Helmholtz-filtered) deformation: solve `(M + l^2 K) u = M d`
1647
+ * over the mesh's own P1 operators and move the points by `u` -- a
1648
+ * screened-Poisson low-pass filter of the raw displacement whose cutoff
1649
+ * wavelength is `lengthScale`. Every top-dimensional block must be a linear
1650
+ * simplex; lower-dimensional blocks ride along. Nothing is pinned by
1651
+ * default. Non-convergence sets `converged` false and returns the last
1652
+ * iterate. See doc/sobolev_deform.md.
1653
+ * @throws {Error} on a missing array or a non-simplex block (naming the fix).
1654
+ */
1655
+ sobolevDeform(
1656
+ mesh: Mesh,
1657
+ array: string,
1658
+ lengthScale: number,
1659
+ fixedPointsArray?: string,
1660
+ fixBoundary?: boolean,
1661
+ recordFiltered?: boolean,
1662
+ maxIterations?: number,
1663
+ tolerance?: number,
1664
+ ): {
1665
+ mesh: Mesh;
1666
+ numIterations: number;
1667
+ residual: number;
1668
+ converged: boolean;
1669
+ numFixed: number;
1670
+ numIsolated: number;
1671
+ maxDisplacement: number;
1672
+ };
1673
+
1530
1674
  /** Partition a mesh into submeshes by type, connected component, or tag. */
1531
1675
  split(mesh: Mesh, by: SplitBy, tagName?: string): { key: string; mesh: Mesh }[];
1532
1676
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshioplusplus/wasm",
3
- "version": "10.20.2",
3
+ "version": "11.0.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
@@ -165,6 +165,10 @@ function resolveVariant(variant) {
165
165
  * remesh: (mesh: Mesh, numClusters: number, subdivide?: number, subsampleRatio?: number, maxSubdivide?: number, maxIterations?: number, maxRepairPasses?: number, metric?: string, gradation?: number, preserveBoundary?: boolean, maxAnisotropy?: number) => {mesh: Mesh, numClusters: number, numIterations: number, subdivideApplied: number, numIsolatedClusters: number, numNonManifoldVertices: number},
166
166
  * remeshVolume: (mesh: Mesh, resolution?: number[], cellSize?: number, bounds?: number[], padding?: number, paddingRelative?: number, maxCells?: number, maxTets?: number, warpFraction?: number, sign?: string, watertightCheck?: string) => {mesh: Mesh, numTets: number, numVerticesWarped: number, numTetsRejected: number, numNonManifoldEdges: number},
167
167
  * optimizeVolume: (mesh: Mesh, maxIterations?: number, relocate?: boolean, flip?: boolean, preserveBoundary?: boolean, minImprovement?: number) => {mesh: Mesh, numFlips: number, num23Flips: number, num32Flips: number, numVerticesMoved: number, numTets: number, minQualityBefore: number, minQualityAfter: number},
168
+ * computeCurvature: (mesh: Mesh, mean?: boolean, gaussian?: boolean, dualArea?: string, includeBoundary?: boolean, recordArea?: boolean, recordPrincipal?: boolean, region?: string) => {mesh: Mesh, numBoundary: number, numIsolated: number, numDegenerate: number, totalAngleDefect: number, quality: {boundaryEdges: number, nonManifoldEdges: number, inconsistentPairs: number, degenerateTriangles: number, watertight: boolean}},
169
+ * repair: (mesh: Mesh, fixOrientation?: boolean, orientOutward?: boolean, fillHoles?: boolean, splitNonManifold?: boolean, maxHoleEdges?: number, weldTolerance?: number, recordProvenance?: boolean) => {mesh: Mesh, qualityBefore: object, qualityAfter: object, numFlipped: number, numComponents: number, largestComponent: number, numOrientedOutward: number, numUnorientable: number, numVerticesSplit: number, numHolesDetected: number, numHolesFilled: number, numHolesSkipped: number, numFacesAdded: number, numPointsAdded: number, pointsWelded: number},
170
+ * shrinkwrap: (mesh: Mesh, target: Mesh, offset?: number, maxDistance?: number, weights?: string, targetRegion?: string, normalWeight?: string, recordDistance?: boolean, recordClosestCell?: boolean) => {mesh: Mesh, quality: object, numProjected: number, numMissed: number, numSkipped: number, maxDisplacement: number},
171
+ * sobolevDeform: (mesh: Mesh, array: string, lengthScale: number, fixedPointsArray?: string, fixBoundary?: boolean, recordFiltered?: boolean, maxIterations?: number, tolerance?: number) => {mesh: Mesh, numIterations: number, residual: number, converged: boolean, numFixed: number, numIsolated: number, maxDisplacement: number},
168
172
  * split: (mesh: Mesh, by: string, tagName?: string) => {key: string, mesh: Mesh}[],
169
173
  * convertCells: (mesh: Mesh, mode?: string, recordParentIds?: boolean) => Mesh,
170
174
  * subdivide: (mesh: Mesh, recordParentIds?: boolean) => Mesh,
@@ -545,6 +549,55 @@ export async function loadMeshioPlusPlus(moduleOverrides = {}, { variant = 'auto
545
549
  ) =>
546
550
  Module.optimizeVolume(mesh, maxIterations, relocate, flip, preserveBoundary,
547
551
  minImprovement),
552
+ computeCurvature: (
553
+ mesh,
554
+ mean = true,
555
+ gaussian = true,
556
+ dualArea = 'mixed-voronoi',
557
+ includeBoundary = false,
558
+ recordArea = false,
559
+ recordPrincipal = false,
560
+ region = '',
561
+ ) =>
562
+ Module.computeCurvature(mesh, mean, gaussian, dualArea, includeBoundary,
563
+ recordArea, recordPrincipal, region),
564
+ repair: (
565
+ mesh,
566
+ fixOrientation = true,
567
+ orientOutward = true,
568
+ fillHoles = true,
569
+ splitNonManifold = true,
570
+ maxHoleEdges = 10,
571
+ weldTolerance = 0,
572
+ recordProvenance = false,
573
+ ) =>
574
+ Module.repair(mesh, fixOrientation, orientOutward, fillHoles, splitNonManifold,
575
+ maxHoleEdges, weldTolerance, recordProvenance),
576
+ shrinkwrap: (
577
+ mesh,
578
+ target,
579
+ offset = 0,
580
+ maxDistance = 0,
581
+ weights = '',
582
+ targetRegion = '',
583
+ normalWeight = 'angle',
584
+ recordDistance = false,
585
+ recordClosestCell = false,
586
+ ) =>
587
+ Module.shrinkwrap(mesh, target, offset, maxDistance, weights, targetRegion,
588
+ normalWeight, recordDistance, recordClosestCell),
589
+ sobolevDeform: (
590
+ mesh,
591
+ array,
592
+ lengthScale,
593
+ fixedPointsArray = '',
594
+ fixBoundary = false,
595
+ recordFiltered = false,
596
+ maxIterations = 128,
597
+ tolerance = 1e-10,
598
+ ) =>
599
+ Module.sobolevDeform(mesh, array, lengthScale, fixedPointsArray, fixBoundary,
600
+ recordFiltered, maxIterations, tolerance),
548
601
  split: (mesh, by, tagName = '') => Module.split(mesh, by, tagName),
549
602
  convertCells: (mesh, mode = 'linearize', recordParentIds = false) =>
550
603
  Module.convertCells(mesh, mode, recordParentIds),