fixed dependencies
This commit is contained in:
6
vendor/gonum.org/v1/gonum/spatial/r1/doc.go
generated
vendored
Normal file
6
vendor/gonum.org/v1/gonum/spatial/r1/doc.go
generated
vendored
Normal 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
10
vendor/gonum.org/v1/gonum/spatial/r1/interval.go
generated
vendored
Normal 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
121
vendor/gonum.org/v1/gonum/spatial/r3/box.go
generated
vendored
Normal 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
6
vendor/gonum.org/v1/gonum/spatial/r3/doc.go
generated
vendored
Normal 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
307
vendor/gonum.org/v1/gonum/spatial/r3/mat.go
generated
vendored
Normal 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
157
vendor/gonum.org/v1/gonum/spatial/r3/mat_safe.go
generated
vendored
Normal 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
151
vendor/gonum.org/v1/gonum/spatial/r3/mat_unsafe.go
generated
vendored
Normal 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
58
vendor/gonum.org/v1/gonum/spatial/r3/rotation.go
generated
vendored
Normal 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
118
vendor/gonum.org/v1/gonum/spatial/r3/triangle.go
generated
vendored
Normal 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
161
vendor/gonum.org/v1/gonum/spatial/r3/vector.go
generated
vendored
Normal 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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user