This is where I ended up with it in the early mornin’
from math import radians, cos, sin
import Rhino.Geometry as rg
"""
Inputs:
roll: Roll angle in degrees
pitch: Pitch angle in degrees
yaw: Yaw angle in degrees
x, y, z: Origin coordinates of the plane
axis_len: Length of preview axis lines
sx, sy: Plane surface size
Outputs:
plane: Constructed plane
origin: Origin point
x_axis: X direction vector
y_axis: Y direction vector
z_axis: Z direction vector
axes: Preview axis lines
srf: Plane surface
rect: Rectangle curve on plane
"""
def RunScript(self, roll, pitch, yaw, x, y, z, axis_len, sx, sy):
# --- Convert to radians ---
roll = radians(roll)
pitch = radians(pitch)
yaw = radians(yaw)
# --- Precompute trig ---
cx, cy, cz = cos(roll), cos(pitch), cos(yaw)
sx_, sy_, sz_ = sin(roll), sin(pitch), sin(yaw)
# --- Rotation matrix (Z-Y-X intrinsic) ---
R = [
[cz*cy, cz*sy_*sx_ - sz_*cx, cz*sy_*cx + sz_*sx_],
[sz_*cy, sz_*sy_*sx_ + cz*cx, sz_*sy_*cx - cz*sx_],
[ -sy_, cy*sx_, cy*cx ]
]
# --- Axes and origin ---
x_axis = rg.Vector3d(R[0][0], R[0][1], R[0][2])
y_axis = rg.Vector3d(R[1][0], R[1][1], R[1][2])
z_axis = rg.Vector3d.CrossProduct(x_axis, y_axis)
origin = rg.Point3d(x, y, z)
# --- Final plane ---
plane = rg.Plane(origin, x_axis, y_axis)
# --- Axes as preview lines ---
lx = rg.Line(origin, origin + x_axis * axis_len)
ly = rg.Line(origin, origin + y_axis * axis_len)
lz = rg.Line(origin, origin + z_axis * axis_len)
axes = [lx, ly, lz]
# --- Centered plane surface ---
srf = rg.PlaneSurface(
plane,
rg.Interval(-sx * 0.5, sx * 0.5),
rg.Interval(-sy * 0.5, sy * 0.5)
)
# --- Rectangle curve ---
rect = rg.Rectangle3d(
plane,
rg.Interval(-sx * 0.5, sx * 0.5),
rg.Interval(-sy * 0.5, sy * 0.5)
)
return plane, origin, x_axis, y_axis, z_axis, axes, srf, rect
This evening:
from math import radians, cos, sin
import Rhino.Geometry as rg
def RunScript(self, roll, pitch, yaw, x, y, z, axis_len, sx, sy):
# ----- safe defaults WITHOUT changing the signature -----
def d(v, default): return default if v is None else v
roll = d(roll, 0.0)
pitch = d(pitch, 0.0)
yaw = d(yaw, 0.0)
x = d(x, 0.0)
y = d(y, 0.0)
z = d(z, 0.0)
axis_len = max(1e-6, d(axis_len, 10.0))
sx = max(1e-6, d(sx, 20.0))
sy = max(1e-6, d(sy, 20.0))
# ----- angles (deg -> rad) -----
roll, pitch, yaw = map(radians, (roll, pitch, yaw))
# ----- trig -----
cx, cy, cz = cos(roll), cos(pitch), cos(yaw)
sx_, sy_, sz_ = sin(roll), sin(pitch), sin(yaw)
# ----- Z-Y-X intrinsic (yaw-pitch-roll) -----
R = [
[cy*cz, cz*sx_*sy_ - cx*sz_, cx*cz*sy_ + sx_*sz_],
[cy*sz_, cx*sy_*sz_ + cz*sx_, cx*cz - sx_*sy_*sz_],
[-sy_, cy*sx_, cx*cy]
]
# ----- axes from columns, orthonormalize -----
x_axis = rg.Vector3d(R[0][0], R[1][0], R[2][0]); x_axis.Unitize()
y_axis = rg.Vector3d(R[0][1], R[1][1], R[2][1]); y_axis.Unitize()
z_axis = rg.Vector3d.CrossProduct(x_axis, y_axis); z_axis.Unitize()
# re-derive y to guarantee right-handed frame
y_axis = rg.Vector3d.CrossProduct(z_axis, x_axis); y_axis.Unitize()
# ----- origin & plane -----
origin = rg.Point3d(x, y, z)
plane = rg.Plane(origin, x_axis, y_axis)
# ----- preview axes -----
axes = [
rg.Line(origin, origin + x_axis * axis_len),
rg.Line(origin, origin + y_axis * axis_len),
rg.Line(origin, origin + z_axis * axis_len),
]
# ----- centered surface & rectangle -----
ix = rg.Interval(-sx * 0.5, sx * 0.5)
iy = rg.Interval(-sy * 0.5, sy * 0.5)
srf = rg.PlaneSurface(plane, ix, iy)
rect = rg.Rectangle3d(plane, ix, iy)
return plane, origin, x_axis, y_axis, z_axis, axes, srf, rect
didn’t think I’d end up with this many inputs/outputs lol 