C++/MATLAB migration of step_mesher.
This repository is the no-Python-runtime target. The current Python
step_mesher repository remains the reference implementation for parity
testing while the C++/MATLAB implementation matures.
This first implementation provides a working vertical slice:
- C++ core library
step_mesher_core step_mesher_clicommand-line driver- MATLAB MEX gateway source,
step_mesher_mex - MATLAB package namespace
+stepmesher - STEP import and CAD surface evaluation through the Gmsh C++ API with its OpenCASCADE backend
- CAD boundary-curve projection and edge blending on scaffold triangles
- triangular RV patch output for MATLAB (
iptype = 1) - MATLAB conversion to
srcvals,surfer,xyzw,.go3,.gidmsh, and area/flux diagnostics
Important limitation: direct OpenCascade C++ calls and the full Python Step 1
continuity-helper fragmentation / Step 1b Newton repair are not fully ported
yet. The current implementation matches the reference data contract much more
closely than the initial scaffold, but examples whose accuracy depends on
internal continuity-helper curves, especially piecewise_bezier_cap.step, are
still not full parity with the Python reference.
On this development machine, Gmsh is available through the Python framework:
- header:
/Library/Frameworks/Python.framework/Versions/3.12/include/gmsh.h - library:
/Library/Frameworks/Python.framework/Versions/3.12/lib/libgmsh.4.12.dylib
Configure and build:
cmake -S . -B build -DSTEP_MESHER_BUILD_MEX=ON \
-DMatlab_ROOT_DIR=/Applications/MATLAB_R2026a.app
cmake --build build
ctest --test-dir build --output-on-failureIf Gmsh lives elsewhere, pass:
cmake -S . -B build \
-DGMSH_INCLUDE_DIR=/path/to/include \
-DGMSH_LIBRARY=/path/to/libgmsh.dylib./build/step_mesher_cli mesh \
--step examples/step_files/test_geometry_1.step \
--order 8 \
--mesh-fraction 0.10 \
--refinement 0 \
--edge-order 16 \
--profile rigid \
--out out/test_geometry_1The CLI writes meta.json, xyz.csv, scaffold_nodes.csv, and
scaffold_triangles.csv.
The CLI currently uses an equispaced triangle-node fallback because the true
RV nodes live in the fmm3dbie MATLAB koorn package. Use MATLAB
stepmesher.export_xyzw or stepmesher.export_go3 for RV-compatible output.
Use stepmesher.export_gidmsh to write the flat scaffold mesh expected by
the fmm3dbie surface smoother as ifiletype = 3.
Add paths:
addpath('/path/to/step_mesher_cpp_matlab/matlab')
addpath('/path/to/fmm3dbie/matlab')Run:
opts = struct('order', 8, 'mesh_fraction', 0.10, ...
'refinement_level', 0, 'edge_gll_order', 16, ...
'mesh_profile', 'rigid');
mesh = stepmesher.mesh_step('examples/step_files/test_geometry_1.step', opts);
[srcvals, norders, iptype, meta] = stepmesher.to_srcvals(mesh);
S = stepmesher.to_surfer(mesh);
payload = stepmesher.export_xyzw(mesh, 'test_geometry_1_xyzw.txt');
go3 = stepmesher.export_go3(mesh, 'test_geometry_1.go3');
gidmsh = stepmesher.export_gidmsh(mesh, 'test_geometry_1.gidmsh');
stats = stepmesher.validate_area_flux(mesh);For a notebook-style entry point, run:
run('examples/run_step_mesher.m')For a convergence-study driver in the same style as the Python notebook:
run('examples/run_convergence_study.m')The convergence CSV includes both CAD-reference area errors and self-convergence errors against the finest/highest-order run:
rel_area_error:abs(numerical_area - cad_area) / cad_arearel_area_error_vs_finest_global:abs(numerical_area - area_ref_global) / abs(area_ref_global)
The driver also writes a per-face convergence CSV with
self_consistency_abs_error and self_consistency_rel_error.
The generated figures are saved under out/convergence_<step-name>/figures.
They include Python-notebook-style log-log plots versus h/n_tri and
semilogy plots versus polynomial order:
area_rel_occ_vs_harea_rel_occ_vs_ntriarea_self_consistency_global_vs_harea_rel_occ_vs_orderarea_self_consistency_global_vs_orderperface_self_consistency_vs_hperface_self_consistency_vs_order
For a regression sweep over all bundled examples:
addpath('/path/to/step_mesher_cpp_matlab/tests/matlab')
results = regression_sweep_examples('/path/to/step_mesher_cpp_matlab', ...
'/path/to/fmm3dbie/matlab', true);The MATLAB mesh struct contains:
xyz:3 x total_nodesprojected node coordinatesnodes_per_patch: scalarnpatches: scalarnorder: scalariptype: scalar, currently1tri_face_tags: original Gmsh/OCC face tag per patchparent_coarse_tri: 1-based scaffold triangle id per patchproj_dist: projection distance per nodescaffold_nodes:3 x nscaffold_nodesscaffold_triangles:3 x nscaffold_triangles, local 1-based node idsscaffold_node_tags: original Gmsh node tagsscaffold_triangle_node_tags: original Gmsh tags for triangle verticesscaffold_face_tags: face tag per scaffold trianglemeta: backend, settings, CAD area, mesh size, and projection metrics
stepmesher.to_srcvals computes derivatives and normals in MATLAB:
uv = koorn.rv_nodes(order);
A = koorn.vals2coefs(order, uv);
[~, Du, Dv] = koorn.ders(order, uv);
coef = R * A.';
du = coef * Du;
dv = coef * Dv;
n = normalize(cross(du, dv));
srcvals = [r; du; dv; n];- Port direct OpenCascade topology descriptors and repair settings.
- Port Step 1 helper-curve handling and closed/periodic face guards.
- Port Step 1b precise node correction.
- Replace the current Gmsh curve-projection edge recovery with the full Python Step 2 GLL edge recovery and 4x4 Newton solve where applicable.
- Port Step 3 Python refinement details exactly.
- Port Step 4 support-surface projection tolerances and diagnostics.
- Add parity tests against the Python reference output for all required examples.