Scripting API
Mirror opposite
from ArtisanPlugin.Scripting import TransformApi as transform
Places a second copy of a detail across the piece: the stone on the other shoulder of a ring, the matching side of a bypass shank, the opposite claw of a pair. It is not the mirror you would get from Rhino’s Mirror — the copy comes out the same way round as the original, which is what you want for a part that has to be manufacturable on both sides rather than a left-hand and a right-hand version.
Usage
ids = transform.MirrorOpposite(objectIds = None, plane = None) # -> the new copies
| Parameter | Default | Meaning |
|---|---|---|
objectIds | None | Objects to copy. None or an empty list uses the current selection |
plane | None | The frame whose origin and Z axis define the opposite side. None uses the active viewport’s construction plane, or world XY when the session has no view |
Two reflections are built from the frame — one across the plane spanned by its Z and X axes, one across the plane spanned by its Y and Z axes — and composed into a single transform. Composing two reflections whose planes meet along the frame’s Z axis gives a rotation of 180° about that Z axis, through the plane’s origin. That is what “keeping its handedness” means concretely: the determinant is positive, so the geometry is rotated, not reflected. Text stays readable, threads keep their direction, and a right-hand part stays a right-hand part. Its X and Y coordinates in the plane’s frame are negated while its height above the plane is unchanged.
What is created
Exactly one copy per object, added to the document with Rhino’s TransformWithHistory, so the copy is history-linked and follows edits to the original (with Record History and Update Children on). The source objects are not modified, moved or deleted.
Returns an IReadOnlyList<Guid>: the ids of the copies, one per object, in input order. An object whose copy fails contributes no id, so the list can be shorter than the input — check its length rather than assuming a one-to-one match.
Ids you pass explicitly must exist — a missing one raises Object {id} does not exist. naming it, and duplicates are collapsed. With no ids and nothing selected it raises Nothing selected: select (or pass) at least one object.. A plane that is not valid geometry raises The mirror plane is not valid..
from ArtisanPlugin.Scripting import TransformApi as transform, Transaction
with Transaction.Begin("Copy to the other shoulder"):
ids = transform.MirrorOpposite([shoulderId])