5. Non-planar slicing on custom base
In this example we describe the process of non-planar slicing of a mesh, generating paths that are an offset to its
custom base. We are using the ScalarFieldSlicer
cleass, which generates paths as contours of a scalar field defined on every
vertex of the mesh. In this case we create a scalar field with the distance of each vertex from the custom base.
The files for this example can be found on the folder /examples/5_non_planar_slicing_on_custom_base/. Once you have run the python file to generate the results, you can visualize them by opening the grasshopper file visualization_scalar_field_slicing.gh.
import logging
from compas.geometry import distance_point_point
from compas.datastructures import Mesh
import os
import compas_slicer.utilities as slicer_utils
from compas_slicer.post_processing import simplify_paths_rdp_igl
from compas_slicer.slicers import ScalarFieldSlicer
import compas_slicer.utilities as utils
from compas_slicer.print_organization import ScalarFieldPrintOrganizer
logger = logging.getLogger('logger')
logging.basicConfig(format='%(levelname)s-%(message)s', level=logging.INFO)
DATA_PATH = os.path.join(os.path.dirname(__file__), 'data')
OUTPUT_PATH = slicer_utils.get_output_directory(DATA_PATH)
MODEL = 'geom_to_slice.obj'
BASE = 'custom_base.obj'
if __name__ == '__main__':
# --- load meshes
mesh = Mesh.from_obj(os.path.join(DATA_PATH, MODEL))
base = Mesh.from_obj(os.path.join(DATA_PATH, BASE))
# --- Create per-vertex scalar field (distance of every vertex from the custom base)
pts = [mesh.vertex_coordinates(v_key, axes='xyz') for v_key in
mesh.vertices()] # list of the vertex coordinates of the mesh as compas.geometry.Point instances
_, projected_pts = utils.pull_pts_to_mesh_faces(base, pts) # list with projections of all mesh vertices on the mesh
u = [distance_point_point(pt, proj_pt) for pt, proj_pt in
zip(pts, projected_pts)] # list with distance between initial+projected pts (one per vertex)
utils.save_to_json(u, OUTPUT_PATH, 'distance_field.json') # save distance field to json for visualization
# --- assign the scalar field to the mesh's attributes, under the name 'scalar_field'
mesh.update_default_vertex_attributes({'scalar_field': 0.0})
for i, (v_key, data) in enumerate(mesh.vertices(data=True)):
data['scalar_field'] = u[i]
# --- Slice model by generating contours of scalar field
slicer = ScalarFieldSlicer(mesh, u, no_of_isocurves=50)
slicer.slice_model()
# simplify_paths_rdp(slicer, threshold=0.3)
slicer_utils.save_to_json(slicer.to_data(), OUTPUT_PATH, 'isocontours.json') # save results to json
# --- Print organization calculations (i.e. generation of printpoints with fabrication-related information)
simplify_paths_rdp_igl(slicer, threshold=0.3)
print_organizer = ScalarFieldPrintOrganizer(slicer, parameters={}, DATA_PATH=DATA_PATH)
print_organizer.create_printpoints()
print_organizer.printout_info()
printpoints_data = print_organizer.output_printpoints_dict()
utils.save_to_json(printpoints_data, OUTPUT_PATH, 'out_printpoints.json') # save results to json