119 lines
4.4 KiB
Python
119 lines
4.4 KiB
Python
#!/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()
|