fixed dependencies

This commit is contained in:
nuknal
2024-10-24 15:46:01 +08:00
parent d16a5bd9c0
commit 1161e8d054
2005 changed files with 690883 additions and 0 deletions

6
vendor/gonum.org/v1/gonum/spatial/r1/doc.go generated vendored Normal file
View File

@@ -0,0 +1,6 @@
// Copyright ©2019 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package r1 provides 1D vectors and intervals and operations on them.
package r1 // import "gonum.org/v1/gonum/spatial/r1"

10
vendor/gonum.org/v1/gonum/spatial/r1/interval.go generated vendored Normal file
View File

@@ -0,0 +1,10 @@
// Copyright ©2019 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package r1
// Interval represents an interval.
type Interval struct {
Min, Max float64
}

121
vendor/gonum.org/v1/gonum/spatial/r3/box.go generated vendored Normal file
View File

@@ -0,0 +1,121 @@
// Copyright ©2022 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package r3
import "math"
// Box is a 3D bounding box. Well formed Boxes Min components
// are smaller than Max components.
type Box struct {
Min, Max Vec
}
// NewBox is shorthand for Box{Min:Vec{x0,y0,z0}, Max:Vec{x1,y1,z1}}.
// The sides are swapped so that the resulting Box is well formed.
func NewBox(x0, y0, z0, x1, y1, z1 float64) Box {
return Box{
Min: Vec{X: math.Min(x0, x1), Y: math.Min(y0, y1), Z: math.Min(z0, z1)},
Max: Vec{X: math.Max(x0, x1), Y: math.Max(y0, y1), Z: math.Max(z0, z1)},
}
}
// IsEmpty returns true if a Box's volume is zero
// or if a Min component is greater than its Max component.
func (a Box) Empty() bool {
return a.Min.X >= a.Max.X || a.Min.Y >= a.Max.Y || a.Min.Z >= a.Max.Z
}
// Size returns the size of the Box.
func (a Box) Size() Vec {
return Sub(a.Max, a.Min)
}
// Center returns the center of the Box.
func (a Box) Center() Vec {
return Scale(0.5, Add(a.Min, a.Max))
}
// Vertices returns a slice of the 8 vertices
// corresponding to each of the Box's corners.
//
// Ordering of vertices 0-3 is CCW in the XY plane starting at box minimum.
// Ordering of vertices 4-7 is CCW in the XY plane starting at box minimum
// for X and Y values and maximum Z value.
//
// Edges for the box can be constructed with the following indices:
//
// edges := [12][2]int{
// {0, 1}, {1, 2}, {2, 3}, {3, 0},
// {4, 5}, {5, 6}, {6, 7}, {7, 4},
// {0, 4}, {1, 5}, {2, 6}, {3, 7},
// }
func (a Box) Vertices() []Vec {
return []Vec{
0: a.Min,
1: {X: a.Max.X, Y: a.Min.Y, Z: a.Min.Z},
2: {X: a.Max.X, Y: a.Max.Y, Z: a.Min.Z},
3: {X: a.Min.X, Y: a.Max.Y, Z: a.Min.Z},
4: {X: a.Min.X, Y: a.Min.Y, Z: a.Max.Z},
5: {X: a.Max.X, Y: a.Min.Y, Z: a.Max.Z},
6: a.Max,
7: {X: a.Min.X, Y: a.Max.Y, Z: a.Max.Z},
}
}
// Union returns a box enclosing both the receiver and argument Boxes.
func (a Box) Union(b Box) Box {
if a.Empty() {
return b
}
if b.Empty() {
return a
}
return Box{
Min: minElem(a.Min, b.Min),
Max: maxElem(a.Max, b.Max),
}
}
// Add adds v to the bounding box components.
// It is the equivalent of translating the Box by v.
func (a Box) Add(v Vec) Box {
return Box{Add(a.Min, v), Add(a.Max, v)}
}
// Scale returns a new Box scaled by a size vector around its center.
// The scaling is done element wise which is to say the Box's X dimension
// is scaled by scale.X. Negative elements of scale are interpreted as zero.
func (a Box) Scale(scale Vec) Box {
scale = maxElem(scale, Vec{})
// TODO(soypat): Probably a better way to do this.
return centeredBox(a.Center(), mulElem(scale, a.Size()))
}
// centeredBox creates a Box with a given center and size.
// Negative components of size will be interpreted as zero.
func centeredBox(center, size Vec) Box {
size = maxElem(size, Vec{}) // set negative values to zero.
half := Scale(0.5, size)
return Box{Min: Sub(center, half), Max: Add(center, half)}
}
// Contains returns true if v is contained within the bounds of the Box.
func (a Box) Contains(v Vec) bool {
if a.Empty() {
return v == a.Min && v == a.Max
}
return a.Min.X <= v.X && v.X <= a.Max.X &&
a.Min.Y <= v.Y && v.Y <= a.Max.Y &&
a.Min.Z <= v.Z && v.Z <= a.Max.Z
}
// Canon returns the canonical version of a. The returned Box has minimum
// and maximum coordinates swapped if necessary so that it is well-formed.
func (a Box) Canon() Box {
return Box{
Min: minElem(a.Min, a.Max),
Max: maxElem(a.Min, a.Max),
}
}

6
vendor/gonum.org/v1/gonum/spatial/r3/doc.go generated vendored Normal file
View File

@@ -0,0 +1,6 @@
// Copyright ©2019 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package r3 provides 3D vectors and boxes and operations on them.
package r3 // import "gonum.org/v1/gonum/spatial/r3"

307
vendor/gonum.org/v1/gonum/spatial/r3/mat.go generated vendored Normal file
View File

@@ -0,0 +1,307 @@
// Copyright ©2021 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package r3
import "gonum.org/v1/gonum/mat"
// Mat represents a 3×3 matrix. Useful for rotation matrices and such.
// The zero value is usable as the 3×3 zero matrix.
type Mat struct {
data *array
}
var _ mat.Matrix = (*Mat)(nil)
// NewMat returns a new 3×3 matrix Mat type and populates its elements
// with values passed as argument in row-major form. If val argument
// is nil then NewMat returns a matrix filled with zeros.
func NewMat(val []float64) *Mat {
if len(val) == 9 {
return &Mat{arrayFrom(val)}
}
if val == nil {
return &Mat{new(array)}
}
panic(mat.ErrShape)
}
// Dims returns the number of rows and columns of this matrix.
// This method will always return 3×3 for a Mat.
func (m *Mat) Dims() (r, c int) { return 3, 3 }
// T returns the transpose of Mat. Changes in the receiver will be reflected in the returned matrix.
func (m *Mat) T() mat.Matrix { return mat.Transpose{Matrix: m} }
// Scale multiplies the elements of a by f, placing the result in the receiver.
//
// See the mat.Scaler interface for more information.
func (m *Mat) Scale(f float64, a mat.Matrix) {
r, c := a.Dims()
if r != 3 || c != 3 {
panic(mat.ErrShape)
}
if m.data == nil {
m.data = new(array)
}
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
m.Set(i, j, f*a.At(i, j))
}
}
}
// MulVec returns the matrix-vector product M⋅v.
func (m *Mat) MulVec(v Vec) Vec {
if m.data == nil {
return Vec{}
}
return Vec{
X: v.X*m.At(0, 0) + v.Y*m.At(0, 1) + v.Z*m.At(0, 2),
Y: v.X*m.At(1, 0) + v.Y*m.At(1, 1) + v.Z*m.At(1, 2),
Z: v.X*m.At(2, 0) + v.Y*m.At(2, 1) + v.Z*m.At(2, 2),
}
}
// MulVecTrans returns the matrix-vector product Mᵀ⋅v.
func (m *Mat) MulVecTrans(v Vec) Vec {
if m.data == nil {
return Vec{}
}
return Vec{
X: v.X*m.At(0, 0) + v.Y*m.At(1, 0) + v.Z*m.At(2, 0),
Y: v.X*m.At(0, 1) + v.Y*m.At(1, 1) + v.Z*m.At(2, 1),
Z: v.X*m.At(0, 2) + v.Y*m.At(1, 2) + v.Z*m.At(2, 2),
}
}
// CloneFrom makes a copy of a into the receiver m.
// Mat expects a 3×3 input matrix.
func (m *Mat) CloneFrom(a mat.Matrix) {
r, c := a.Dims()
if r != 3 || c != 3 {
panic(mat.ErrShape)
}
if m.data == nil {
m.data = new(array)
}
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
m.Set(i, j, a.At(i, j))
}
}
}
// Sub subtracts the matrix b from a, placing the result in the receiver.
// Sub will panic if the two matrices do not have the same shape.
func (m *Mat) Sub(a, b mat.Matrix) {
if r, c := a.Dims(); r != 3 || c != 3 {
panic(mat.ErrShape)
}
if r, c := b.Dims(); r != 3 || c != 3 {
panic(mat.ErrShape)
}
if m.data == nil {
m.data = new(array)
}
m.Set(0, 0, a.At(0, 0)-b.At(0, 0))
m.Set(0, 1, a.At(0, 1)-b.At(0, 1))
m.Set(0, 2, a.At(0, 2)-b.At(0, 2))
m.Set(1, 0, a.At(1, 0)-b.At(1, 0))
m.Set(1, 1, a.At(1, 1)-b.At(1, 1))
m.Set(1, 2, a.At(1, 2)-b.At(1, 2))
m.Set(2, 0, a.At(2, 0)-b.At(2, 0))
m.Set(2, 1, a.At(2, 1)-b.At(2, 1))
m.Set(2, 2, a.At(2, 2)-b.At(2, 2))
}
// Add adds a and b element-wise, placing the result in the receiver. Add will panic if the two matrices do not have the same shape.
func (m *Mat) Add(a, b mat.Matrix) {
if r, c := a.Dims(); r != 3 || c != 3 {
panic(mat.ErrShape)
}
if r, c := b.Dims(); r != 3 || c != 3 {
panic(mat.ErrShape)
}
if m.data == nil {
m.data = new(array)
}
m.Set(0, 0, a.At(0, 0)+b.At(0, 0))
m.Set(0, 1, a.At(0, 1)+b.At(0, 1))
m.Set(0, 2, a.At(0, 2)+b.At(0, 2))
m.Set(1, 0, a.At(1, 0)+b.At(1, 0))
m.Set(1, 1, a.At(1, 1)+b.At(1, 1))
m.Set(1, 2, a.At(1, 2)+b.At(1, 2))
m.Set(2, 0, a.At(2, 0)+b.At(2, 0))
m.Set(2, 1, a.At(2, 1)+b.At(2, 1))
m.Set(2, 2, a.At(2, 2)+b.At(2, 2))
}
// VecRow returns the elements in the ith row of the receiver.
func (m *Mat) VecRow(i int) Vec {
if i > 2 {
panic(mat.ErrRowAccess)
}
if m.data == nil {
return Vec{}
}
return Vec{X: m.At(i, 0), Y: m.At(i, 1), Z: m.At(i, 2)}
}
// VecCol returns the elements in the jth column of the receiver.
func (m *Mat) VecCol(j int) Vec {
if j > 2 {
panic(mat.ErrColAccess)
}
if m.data == nil {
return Vec{}
}
return Vec{X: m.At(0, j), Y: m.At(1, j), Z: m.At(2, j)}
}
// Outer calculates the outer product of the vectors x and y,
// where x and y are treated as column vectors, and stores the result in the receiver.
//
// m = alpha * x * yᵀ
func (m *Mat) Outer(alpha float64, x, y Vec) {
ax := alpha * x.X
ay := alpha * x.Y
az := alpha * x.Z
m.Set(0, 0, ax*y.X)
m.Set(0, 1, ax*y.Y)
m.Set(0, 2, ax*y.Z)
m.Set(1, 0, ay*y.X)
m.Set(1, 1, ay*y.Y)
m.Set(1, 2, ay*y.Z)
m.Set(2, 0, az*y.X)
m.Set(2, 1, az*y.Y)
m.Set(2, 2, az*y.Z)
}
// Det calculates the determinant of the receiver using the following formula
//
// ⎡a b c⎤
// m = ⎢d e f⎥
// ⎣g h i⎦
// det(m) = a(ei fh) b(di fg) + c(dh eg)
func (m *Mat) Det() float64 {
a := m.At(0, 0)
b := m.At(0, 1)
c := m.At(0, 2)
deta := m.At(1, 1)*m.At(2, 2) - m.At(1, 2)*m.At(2, 1)
detb := m.At(1, 0)*m.At(2, 2) - m.At(1, 2)*m.At(2, 0)
detc := m.At(1, 0)*m.At(2, 1) - m.At(1, 1)*m.At(2, 0)
return a*deta - b*detb + c*detc
}
// Skew sets the receiver to the 3×3 skew symmetric matrix
// (right hand system) of v.
//
// ⎡ 0 -z y⎤
// Skew({x,y,z}) = ⎢ z 0 -x⎥
// ⎣-y x 0⎦
func (m *Mat) Skew(v Vec) {
m.Set(0, 0, 0)
m.Set(0, 1, -v.Z)
m.Set(0, 2, v.Y)
m.Set(1, 0, v.Z)
m.Set(1, 1, 0)
m.Set(1, 2, -v.X)
m.Set(2, 0, -v.Y)
m.Set(2, 1, v.X)
m.Set(2, 2, 0)
}
// Hessian sets the receiver to the Hessian matrix of the scalar field at the point p,
// approximated using finite differences with the given step sizes.
// The field is evaluated at points in the area surrounding p by adding
// at most 2 components of step to p. Hessian expects the field's second partial
// derivatives are all continuous for correct results.
func (m *Mat) Hessian(p, step Vec, field func(Vec) float64) {
dx := Vec{X: step.X}
dy := Vec{Y: step.Y}
dz := Vec{Z: step.Z}
fp := field(p)
fxp := field(Add(p, dx))
fxm := field(Sub(p, dx))
fxx := (fxp - 2*fp + fxm) / (step.X * step.X)
fyp := field(Add(p, dy))
fym := field(Sub(p, dy))
fyy := (fyp - 2*fp + fym) / (step.Y * step.Y)
aux := Add(dx, dy)
fxyp := field(Add(p, aux))
fxym := field(Sub(p, aux))
fxy := (fxyp - fxp - fyp + 2*fp - fxm - fym + fxym) / (2 * step.X * step.Y)
fzp := field(Add(p, dz))
fzm := field(Sub(p, dz))
fzz := (fzp - 2*fp + fzm) / (step.Z * step.Z)
aux = Add(dx, dz)
fxzp := field(Add(p, aux))
fxzm := field(Sub(p, aux))
fxz := (fxzp - fxp - fzp + 2*fp - fxm - fzm + fxzm) / (2 * step.X * step.Z)
aux = Add(dy, dz)
fyzp := field(Add(p, aux))
fyzm := field(Sub(p, aux))
fyz := (fyzp - fyp - fzp + 2*fp - fym - fzm + fyzm) / (2 * step.Y * step.Z)
m.Set(0, 0, fxx)
m.Set(0, 1, fxy)
m.Set(0, 2, fxz)
m.Set(1, 0, fxy)
m.Set(1, 1, fyy)
m.Set(1, 2, fyz)
m.Set(2, 0, fxz)
m.Set(2, 1, fyz)
m.Set(2, 2, fzz)
}
// Jacobian sets the receiver to the Jacobian matrix of the vector field at
// the point p, approximated using finite differences with the given step sizes.
//
// The Jacobian matrix J is the matrix of all first-order partial derivatives of f.
// If f maps an 3-dimensional vector x to an 3-dimensional vector y = f(x), J is
// a 3×3 matrix whose elements are given as
//
// J_{i,j} = ∂f_i/∂x_j,
//
// or expanded out
//
// [ ∂f_1/∂x_1 ∂f_1/∂x_2 ∂f_1/∂x_3 ]
// J = [ ∂f_2/∂x_1 ∂f_2/∂x_2 ∂f_2/∂x_3 ]
// [ ∂f_3/∂x_1 ∂f_3/∂x_2 ∂f_3/∂x_3 ]
//
// Jacobian expects the field's first order partial derivatives are all
// continuous for correct results.
func (m *Mat) Jacobian(p, step Vec, field func(Vec) Vec) {
dx := Vec{X: step.X}
dy := Vec{Y: step.Y}
dz := Vec{Z: step.Z}
dfdx := Scale(0.5/step.X, Sub(field(Add(p, dx)), field(Sub(p, dx))))
dfdy := Scale(0.5/step.Y, Sub(field(Add(p, dy)), field(Sub(p, dy))))
dfdz := Scale(0.5/step.Z, Sub(field(Add(p, dz)), field(Sub(p, dz))))
m.Set(0, 0, dfdx.X)
m.Set(0, 1, dfdy.X)
m.Set(0, 2, dfdz.X)
m.Set(1, 0, dfdx.Y)
m.Set(1, 1, dfdy.Y)
m.Set(1, 2, dfdz.Y)
m.Set(2, 0, dfdx.Z)
m.Set(2, 1, dfdy.Z)
m.Set(2, 2, dfdz.Z)
}

157
vendor/gonum.org/v1/gonum/spatial/r3/mat_safe.go generated vendored Normal file
View File

@@ -0,0 +1,157 @@
// Copyright ©2021 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build safe
// +build safe
// TODO(kortschak): Get rid of this rigmarole if https://golang.org/issue/50118
// is accepted.
package r3
import (
"gonum.org/v1/gonum/blas/blas64"
"gonum.org/v1/gonum/mat"
)
type array [9]float64
// At returns the value of a matrix element at row i, column j.
// At expects indices in the range [0,2].
// It will panic if i or j are out of bounds for the matrix.
func (m *Mat) At(i, j int) float64 {
if uint(i) > 2 {
panic(mat.ErrRowAccess)
}
if uint(j) > 2 {
panic(mat.ErrColAccess)
}
if m.data == nil {
m.data = new(array)
}
return m.data[i*3+j]
}
// Set sets the element at row i, column j to the value v.
func (m *Mat) Set(i, j int, v float64) {
if uint(i) > 2 {
panic(mat.ErrRowAccess)
}
if uint(j) > 2 {
panic(mat.ErrColAccess)
}
if m.data == nil {
m.data = new(array)
}
m.data[i*3+j] = v
}
// Eye returns the 3×3 Identity matrix
func Eye() *Mat {
return &Mat{&array{
1, 0, 0,
0, 1, 0,
0, 0, 1,
}}
}
// Skew returns the 3×3 skew symmetric matrix (right hand system) of v.
//
// ⎡ 0 -z y⎤
// Skew({x,y,z}) = ⎢ z 0 -x⎥
// ⎣-y x 0⎦
//
// Deprecated: use Mat.Skew()
func Skew(v Vec) (M *Mat) {
return &Mat{&array{
0, -v.Z, v.Y,
v.Z, 0, -v.X,
-v.Y, v.X, 0,
}}
}
// Mul takes the matrix product of a and b, placing the result in the receiver.
// If the number of columns in a does not equal 3, Mul will panic.
func (m *Mat) Mul(a, b mat.Matrix) {
ra, ca := a.Dims()
rb, cb := b.Dims()
switch {
case ra != 3:
panic(mat.ErrShape)
case cb != 3:
panic(mat.ErrShape)
case ca != rb:
panic(mat.ErrShape)
}
if m.data == nil {
m.data = new(array)
}
if ca != 3 {
// General matrix multiplication for the case where the inner dimension is not 3.
var t mat.Dense
t.Mul(a, b)
copy(m.data[:], t.RawMatrix().Data)
return
}
a00 := a.At(0, 0)
b00 := b.At(0, 0)
a01 := a.At(0, 1)
b01 := b.At(0, 1)
a02 := a.At(0, 2)
b02 := b.At(0, 2)
a10 := a.At(1, 0)
b10 := b.At(1, 0)
a11 := a.At(1, 1)
b11 := b.At(1, 1)
a12 := a.At(1, 2)
b12 := b.At(1, 2)
a20 := a.At(2, 0)
b20 := b.At(2, 0)
a21 := a.At(2, 1)
b21 := b.At(2, 1)
a22 := a.At(2, 2)
b22 := b.At(2, 2)
*(m.data) = array{
a00*b00 + a01*b10 + a02*b20, a00*b01 + a01*b11 + a02*b21, a00*b02 + a01*b12 + a02*b22,
a10*b00 + a11*b10 + a12*b20, a10*b01 + a11*b11 + a12*b21, a10*b02 + a11*b12 + a12*b22,
a20*b00 + a21*b10 + a22*b20, a20*b01 + a21*b11 + a22*b21, a20*b02 + a21*b12 + a22*b22,
}
}
// RawMatrix returns the blas representation of the matrix with the backing
// data of this matrix. Changes to the returned matrix will be reflected in
// the receiver.
func (m *Mat) RawMatrix() blas64.General {
if m.data == nil {
m.data = new(array)
}
return blas64.General{Rows: 3, Cols: 3, Data: m.data[:], Stride: 3}
}
func arrayFrom(vals []float64) *array {
return (*array)(vals)
}
// Mat returns a 3×3 rotation matrix corresponding to the receiver. It
// may be used to perform rotations on a 3-vector or to apply the rotation
// to a 3×n matrix of column vectors. If the receiver is not a unit
// quaternion, the returned matrix will not be a pure rotation.
func (r Rotation) Mat() *Mat {
w, i, j, k := r.Real, r.Imag, r.Jmag, r.Kmag
ii := 2 * i * i
jj := 2 * j * j
kk := 2 * k * k
wi := 2 * w * i
wj := 2 * w * j
wk := 2 * w * k
ij := 2 * i * j
jk := 2 * j * k
ki := 2 * k * i
return &Mat{&array{
1 - (jj + kk), ij - wk, ki + wj,
ij + wk, 1 - (ii + kk), jk - wi,
ki - wj, jk + wi, 1 - (ii + jj),
}}
}

151
vendor/gonum.org/v1/gonum/spatial/r3/mat_unsafe.go generated vendored Normal file
View File

@@ -0,0 +1,151 @@
// Copyright ©2021 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !safe
// +build !safe
package r3
import (
"unsafe"
"gonum.org/v1/gonum/blas/blas64"
"gonum.org/v1/gonum/mat"
)
type array [3][3]float64
// At returns the value of a matrix element at row i, column j.
// At expects indices in the range [0,2].
// It will panic if i or j are out of bounds for the matrix.
func (m *Mat) At(i, j int) float64 {
if m.data == nil {
m.data = new(array)
}
return m.data[i][j]
}
// Set sets the element at row i, column j to the value v.
func (m *Mat) Set(i, j int, v float64) {
if m.data == nil {
m.data = new(array)
}
m.data[i][j] = v
}
// Eye returns the 3×3 Identity matrix
func Eye() *Mat {
return &Mat{&array{
{1, 0, 0},
{0, 1, 0},
{0, 0, 1},
}}
}
// Skew returns the 3×3 skew symmetric matrix (right hand system) of v.
//
// ⎡ 0 -z y⎤
// Skew({x,y,z}) = ⎢ z 0 -x⎥
// ⎣-y x 0⎦
//
// Deprecated: use Mat.Skew()
func Skew(v Vec) (M *Mat) {
return &Mat{&array{
{0, -v.Z, v.Y},
{v.Z, 0, -v.X},
{-v.Y, v.X, 0},
}}
}
// Mul takes the matrix product of a and b, placing the result in the receiver.
// If the number of columns in a does not equal 3, Mul will panic.
func (m *Mat) Mul(a, b mat.Matrix) {
ra, ca := a.Dims()
rb, cb := b.Dims()
switch {
case ra != 3:
panic(mat.ErrShape)
case cb != 3:
panic(mat.ErrShape)
case ca != rb:
panic(mat.ErrShape)
}
if m.data == nil {
m.data = new(array)
}
if ca != 3 {
// General matrix multiplication for the case where the inner dimension is not 3.
t := mat.NewDense(3, 3, m.slice())
t.Mul(a, b)
return
}
a00 := a.At(0, 0)
b00 := b.At(0, 0)
a01 := a.At(0, 1)
b01 := b.At(0, 1)
a02 := a.At(0, 2)
b02 := b.At(0, 2)
a10 := a.At(1, 0)
b10 := b.At(1, 0)
a11 := a.At(1, 1)
b11 := b.At(1, 1)
a12 := a.At(1, 2)
b12 := b.At(1, 2)
a20 := a.At(2, 0)
b20 := b.At(2, 0)
a21 := a.At(2, 1)
b21 := b.At(2, 1)
a22 := a.At(2, 2)
b22 := b.At(2, 2)
m.data[0][0] = a00*b00 + a01*b10 + a02*b20
m.data[0][1] = a00*b01 + a01*b11 + a02*b21
m.data[0][2] = a00*b02 + a01*b12 + a02*b22
m.data[1][0] = a10*b00 + a11*b10 + a12*b20
m.data[1][1] = a10*b01 + a11*b11 + a12*b21
m.data[1][2] = a10*b02 + a11*b12 + a12*b22
m.data[2][0] = a20*b00 + a21*b10 + a22*b20
m.data[2][1] = a20*b01 + a21*b11 + a22*b21
m.data[2][2] = a20*b02 + a21*b12 + a22*b22
}
// RawMatrix returns the blas representation of the matrix with the backing
// data of this matrix. Changes to the returned matrix will be reflected in
// the receiver.
func (m *Mat) RawMatrix() blas64.General {
if m.data == nil {
m.data = new(array)
}
return blas64.General{Rows: 3, Cols: 3, Data: m.slice(), Stride: 3}
}
// Mat returns a 3×3 rotation matrix corresponding to the receiver. It
// may be used to perform rotations on a 3-vector or to apply the rotation
// to a 3×n matrix of column vectors. If the receiver is not a unit
// quaternion, the returned matrix will not be a pure rotation.
func (r Rotation) Mat() *Mat {
w, i, j, k := r.Real, r.Imag, r.Jmag, r.Kmag
ii := 2 * i * i
jj := 2 * j * j
kk := 2 * k * k
wi := 2 * w * i
wj := 2 * w * j
wk := 2 * w * k
ij := 2 * i * j
jk := 2 * j * k
ki := 2 * k * i
return &Mat{&array{
{1 - (jj + kk), ij - wk, ki + wj},
{ij + wk, 1 - (ii + kk), jk - wi},
{ki - wj, jk + wi, 1 - (ii + jj)},
}}
}
func arrayFrom(vals []float64) *array {
return (*array)(unsafe.Pointer(&vals[0]))
}
func (m *Mat) slice() []float64 {
return (*[9]float64)(unsafe.Pointer(m.data))[:]
}

58
vendor/gonum.org/v1/gonum/spatial/r3/rotation.go generated vendored Normal file
View File

@@ -0,0 +1,58 @@
// Copyright ©2021 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package r3
import (
"math"
"gonum.org/v1/gonum/num/quat"
)
// TODO: possibly useful additions to the current rotation API:
// - create rotations from Euler angles (NewRotationFromEuler?)
// - create rotations from rotation matrices (NewRotationFromMatrix?)
// - return the equivalent Euler angles from a Rotation
//
// Euler angles have issues (see [1] for a discussion).
// We should think carefully before adding them in.
// [1]: http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/
// Rotation describes a rotation in space.
type Rotation quat.Number
// NewRotation creates a rotation by alpha, around axis.
func NewRotation(alpha float64, axis Vec) Rotation {
if alpha == 0 {
return Rotation{Real: 1}
}
q := raise(axis)
sin, cos := math.Sincos(0.5 * alpha)
q = quat.Scale(sin/quat.Abs(q), q)
q.Real += cos
if len := quat.Abs(q); len != 1 {
q = quat.Scale(1/len, q)
}
return Rotation(q)
}
// Rotate returns p rotated according to the parameters used to construct
// the receiver.
func (r Rotation) Rotate(p Vec) Vec {
if r.isIdentity() {
return p
}
qq := quat.Number(r)
pp := quat.Mul(quat.Mul(qq, raise(p)), quat.Conj(qq))
return Vec{X: pp.Imag, Y: pp.Jmag, Z: pp.Kmag}
}
func (r Rotation) isIdentity() bool {
return r == Rotation{Real: 1}
}
func raise(p Vec) quat.Number {
return quat.Number{Imag: p.X, Jmag: p.Y, Kmag: p.Z}
}

118
vendor/gonum.org/v1/gonum/spatial/r3/triangle.go generated vendored Normal file
View File

@@ -0,0 +1,118 @@
// Copyright ©2022 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package r3
import "math"
// Triangle represents a triangle in 3D space and
// is composed by 3 vectors corresponding to the position
// of each of the vertices. Ordering of these vertices
// decides the "normal" direction.
// Inverting ordering of two vertices inverts the resulting direction.
type Triangle [3]Vec
// Centroid returns the intersection of the three medians of the triangle
// as a point in space.
func (t Triangle) Centroid() Vec {
return Scale(1.0/3.0, Add(Add(t[0], t[1]), t[2]))
}
// Normal returns the vector with direction
// perpendicular to the Triangle's face and magnitude
// twice that of the Triangle's area. The ordering
// of the triangle vertices decides the normal's resulting
// direction. The returned vector is not normalized.
func (t Triangle) Normal() Vec {
s1, s2, _ := t.sides()
return Cross(s1, s2)
}
// IsDegenerate returns true if all of triangle's vertices are
// within tol distance of its longest side.
func (t Triangle) IsDegenerate(tol float64) bool {
longIdx := t.longIdx()
// calculate vertex distance from longest side
ln := line{t[longIdx], t[(longIdx+1)%3]}
dist := ln.distance(t[(longIdx+2)%3])
return dist <= tol
}
// longIdx returns index of the longest side. The sides
// of the triangles are are as follows:
// - Side 0 formed by vertices 0 and 1
// - Side 1 formed by vertices 1 and 2
// - Side 2 formed by vertices 0 and 2
func (t Triangle) longIdx() int {
sides := [3]Vec{Sub(t[1], t[0]), Sub(t[2], t[1]), Sub(t[0], t[2])}
len2 := [3]float64{Norm2(sides[0]), Norm2(sides[1]), Norm2(sides[2])}
longLen := len2[0]
longIdx := 0
if len2[1] > longLen {
longLen = len2[1]
longIdx = 1
}
if len2[2] > longLen {
longIdx = 2
}
return longIdx
}
// Area returns the surface area of the triangle.
func (t Triangle) Area() float64 {
// Heron's Formula, see https://en.wikipedia.org/wiki/Heron%27s_formula.
// Also see William M. Kahan (24 March 2000). "Miscalculating Area and Angles of a Needle-like Triangle"
// for more discussion. https://people.eecs.berkeley.edu/~wkahan/Triangle.pdf.
a, b, c := t.orderedLengths()
A := (c + (b + a)) * (a - (c - b))
A *= (a + (c - b)) * (c + (b - a))
return math.Sqrt(A) / 4
}
// orderedLengths returns the lengths of the sides of the triangle such that
// a ≤ b ≤ c.
func (t Triangle) orderedLengths() (a, b, c float64) {
s1, s2, s3 := t.sides()
l1 := Norm(s1)
l2 := Norm(s2)
l3 := Norm(s3)
// sort-3
if l2 < l1 {
l1, l2 = l2, l1
}
if l3 < l2 {
l2, l3 = l3, l2
if l2 < l1 {
l1, l2 = l2, l1
}
}
return l1, l2, l3
}
// sides returns vectors for each of the sides of t.
func (t Triangle) sides() (Vec, Vec, Vec) {
return Sub(t[1], t[0]), Sub(t[2], t[1]), Sub(t[0], t[2])
}
// line is an infinite 3D line
// defined by two points on the line.
type line [2]Vec
// vecOnLine takes a value between 0 and 1 to linearly
// interpolate a point on the line.
//
// vecOnLine(0) returns l[0]
// vecOnLine(1) returns l[1]
func (l line) vecOnLine(t float64) Vec {
lineDir := Sub(l[1], l[0])
return Add(l[0], Scale(t, lineDir))
}
// distance returns the minimum euclidean distance of point p
// to the line.
func (l line) distance(p Vec) float64 {
// https://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
num := Norm(Cross(Sub(p, l[0]), Sub(p, l[1])))
return num / Norm(Sub(l[1], l[0]))
}

161
vendor/gonum.org/v1/gonum/spatial/r3/vector.go generated vendored Normal file
View File

@@ -0,0 +1,161 @@
// Copyright ©2019 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package r3
import "math"
// Vec is a 3D vector.
type Vec struct {
X, Y, Z float64
}
// Add returns the vector sum of p and q.
func Add(p, q Vec) Vec {
return Vec{
X: p.X + q.X,
Y: p.Y + q.Y,
Z: p.Z + q.Z,
}
}
// Sub returns the vector sum of p and -q.
func Sub(p, q Vec) Vec {
return Vec{
X: p.X - q.X,
Y: p.Y - q.Y,
Z: p.Z - q.Z,
}
}
// Scale returns the vector p scaled by f.
func Scale(f float64, p Vec) Vec {
return Vec{
X: f * p.X,
Y: f * p.Y,
Z: f * p.Z,
}
}
// Dot returns the dot product p·q.
func Dot(p, q Vec) float64 {
return p.X*q.X + p.Y*q.Y + p.Z*q.Z
}
// Cross returns the cross product p×q.
func Cross(p, q Vec) Vec {
return Vec{
p.Y*q.Z - p.Z*q.Y,
p.Z*q.X - p.X*q.Z,
p.X*q.Y - p.Y*q.X,
}
}
// Rotate returns a new vector, rotated by alpha around the provided axis.
func Rotate(p Vec, alpha float64, axis Vec) Vec {
return NewRotation(alpha, axis).Rotate(p)
}
// Norm returns the Euclidean norm of p
//
// |p| = sqrt(p_x^2 + p_y^2 + p_z^2).
func Norm(p Vec) float64 {
return math.Hypot(p.X, math.Hypot(p.Y, p.Z))
}
// Norm2 returns the Euclidean squared norm of p
//
// |p|^2 = p_x^2 + p_y^2 + p_z^2.
func Norm2(p Vec) float64 {
return p.X*p.X + p.Y*p.Y + p.Z*p.Z
}
// Unit returns the unit vector colinear to p.
// Unit returns {NaN,NaN,NaN} for the zero vector.
func Unit(p Vec) Vec {
if p.X == 0 && p.Y == 0 && p.Z == 0 {
return Vec{X: math.NaN(), Y: math.NaN(), Z: math.NaN()}
}
return Scale(1/Norm(p), p)
}
// Cos returns the cosine of the opening angle between p and q.
func Cos(p, q Vec) float64 {
return Dot(p, q) / (Norm(p) * Norm(q))
}
// Divergence returns the divergence of the vector field at the point p,
// approximated using finite differences with the given step sizes.
func Divergence(p, step Vec, field func(Vec) Vec) float64 {
sx := Vec{X: step.X}
divx := (field(Add(p, sx)).X - field(Sub(p, sx)).X) / step.X
sy := Vec{Y: step.Y}
divy := (field(Add(p, sy)).Y - field(Sub(p, sy)).Y) / step.Y
sz := Vec{Z: step.Z}
divz := (field(Add(p, sz)).Z - field(Sub(p, sz)).Z) / step.Z
return 0.5 * (divx + divy + divz)
}
// Gradient returns the gradient of the scalar field at the point p,
// approximated using finite differences with the given step sizes.
func Gradient(p, step Vec, field func(Vec) float64) Vec {
dx := Vec{X: step.X}
dy := Vec{Y: step.Y}
dz := Vec{Z: step.Z}
return Vec{
X: (field(Add(p, dx)) - field(Sub(p, dx))) / (2 * step.X),
Y: (field(Add(p, dy)) - field(Sub(p, dy))) / (2 * step.Y),
Z: (field(Add(p, dz)) - field(Sub(p, dz))) / (2 * step.Z),
}
}
// minElem return a vector with the minimum components of two vectors.
func minElem(a, b Vec) Vec {
return Vec{
X: math.Min(a.X, b.X),
Y: math.Min(a.Y, b.Y),
Z: math.Min(a.Z, b.Z),
}
}
// maxElem return a vector with the maximum components of two vectors.
func maxElem(a, b Vec) Vec {
return Vec{
X: math.Max(a.X, b.X),
Y: math.Max(a.Y, b.Y),
Z: math.Max(a.Z, b.Z),
}
}
// absElem returns the vector with components set to their absolute value.
func absElem(a Vec) Vec {
return Vec{
X: math.Abs(a.X),
Y: math.Abs(a.Y),
Z: math.Abs(a.Z),
}
}
// mulElem returns the Hadamard product between vectors a and b.
//
// v = {a.X*b.X, a.Y*b.Y, a.Z*b.Z}
func mulElem(a, b Vec) Vec {
return Vec{
X: a.X * b.X,
Y: a.Y * b.Y,
Z: a.Z * b.Z,
}
}
// divElem returns the Hadamard product between vector a
// and the inverse components of vector b.
//
// v = {a.X/b.X, a.Y/b.Y, a.Z/b.Z}
func divElem(a, b Vec) Vec {
return Vec{
X: a.X / b.X,
Y: a.Y / b.Y,
Z: a.Z / b.Z,
}
}