Skip to content

Feature/mmgpy#124

Open
chemiskyy wants to merge 18 commits into
mainfrom
feature/mmgpy
Open

Feature/mmgpy#124
chemiskyy wants to merge 18 commits into
mainfrom
feature/mmgpy

Conversation

@chemiskyy
Copy link
Copy Markdown
Member

Replace subprocess MMG bindings with mmgpy

mmgpy (kmarchais/mmgpy) bundles the MMG native library and exposes a
typed Python API. Mmg.mmg2d / Mmg.mmgs / Mmg.mmg3d keep the same kwargs
but now delegate to mmgpy.mmg{2d,s,3d}.remesh, removing the dependency
on a system MMG install and the brittle subprocess plumbing.

Add a [mmg] extra; environment.yml conda dep is now mmgpy.

Introduce F-rep implicit operations and integrate implicit-field support into Shape. Adds new module microgen.shape.implicit_ops (boolean, smooth blending, batch_smooth_union, repeat, shell, blend, from_field, etc.) and comprehensive tests. Refactors microgen/shape/shape.py to carry optional implicit fields, provide evaluation, default generate_vtk/generate via marching-cubes -> CadQuery, boolean operators, smooth booleans, and transform helpers (translate/rotate/scale). Updates package exports and docs to expose implicit_ops and related helpers; re-exports ShellCreationError from tpms for backward compatibility.
Include autograd in pip dependencies for both the conda build recipe and the environment file (conda.recipe/meta.yaml and environment.yml) so the package is installed during build/test and available in the development environment.
Replace numpy imports with autograd.numpy in microgen/shape/surface_functions.py so TPMS surface functions are compatible with autograd (enabling automatic differentiation). Add autograd to pyproject.toml dependencies to ensure the new import is available. No behavior changes beyond making the functions differentiable with autograd.
Introduce F-rep based implicit fields for Tpms and its curvilinear variants so TPMS can be used with SDF-normalized operations (shell, complement, booleans). Adds _setup_frep_field to Tpms, CylindricalTpms and SphericalTpms (using from_field + normalize_to_sdf), exposes raw_field, and adds convenience methods as_sheet, as_upper_skeletal and as_lower_skeletal. generate_vtk was updated to build parts from the F-rep Shapes and to use the normalized field/bounds; offset checks and density-based offset computation are preserved. A comprehensive test suite (tests/shapes/test_tpms_frep.py) was added to validate SDF normalization, TPMS F-rep evaluation, sheet/skeletal helpers, boolean composition, generate_vtk compatibility and curvilinear TPMS behavior.
Introduce _finalize_frep to centralize raw field -> SDF normalization and setting of _raw_field_func, _func and _bounds. Replace duplicated normalization code in Tpms, CylindricalTpms and SphericalTpms with calls to the new helper. Adjust generate_vtk resolution logic to compute an isotropic resolution from repeat_cell (using geometric mean) and enforce a sensible minimum, and wrap shell return in a plain Shape to avoid recursive generate_vtk calls. Also include minor formatting and expression cleanups.
Refactor implicit ops and shape bounds handling. Move implicit_ops import to module scope and route Shape boolean/transform methods through it. Add SDF utilities: normalize_to_sdf (uses autograd with finite-difference fallback) and variable_shell, plus an FD-based _fd_sdf helper. Improve Shape behavior: document evaluate's local-frame semantics, recompute AABB on rotate by rotating box corners, handle negative scale factors by swapping axis mins/maxes, and tidy lambda argument formatting. Misc: bump conda recipe/min Python to >=3.10, update CI comment about CadQuery, tighten dev dependency ruff, remove some Jupyter viewer packages from examples/pyproject entries, and apply small test formatting fixes.
Add variable-thickness and SDF utilities and refactor TPMS F-rep pipeline.

Key changes:
- implicit_ops.shell: allow thickness to be a callable Field (spatially-varying) and add docs; add box() SDF primitive; improve gradient-normalization fallback to preserve sign when grad is degenerate.
- tpms.Tpms: store offset callables, accept callable offsets and preserve them for re-evaluation; compute density→offset via the same marching-cubes pipeline (generate_vtk) and handle bracket failures; expose as_sheet that accepts variable offsets; add helpers (_half_offset_field, _cell_box, clipped variants) and pick F-rep shapes for parts.
- Mesh -> CadQuery conversion: replace previous face assembly with sewing (BRepBuilderAPI_Sewing) to produce a proper shell; best-effort upgrade to solids via _try_make_solid; generate() now uses the pure F-rep path (marching cubes on SDF Shape) and applies smoothing/solid conversion; generate_vtk mirrors the same F-rep pipeline and short-circuits full-density case by returning a box mesh.
- Misc: add _isotropic_resolution to map per-axis resolution to a single isotropic value; improve argument validation and error messages; reset cached _offset_func on assignment.
- tests: update TPMS surface function discovery to filter out camelCase aliases and non-TPMS callables by checking function signatures (3 parameters).

These changes make TPMS generation consistent between the VTK and CAD paths, enable spatially-varying thickness, and improve robustness around degenerate fields and solid construction.
Introduce a Conformal TPMS implementation and related improvements, plus two example scripts.

Changes:
- Add Conformal class to microgen.shape.tpms: builds TPMS in a local (w,u,v) frame using signed-distance as the radial coord, supports default_tangent_axis and optional clipping to the envelope. Overrides grid creation and cell-box to use the envelope surface.
- Adjust Tpms density handling: density computations now measure against an envelope volume via _density_envelope_volume(), avoid cloning instances during root-finding, and correctly restore density after computing offset.
- Infill now measures density relative to the provided object volume and overrides the cell-box to clip to the object envelope.
- Add examples/conformal_vs_cartesian_bunny.py demonstrating side-by-side Cartesian vs Conformal gyroid infill on the Stanford bunny.
- Add gyroid_gd_bunny.py utility script for visualizing a gyroid field clipped to a bunny and computing relative density.

Rationale: provide a conformal TPMS mode that follows an arbitrary envelope surface (onion-shell style cells), make density semantics consistent (relative to the intended envelope), and ship examples to illustrate the difference.
Major refactor and feature additions to TPMS generation and infill handling.

Key changes:
- Add parametric-grid generation path for Cylindrical, Spherical and a new Sweep class (TPMS along a curve) to avoid MC Cartesian sampling artefacts; introduce _uses_parametric_grid flag and seam merge logic.
- Add Sweep: builds parallel-transport frames, interpolates curve frames, maps (s,r,θ) parametric grid to Cartesian, and provides tube SDF and resolution heuristics.
- Fix angle/arc conversions for cylindrical/spherical grids (use y/radius and z/radius) and tighten F-rep bounds; implement proper cell_box SDFs for cylindrical/spherical shells and Sweep tube.
- Improve Tpms.generate path: support full-density envelope mesh via _envelope_mesh_at_full_density/_via_cell_box and prefer parametric-grid extraction when applicable; sample callable offsets from StructuredGrid or raw points.
- Infill improvements: auto-orient normals, preserve original input volume for density calculations, route sheet/upper/lower properties to generate_vtk, and use object bbox for F-rep bounds.
- Add helper SDFs and utilities: wedge and double-cone SDFs, per-axis interp helper.
- Add new example scripts (tpms_infill_gallery.py, gyroid_gd_bunny.py), remove conformal_vs_cartesian_bunny.py, and add new tests (test_implicit_cylinder.py, test_kevin.py) plus updates to tests/shapes/test_tpms.py.

Rationale: fix sampling artefacts near poles/axes, make full-density shortcut geometrically correct for non-box envelopes, support TPMS swept along arbitrary curves, and make density-fitting for infill robust to non-manifold/oriented inputs. Files added/removed include examples and small demo scripts.
Minor formatting and style-only changes across several files: examples/tpms_infill_gallery.py (whitespace), gyroid_gd_bunny.py (numeric literal spacing, array formatting, string quote/style normalization, minor spacing and comment formatting), microgen/shape/implicit_ops.py (wrap long expression), microgen/shape/tpms.py (reflowed long lines, added trailing commas and consistent spacing, minor type annotation formatting), and tests/shapes/test_tpms.py (compact conditional and assert formatting). No functional logic changes are intended—these edits improve readability and adhere to consistent code style.
Enable ruff auto-fixing in pre-commit and apply broad code cleanups across the package: normalize docstring formatting, adjust typing usages (use collections.abc types, prefer tuple/list/ dict annotations), add strict=False to zipped/product iterations to guard against length mismatches, and tidy trailing commas/formatting. Reorder and restore several symbols in microgen.__init__.py exports. Minor behavioral changes are limited to typing/formatting and import/order/namespace adjustments.
Introduce a new optional CAD backend (microgen.cad) that uses cadquery-ocp / OCP as a direct OCCT binding, and refactor boolean/transform operations to use a CadShape wrapper with deferred OCP imports. Make the CAD path optional via the [cad] extra and update docs (README), conda recipe and environment files to recommend ocp and relax VTK/pyvista pinning for the core (mesh + F-rep) install. Split GitHub Actions into a lightweight core-no-cad job (tests for mesh/implicit-field with VTK 9.4+) and a full cad job that installs the [cad] extras. Add a test for optional CAD import (tests/test_cad_optional.py) and remove jupyter-cadquery from example deps. These changes decouple heavy OCCT/CadQuery constraints from the default install, reducing dependency footprint while preserving a full CAD-enabled mode.
Add Python 3.14 to GitHub Actions matrices (build-and-test and integration), including a comment in integration explaining conda-forge ocp wheels availability. Update pyproject classifiers to advertise Python 3.14 and add README notes about core support for 3.10–3.14 and the `[cad]` extra using conda-forge if PyPI lacks cadquery-ocp wheels. This brings CI, docs, and packaging into alignment for the new Python release.
Add CadQuery-compatible helpers and robustness fixes for OCCT bindings: introduce CadShape.Vertices, Faces and Closed; make Volume return the absolute value to avoid negative volumes from inverted orientation; correct __slots ordering. Clean up and normalize OCP imports (remove excessive noqa markers), switch to collections.abc Iterable/Sequence and add typing.Any for raw TopoDS passthrough. Small API/robustness tweaks across mesh/shell/shape helpers (formatting, exception handling, safe zip use) and simplify shape module imports. Update ruff ignores in pyproject.toml to accommodate needed typing and third‑party API patterns.
Refactor examples to use microgen.cad helpers instead of importing cadquery directly: replace imports and usage with make_compound, make_compound_from_solids, import_step, make_box, and use shape.export_step / export_stl methods. Add import_step implementation to microgen.cad to load STEP files (merging multi-root STEP into a compound via OCP). Update docs workflow to install the [cad] extra (cadquery-ocp) so Sphinx-executed examples can render, and remove Python 3.14 from the build-and-test matrix due to missing vtk PyPI wheels (3.14 is covered via the conda-based integration job). These changes consolidate CAD operations behind microgen.cad and remove direct CadQuery usage across example scripts.
Introduce mmgpy-based remeshing support: add mmgpy to environment.yml and pyproject extras and include it in the `all` extras. Refactor microgen.external.Mmg to call mmgpy bindings instead of spawning mmg CLI binaries, adding a lazy importer (_require_mmgpy), option translation (_build_mmg_options), and a wrapper to invoke mmgpy remesh functions (_run_mmg). Preserve backward-compatible CLI signatures and keep the legacy subprocess hook for compatibility; update docs and error messages with installation hints for mmgpy.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant