Source code for session_py.quaternion

import uuid
import math
from .vector import Vector


[docs] class Quaternion:
[docs] def __init__(self, s=1.0, v=None): self.typ = "Quaternion" self.guid = str(uuid.uuid4()) self.name = "my_quaternion" self.s = s self.v = v if v is not None else Vector(0.0, 0.0, 0.0)
[docs] @staticmethod def identity(): return Quaternion(1.0, Vector(0.0, 0.0, 0.0))
[docs] @staticmethod def from_sv(s, x, y, z): return Quaternion(s, Vector(x, y, z))
[docs] @staticmethod def from_axis_angle(axis, angle): axis = axis.normalize() half_angle = angle * 0.5 s = math.cos(half_angle) v = axis * math.sin(half_angle) return Quaternion(s, v)
[docs] def rotate_vector(self, v): qv = self.v uv = qv.cross(v) uuv = qv.cross(uv) return v + (uv * self.s + uuv) * 2.0
[docs] def magnitude(self): return math.sqrt( self.s * self.s + self.v.x * self.v.x + self.v.y * self.v.y + self.v.z * self.v.z )
[docs] def normalize(self): mag = self.magnitude() if mag > 1e-10: q = Quaternion(self.s / mag, self.v / mag) q.typ = self.typ q.guid = self.guid q.name = self.name return q else: return Quaternion.identity()
[docs] def conjugate(self): q = Quaternion(self.s, self.v * -1.0) q.typ = self.typ q.guid = self.guid q.name = self.name return q
def __mul__(self, other): if isinstance(other, Quaternion): s = self.s * other.s - self.v.dot(other.v) v = other.v * self.s + self.v * other.s + self.v.cross(other.v) return Quaternion(s, v) raise TypeError("Quaternion can only be multiplied with another Quaternion") def __jsondump__(self): """Serialize to polymorphic JSON format with type field. Returns ------- dict Dictionary with 'type', 'guid', 'name', and object fields. """ return { "type": f"{self.__class__.__name__}", "guid": self.guid, "name": self.name, "s": self.s, "x": self.v.x, "y": self.v.y, "z": self.v.z, } @classmethod def __jsonload__(cls, data, guid=None, name=None): """Deserialize from polymorphic JSON format. Parameters ---------- data : dict Dictionary containing quaternion data. guid : str, optional GUID for the quaternion. name : str, optional Name for the quaternion. Returns ------- :class:`Quaternion` Reconstructed quaternion instance. """ from .encoders import decode_node from .vector import Vector # Support both old format (v as Vector) and new format (x, y, z) if "v" in data: v = decode_node(data["v"]) else: v = Vector(data["x"], data["y"], data["z"]) q = cls(data["s"], v) q.guid = guid q.name = name return q