gonum.org/v1/gonum@v0.15.1-0.20240517103525-f853624cb1bb/spatial/r3/slerp_example_test.go (about)

     1  // Copyright ©2022 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package r3_test
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  
    11  	"gonum.org/v1/gonum/num/quat"
    12  	"gonum.org/v1/gonum/spatial/r3"
    13  )
    14  
    15  // slerp returns the spherical interpolation between q0 and q1
    16  // for t in [0,1]; 0 corresponds to q0 and 1 corresponds to q1.
    17  func slerp(r0, r1 r3.Rotation, t float64) r3.Rotation {
    18  	q0 := quat.Number(r0)
    19  	q1 := quat.Number(r1)
    20  	// Based on Simo Särkkä "Notes on Quaternions" Eq. 35
    21  	//  p(t) = (q1 ∗ q0^−1) ^ t ∗ q0
    22  	// https://users.aalto.fi/~ssarkka/pub/quat.pdf
    23  	q1 = quat.Mul(q1, quat.Inv(q0))
    24  	q1 = quat.PowReal(q1, t)
    25  	return r3.Rotation(quat.Mul(q1, q0))
    26  }
    27  
    28  // Spherically interpolate between two quaternions to obtain a rotation.
    29  func Example_slerp() {
    30  	const steps = 10
    31  	// An initial rotation of pi/4 around the x-axis (45 degrees).
    32  	initialRot := r3.NewRotation(math.Pi/4, r3.Vec{X: 1})
    33  	// Final rotation is pi around the x-axis (180 degrees).
    34  	finalRot := r3.NewRotation(math.Pi, r3.Vec{X: 1})
    35  	// The vector we are rotating is (1, 1, 1).
    36  	// The result should then be (1, -1, -1) when t=1 (finalRot) since we invert the y and z axes.
    37  	v := r3.Vec{X: 1, Y: 1, Z: 1}
    38  	for i := 0.0; i <= steps; i++ {
    39  		t := i / steps
    40  		rotated := slerp(initialRot, finalRot, t).Rotate(v)
    41  		fmt.Printf("%.2f %+.2f\n", t, rotated)
    42  	}
    43  
    44  	// Output:
    45  	//
    46  	// 0.00 {+1.00 -0.00 +1.41}
    47  	// 0.10 {+1.00 -0.33 +1.38}
    48  	// 0.20 {+1.00 -0.64 +1.26}
    49  	// 0.30 {+1.00 -0.92 +1.08}
    50  	// 0.40 {+1.00 -1.14 +0.83}
    51  	// 0.50 {+1.00 -1.31 +0.54}
    52  	// 0.60 {+1.00 -1.40 +0.22}
    53  	// 0.70 {+1.00 -1.41 -0.11}
    54  	// 0.80 {+1.00 -1.34 -0.44}
    55  	// 0.90 {+1.00 -1.21 -0.74}
    56  	// 1.00 {+1.00 -1.00 -1.00}
    57  }