Skip to main content

A fast geometry manipulation and creation library written in Rust, wrapped in python

Project description

GMAC

Build & Test License: MIT

A fast mesh manipulation and creation library made in rust, with a convenient python interface, and very few dependencies. Primary features include:

  • Deform meshes using RBF and FFD
  • Transform meshes (or selection just a selection of nodes)
  • Large range of selection and transformation tools
  • Import/export stl, obj and vtk-type files
  • Convenient python interface
  • Create primitives
  • Great performance

Here's a demonstration of a plane tail deformed using the Free Form deformer (FFD):

Variation 1 Variation 2

Add to your rust project

Add the following to your Cargo.toml:

[dependencies]
gmac = "^0.2.0"

This includes rayon by default, for those who want a lightweight dependency free version use default-features = false

For Rbf specifically, if you still need more performance try adding features openblas or intel-mkl. Make sure you have the required dependencies installed for the features you choose. For openblas openssl is required.

Examples in Rust

Deforming with Free Form Deformer (FFD)

Heres a demonstration of deformation using the FreeFormDeformer:

use gmac::{
    core::{
        primitives::generate_box,
        transformation::{build_transformation_matrix, transform_selected_nodes},
    },
    io::stl::StlFormat,
    morph::{design_block::DesignBlock, ffd::FreeFormDeformer},
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a simple primitive or import something else
    let mut mesh = generate_box(
        [2.0, 1.0, 1.0],  // Lengths (x, y, z)
        [0.0, 0.0, 0.0],  // Center coordinates
        [0.0, 0.0, 0.0],  // Rotation angles (degrees)
        [12, 12, 12],     // Elements in each direction
    )?;
    
    // Alternative: mesh = Mesh::from_stl("path_to_stl")? or from_obj

    // Create a design block (control lattice) for FFD
    // This should contain the region you wish to deform
    let design_block = DesignBlock::new(
        [1.8, 1.2, 1.2],  // Lengths (x, y, z)
        [0.2, 0.0, 0.0],  // Center offset
        [0.0, 0.0, 0.0],  // Rotation angles (degrees)
        [3, 2, 2],        // Control points each direction
    )?;

    // Select which control points will be free to move during 
    // deformation, the second parameter specifies the number of 
    // fixed layers of control points at the boundaries
    let free_design_ids = design_block
        .select_free_design_nodes(&mesh, Some(2))?;

    // Apply the transformation to each free control point
    let transform_matrix = build_transformation_matrix(
        [0.25, 0.0, 0.0],   // Translation vector (x, y, z)
        [125.0, 0.0, 0.0],  // Rotation angles (degrees)
        [1.0, 1.25, 1.25],  // Scaling factors (x, y, z)
    );

    let deformed_design_nodes = design_block.transform_subset(
        &free_design_ids,
        &transform_matrix,
        &[0.2, 0.0, 0.0], // Pivot point
    );

    // Create a Free-Form Deformer with original design block
    let ffd = FreeFormDeformer::new(design_block)?;

    // Apply the deformation to the original geometry
    mesh.nodes = ffd.deform(&mesh.nodes, &deformed_design_nodes)?;

    // Save the final deformed geometry as an STL/OBJ/VTK file
    mesh.write_stl(Some("deformed.stl"), Some(StlFormat::Binary))?;

    Ok(())
}
Original mesh & control points Deformed mesh & control points

Note: There are many ways to achieve the same result with all the tools provided, this is just one of them.

Deforming with Radial Basis Functions (RBF)

Using the RbfDeformer is very similar to using the FFD, but instead of using a design block (control lattice), you use a set of control points:

use gmac::core::{
    clusters::generate_block_cluster,
    primitives::generate_torus,
    selection::select_nodes_in_plane_direction,
    transformation::{build_transformation_matrix, transform_selected_nodes},
};
use gmac::morph::rbf::RbfDeformer;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a simple geometry or import one
    let mut mesh = generate_torus(1.0, 0.3, [0.0, 0.0, 0.0], 64, 64)?;

    // Create a set of control points
    let original_control_points = generate_block_cluster(
        [2.8, 1.0, 2.8], // Slightly larger than the original box
        [0.0, 0.0, 0.0], // Centered at the origin
        [0.0, 0.0, 0.0], // No rotation
        [3, 3, 3],       // Control points in each direction
    )?;

    // Select control points that lie in a plane defined 
    let target_control_point_ids = select_nodes_in_plane_direction(
        &original_control_points,
        [0.0, 0.0, 0.0], // A point in the plane
        [1.0, 0.0, 0.0], // Normal vector (x-axis in this case)
    );

    // Apply transformation to the selected control points
    let transform_matrix = build_transformation_matrix(
        [0.0, 0.0, 0.0],   // Translation
        [45.0, 20.0, 0.0], // Rotation
        [1.0, 1.0, 1.0],   // Scale
    );

    let deformed_control_points = transform_selected_nodes(
        &original_control_points,
        &target_control_point_ids,
        &transform_matrix,
        &[0.0, 0.0, 0.0], // Origin/pivot point
    );

    // Create an RBF deformer with the control point configurations
    let rbf = RbfDeformer::new(
        original_control_points,
        deformed_control_points,
        Some("thin_plate_spline"), // Type of RBF kernel
        Some(1.0),                 // Shape parameter
    )?;

    // Apply the RBF deformation to the original geometry
    mesh.nodes = rbf.deform(&mesh.nodes)?;

    // Save the final deformed geometry as an STL/OBJ/VTK file
    mesh.write_stl(Some("deformed.stl"), None)?;

    Ok(())
}

Here you can see the original control points and mesh, as well as the deformed control points and mesh:

Original mesh & control points Deformed mesh & control points

Examples in Python

Using GMAC to deform a box

Heres a simple demonstration of using the Free Form Deformer (FFD) to deform a generated box (or an imported STL file).

import gmac as gm

# Create a simple primitive geometry or import something
mesh = gm.generate_box([2.0, 1.0, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [12, 12, 12])

# Alternative: mesh = gm.Mesh.from_stl("path_to_stl") or obj

# Create a design block (control lattice) for FFD
design_block = gm.morph.DesignBlock(
    [1.8, 1.2, 1.2],  # Dimensions of the control lattice
    [0.2, 0.0, 0.0],  # Center offset
    [0.0, 0.0, 0.0],  # Rotation angles (degrees)
    [3, 2, 2],        # Control points in each direction
)

# Select which control points will be free to move
free_design_ids = design_block.select_free_design_nodes(mesh, 2)

# Transform only the free control points using transformation matrix
transformation_matrix = gm.build_transformation_matrix(
    [0.25, 0.0, 0.0],  # Translation vector
    [125.0, 0.0, 0.0],  # Rotation angles
    [1.0, 1.25, 1.25],  # Scaling factors
)

deformed_design_nodes = gm.transform_selected_nodes(
    design_block.nodes,
    free_design_ids,
    transformation_matrix,
    [0.2, 0.0, 0.0],
)

# Save the deformed control points for visualisation
gm.io.write_vtp(deformed_design_nodes, "deformed_design_nodes.vtp")

# Create a Free-Form Deformer with the original design block
ffd = gm.morph.FreeFormDeformer(design_block)

# Apply the deformation to the original geometry
mesh.nodes = ffd.deform(mesh.nodes, deformed_design_nodes)

# Save the deformed geometry as STL/OBJ/VTK file
mesh.write_stl("deformed_geometry.stl") # binary default

For Radial Basis Function (RBF) deformation, see the RbfDeformer example in examples.

Build python from source

These instructions assume that Python3 and Cargo are installed on your system. To set up this project, follow these steps:

  1. Clone the repository:
    git clone https://github.com/alexlovric/gmac.git
    cd gmac/gmac_py
    
  2. Create a virtual environment and install build system:
    python3 -m venv .venv
    source .venv/bin/activate # In windows /Scripts/activate
    python3 -m pip install -r requirements.txt
    
  3. Build the release binary:
    maturin develop --release
    
  4. Build the python wheel:
    maturin build --release
    
  5. Running examples:
    python3 -m pip install <path to wheel (target/wheels/*.whl)>
    cd examples
    python3 -m pip install -r requirements.txt
    python3 *simple_ffd_deformation*.py
    

References

The gmac_morph is heavily influenced by PyGEM (https://github.com/mathLab/PyGeM), and the following

Sieger, Menzel, Botsch. On Shape Deformation Techniques for Simulation-based Design Optimization. SEMA SIMAI Springer Series, 2015.

Lombardi, Parolini, Quarteroni, Rozza. Numerical Simulation of Sailing Boats: Dynamics, FSI, and Shape Optimization. Springer Optimization and Its Applications, 2012.

License

MIT License - See LICENSE for details.

Support

If you'd like to support the project consider:

  • Identifying the features you'd like to see implemented or bugs you'd like to fix and open an issue.
  • Contributing to the code by resolving existing issues, I'm happy to have you.
  • Donating to help me continue development, Buy Me a Coffee

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

gmac-0.2.0-cp38-abi3-win_amd64.whl (355.1 kB view details)

Uploaded CPython 3.8+Windows x86-64

gmac-0.2.0-cp38-abi3-manylinux_2_34_x86_64.whl (452.3 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.34+ x86-64

gmac-0.2.0-cp38-abi3-macosx_11_0_arm64.whl (394.1 kB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

File details

Details for the file gmac-0.2.0-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: gmac-0.2.0-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 355.1 kB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.9.0

File hashes

Hashes for gmac-0.2.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 48042453603eae8320edd82a48b82bffb1be885026ec4abf9701b14ae606f308
MD5 86729bd819070c67b3305ac859fc9dc5
BLAKE2b-256 0e7813b82f44cb3ec2b1d150bf31073994236cdee08a0a44f13aa7a653565f80

See more details on using hashes here.

File details

Details for the file gmac-0.2.0-cp38-abi3-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for gmac-0.2.0-cp38-abi3-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 c7987bbe8a1b59226816de4d4103c1c624c3c552a3bca7dd5af204fcdbbf45de
MD5 9181b2ee24a7b714f909e62b9d7afd8e
BLAKE2b-256 f22bb7a956a365fa0adae08695573594ef0c6bad802121d517531760f815b27c

See more details on using hashes here.

File details

Details for the file gmac-0.2.0-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gmac-0.2.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c6ffc11b66de5f92f63496d40c74154d8bfa0d45302dc4537fa5b03d186395e0
MD5 d7815cb2f63d2be78e68d8fc0497e5f7
BLAKE2b-256 7784aba6ddf4c0a4814922ef39938d66ee7b1ba55375b476b527a6a39c12ee95

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page