Skip to the content.

30 Dec 2023

Эта заметка потихоньку дополняется. Информация из самых разных источников, местами используется разные обозначения.

Полезные ссылки и выдержки из них:

Про разницу между разными алгебрами: https://math.stackexchange.com/questions/4478664/what-is-the-difference-between-projective-geometric-clifford-algebra-grassman

Геометрическая алгебра и алгебра Клиффорда (Geometric Algebra and Clifford Algebra) это по-сути одно и то же. Сигнатура (p, q, r) обозначает, что есть p базисных векторов, квадрат которых равен единице, q векторов с квадратом-минус единицей и r с квадратом-нулём. В них есть wedge product и geometric product.

Проективная геометрическая алгебра (Projective Geometric Algebra, PGA): добаляется ещё одно измерение, получается сигнатура (n, 0, 1).

Внешнаяя алгебра и алгебра Грассмана (Grassmann Algebra and Exterior Algebra) опять одно и то же. Это часть геометрической алгебры, в которой не используют geometric product. Например, wedge product из двух точек сделает прямую. meet сделет наоборот (например, вместо двух плоскостей даст прямую-пересечение).

Кватернионы содержатся в GA(3, 0, 0), которое содержится в GA(3, 0, 1)

Конформная геометрическая алгебра (Conformal Geometric Algebra) - расширение PGA, включает ещё одну размерность. (n + 1, 1, 0) (Возможно, тут опечатка и надо поменять 0 с 1 местами). PGA включает только плоскую геометрию (точки, прямые, плоскости), CGA ещё содержит круглые штуки типа кругов, сфер и может описывать консормные преобразования.

Есть два сайта с разными определениями, наверно лучше использовать только первый.

  1. https://bivector.net/index.html
  2. Cайт, на нём есть шпаргалочки в pdf: https://projectivegeometricalgebra.org/ и на нём же ссылка на wiki: https://rigidgeometricalgebra.org/wiki/index.php?title=Main_Page

В чём разница: На bivector используется базис wxyz, а на projectiveGeometricAlgebra - xyzw = -wxyz. Из-за этого в формулах типа правого или левого дополнения будут другие знаки. Что ещё важнее - в bivector считается, что вектор - это плоскость, бивектор - пересечение двух плоскостей (линия), тривектор - точка. И геометрическое произведение позволяет переходить от одного к другому. Вдобавок есть обратимая операция dual, которая превращает плоскости в вектора и наоборот. Антигеометрическое произведение определено как геометрическое в дуальном пространстве.

На projectiveGeometricAlgebra вместо этого предполагается, что вектора - это вектора, а плоскости - это тривектора. При этом для повышения размерности вводится анти-геометрическое произведение, и оно почему-то определено через rightComplement и leftComplement. У меня получилось, что это определение почему-то не совпадает с определением от bivector и вдобавок вместо одного универсального dual надо не забывать использовать leftComplement и rightComplement - в общем, мне всё это не понравилось.

Вдобавок для bivector есть работающий код, а для другого сайта нет.

Можно скачать код на python или С++ и посмотреть как оно должно быть реализовано: https://bivector.net/tools.html?p=3&q=0&r=1

И есть шпаргалочки: https://bivector.net/3DPGA.pdf

А ещё там есть ссылка на книжку в 66 страниц: Geometric Algebra Primer

библиотека на С++ с бивекторами, моторами и т.п. а так же элементами конформной алгебры : https://github.com/EricLengyel/Terathon-Math-Library

википедия: Geometric algebra, Exterior algebra

Есть книжка, в которой автор попробовал выразить уравнения физики через геометрическую алгебру: D. Hestenes - New Foundations for Classical Mechanics (geometric algebra), я нашёл second edition 2022 года. Но книжка мне не очень понравилась - во-первых, используется обычная алгебра (а не геометрическая) и преобразования записываются как Y = R X R + B, во вторых некоторые упоминаемые вещи работают только для трёхмерного пространства (например, что для ветора ai = ia, но вообще говоря это зависит от чётности количества измерений и может быть ai = -ia

хорошая статья про проективную алгебру: https://arxiv.org/abs/1901.05873

Статья с хабра со взглядом с точки зрения физики: https://habr.com/ru/articles/732926/. На мой взгляд самая интересная часть про проекторы и идеалы.

Видео с ютуба:

  1. https://www.youtube.com/watch?v=2AKt6adG_OI
  2. https://www.youtube.com/watch?v=0i3ocLhbxJ4
  3. SIBGRAPI2021 про силы, ускорения, момент инерции и т.п.

Заметки из Geometric Algebra Primer

Внешнее произведение (outer product): a^b = -b^a. Из определения получается, что a^a = -a^a = 0.

Если есть N базисных векторов (basis vectors), то получится 2^N возможных сочетаний (basis blades). Потому что каждый из векторов либо есть, либо нет. Если он появится два раза, то всё обнулится.

Скаляры, вектора, бивектора и т.п. - 0-blades, 1-blades, 2-blades …

Геометрическое произведение (geometric product): ab = a⋅b + a^b

  1. Если базовые вектора разные, то a⋅b==0 и выражение упрощается до ab = a^b. По-сути в формулах над базисными векторами можно свободно одно заменять на другое, когда вектора разные.
  2. Если одинаковые, то аа = а⋅а.
  3. Геометрическое произведение ассоциативно: (AB)C = A(BC)
  4. Оно коммутативно с умножением на скаляр: As = sA
  5. Дистрибутивно для сложения: A(B+C) = AB + AC
  6. В общем случае геометрическое произведение не коммутативно.

Линейную комбинацию k-blades называют мультивектором.

Что забавно, для 2-вектора геометрическое произвдение с ним самим будет равно минус единице: \((e_1 e_2) (е_1 e_2) = -e_1 (e_1 e_2) e_2 = -1\)

Для двухмерного случая таблица умножения получится такая:

  1 e_1 e_2 I
1 1 e_1 e_2 I
e_1 e_1 1 I e_2
e_2 e_2 -I 1 -e_1
I 1 -e_2 e_1 -1

Можно выразить скалярное и внешнее произведения через геометрическое:

В некоторых книжках “базовым” является геометрическое провизедение и всё выражают через него, в других наборот выражают через внешнее и внутреннее.

Внутренних произведений много разных, дальше рассматривается contraction inner product

скаляры \(a \lrcorner b = a b\) вектор и склаяр \(a \lrcorner b = 0\) скаляр и вектор \(a \lrcorner b = ab\) вектора \(a \lrcorner b = a \cdot b\) вектор, мультивектор \(a \lrcorner (b \wedge C) = (a \lrcorner b) \wedge C - b \wedge (a \lrcorner C)\) дистрибутивность: \((A \wedge B) \lrcorner C = A \lrcorner (B \lrcorner A)\)

но якобы скалярное произведение и внутреннее в каких-то контекстах одно и то же, так что дальше по книжке будут пистать a⋅b

Обратный элемент

Как и с матрицами, в общем случае сложно. Частный случай: versor: вектор, который является геометрическим произведением векторов (которые 1-blades)

для версора \(А = v_1 v_2 ... v_k\)

вводится reverse (его почему-то обозначают плюсиком)

\[A^{†} = v_k ... v_2 v_1\]

а дальше обратный вводится как

\[A^{-1} = \dfrac{A^{†}}{A^{†} A}\]

\(A^{-1} A = \dfrac{A^{†} A}{A^{†} A} = 1\) если конечно версор не нулевой.

А ещё для версоров обратный элемент слева и справа совпадает. А ещё единичный вектор равен обратному к себе же.

Дуальность

Можно взять произведение всех векторочков, например для GA 2 будет \(I = e_1 e_2\)

Это будет всевдоскаляр в видео одного чиселка. Дуальное вводится так:

\[A^* A = I\]

например, в GA 3 \(e^{*}_{12} = e_3\)

Projection, Rejection

Если есть вектор a и бивектор B, то можно разложить a на две компоненты - проекцию на B и перпендикулярную часть.

Вообще говоря в этом месте B может быть любой размерности, но главное чтобы размерность всех компонент совпадала.

\[aB = a_{||_B} \cdot B + a_{⊥_B} \wedge B\]

С ними довольно логично:

\[a_{⊥_B} \cdot B = 0\] \[a_{||_B} \wedge B = 0\]

И можно выразить так:

\[a_{⊥_B} B = a \wedge B\] \[a_{⊥_B} = (a \wedge B) B^{-1}\]

Аналогично для второй компоненты:

\[a_{||_B} B = a_{||_B} \cdot B\] \[a_{||_B} = (a_{||_B} \cdot B) B^{-1}\]

отражения

пусть есть бивектор U, к нему дуальным будет вектор нормали u

\[ua = u(a_{||_{U}} + a_{⊥_U}) = u \cdot a_{||_{U}} + u \wedge a_{||_{U}} + u \cdot a_{⊥_U} + u \wedge a_{|⊥_U}\]

Тут надо не перепутать U и u, перпендикулярная к U часть паралелльна u. Внутренне произведедние между векторами коммутативно, внешнее антикоммутативно

\[ua = u \wedge a_{||_{U}} + u \cdot a_{⊥_U} = a_{⊥_U} \cdot u - a_{||_{U}} \wedge u = (a_{⊥_U} - a_{||_{U}}) u\] \[-ua = (a_{||_{U} - a_{⊥_U}}) u\] \[-uau^{-1} = a_{||_{U} - a_{⊥_U}}\]

обычно вектор u берут единичной длины, тогда для него \(u^{-1} = u\)

и отражение упрощается до -uau

В Plane-based геометрической алгебре минус вообще не важен, так как домножение элемента на ненулевую константу ничего не меняет.

Причём поворот можно предстаить как два отражения (а два отражения при перемножении превращаются в скаляр и бивектор, который в терминах геометрической алгебры называется спинором, а по-сути это привычный кватернион)

А произведение двух спиноров - опять спинор. Спиноры обычно обозначают буквой R.

Линии

уравнение для линии, паралелльной вектору u и происходящей через начало координат: x^u = 0. Для сдвинутого центра будет (x-a)^u = 0

\((x - a) \wedge u = 0\) \(x \wedge u - a \wedge u = 0\) \(x \wedge u = a \wedge u = U\)

Если u - вектор единичной длины, то |U| равен расстояние от центра координат до прямой. Вектор кратчайшего расстояния от центра до прямой \(d = \dfrac{U}{u} = Uu\)

Повороты в 3d

Что забавно, если поворот записать как произведение двух векторов: R = st, то обратный будет довольно красиво выражаться

\(R = st = s \cdot t + s \wedge t\) \(R^† = ts = s \cdot t - s \wedge t\)

вращение записывается так:

\[v' = R^† v R\]

так как поворот это комбинация двух отражий, -1 появляется дважды и самоуничтожается

\[v = -t (-svs) t = tsvst = R^† v R\]

Плоскость

Уравнение плоскости, где B - бивектор: \(x \wedge B = 0\). Аналогично с прямой для прождения не через центр

\((x - a) \wedge B = 0\) \(x \wedge B = a \wedge B = U\)

В PGA вектор ax+by+cz+dw - это плоскость, заданая уравнением \(ax + by + cz + d = 0\)

Homogeneous Space

вводится ещё один базисный вектор (e), перпендикулярный e_1, e_2, e_3

(x,y,z) описываются как \((x, y, z) = (\dfrac{x}{w}, \dfrac{y}{w}, \dfrac{z}{w}, \dfrac{w}{w})\)

Такой подход позволит кодировать позицию и уравнения прямых, плоскостей и т.п. упрощаются.

Будет разница между вектором(направлением) и точкой в пространстве - у вектора w=0, у точки w=1.

Причём пересечение плоскостей считается легко: \((P \wedge Q) ∩ (N \wedge M) = (P \wedge Q)^* \cdot N \wedge M)\)

В этом пространстве домножение на константу не влияет. Условно, вектор (x, y, z, 1) превратится в (xw, yw, z*w, w) и при нормировке это можно будет убрать.

Если получить прямую или плоскость как внешнее произведение двух или трёх точек, то в общем случае они не будут отнормированы.

квадрат базисного вектора обязан быть нулём, тогда экспоненциирование сводится к линейной операции $e^a = (1 + a)$ и это будут линейные перемещения.

Заметка из https://habr.com/ru/articles/732926/

Честно говоря не вижу применения для своих целей, но как красивая концепция - пускай будет.

Надо быть аккуратным, есть отличия от привычных мне обозначений. Здесь reverse в sandwich product делается для левого аргумента, а не для правого, и ещё почему-то после возведения в квадрат автор почему-то домножает на reverse.

Можно взять вектор единичной длины: \(v^2 = 1\)

Проекторы: \(p_+ = \dfrac{1}{2}(1 + v)\) \(p_- = \dfrac{1}{2}(1 - v)\)

\(p_+ + p_- = 1\) \(p_+ - p_- = v\)

Фишка в том, что квадрат проектора равен ему самому: \(p_+^2 = \dfrac{1}{2}(1 + v) \dfrac{1}{2}(1 + v) = \dfrac{1}{4}(1 + 2v + v^2) = \dfrac{1}{4}(1 + 2v + 1) = \dfrac{1}{2}(1 + v)\)

Поэтому произведение любого элемента алгебры на проекцию тоже будет проекцией. Идеал может быть левым или правым в зависимости от того, с какой стороны домножать.

И ещё момент:

\[p_+ v = \dfrac{1}{2}(1 + v)v = \dfrac{1}{2}(v + v^2) = \dfrac{1}{2}(v + 1)\]

Любой мультивектор можно разложить по двум проекциям: \(A = A 1 = A (p_+ + p_-) = Ap_+ + Ap_-\)

А ещё \(v = p_+ - p_- = p_+^2- p_-^2 = p_+ p_+^† - p_- p_-^†\)

Дальше можно вспомнить вращение вектора \(R v R^† = R (p_+ p_+^† - p_- p_-^†) R^† = R p_+ p_+^† R^† - R p_- p_-^† R^† = R p_+ (R p_+)^† - R p_- (R p_-)^†\)

Из видео: https://www.youtube.com/watch?v=2AKt6adG_OI

Magnitude Предлагается вместо длины определять сразу квадрат длины, так как в некоторых алгебрах результат может быть отрицательным и извлекать корень будет некрасиво. Якобы обычно достаточно квадрата длины.

Квадрат длины как $$ A ^2 = A^† A$$, причём предлагается брать только скалярную часть. Потому что в обещем случае там могут быть прочие компоненты.

Если попытаться определить dual как AI, то будет фиаско для векторов, квадрат которых равен нулю (тот самый в проективной алгебре). А ещё дуальное пространство - дополнение до полного, и знак может быть произвольным.

Поэтому там используется hodge star. Типа \(A dual(A) = A ★A = I\) В моём коде это rightComplement

Для ненормированных векторов: $$A ★A = A ^2 I$$

В других местах это называется right сomplement и left сomplement. Ещё момент - v зависит от размерности пространства, например \(e_{12} v e_{32} = - e_3\) в 3д и равно нулю в 4д.

Интересно, что внутренних произведений несколько и они хитро опеределны: есть проекция слева направо (left contraction), причём правый вектор должен содержать все-все компоненты правого, и они уйдут), есть проекция справа налево, а так же есть inner product, который проецирует либо левое на правое, либо наоборот. И эти операторы строго снижают размерность (из n и k делают |n-k|)

И типа aB =leftContraction(a, B) + a \wedge B? если а - вектор и B - мультивектор.

Из ещё одного видео: https://www.youtube.com/watch?v=0i3ocLhbxJ4

Кажется, в нём все-все размышления в дуальном пространстве, потому что у автора для 2д вектор это линия, а бивектор точка, и для 3д - вектор это плоскость, бивектор - линия, тривектор - точка. А я привык наоборот.

Интересная идея - можно брать линейную комбинацию двух линий и получать что-то промежуточное. Причём можно использовать и отрицательные коэффициенты.

И ещё тут возможна “точка в бесконечности”, которая вяляется пересеченим параллельных прямых.

meet: outer product (^) join: (regressive product (v)) inner product используется для проекции прямой на точку, прямой на точку или линии на точку. типа (a . B) B.

Причём когда а - линия и B - точка (бивектор), то (a . B) B - линия через точку, (a . B) B - точка проекции точки на линию.

inner product двух бивекторов - скаляр.

Почему-то примененеи ротора определено как \(R+† p R\)

Ещё интересный момент с экспонентой (u, v - перпендикулярные линии, alpha - угол., \((uv)^2 = 1\)

\[e^{uv \alpha} = \cos(\alpha) + uv \sin(\alpha) = 1 \cos(\alpha) + uv \sin(\alpha) = uu \cos(\alpha) + uv \sin(\alpha) = u (u \cos(\alpha) + v \sin(\alpha))\]

В последнем выражении получается вектор u и вектор (u \cos(\alpha) + v \sin(\alpha)), который зависит от угла.

Перенос - это поворот относительно бесконечно далёкой точки. Причём e_0^2 == 0, поэтому разложение в экспоненциальный вид имеет только два слагаемых.

\[e^{u e_o x} = 1 + u e_o x + \dfrac{(u e_o x)^2}{2} + .... = 1 + u e_o x = uu + u e_o x = u (u + e_o x)\]

SIBGRAPI2021 ep3 про силы, ускорения и т.п.

Следующие видео тоже очень интересные.

Ускорние, скорость, позиция - 2-вектора. Сила и момент - дуальные к ним, (d-1)-вектора

Обозначения:

Forque (force + torque) = F = P’ Momentum = P Acceleration A = V’ = M’’ Velocity = V Position (Motor) = M

\[F = A*\] \[M' = -\dfrac{1}{2}MV\]

Мои наблюдения

$$ A   B = A ⟑ B $$
Для проективной алгебры норма не сохраняется, просто из-за того, что для одного из измерений $$ w ⟑ w = 0$$ и эта часть в скалярную не попадёт.        

В bivector.net в коде используется хитрый базис:

self._base = ["1", "e0", "e1", "e2", "e3", "e01", "e02", "e03", "e12", "e31", "e23", "e021", "e013", "e032", "e123", "e0123"]

В нём некоторые элементы перевёрнуты. И в таком базисе дуальное определено просто как замена между первым и последнием элементом, вторым и предпоследним и т.п. И так как дуальное нигде не меняет знаков, очевидно что оно обратимо само себе (и это очень удобно)

Прямая задаётся вектором (уравнение прямой - ax + by + cz + d = 0). Причём надо обратить внимание на то, что d = - dot(normal, pointOnAPlane).

plane.sandwich(_) становится операцией отражения.

бивектор (произведение двух плоскостей) как два отражения превращается в перенос и вращение

тривектор (точка) - отражение относительно точки

внешнее произведение двух плоскостей - линия.

Уравнение линии из точки а с направлением n

a v (a + n) == MultiVector(
    wx -> (a.y * n.z - a.z * n.y)
    wy -> (a.z * n.x - a.x * n.z)
    wz -> (a.x * n.y - a.y * n.x)
    xy -> n.z
    xz -> -n.y
    yz -> n.x
)

по-сути в xy, xz, yz лежит направление и в wx, wy, wz - (a x n) - закодирован сдвиг от центра координат. Если предположить, что длина n = 1, а - ближайшая точка прямой к центру координат, то n x a будет перпендикулярно обоим и с длиной как расстояние до центра координат.

Линия как пересечение двух плоскостей:

a ^ c == MultiVector(
    wx -> (a.d * c.nx - a.nx * c.d)
    wy -> (a.d * c.ny - a.ny * c.d)
    wz -> (a.d * c.nz - a.nz * c.d)
    xy -> (a.nx * c.ny - a.ny * c.nx)
    xz -> (a.nx * c.nz - a.nz * c.nx)
    yz -> (a.ny * c.nz - a.nz * c.ny)
)

Линия как внутренне произведение точки и направления:

pos = MultiVector(
    wxy -> -pos.z
    wxz -> pos.y
    wyz -> -pos.x
    xyz -> 1.0
)
shift = MultiVector(
    x -> s.x
    y -> s.y
    z -> s.z
)
pos dot shift = MultiVector(
    wx -> (pos.y * s.z - pos.z * s.y)
    wy -> (pos.z * s.x - pos.x * s.z)
    wz -> (pos.x * s.y - pos.y * s.x)
    xy -> s.z
    xz -> -s.y
    yz -> s.x
)

Если перемножить две паралельные плоскости, то xy, yz, xz будут нулями, и бивектор будет описывать перемещение.

Оператор перемещения на dx, dy, dz:

MultiVector(
    1 -> 1.0
    wx -> -0.5 * d.x
    wy -> -0.5 * d.y
    wz -> -0.5 * d.z
)

Причём все попарные произведения произведения типа wx wx, wx wy равны нулю, и \(exp(v) = exp(a wx + b wy + c wz) = 1 + a wx + b wy + c wz = 1 + v\)

Так что логарифм оператора перемещения выглядит практически так же:

MultiVector(
    wx -> -0.5 * d.x
    wy -> -0.5 * d.y
    wz -> -0.5 * d.z
)

Для вращательных” компонент посложнее:

\[v^2 = (a xy + b xz + c yz)^2 = a^2 (xy)^2 + b^2 (xz)^2 + c^2 (yz)^2 - ab (xyxz + xzxy) + ... = - a^2 - b^2 - c^2 = -|v|^2\] \[exp(v) = exp(a xy + b xz + c yz) = 1 + v + \dfrac{v^2}{2} + \dfrac{v^3}{3!} + ... = 1 + v - \dfrac{|v|^2}{2} - \dfrac{|v|^2 v}{3!} + \dfrac{|v|^4}{4} - ...\] \[= (1 - \dfrac{|v|^2}{2} + \dfrac{|v|^4}{4} - ...) + v(1 - \dfrac{|v|^2}{3!} + \dfrac{|v|^4}{5!} - ...) = cos(|v|) + \dfrac{v} {|v|} sin(|v|)\]

Если скомбинировать сразу перемещение и вращение, что квадрат не будет скаляром, там ещё появится четыре-вектор (wxyz).

a = MultiVector(
    wx -> a.wx
    wy -> a.wy
    wz -> a.wz
    xy -> a.xy
    xz -> a.xz
    yz -> a.yz
)
a geometric a = MultiVector(
    1 -> (-a.xy * a.xy - a.xz * a.xz - a.yz * a.yz)
    I -> (-2.0 * a.wy * a.xz + 2.0 * a.wx * a.yz + 2.0 * a.wz * a.xy)
)

Но если получить прямую пересечением двух плоскостей или объединением двух точек, то (wx, wy, wz) и (a.xy, a.xz, a.yz) будут перпендикулярными и тогда I = 0

А вот если это не уравнение прямой, а какой-то бивектор (например, описывающий скорость тела), то в I будет закодирован сдвиг вдоль оси вращения.

Комбинация вращения и переноса:

q = MultiVector(
    1 -> q.cos
    xy -> q.xy
    xz -> q.xz
    yz -> q.yz
)
tr = MultiVector(
    1 -> 1.0
    wx -> t.x
    wy -> t.y
    wz -> t.z
)
tr q = MultiVector(
    1 -> q.cos
    wx -> (q.cos * t.x - q.xy * t.y - q.xz * t.z)
    wy -> (q.cos * t.y + q.xy * t.x - q.yz * t.z)
    wz -> (q.cos * t.z + q.xz * t.x + q.yz * t.y)
    xy -> q.xy
    xz -> q.xz
    yz -> q.yz
    I -> (q.xy * t.z + q.yz * t.x - q.xz * t.y)
)
q tr = MultiVector(
    1 -> q.cos
    wx -> (q.cos * t.x + q.xy * t.y + q.xz * t.z)
    wy -> (q.cos * t.y + q.yz * t.z - q.xy * t.x)
    wz -> (q.cos * t.z - q.xz * t.x - q.yz * t.y)
    xy -> q.xy
    xz -> q.xz
    yz -> q.yz
    I -> (q.xy * t.z + q.yz * t.x - q.xz * t.y)
)

Перенос не влияет на компоненты кватерниона, но добавляет новых в wx, wy, wz и I.

Импульс

Момент точки с какой-то массой и скоростью:

\[P = m X ∨ X' = m v ⋅ X\]

кроме того

\[X' = X × B\] \[P = I[B] = m X ∨ (X × B) = m X ∨ (XB - BX)\]

бивектор B, а момент P получается размерности d-1.

pos = MultiVector(
    wxy -> -pos.z
    wxz -> pos.y
    wyz -> -pos.x
    xyz -> 1.0
)
v = MultiVector(
    x -> v.x
    y -> v.y
    z -> v.z
)
forque = (v dot pos * mass) = MultiVector(
    wx -> (mass * pos.y * v.z - mass * pos.z * v.y)
    wy -> (mass * pos.z * v.x - mass * pos.x * v.z)
    wz -> (mass * pos.x * v.y - mass * pos.y * v.x)
    xy -> mass * v.z
    xz -> -mass * v.y
    yz -> mass * v.x
)
forque.dual = MultiVector(
    wx -> mass * v.x
    wy -> mass * v.y
    wz -> mass * v.z
    xy -> (mass * pos.x * v.y - mass * pos.y * v.x)
    xz -> (mass * pos.x * v.z - mass * pos.z * v.x)
    yz -> (mass * pos.y * v.z - mass * pos.z * v.y)
)

момент относительно точки pos (нет вращательной компоненты):

forque in point x = forque - ((v * mass) dot (x.weight) = MultiVector(
    wx -> 0.0
    wy -> 0.0
    wz -> 0.0
    xy -> mass * v.z
    xz -> -mass * v.y
    yz -> mass * v.x
)

Импульс точек с x и -x и скоростью в одном направлении (т.е., нет вращательного момента относительно центра координат):

MultiVector(
    wx -> 0.0
    wy -> 0.0
    wz -> 0.0
    xy -> 2.0 * mass * v.z
    xz -> -2.0 * mass * v.y
    yz -> 2.0 * mass * v.x
)

импульс противоположных точек со скоростью в противоположном направлении (т.е., нет поступательного импусльса, есть только вращенеи вокруг центра)

MultiVector(
    wx -> (-2.0 * mass * pos.z * v.y + 2.0 * mass * pos.y * v.z)
    wy -> (-2.0 * mass * pos.x * v.z + 2.0 * mass * pos.z * v.x)
    wz -> (-2.0 * mass * pos.y * v.x + 2.0 * mass * pos.x * v.y)
    xy -> 0.0
    xz -> 0.0
    yz -> 0.0
)