From b1cfcb5f858057453f063399d46105cafacec5ce Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sat, 13 Feb 2016 16:53:26 +0100 Subject: [PATCH] Quaternion: minor tweaks, opt-out unclear functions from SemVer with Obsolete attribute Some of the functions of the Quaternion module have not been finalized yet. In order to unblock a release, these functions are now marked with the Obsolete attribute with a warning that they opt-out from semantic versioning. They may change in breaking ways between minor versions. --- src/FSharp/Quaternion.fs | 58 ++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/src/FSharp/Quaternion.fs b/src/FSharp/Quaternion.fs index ce7e06a0..b44ce59c 100644 --- a/src/FSharp/Quaternion.fs +++ b/src/FSharp/Quaternion.fs @@ -39,32 +39,31 @@ type Quaternion = } with static member (+) (r: Quaternion, q: Quaternion) = - {w=r.w+q.w;x=r.x+q.x;y=r.y+q.y;z=r.z+q.z} + { w=r.w+q.w; x=r.x+q.x; y=r.y+q.y; z=r.z+q.z } static member (-) (r: Quaternion, q: Quaternion) = - {w=r.w-q.w;x=r.x-q.x;y=r.y-q.y;z=r.z-q.z} + { w=r.w-q.w; x=r.x-q.x; y=r.y-q.y; z=r.z-q.z } static member (*) (r: Quaternion, q: Quaternion) = let w = r.w*q.w - r.x*q.x - r.y*q.y - r.z*q.z let x = r.w*q.x + r.x*q.w - r.y*q.z + r.z*q.y let y = r.w*q.y + r.x*q.z + r.y*q.w - r.z*q.x let z = r.w*q.z - r.x*q.y + r.y*q.x + r.z*q.w - {w=w;x=x;y=y;z=z} + { w=w; x=x; y=y; z=z } static member (/) (r: Quaternion, q: Quaternion) = let d = (r.w**2.0 + r.x**2.0 + r.y**2.0 + r.z**2.0) - let w = (r.w*q.w + r.x*q.x + r.y*q.y + r.z*q.z) / d let x = (r.w*q.x - r.x*q.w - r.y*q.z + r.z*q.y) / d let y = (r.w*q.y + r.x*q.z - r.y*q.w - r.z*q.x) / d let z = (r.w*q.z - r.x*q.y + r.y*q.x - r.z*q.w) / d - {w=w;x=x;y=y;z=z} + { w=w; x=x; y=y; z=z } static member (/) (q:Quaternion, a) = - {w=q.w/a; x=q.x/a;y=q.y/a;z=q.z/a} + { w=q.w/a; x=q.x/a; y=q.y/a; z=q.z/a } -[] +[] module Quaternion = //Reference: @@ -74,21 +73,27 @@ module Quaternion = //https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#The_conjugation_operation let normSquared q = - q.w**2.0 + q.x**2.0 + q.y**2.0 + q.z**2.0 + q.w*q.w + q.x*q.x + q.y*q.y + q.z*q.z + /// Euclidean Norm let norm q = normSquared q |> sqrt + /// Normalize a quaternion to unit quaternion with norm 1. let normalize q = let invNorm = 1.0 / (norm q) - {w=q.w*invNorm;x=q.x*invNorm;y=q.y*invNorm;z=q.z*invNorm} + { w=q.w*invNorm; x=q.x*invNorm; y=q.y*invNorm; z=q.z*invNorm } let conjugate q = - {w=q.w; x= -q.x; y= -q.y; z= -q.z} + { w=q.w; x= -q.x; y= -q.y; z= -q.z } let inverse q = conjugate q / normSquared q + /// Dot product + let dot q1 q2 = + q1.w*q2.w + q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + //create a new quaternion //angle in radians //http://www.astro.rug.nl/software/kapteyn/_downloads/attitude.pdf @@ -96,28 +101,26 @@ module Quaternion = // _ _ // qa (α, n) := | cos α/2 | // | n sin α/2 | - // - - + // + [] let create (angle:float) (x:float) (y:float) (z:float) = //axis needs to be unit vector - let vNorm = x**2.0+y**2.0+z**2.0 - let invNorm = 1.0 / (vNorm |> sqrt) + let vNorm = x*x + y*y + z*z + let invNorm = 1.0 / (sqrt vNorm) let x' = x*invNorm let y' = y*invNorm let z' = z*invNorm let halfAngle = angle * 0.5 - let s = halfAngle |> sin - let c = halfAngle |> cos - {w=c; x=x'*s; y=y'*s; z=z'*s} - - //dot product - let dot q1 q2 = - q1.w*q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z - - //rotate a vector(x,y,z) by a quaternion - // p is a pure quaternion(i.e w=0.0) - // p' = qpq**-1.0 - // https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#The_conjugation_operation + let s = sin halfAngle + let c = cos halfAngle + { w=c; x=x'*s; y=y'*s; z=z'*s } + + /// rotate a vector(x,y,z) by a quaternion + /// p is a pure quaternion(i.e w=0.0) + /// p' = qpq**-1.0 + /// https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#The_conjugation_operation + [] let rotate q1 x y z = let q = normalize q1 //ensure unit quaternion let p = {w=0.0; x=x; y=y; z=z} @@ -129,4 +132,7 @@ module Quaternion = /// The first Quaternion rotation in the series. /// The second Quaternion rotation in the series. /// A new Quaternion representing the concatenation of the value1 rotation followed by the value2 rotation. - let concat (q:Quaternion) (q':Quaternion) = q' * q //concat rotation is actually q' * q instead of q * q'. + [] + let concat (q:Quaternion) (q':Quaternion) = + //concat rotation is q' * q instead of q * q'. + q' * q