visualdynamics.rotate¶
rotate
¶
Turning and sliding a coordinate system by dragging it in the 3-D view.
The geometry and the angle arithmetic are kept here, apart from Qt and VTK, so which way a drag turns or moves the frame, and by how much, can be tested without a window.
A coordinate system is stored as four rows: three orthonormal basis vectors and an origin. Dragging a ring around one of the frame's axes turns the frame about that axis; a rotation changes only the basis, and the origin stays where it is.
Dragging an arrow along one of the frame's axes slides the origin along that axis and snaps it to a grid in the geometry's own axes: a tenth of an inch for the inch family of units, a centimeter for the metric one. A frame or a block then lands on round coordinates whichever way it is turned.
Functions:
| Name | Description |
|---|---|
rotation_about |
The 3x3 rotation of |
ring_points |
|
rotate_frame |
A copy of |
angle_in_plane |
Where a world point sits around one principal axis, in radians. |
wrapped |
An angle in radians folded into [-pi, pi), so a drag across the |
ring_under_cursor |
The axis of the ring a pixel is over, or None. |
plane_hit |
Where the ray from |
identity_frame |
The frame with its rotation undone: the identity basis at the |
grid_step |
The grid a slide lands on, in the display |
arrow_points |
|
translate_frame |
A copy of |
axis_hit |
The point on the axis line (through |
distance_along |
How far a world point is from the frame's origin along one of |
snapped |
|
frame_from_angles |
A frame at |
angles_of |
The fixed-axis X, Y, Z angles in degrees that turn the geometry's |
Functions:¶
rotation_about
¶
The 3x3 rotation of angle radians about axis, by Rodrigues'
formula.
axis is normalized here, so it need not be a unit vector. A
positive angle turns counterclockwise looking down the axis toward
the origin (the right-hand rule).
Source code in src/visualdynamics/rotate.py
ring_points
¶
steps points evenly spaced on a circle of radius around one
principal axis of a frame, centered on its origin.
The ring for the X axis lies in the frame's own Y-Z plane, so it is the circle swept by turning about X. It starts on the next axis (Y for X) and the first point is not repeated at the end.
Source code in src/visualdynamics/rotate.py
rotate_frame
¶
A copy of matrix with its basis turned angle radians about one
of its own axes.
The axis moves with the frame, so turning about X twice by 45 degrees is turning about the frame's X by 90 degrees, not about the world's X. The origin is unchanged.
Source code in src/visualdynamics/rotate.py
angle_in_plane
¶
Where a world point sits around one principal axis, in radians.
Measured in the ring's own plane from the first of the two axes it
spans, so it pairs with ring_points.
Source code in src/visualdynamics/rotate.py
wrapped
¶
An angle in radians folded into [-pi, pi), so a drag across the +/-180 degree line stays small: from 179 to -179 degrees is 2 degrees, not 358.
Source code in src/visualdynamics/rotate.py
ring_under_cursor
¶
ring_under_cursor(rings: Sequence[tuple[int, ndarray]], cursor: ArrayLike, tolerance: float = 14.0) -> int | None
The axis of the ring a pixel is over, or None.
rings is a list of (axis, screen points), each a polyline; the
caller closes a ring by repeating its first point. The distance is
measured to the polyline's segments, not to its points. The rings
cross each other, so the nearest one closer than tolerance pixels
wins, not the first one listed. An arrow from arrow_points is
picked the same way.
Source code in src/visualdynamics/rotate.py
plane_hit
¶
plane_hit(origin: ArrayLike, normal: ArrayLike, eye: ArrayLike, direction: ArrayLike) -> ndarray | None
Where the ray from eye along direction meets the plane
through origin with normal normal, or None when they are
parallel.
Dragging a ring follows the cursor around the plane the ring lies in, and this is the point on that plane.
Source code in src/visualdynamics/rotate.py
identity_frame
¶
The frame with its rotation undone: the identity basis at the same origin.
Source code in src/visualdynamics/rotate.py
grid_step
¶
The grid a slide lands on, in the display unit: a tenth of an
inch for the inch family (INCH_FAMILY), a centimeter for every
other unit.
Source code in src/visualdynamics/rotate.py
arrow_points
¶
steps points along the arrow for one principal axis of a frame,
from the origin out to length along it. It is a polyline like a
ring, so ring_under_cursor picks an arrow the same way.
Source code in src/visualdynamics/rotate.py
translate_frame
¶
A copy of matrix with its origin moved distance along one of
its own axes. The basis is unchanged; rotate_frame is the
opposite case.
Source code in src/visualdynamics/rotate.py
axis_hit
¶
The point on the axis line (through origin along direction)
nearest the cursor's ray (from eye along ray), or None when the
two are parallel.
A ray from the cursor almost never meets the axis line exactly, so a drag along an arrow is read at the point where the two lines come closest.
Source code in src/visualdynamics/rotate.py
distance_along
¶
How far a world point is from the frame's origin along one of its axes: the distance a slide reads, before the snap.
Source code in src/visualdynamics/rotate.py
snapped
¶
point moved to the nearest multiple of step in each
coordinate. The coordinates are the geometry's own, so a turned frame
still lands on round coordinates. A step of zero or less returns an
unchanged copy.
Source code in src/visualdynamics/rotate.py
frame_from_angles
¶
A frame at origin turned by angles, in degrees, about the
geometry's fixed X, then Y, then Z axes, the order a person types
them in. The first three rows are the frame's axes and the fourth is
its origin, as in a coordinate system.
Source code in src/visualdynamics/rotate.py
angles_of
¶
The fixed-axis X, Y, Z angles in degrees that turn the geometry's
axes into the frame's, the inverse of frame_from_angles. X and Z
are in (-180, 180] and Y in [-90, 90]. At a quarter turn about Y the
X and Z turns are about the same axis, and the angle is given as Z
with X at zero.