JuliaGeometry / Quaternions.jl

A Julia implementation of quaternions
https://juliageometry.github.io/Quaternions.jl
MIT License
116 stars 38 forks source link

Algebraic quaternions vs geometric quaternions #10

Closed andyferris closed 2 years ago

andyferris commented 8 years ago

Hi @SimonDanisch, we at Roames (myself, @awbsmith and @c42f) have been using and thinking about quaternions, and there seems to be a few conceptual blockers to e.g. using * as in you suggest in #3.

Primarily, a quaternion is a algebraic object, Quaternion{T} <: Number, much like Complex{T} <: Number. They form a ring, and algebraic operations + and * have a single unambiguous meaning. However, some quaternions, especially normalized quaternions, are useful for geometry, and it sure would be useful to implement rotations of 3-vectors.

I'm proposing that we break up the structure a little bit, so that Quaternion is a pure algebraic number and UnitQuaternion or RotationQuaternion or similar is an object that either inherits from AbstractQuaternion or else is a simple struct containing a Quaternion.

As an exaple, we would want

Quaternion(1.0,2.0,3.0,4.0) * Vec(1.0,2.0,3.0) <: Vec{3,Quaternion{Float64}} # elementwise multiplication with standard multiplication rules

(you could replace Vec with Vector, Point, any FixedVector, etc).

and

RotationQuaternion(cos(t), sin(t), 0.0, 0.0) * Vec(1.0,0.0,0.0) == Vec(cos(t), sin(t), 0.0) # or whatever it is for this rotation...

For a simple gist, see here.

This would help us in Rotations.jl, plus clean up the whole interface for people who want to do either just algebra or just geometry. In fact, there is some small argument to say the algebraic part belongs outside of JuliaGeometry, but the simplest thing is to make a separation.

Orbots commented 5 years ago

I don't think having the flag to indicate a quaternion is normalized is useful. I'd like to use this, but it just seems wasteful so I'm writing my own Quaternion type. The reason the norm flag is not useful is that it doesn't adequately answer the question "when" do we renormalize/project. Well, it appears that it does answer that question with ? (q.norm) never : always which will give you problems with drift ( you need to renormalize unit quaternions after awhile ).

Also this layout isn't the best for potential SIMD optimization.

SimonDanisch commented 5 years ago

I admit I also rolled my own Quaternion type because of this :D But I have no idea about quaternions, so I dont feel able to actually refactor this package, to be mathematical sound...

Orbots commented 5 years ago

I initially didn't intend to hijack this issue with an somewhat orthogonal issue ( representation/implementation of unit quaternions ).

To bring it back to the original issue.

Quaternions are an extension of complex numbers right? So it's more Quaternion{T} <: Complex{T}.

The nicest representation of Quaternions is via Geometric Algebra/Grassmann Algebra/Clifford Algebra ( history and relationship between these are confusing ). But then you potentially would have some performance hit?

Anyways, I'm in support of having a more algebraic context-free Quaternion type as the "go to" Quaternion type. Although they are kind of geometric objects by nature.

andyferris commented 5 years ago

So it's more Quaternion{T} <: Complex{T}

Don't think about subsets or isomorphisms with <:.

From the perspective of dispatch, subtypes inherit the interface (and importantly - all the guarantees - if you want to make generic code possible) of the supertype.

Orbots commented 5 years ago

The interface guarantee that making a Quaternion a subtype of Complex is that they both can have a set of functions with a notion of relative "angles"*. Also a guarantee that they can not be ordered ( less useful ). So if you had a function foo that you wanted to operate on all Numbers which have "angles" as conceptualized by Complex numbers. You could explicitly constrain the inputs with foo( ::Complex, ::Complex ). This could operate happily on Quaternion <: Complex type.

But yeah, abstract type inheritance is a bit of a goofy thing especially when you consider contra/covariance etc. So maybe these commonalities would be better expressed via a traits mechanism or just left as a MethodError. I think it could have some utility though.

*IANAM: I am not a mathematician.

chakravala commented 5 years ago

Hi, I think you all might find my new package Grassmann.jl interesting, since it provides a unified language for both vector spaces and geometric algebra. It can also handle quaternions (less specifically but in a more general sense combined with Grassmann numbers), it is very good for providing a unified general interface in which geometry and algebra are fully unified, including the vector basis and covector basis.

Please carry on with your work on this package, but keep in mind that with my package you can explore the quaternions from a more abstract geometric algebra perspective, which is also an attempt at providing a single unified interface for different kinds of rotational algebras as you discuss here. Regards.

hyrodium commented 2 years ago

I'll close this issue because the original issue seems solved.

This would help us in Rotations.jl, plus clean up the whole interface for people who want to do either just algebra or just geometry. In fact, there is some small argument to say the algebraic part belongs outside of JuliaGeometry, but the simplest thing is to make a separation.

Now Rotations.jl has a dependency on Quaternions.jl with https://github.com/JuliaGeometry/Rotations.jl/pull/175.

I don't think having the flag to indicate a quaternion is normalized is useful.

This will be solved in #75, and there is a new discussion in #60.