Feature/tpms frep#122
Draft
chemiskyy wants to merge 12 commits into
Draft
Conversation
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.
Implement OffsetGrading.as_field to produce a (x,y,z)->array callable that builds transient PolyData and calls compute_offset, allowing grading to be re-evaluated on arbitrary grids (used by the F-rep / marching-cubes path). Store this callable on Tpms instances when given an OffsetGrading so shell()/as_sheet() can re-sample offsets on the marching-cubes grid (avoids failures like float(t) on array inputs). Also replace a hardcoded OUT path in the example with Path(__file__).parent and tidy related imports.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request introduces several enhancements and fixes to the TPMS (Triply Periodic Minimal Surface) functionality, focusing on improved mathematical robustness, new features for shape generation, and expanded testing and documentation. The most significant changes include switching to
autogradfor differentiable surface functions, adding a newboxshape primitive, improving the robustness of signed distance field (SDF) normalization, and adding new examples and regression tests for TPMS coordinate frames.Core mathematical and API improvements:
autograd.numpyto enable automatic differentiation and improved compatibility with optimization and gradient-based workflows. (microgen/shape/surface_functions.py, dependency updates inenvironment.yml,conda.recipe/meta.yaml, andpyproject.toml) [1] [2] [3] [4]shelloperation now supports spatially-varying thickness by accepting a callable field, not just a scalar. This enables advanced shelling operations with locally controlled thickness. (microgen/shape/implicit_ops.py)New features:
boxshape primitive for axis-aligned bounding boxes, useful for clipping and bounding TPMS fields. (microgen/shape/implicit_ops.py)Robustness and bug fixes:
microgen/shape/implicit_ops.py) [1] [2]Testing and documentation:
tests/shapes/test_tpms.py) [1] [2]examples/tpms_infill_gallery.py,gyroid_gd_bunny.py) [1] [2]These changes collectively improve the flexibility, reliability, and usability of the TPMS module for both research and practical applications.