#!/usr/bin/env python3 """ CUDASlicer Python Quickstart & Integration Example ================================================= Demonstrates how to use `cudaslicer` in a Python project with: - first_layer_height - perimeters_count and layer_width (Perimeter 1: -0.5w, Perimeter 2: -1.5w, etc.) - default pitch_mm = 0.10 - outputs: perimeters and infill_mask (-perimeters_count * layer_width) """ import time import numpy as np import trimesh import cudaslicer def example_mask_offsetting(): print("--- 1. GPU Mask Offsetting ---") # Create a 200x200 test grid with a square grid = np.zeros((200, 200), dtype=np.uint8) grid[50:150, 50:150] = 1 t0 = time.perf_counter() # Generate 2 perimeters and infill mask with layer_width=0.45 mm, default pitch_mm=0.10 mm perimeters, infill_mask = cudaslicer.offset_masks( masks=grid, perimeters_count=2, layer_width=0.45, pitch_mm=0.10 # default is 0.10 ) t1 = time.perf_counter() print(f"Mask offset completed in {(t1 - t0)*1000:.3f} ms") print(f"Original area (pixels): {grid.sum()}") print(f"Perimeter 1 (-0.5*width = -0.225mm) area (pixels): {perimeters[0].sum()}") print(f"Perimeter 2 (-1.5*width = -0.675mm) area (pixels): {perimeters[1].sum()}") print(f"Infill mask (-2.0*width = -0.900mm) area (pixels): {infill_mask.sum()}\n") def example_polygon_offsetting(): print("--- 2. Single Layer Polygon Offsetting ---") # Define an L-shaped polygon l_poly = np.array([ [0.0, 0.0], [30.0, 0.0], [30.0, 10.0], [10.0, 10.0], [10.0, 30.0], [0.0, 30.0] ], dtype=np.float32) t0 = time.perf_counter() layer_res = cudaslicer.offset_polygons( layers=[l_poly], perimeters_count=2, layer_width=0.45, pitch_mm=0.10, pad_mm=1.0, return_infill_mask=True ) t1 = time.perf_counter() perimeters, infill_mask = layer_res # Unpack directly! print(f"Polygon offsetting completed in {(t1 - t0)*1000:.3f} ms") print(f" Perimeter 1 (-0.225mm): {len(perimeters[0])} loop(s), vertex count: {[len(c) for c in perimeters[0]]}") print(f" Perimeter 2 (-0.675mm): {len(perimeters[1])} loop(s), vertex count: {[len(c) for c in perimeters[1]]}") print(f" Infill contours (-0.900mm): {len(layer_res.infill_contours)} loop(s), vertex count: {[len(c) for c in layer_res.infill_contours]}") if infill_mask is not None: print(f" Infill mask raster shape: {infill_mask.shape}, active pixels: {infill_mask.sum()}") print() def example_mesh_slicing_and_offset(): print("--- 3. 100% GPU Direct 3D Mesh Slicing & Offsetting ---") mesh = trimesh.load("benchy.stl") print(f"Loaded mesh with {len(mesh.faces)} triangles. Running 100% GPU Slicing pipeline...") t0 = time.perf_counter() layers = cudaslicer.slice_mesh_and_offset( mesh_or_triangles=mesh, layer_height=0.20, first_layer_height=0.25, # custom first layer height perimeters_count=2, layer_width=0.45, pitch_mm=0.10, # default 0.10 pad_mm=1.5, return_infill_mask=True ) t1 = time.perf_counter() total_ms = (t1 - t0) * 1000 print(f"100% GPU Slicing & Offsetting done in {total_ms:.2f} ms ({len(layers)} layers)") print(f"Throughput: {len(layers) / (total_ms / 1000.0):.1f} layers/second!") # Inspect first layer and a middle layer layer_0 = layers[0] print(f"\nLayer 0 (Z = {layer_0.z:.2f} mm - First Layer Height):") perims_0, infill_mask_0 = layer_0 print(f" Perimeters: {len(perims_0)} passes (Outer: {len(perims_0[0])} loops, Inner: {len(perims_0[1])} loops)") print(f" Infill Mask: {infill_mask_0.shape}, Infill Contours: {len(layer_0.infill_contours)} loop(s)") mid_idx = len(layers) // 2 layer_mid = layers[mid_idx] print(f"Layer {mid_idx} (Z = {layer_mid.z:.2f} mm):") perims_mid, infill_mask_mid = layer_mid print(f" Perimeters: {len(perims_mid)} passes (Outer: {len(perims_mid[0])} loops, Inner: {len(perims_mid[1])} loops)") print(f" Infill Mask: {infill_mask_mid.shape}, Infill Contours: {len(layer_mid.infill_contours)} loop(s)\n") if __name__ == "__main__": if not cudaslicer.is_available(): print("Error: CUDA GPU is not available.") exit(1) print(f"CUDASlicer Version: {cudaslicer.__version__}") example_mask_offsetting() example_polygon_offsetting() example_mesh_slicing_and_offset()