API Reference
Coordinate frames
- class coordframe.CoordFrame(m=None, **kwargs)
Coordinate frame defined by an origin and three unit vectors.
Unit vectors are given in world coordinates (origin at zero, matrix is
eye(4)). Every transformation in this package is applied within the context of some coordinate frame.Applying a transformation in this frame:
new_crd = self.m @ tfmat @ inv(self.m) @ crd
Where
inv(m) @ crdbrings world coordinates into this frame,tfmat @applies the transformation in this frame, andm @moves coordinates back into world space.- Convention:
The parent of any
CoordFrameis the world frame. The columns ofm(this frame’s unit vectors) are defined in the world frame.
- Parameters:
m (np.ndarray | None) –
- property m: ndarray
4x4 transformation matrix to bring points from this frame to the world.
- property origin: ndarray
Origin of the coordinate system.
- property i: ndarray
X unit vector represented in world coordinates.
- property j: ndarray
Y unit vector represented in world coordinates.
- property k: ndarray
Z unit vector represented in world coordinates.
- as_points()
Return coordinate frame as a set of four points in world coordinates.
- Return type:
- transform(tfmat, tf_frame=None)
Transform this coordinate frame in the reference frame
tf_frame.Use this for “change frame, keep point relationships to the frame” transforms.
- Parameters:
tfmat (ndarray) – 4x4 transformation matrix.
tf_frame (CoordFrame | None) – Reference frame in which to apply the transform. Defaults to the world frame.
- Returns:
A new
CoordFrame(this one is not modified).- Return type:
- from_world(coord_world)
Return point locations in the current frame of reference.
- Parameters:
coord_world (ndarray) –
- Return type:
ndarray
- to_world(coord_local)
Return point locations in the world frame.
- Parameters:
coord_local (ndarray) –
- Return type:
ndarray
- __repr__()
Return repr(self).
- Return type:
str
Point clouds
- class coordframe.PointCloud(vert, frame=array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.]]))
A numpy array of 3D points bound to a reference frame.
Example
v = PointCloud(vert, local_frame) v.co # coordinates in local_frame v.frame # the reference frame for these coordinates
Remember: a coordinate frame is a point cloud (four points: origin plus the three axis tips).
- Parameters:
vert (np.ndarray) –
frame (np.ndarray | CoordFrame) –
- property n: int
Number of points in the cloud.
- as_frame()
Return this 4-point cloud as a coordinate frame.
The first point is treated as the origin; the vectors from the origin to the second, third, and fourth points become
i,j,krespectively (not normalized).- Return type:
- property center: PointCloud
Center of the point cloud as a new pointcloud object
- in_frame(output_coord_system)
Return point cloud in the given frame of reference (output_coord_system).
- Parameters:
output_coord_system (ndarray | CoordFrame) –
- Return type:
- in_world()
Return this point cloud expressed in the world frame.
Notes
When
tfmatis the identity, the general formula incoordframe.transform()reduces toinv(out_frame) @ vert_frame; without_framealso the identity (world), this further reduces to justvert_frame.- Return type:
- transform(tfmat, tf_frame=None)
Apply a transform in the reference frame
tf_frame.Use this for “keep frame, change point relationships to the frame” transforms.
- Parameters:
tfmat (ndarray) – Transformation matrix (3x3 or 4x4).
tf_frame (ndarray | CoordFrame | None) – Reference frame for the transform. Defaults to the current frame of reference (
self.frame).
- Returns:
A new
PointCloudwith the sameframebut transformed coordinates.- Return type:
- reframe(new_frame)
Re-frame the points. This maintains point locations in the world frame, but changes the current frame of reference.
- Parameters:
new_frame (ndarray | CoordFrame) –
- Return type:
- reframe_pca(**mapping)
Re-frame the point cloud along its principal-component axes.
Body-axis convention used for the sign of each component:
z_dir = +1: up is positive.z_dir = -1: down is positive (e.g. arm bones).Positive
x_diris facing forward.y_dir = z_dir × x_dir(right-hand-rule).
- Parameters:
**mapping – Supply two of
i,j,k; the third is computed assuming a right-handed frame.{'i': 1, 'j': 2}means the new frame’si-direction uses PC1 andj-direction uses PC2.- Return type:
- __call__()
Return the coordinates in the world frame.
If there is only one point in the cloud, a 1-D array is returned. Convenient for single-point clouds (e.g. origins):
o = PointCloud([a, b, c], frm) o() # instead of o.in_world().co[0, :]
- Return type:
ndarray
- pts_in_box(bbox)
Check if marker coordinates are within a bounding box.
- Parameters:
bbox (dict) –
- Return type:
ndarray
- in_box(bbox)
Returns (bool) True if all the marker’s points are within a bounding box.
- Parameters:
bbox (dict) –
- Return type:
bool
- frac_pts_in_box(bbox)
Returns (float) fraction of marker’s points inside the bounding box
- Parameters:
bbox (dict) –
- Return type:
float
Quaternions
- class coordframe.Quat(vec, theta=None, frame=None, **kwargs)
Unit quaternion for 3D rotation.
Inputs are normalized on construction.
q = cos(angle/2) + sin(angle/2) * unit_normal(normal in the world frame by default).Example
q = Quat([1, 2, 3, 4]) # normalized on construction q[:] # 4-element quaternion vector (w, x, y, z) q.angle # rotation angle q.normal # rotation axis q2 * q # compose: apply q, then q2 q * v # rotate a 3-vector (or nx3 array) q * frame # rotate a CoordFrame in world coordinates q * pcloud # rotate a PointCloud in its own frame
Typical use inside
bpn:s = new.sphere('sph', u=4, v=3) s.show_frame() # rotate around the object center in the world y-direction by 45° s.frame = cf.Quat([0, 1, 0], np.pi/4, origin=s.loc) * s.frame # rotate around the object center in the local-frame x-direction s.frame = cf.Quat([1, 0, 0], np.pi/4, s.frame) * s.frame
- Parameters:
vec (np.ndarray | list | tuple) –
theta (float | None) –
frame (CoordFrame | None) –
- to_euler()
Convert this quaternion to Euler angles
(roll, pitch, yaw).All three angles are in radians, counterclockwise:
roll: rotation around X.pitch: rotation around Y.yaw: rotation around Z.
- Returns:
(roll, pitch, yaw).- Return type:
tuple[float, float, float]
Helpers
- coordframe.transform(tfmat, vert, vert_frame_mat=array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.]]), tf_frame_mat=None, out_frame_mat=None)
Apply a transformation matrix, with explicit input/transform/output frames.
The most general form of a 3D transform in this package. Applies
tfmatto vertices that are specified invert_frame_mat, interprets the transformation intf_frame_mat, and returns the vertices expressed inout_frame_mat.- Parameters:
tfmat (np.ndarray) – 3x3 or 4x4 transformation matrix.
vert (np.ndarray) –
(nV, 3)vertex coordinates invert_frame_mat.vert_frame_mat (np.ndarray | CoordFrame) – Reference frame in which
vertis given. Defaults to the world frame.tf_frame_mat (np.ndarray | CoordFrame | None) – Frame in which
tfmatis applied. Defaults tovert_frame_mat.out_frame_mat (np.ndarray | CoordFrame | None) – Frame in which the result is expressed. Defaults to
vert_frame_mat.
- Returns:
(nV, 3)transformed vertices inout_frame_mat.- Return type:
np.ndarray
Notes
The five-step expansion is:
Bring vertices to world frame:
vert_frame.to_world(vert).Bring vertices to tf frame:
tf_frame.from_world(vert).Apply
tfmatin the tf frame.Bring vertices back to world:
tf_frame.to_world(vert).Bring vertices to the output frame:
out_frame.from_world(vert).
- coordframe.m4(m=None, **kwargs)
Construct a 4x4 transformation matrix from a variety of inputs.
Example
m4(m=mat) # mat is 3x3 or 4x4 m4(i=i1, j=j1, k=k1, origin=o1) m4(i=i1, j=j1, k=k1) # origin defaults to (0, 0, 0) m4() # 4x4 identity (world frame) m4(..., unit_vectors=True) # normalize i, j, k
- Parameters:
m (ndarray | None) – Input matrix (3x3 or 4x4).
Noneproduces the identity.**kwargs –
i,j,k(basis vectors),origin/center,unit_vectors(defaultFalse). Per-key assignments overridem.
- Returns:
A 4x4 numpy array.
- Return type:
ndarray
- coordframe.v4(vert)
Append a column of ones so
(nV, 3)becomes(nV, 4).Lets a 4x4 transformation matrix be applied to
(nV, 3)coordinates.- Parameters:
vert (ndarray) –
- Return type:
ndarray
- coordframe.apply_matrix(mat, vert)
Apply a transformation matrix to a set of vertices.
- Parameters:
mat (ndarray) – 3x3 or 4x4 transformation matrix.
vert (ndarray) –
(nV, 3)array of vertices.
- Returns:
(nV, 3)array of transformed vertices.- Return type:
ndarray
- coordframe.normal2tfmat(n, out=None)
Compute a rotation matrix taking
(0, 0, 1)to the directionn.The transformation is not unique (there is one free degree of twist). This routine picks the one of two candidates (
RxRyvs.RyRx) that displacesxandythe least, so the output is deterministic: a givennalways yields the same matrix.- Parameters:
n (ndarray) – 3-element direction vector. Normalized internally if not already a unit vector. Treated as the new
k_hat.out (str | None) – If
'rxry'or'ryrx', force that decomposition. Otherwise the smaller-displacement option is chosen.
- Returns:
A 3x3 rotation matrix.
- Return type:
ndarray
Notes
Intuitively the two candidates minimize twist, but this has not been proven mathematically.
- coordframe.twisttf(θ)
Return a 3x3 rotation matrix around the Z axis by
θradians.- Parameters:
θ (float) –
- Return type:
ndarray
- coordframe.scaletf(s)
Construct a 3x3 scale matrix.
- Parameters:
s (float | ndarray | list | tuple) – Either a scalar (uniform scale) or a 3-element vector (per-axis scale).
- Return type:
ndarray
- coordframe.norm_vec(vec)
Return unit vector, and return zero for zero vector.
- Parameters:
vec (ndarray | list | tuple) –
- Return type:
ndarray