Scripting API
Decimator
from ArtisanPlugin.Scripting import MeshApi as mesh
Repaired and scanned meshes are heavy — millions of faces that slow down slicers, viewers and file transfers. Two reducers, with opposite priorities: Decimate hits a face count and lets the shape suffer; DecimateToTolerance guarantees the shape stays within a deviation budget and takes whatever face count falls out. For final delivery of jewellery geometry, the tolerance-driven one is usually the right tool.
Both replace each mesh in place, keeping its Guid, so wrap the calls in a Transaction. In both, objectIds = None (or empty) means the current selection, and non-mesh objects are skipped silently.
Decimate
Rhino’s quadric edge-collapse reduction (the ArtisanMeshDecimate command, headless). Distortion is allowed: the reducer prioritises hitting the target face count over shape fidelity, so heavy percentages give a faceted low-poly look.
r = mesh.Decimate(objectIds = None, percentage = 50)
| Parameter | Default | Meaning |
|---|---|---|
objectIds | None = current selection | Meshes to decimate |
percentage | 50 | Faces to remove, 1–99. percentage = 80 keeps 20% of the faces |
The target is floored at 4 faces, so a tiny mesh never collapses to nothing. A mesh whose reduction fails is skipped and simply not counted.
Returns a DecimateResult with the totals, so the script can report “N meshes: X faces → Y faces”:
| Field | Type | Meaning |
|---|---|---|
MeshesDecimated | int | Meshes actually replaced |
FacesBefore | int | Total faces across those meshes, before |
FacesAfter | int | Total faces after |
Validation that throws:
- Out-of-range percentage:
"Percentage must be between 1 and 99." - No meshes at all:
"Nothing to decimate: select (or pass) at least one mesh."
DecimateToTolerance
Reduces each mesh as much as a deviation budget allows (the ArtisanMeshDecimateTolerance command, headless): the mesh is taken to the heaviest reduction whose result still stays within toleranceMm of the original surface. The shape is guaranteed; the face count is whatever falls out.
r = mesh.DecimateToTolerance(objectIds = None, toleranceMm = 0)
| Parameter | Default | Meaning |
|---|---|---|
objectIds | None = current selection | Meshes to decimate |
toleranceMm | 0 = 0.05 | Maximum deviation from the original surface, in millimetres, regardless of the document’s units. Valid range 0.001–100 |
A mesh that cannot lose even one percent within the tolerance is left untouched and counted in MeshesUnchanged — the call never makes a mesh worse than the budget just to shrink it.
Returns a DecimateToleranceResult:
| Field | Type | Meaning |
|---|---|---|
MeshesDecimated | int | Meshes replaced |
MeshesUnchanged | int | Meshes left untouched because nothing fit the budget |
TrianglesBefore | int | Total triangles before, across the decimated meshes |
TrianglesAfter | int | Total triangles after |
MaxDeviationMm | float | Largest deviation across every decimated mesh (mm) — always ≤ toleranceMm |
The counts are in triangles, not faces: the reducer triangulates quads first, so a quad mesh’s face count is not comparable with the result’s.
Validation that throws:
- Out-of-range tolerance:
"Tolerance must be between 0.001 and 100 mm." - No meshes at all:
"Nothing to decimate: select (or pass) at least one mesh."
from ArtisanPlugin.Scripting import MeshApi as mesh, Transaction
with Transaction.Begin("Decimate for delivery"):
r = mesh.DecimateToTolerance(toleranceMm = 0.05)
print(f"{r.MeshesDecimated} meshes: {r.TrianglesBefore} -> {r.TrianglesAfter} triangles, "
f"max deviation {r.MaxDeviationMm:.3f} mm ({r.MeshesUnchanged} unchanged)")