Shelling

Shelling

This example uses Metafold API/SDK to create a shell around a primitive shape and creates a shell around it then evaluates the shape metrics.

The graph

Every graph begins with the GenerateSamplePoints node, which establishes a grid or set of points for sampling the volume. The final two operators in all graphs are redistance and threshold. TheRedistance function transforms the grid of samples into signed distances from the zero level set, providing important distance data for further processing. Meanwhile, the Threshold operation clamps sample values within a specified range centered around zero and normalizes them to the signed range [-1, 1], outputting the values as bytes.

Shelling and filling requires the use of another 2 operators:

  1. Samplebox This operator allows users to create common 3D shapes
  2. Shell Creates a shell with a given thickness around the center of a level set, with its position controlled by the offset parameter.
image

Steps

  1. Import all necessary libraries
  2. Insert project and token information
  3. Define the Scene parameters
  4. Set the primitive shape and size
  5. Choose the shell thickness and offset
  6. Create the Metafold graph
  7. Evaluate metrics and export the part as STL

1- Import all necessary libraries

Start by importing the required libraries

import pandas as pd
import numpy as np
import os
import csv
from numpy.typing import ArrayLike
from pprint import pprint
from scipy.spatial.transform import Rotation as R
from metafold import MetafoldClient
from metafold.func_types import JSONEvaluator, FuncType, Vec3f, Mat4f
from metafold.func import *

2- Insert project and token information

In the following code snippet, we create a MetafoldClient instance and assign it to the variable client. This step is crucial for interacting with the Metafold API. The access_token parameter should contain your authentication token, which grants you access to the Metafold service. Similarly, the project_id parameter specifies the specific project or workspace you want to work with. Make sure to replace access_token and project_id with your own credentials and identifiers for this to work properly.

project_id = 5701
access_token = "..."
client=MetafoldClient(access_token,project_id)

3- Define the Scene parameters

To create a grid of sample points, GenerateSamplePoints is used. The generated grid includes sample points at the boundary minimum and maximum as defined by the offset and size. The grid is also commonly referred to as a patch.) More information about Metafold’s implicit representations can be found here.

source = GenerateSamplePoints({
						"offset": [ -2, -2, -1],
						"size": [4, 4, 1],
						"resolution": [256, 256, 256]
					}

4- Set the primitive shape and size

The next step is setting up parameters for a box shape using a dictionary named box_params. The rotation of the box is defined with an array box_rot as [0, 0.0, 0.0], while the position is represented by the array box_pos as [0.0, 0.0, 0.0]. The dimensions of the box are specified as [2, 2, 2].

To create the transformation matrix for the box, we utilize the xform function we defined earlier with the rotation and position values, and then flatten the matrix before incorporating it into the box_params dictionary under the "xform" key.

This setup in the box_params dictionary encapsulates all the necessary information for defining a box shape within a 3D space, including its size, placement, and orientation through a transformation matrix.

For the shape type, box can be replaced by Cylinder, BoxFrame, Ellipsoid or other shapes supported by Metafold, you can find a detailed description here.

The SampleBox function enables the sampling of a primitive shape within a defined space of specified sample points.

cyl_rot = np.array([0, 0.0, 0.0])
cyl_pos = np.array([0.0, 0.0, 0.0])
cyl_params = {
    "shape_type": "Cylinder",
    "size": [2, 2, 4],
    "xform": xform(cyl_rot, cyl_pos).flatten()
}
Cylinder = SampleBox (source, parameters=cyl_params)

5-Choose the shell thickness and offset

Then the shell parameters should be defined

for an outer shell a negative offset should be assigned

for an inner shell a positive offset should be assigned

shell_thickness=0.25
shell = Shell(
            Cylinder,
    {
        "thickness": shell_thickness,
        "offset": -0.5*shell_thickness,
    },
)

6- Create the Metafold graph

We now use the operators defined earlier in the graph section to create our Metafold shape

shape_func= Threshold(
                Redistance(
                    shell
                )
            )    

JSONEvaluator is used to evaluate the graph

evaluator = JSONEvaluator(source) 
shape_func(evaluator)
graph_json=evaluator.json()

7- Evaluate metrics and export

Use the evaluate_metrics job to evaluate the approximate interior volume and surface area of the implicit surface defined by the given Metafold shape definition.

job= client.jobs.run("evaluate_metrics", {"graph": graph_json, "point_source": 0})

use pprint to print the desired information from evaluate_metrics, in this specific example “relative_density” was retrieved.

pprint((job.meta["relative_density"]))

An STL file can be exported using the export_job

export_job = client.jobs.run("export_triangle_mesh", {
        "graph": graph_json,
        "point_source": 0,
    })
export_asset = export_job.assets[0].id
client.assets.download_file(export_asset, "cylinder.stl")

The STL file exported from python script , showing a solid cylinder, a cylinder with an outer shell thickness and another with an inner shell thickness

image