trimesh¶
trimesh¶
Triangulated-surface container (TriMesh) and its surface ops.
- class nekmeshpy.trimesh.TriMesh[source]¶
Bases:
objectA triangular surface mesh:
points(P,3)andtris(T,3)connectivity.- __init__(points, tris)[source]¶
- Parameters:
points (NDArray[float64])
tris (NDArray[int64])
- Return type:
None
- classmethod from_files(vtx_file, tri_file)[source]¶
Load a surface triangulation from point-list and 1-based triangle-index files.
- classmethod from_faces(V, faces)[source]¶
Build a sub-mesh from
Vrestricted tofaces; returns(TriMesh, vids)wherevidsmaps sub-index -> V-index.
- EDGE_POINTS = array([[0, 1], [1, 2], [2, 0]])¶
- boundary_edges()[source]¶
(K,2)array of[triangle id, local edge (1-3)]for every open-boundary edge.- Return type:
NDArray[int64]
- boundary_elements()[source]¶
Sorted unique triangle ids with at least one edge on the open boundary.
- Return type:
NDArray[int64]
- boundary_points()[source]¶
Sorted unique point ids lying on the open boundary.
- Return type:
NDArray[int64]
trimesh.ops¶
Surface algorithms on a TriMesh as free functions. All indices 0-based.
- nekmeshpy.trimesh.ops.cotan_laplacian(surface)[source]¶
Linear (P1) cotangent-weight stiffness matrix (recomputed each call).
- Parameters:
surface (TriMesh)
- Return type:
- nekmeshpy.trimesh.ops.solve_dirichlet(surface, dpoints, dvals)[source]¶
Solve the Laplace system with Dirichlet values at
dpoints; returns an(nv,)field.- Parameters:
surface (TriMesh)
dpoints (NDArray[int64])
dvals (NDArray[float64])
- Return type:
NDArray[float64]
- nekmeshpy.trimesh.ops.boundary_loops(surface)[source]¶
Group open-boundary edges into connected loops; returns a list of vertex-index arrays.
- nekmeshpy.trimesh.ops.order_boundary_loop(surface, lv)[source]¶
Return the vertices of one boundary loop
lvin cyclic order.- Parameters:
surface (TriMesh)
lv (NDArray[int64])
- Return type:
NDArray[int64]
- nekmeshpy.trimesh.ops.conduction_field(surf, gloops, neumann, dvals)[source]¶
Laplace with Neumann on loop
neumann, Dirichletdvalson the other two, shifted to zero mean on the free loop.
- nekmeshpy.trimesh.ops.seam_fields(surf, gloops)[source]¶
The three conduction seam fields
U(nv, 3): columnkis 0 on openingk, 1 on the next opening round, and Neumann (free) on the third – so its sign is whatcut_surface_from_fields()reads to place seamk.
- nekmeshpy.trimesh.ops.leg_label(F)[source]¶
Which of the three legs (1, 2 or 3) each row of seam-field values
F(n, 3)falls in, by the sign patternseam_fields()gives each leg.- Parameters:
F (NDArray[float64])
- Return type:
NDArray[int64]
- nekmeshpy.trimesh.ops.cut_surface_from_fields(surf, F)[source]¶
Cut
surfinto three legs defined by seam fieldsF(nv, 3), retriangulating triangles a seam crosses. Returns(V, faces):Vis the surface’s own points plus every new seam-crossing and triple point, andfacesis a 3-element list of(T,3)arrays – one leg’s triangles each – both indexing intoV.
- nekmeshpy.trimesh.ops.leg_field(V, faces, leg, gloops)[source]¶
One leg as a sub-mesh with Laplace solved (0 on opening, 1 on seam). Returns
(sub, us, opening, seam, vids).
- nekmeshpy.trimesh.ops.arc_curve(V, arcverts, iA1, n, keep=0.5)[source]¶
Analytic
A1 -> A2seam arc: the scanned polyline’s deviation from its own chord, refit as a truncated sine series in the normalized arc-length parameters, and returned as a callablep(s)on[0, 1].This is
fourier_ring()’s open-curve sibling, and the basis is chosen for the one property the seam needs: everysin(k*pi*s)vanishes at both ends, soA1andA2– the triple points where all three arcs meet – stay bit-exact however many modes are kept. That is what lets the three legs keep welding: each arc is fitted once, globally, and the same mesh is handed to both legs that share it, so no leg ever sees a privately-refitted seam (which is why the seam ring could not simply go throughfourier_wall()– refitting per leg would mix the two arcs that leg happens to see).Dropping the upper modes removes the STL facet noise for the same reason it does on a station ring, and
keepis applied to the modes the mesh can resolve (nelements ->n-1interior nodes -> modes1..n-1), mirroringfourier_ring()’skeep * (M // 2 + 1).
- nekmeshpy.trimesh.ops.arc_mesh(p, n, order, element_tag)[source]¶
Mesh an
arc_curve()intonhigh-order elements of the givenorder, evenly spaced by arc length.LineMesh.loft_fnevaluatespat every node – corners and the private GLL interiors – so no node lands on a chord.
- nekmeshpy.trimesh.ops.seam_rings(V, faces, gloops, n_half, *, order, keep=0.5, element_tag='wall')[source]¶
Build the three conformal seam rings + spine. Returns
(rings, A1, A2, spine).
- nekmeshpy.trimesh.ops.fourier_ring(P, keep=0.5)[source]¶
Refit a closed scanned ring as a truncated Fourier series
p(t), periodic on[0, 2*pi)with samplejatt = 2*pi*j/M.x,yandzare transformed independently (np.fft.rfftagainst the uniform parameter) and only the lowestkeepfraction of the modes is retained; the rest – facet-scale noise from the STL projection, which a high-order wall would otherwise resolve faithfully – is dropped. The result is a genuine closed-form curve, soLineMesh.loft_fncan place every GLL node on it instead of on the chords between the samples (see the straight-GLL-subdivision trap in CLAUDE.md).
- nekmeshpy.trimesh.ops.fourier_wall(P, order, element_tag, keep=0.5)[source]¶
Closed high-order wall
LineMeshthroughfourier_ring(), sampled at the sameMparameters asPso index 0 /M//2still land on the spine rails.LineMesh.loft_fnonly ever makes an open chain, so weld the two ends into a loop the way the toolkit expects (linemesh.merge).
- nekmeshpy.trimesh.ops.extract_isocontour(surface, u, level)[source]¶
Extract {u == level} as the largest closed
LineMeshloop, orNone.
- nekmeshpy.trimesh.ops.extract_rings(surface, u, levels, min_loop_pts)[source]¶
Cross-section rings of
uat each level; returns(rings, levels_kept).
- nekmeshpy.trimesh.ops.resample_polyline(points, fractions, *, closed=False)[source]¶
Arc-length resample of a polyline at normalized
fractionsin[0, 1]. Withclosed=Truethe polyline wraps (fraction1returns to the start). Returns(len(fractions), 3).- Parameters:
points (NDArray[float64])
fractions (NDArray[float64])
closed (bool)
- Return type:
NDArray[float64]
- nekmeshpy.trimesh.ops.conform_ring_stack(fine_rings, seam_ring, frlev, n_half)[source]¶
Conformalize a stack of scanned interior rings (arbitrary per-ring point counts) onto the seam ring’s topology.