gonum.org/v1/gonum@v0.14.0/num/quat/quat_example_test.go (about)

     1  // Copyright ©2018 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 quat_test
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  
    11  	"gonum.org/v1/gonum/floats/scalar"
    12  	"gonum.org/v1/gonum/num/quat"
    13  )
    14  
    15  // point is a 3-dimensional point/vector.
    16  type point struct {
    17  	x, y, z float64
    18  }
    19  
    20  // raise raises the dimensionality of a point to a quaternion.
    21  func raise(p point) quat.Number {
    22  	return quat.Number{Imag: p.x, Jmag: p.y, Kmag: p.z}
    23  }
    24  
    25  // rotate performs the quaternion rotation of p by the given quaternion
    26  // and scaling by the scale factor.
    27  func rotate(p point, by quat.Number, scale float64) point {
    28  	// Ensure the modulus of by is correctly scaled.
    29  	if len := quat.Abs(by); len != scale {
    30  		by = quat.Scale(math.Sqrt(scale)/len, by)
    31  	}
    32  
    33  	// Perform the rotation/scaling.
    34  	pp := quat.Mul(quat.Mul(by, raise(p)), quat.Conj(by))
    35  
    36  	// Extract the point.
    37  	return point{x: pp.Imag, y: pp.Jmag, z: pp.Kmag}
    38  }
    39  
    40  // Rotate a cube 120° around the diagonal vector [1, 1, 1].
    41  func Example_rotate() {
    42  	alpha := 2 * math.Pi / 3
    43  	q := raise(point{1, 1, 1})
    44  	scale := 1.0
    45  
    46  	q = quat.Scale(math.Sin(alpha/2)/quat.Abs(q), q)
    47  	q.Real += math.Cos(alpha / 2)
    48  
    49  	for i, p := range []point{
    50  		{x: 0, y: 0, z: 0},
    51  		{x: 0, y: 0, z: 1},
    52  		{x: 0, y: 1, z: 0},
    53  		{x: 0, y: 1, z: 1},
    54  		{x: 1, y: 0, z: 0},
    55  		{x: 1, y: 0, z: 1},
    56  		{x: 1, y: 1, z: 0},
    57  		{x: 1, y: 1, z: 1},
    58  	} {
    59  		pp := rotate(p, q, scale)
    60  
    61  		// Clean up floating point error for clarity.
    62  		pp.x = scalar.Round(pp.x, 2)
    63  		pp.y = scalar.Round(pp.y, 2)
    64  		pp.z = scalar.Round(pp.z, 2)
    65  
    66  		fmt.Printf("%d %+v -> %+v\n", i, p, pp)
    67  	}
    68  
    69  	// Output:
    70  	//
    71  	// 0 {x:0 y:0 z:0} -> {x:0 y:0 z:0}
    72  	// 1 {x:0 y:0 z:1} -> {x:1 y:0 z:0}
    73  	// 2 {x:0 y:1 z:0} -> {x:0 y:0 z:1}
    74  	// 3 {x:0 y:1 z:1} -> {x:1 y:0 z:1}
    75  	// 4 {x:1 y:0 z:0} -> {x:0 y:1 z:0}
    76  	// 5 {x:1 y:0 z:1} -> {x:1 y:1 z:0}
    77  	// 6 {x:1 y:1 z:0} -> {x:0 y:1 z:1}
    78  	// 7 {x:1 y:1 z:1} -> {x:1 y:1 z:1}
    79  }