這個問題和@senderle給出的答案真的幫助了我的乙個專案。答案是最小的,涵蓋了乙個人可能需要執行的大多數四元數計算的核心。
對於我自己的專案,我發現為所有操作分別使用函式並在每次需要時逐個匯入它們是很乏味的,所以我實現了乙個物件導向的版本。
四元數.py:import numpy as np
from math import sin, cos, acos, sqrt
def normalize(v, tolerance=0.00001):
mag2 = sum(n * n for n in v)
if abs(mag2 - 1.0) > tolerance:
mag = sqrt(mag2)
v = tuple(n / mag for n in v)
return np.array(v)
class quaternion:
def from_axisangle(theta, v):
theta = theta
v = normalize(v)
new_quaternion = quaternion()
new_quaternion._axisangle_to_q(theta, v)
return new_quaternion
def from_value(value):
new_quaternion = quaternion()
new_quaternion._val = value
return new_quaternion
def _axisangle_to_q(self, theta, v):
x = v[0]
y = v[1]
z = v[2]
w = cos(theta/2.)
x = x * sin(theta/2.)
y = y * sin(theta/2.)
z = z * sin(theta/2.)
self._val = np.array([w, x, y, z])
def __mul__(self, b):
if isinstance(b, quaternion):
return self._multiply_with_quaternion(b)
elif isinstance(b, (list, tuple, np.ndarray)):
if len(b) != 3:
raise exception(f"input vector has invalid length ")
return self._multiply_with_vector(b)
else:
raise exception(f"multiplication with unknown type ")
def _multiply_with_quaternion(self, q2):
w1, x1, y1, z1 = self._val
w2, x2, y2, z2 = q2._val
w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2
x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2
y = w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2
z = w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2
result = quaternion.from_value(np.array((w, x, y, z)))
return result
def _multiply_with_vector(self, v):
return (self * q2 * self.get_conjugate())._val[1:]
def get_conjugate(self):
w, x, y, z = self._val
result = quaternion.from_value(np.array((w, -x, -y, -z)))
return result
def __repr__(self):
theta, v = self.get_axisangle()
return f"((%.6f; %.6f, %.6f, %.6f))"%(theta, v[0], v[1], v[2])
def get_axisangle(self):
w, v = self._val[0], self._val[1:]
theta = acos(w) * 2.0
return theta, normalize(v)
def tolist(self):
return self._val.tolist()
def vector_norm(self):
w, v = self.get_axisangle()
return np.linalg.norm(v)
在這個版本中,我們可以使用四元數向量乘法和四元數向量乘法的過載運算子from quaternion import quaternion
import numpy as np
x_axis_unit = (1, 0, 0)
y_axis_unit = (0, 1, 0)
z_axis_unit = (0, 0, 1)
r1 = quaternion.from_axisangle(np.pi / 2, x_axis_unit)
r2 = quaternion.from_axisangle(np.pi / 2, y_axis_unit)
r3 = quaternion.from_axisangle(np.pi / 2, z_axis_unit)
# quaternion - vector multiplication
v = r1 * y_axis_unit
v = r2 * v
v = r3 * v
print(v)
# quaternion - quaternion multiplication
r_total = r3 * r2 * r1
v = r_total * y_axis_unit
print(v)
BZOJ3707 圈地 (幾何,旋轉座標系)
description 2維平面上有n個木樁,黃學長有一次圈地的機會並得到圈到的土地,為了體現他的高風亮節,他要使他圈到的土地面積盡量小。圈地需要圈乙個至少3個點的多邊形,多邊形的頂點就是乙個木樁,圈得的土地就是這個多邊形內部的土地。因為黃學長非常的神,所以他允許圈出的第n點共線,那樣面積算0 in...
bzoj3210 花神的澆花集會 旋轉座標系
題目描述 在花老師的指導下,每週4都有乙個集會活動,俗稱 澆水 活動。具體澆水活動詳情請見bzoj3153 但這不是重點 花神為了準備澆花集會的題,必須找一道盡量適合所有人的題 現在花神知道每個人的 能力x和演算法能力y,一道題 難度x演算法難度y 對這個人的不適合度為 max abs x x ab...
齊次座標 四元數
一 齊次座標 齊次座標表示是計算機圖形學的重要手段之一,它既能夠用來明確區分向量和點,同時也更易用於進行仿射 線性 幾何變換。f.s.hill,jr。對於乙個向量 v以及基 oabc 可以找到一組座標 v1,v2,v3 使得v v1 a v2 b v3c 1 對於乙個點 p,則可以找到一組座標 p1...