geom

package
v0.0.0-...-405cb25 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 8, 2020 License: GPL-3.0 Imports: 2 Imported by: 0

Documentation

Overview

Package geom provides geometric primitives: vectors, matrices and transformations.

Index

Examples

Constants

View Source
const (
	// Deg is one degree in radians. Useful for conversions, e.g.: 90*Deg.
	Deg = Pi / 180

	// Pi is shorthand for math.Pi.
	Pi = math.Pi
)
View Source
const (
	X = 0
	Y = 1
	Z = 2
)

Vector components.

Variables

View Source
var Ex = Vec{1, 0, 0}

Ex is shorthand for the basis vector [1 0 0].

View Source
var Ey = Vec{0, 1, 0}

Ey is shorthand for the basis vector [0 1 0].

View Source
var Ez = Vec{0, 0, 1}

Ez is shorthand for the basis vector [0 0 1].

View Source
var Inf = math.Inf(1)
View Source
var O = Vec{0, 0, 0}

O is shorthand for the zero vector [0 0 0].

Functions

This section is empty.

Types

type AffineTransform

type AffineTransform struct {
	A Matrix
	B Vec
}

AffineTransform represents an 3D affine transformation

y = A x + b

func ComposeLR

func ComposeLR(t ...*AffineTransform) *AffineTransform

ComposeLR composes affine transformations left-to-right. I.e., the leftmost argument is applied first.

func MapBaseTo

func MapBaseTo(o, x, y, z Vec) *AffineTransform

func Pitch

func Pitch(angle float64) *AffineTransform

Pitch tilts the camera upwards by the given angle (in radians). E.g.:

camera.Pitch(  0*Deg) // look horizontally
camera.Pitch(-90*Deg) // look at your feet
camera.Pitch(+90*Deg) // look at the zenith

Yaw, Pitch and Roll are not commutative. Use YawPitchRoll to apply them in canonical order.

func Roll

func Roll(angle float64) *AffineTransform

Roll rotates the camera counterclockwise around the line of sight. E.g.:

camera.Roll( 0*Deg) // horizon runs straight
camera.Roll(45*Deg) // horizon runs diagonally, from top left to bottom right.

Yaw, Pitch and Roll are not commutative. Use YawPitchRoll to apply them in canonical order.

func Rotate

func Rotate(origin Vec, axis Vec, angle float64) *AffineTransform

Rotate returns a Transform that rotates around an arbitrary axis, with origin as the fixed point. The rotation is counterclockwise in a right-handed space.

Example
angle := 30 * Deg
inputs := [3]Vec{Ex, Ey, Ez}

Rx := Rotate(O, Vec{1, 0, 0}, angle)
for _, v := range inputs {
	fmt.Printf("Rx: % .2f -> % .2f\n", v, Rx.TransformPoint(v))
}
fmt.Println()

Ry := Rotate(O, Vec{0, 1, 0}, angle)
for _, v := range inputs {
	fmt.Printf("Ry: % .2f -> % .2f\n", v, Ry.TransformPoint(v))
}
fmt.Println()

Rz := Rotate(O, Vec{0, 0, 1}, angle)
for _, v := range inputs {
	fmt.Printf("Rz: % .2f -> % .2f\n", v, Rz.TransformPoint(v))
}
fmt.Println()
Output:

Rx: [ 1.00  0.00  0.00] -> [ 1.00  0.00  0.00]
Rx: [ 0.00  1.00  0.00] -> [ 0.00  0.87  0.50]
Rx: [ 0.00  0.00  1.00] -> [ 0.00 -0.50  0.87]

Ry: [ 1.00  0.00  0.00] -> [ 0.87  0.00 -0.50]
Ry: [ 0.00  1.00  0.00] -> [ 0.00  1.00  0.00]
Ry: [ 0.00  0.00  1.00] -> [ 0.50  0.00  0.87]

Rz: [ 1.00  0.00  0.00] -> [ 0.87  0.50  0.00]
Rz: [ 0.00  1.00  0.00] -> [-0.50  0.87  0.00]
Rz: [ 0.00  0.00  1.00] -> [ 0.00  0.00  1.00]

func Scale

func Scale(origin Vec, s float64) *AffineTransform

Scale returns a transform that scales by factor s, with origin as the fixed point.

Example
tf := Scale(O, 2)
v := Vec{1, 2, 3}
fmt.Printf("point: % g -> % g\n", v, tf.TransformPoint(v))
fmt.Printf("dir:   % g -> % g\n", v, tf.TransformDir(v))
Output:

point: [ 1  2  3] -> [ 2  4  6]
dir:   [ 1  2  3] -> [ 2  4  6]

func Translate

func Translate(delta Vec) *AffineTransform

Translate returns a Transform that translates by delta. Translation affects points (TransformPoint), but not directions (TransformDir).

Example
tf := Translate(Vec{1, 0, 0})
v := Vec{1, 2, 3}
fmt.Printf("point: % g -> % g\n", v, tf.TransformPoint(v))
fmt.Printf("dir:   % g -> % g\n", v, tf.TransformDir(v))
Output:

point: [ 1  2  3] -> [ 2  2  3]
dir:   [ 1  2  3] -> [ 1  2  3]

func UnitTransform

func UnitTransform() *AffineTransform

func Yaw

func Yaw(angle float64) *AffineTransform

Yaw rotates the camera counterclockwise by the given angle (in radians), while keeping it horizontal. E.g.:

camera.Yaw(  0*Deg) // look North
camera.Yaw(+90*Deg) // look West
camera.Yaw(-90*Deg) // look East
camera.Yaw(180*Deg) // look South

Yaw, Pitch and Roll are not commutative. Use YawPitchRoll to apply them in canonical order.

func YawPitchRoll

func YawPitchRoll(yaw, pitch, roll float64) *AffineTransform

func (*AffineTransform) After

After returns a composite transform that applies s first, followed by t.

Example
R := Rotate(O, Ez, 90*Deg)
S := Scale(O, 2)
T := Translate(Vec{1, 0, 0})

ST := S.After(T)
TR := T.After(R)
RS := R.After(S)
TS := T.After(S)
RT := R.After(T)
SR := S.After(R)
RST := R.After(S).After(T)
STR := S.After(T).After(R)
TRS := T.After(R).After(S)

x := Vec{1, 0, 0}

fmt.Printf("R               : % g -> % g\n", x, R.TransformPoint(x))
fmt.Printf("S               : % g -> % g\n", x, S.TransformPoint(x))
fmt.Printf("T               : % g -> % g\n", x, T.TransformPoint(x))
fmt.Printf("ST              : % g -> % g\n", x, ST.TransformPoint(x))
fmt.Printf("S(T)            : % g -> % g\n", x, S.TransformPoint(T.TransformPoint(x)))
fmt.Printf("TR              : % g -> % g\n", x, TR.TransformPoint(x))
fmt.Printf("T(R)            : % g -> % g\n", x, T.TransformPoint(R.TransformPoint(x)))
fmt.Printf("RS              : % g -> % g\n", x, RS.TransformPoint(x))
fmt.Printf("R(S)            : % g -> % g\n", x, R.TransformPoint(S.TransformPoint(x)))
fmt.Printf("TS              : % g -> % g\n", x, TS.TransformPoint(x))
fmt.Printf("T(S)            : % g -> % g\n", x, T.TransformPoint(S.TransformPoint(x)))
fmt.Printf("RT              : % g -> % g\n", x, RT.TransformPoint(x))
fmt.Printf("R(T)            : % g -> % g\n", x, R.TransformPoint(T.TransformPoint(x)))
fmt.Printf("SR              : % g -> % g\n", x, SR.TransformPoint(x))
fmt.Printf("S(R)            : % g -> % g\n", x, S.TransformPoint(R.TransformPoint(x)))
fmt.Printf("RST             : % g -> % g\n", x, RST.TransformPoint(x))
fmt.Printf("R(S(T))         : % g -> % g\n", x, R.TransformPoint(S.TransformDir(T.TransformPoint(x))))
fmt.Printf("ComposeLR(T,S,R): % g -> % g\n", x, ComposeLR(T, S, R).TransformPoint(x))
fmt.Printf("STR             : % g -> % g\n", x, STR.TransformPoint(x))
fmt.Printf("S(T(R))         : % g -> % g\n", x, S.TransformPoint(T.TransformPoint(R.TransformPoint(x))))
fmt.Printf("ComposeLR(R,T,S): % g -> % g\n", x, ComposeLR(R, T, S).TransformPoint(x))
fmt.Printf("TRS             : % g -> % g\n", x, TRS.TransformPoint(x))
fmt.Printf("T(R(S))         : % g -> % g\n", x, T.TransformPoint(R.TransformPoint(S.TransformPoint(x))))
fmt.Printf("ComposeLR(S,R,T): % g -> % g\n", x, ComposeLR(S, R, T).TransformPoint(x))
Output:

R               : [ 1  0  0] -> [ 0  1  0]
S               : [ 1  0  0] -> [ 2  0  0]
T               : [ 1  0  0] -> [ 2  0  0]
ST              : [ 1  0  0] -> [ 4  0  0]
S(T)            : [ 1  0  0] -> [ 4  0  0]
TR              : [ 1  0  0] -> [ 1  1  0]
T(R)            : [ 1  0  0] -> [ 1  1  0]
RS              : [ 1  0  0] -> [ 0  2  0]
R(S)            : [ 1  0  0] -> [ 0  2  0]
TS              : [ 1  0  0] -> [ 3  0  0]
T(S)            : [ 1  0  0] -> [ 3  0  0]
RT              : [ 1  0  0] -> [ 0  2  0]
R(T)            : [ 1  0  0] -> [ 0  2  0]
SR              : [ 1  0  0] -> [ 0  2  0]
S(R)            : [ 1  0  0] -> [ 0  2  0]
RST             : [ 1  0  0] -> [ 0  4  0]
R(S(T))         : [ 1  0  0] -> [ 0  4  0]
ComposeLR(T,S,R): [ 1  0  0] -> [ 0  4  0]
STR             : [ 1  0  0] -> [ 2  2  0]
S(T(R))         : [ 1  0  0] -> [ 2  2  0]
ComposeLR(R,T,S): [ 1  0  0] -> [ 2  2  0]
TRS             : [ 1  0  0] -> [ 1  2  0]
T(R(S))         : [ 1  0  0] -> [ 1  2  0]
ComposeLR(S,R,T): [ 1  0  0] -> [ 1  2  0]

func (*AffineTransform) Before

Before returns a composite transform that applies t first, followed by s.

func (*AffineTransform) Inverse

func (t *AffineTransform) Inverse() *AffineTransform

Inverse returns the inverse affine transformation.

func (*AffineTransform) TransformDir

func (t *AffineTransform) TransformDir(dir Vec) Vec

TransformDir applies affine transformation t to vector dir, returning

A x

Directions are invariant against the the translation part of the transform. Use TransformPoint to transform a point, which does undergo translation.

func (*AffineTransform) TransformPoint

func (t *AffineTransform) TransformPoint(x Vec) Vec

TransformPoint applies affine transformation t to point x, returning

A x + b

Use TransformDir to transform a direction (vector).

func (*AffineTransform) WithOrigin

func (t *AffineTransform) WithOrigin(o Vec) *AffineTransform

WithOrigin returns a translated version of t so that o is the new origin (fixed point). E.g.:

Rotate(Vec{}, Ez, θ).WithOrigin(Vec{1,2,0})

rotates around [1, 2, 0] rather than [0, 0, 0]

type Matrix

type Matrix [3]Vec

Matrix is a 3x3 matrix intended for linear transformations.

func UnitMatrix

func UnitMatrix() Matrix

func (*Matrix) Inverse

func (m *Matrix) Inverse() Matrix

Inverse returns the inverse matrix.

Example
m := Matrix{{1, 2, 3}, {3, -1, 2}, {2, 3, -1}}
inv := m.Inverse()
check := inv.Mul(&m)

for i := range check {
	for j, v := range check[i] {
		if math.Abs(v) < 1e-9 {
			check[i][j] = 0
		}
	}
}
fmt.Printf("% 4.3f", check)
Output:

[[ 1.000  0.000  0.000] [ 0.000  1.000  0.000] [ 0.000  0.000  1.000]]

func (*Matrix) Mul

func (m *Matrix) Mul(b *Matrix) Matrix

Mul performs a Matrix-Matrix multiplication

Example
theta := 45 * math.Pi / 180
c := math.Cos(theta)
s := math.Sin(theta)
a := Matrix{{c, s, 0}, {-s, c, 0}, {0, 0, 1}}
fmt.Printf("% 4.1f", a.Mul(&a))
Output:

[[ 0.0  1.0  0.0] [-1.0  0.0  0.0] [ 0.0  0.0  1.0]]

func (*Matrix) MulVec

func (m *Matrix) MulVec(v Vec) Vec

MulVec performs a Matrix-Vector multiplication

m . vT
Example
theta := 30 * math.Pi / 180
c := math.Cos(theta)
s := math.Sin(theta)

m := Matrix{{c, s, 0}, {-s, c, 0}, {0, 0, 1}}
fmt.Printf("% 3f\n", m.MulVec(Vec{1, 0, 0}))
fmt.Printf("% 3f\n", m.MulVec(Vec{0, 1, 0}))
fmt.Printf("% 3f\n", m.MulVec(Vec{0, 0, 1}))
Output:

[ 0.866025  0.500000  0.000000]
[-0.500000  0.866025  0.000000]
[ 0.000000  0.000000  1.000000]

func (*Matrix) Mulf

func (m *Matrix) Mulf(f float64) Matrix

Mulf multiplies element-wise by a scalar.

type Vec

type Vec [3]float64

Vec is a 3-component vector. Used to represent either points in space or vectors.

Example
a := Vec{1, 2, 3}
b := Vec{0, 1, -2}

fmt.Printf("% g.Add(% g)     = % g\n", a, b, a.Add(b))
fmt.Printf("% g.Cross(% g)   = % g\n", a, b, a.Cross(b))
fmt.Printf("% g.Dot(% g)     = % g\n", a, b, a.Dot(b))
fmt.Printf("% g.MAdd(2, % g) = % g\n", a, b, a.MAdd(2, b))
fmt.Printf("% g.Sub(% g)     = % g\n", a, b, a.Sub(b))

fmt.Printf("% g.IsNaN()     = %v\n", a, a.IsNaN())
fmt.Printf("% g.Mul(2)      = % g\n", a, a.Mul(2))
fmt.Printf("% g.Len()       = % g\n", a, a.Len())
fmt.Printf("% g.Len2()     = % 3g\n", a, a.Len2())
fmt.Printf("% g.Normalized()= % g\n", a, a.Normalized())
Output:

[ 1  2  3].Add([ 0  1 -2])     = [ 1  3  1]
[ 1  2  3].Cross([ 0  1 -2])   = [-7  2  1]
[ 1  2  3].Dot([ 0  1 -2])     = -4
[ 1  2  3].MAdd(2, [ 0  1 -2]) = [ 1  4 -1]
[ 1  2  3].Sub([ 0  1 -2])     = [ 1  1  5]
[ 1  2  3].IsNaN()     = false
[ 1  2  3].Mul(2)      = [ 2  4  6]
[ 1  2  3].Len()       =  3.7416573867739413
[ 1  2  3].Len2()     =  14
[ 1  2  3].Normalized()= [ 0.2672612419124244  0.5345224838248488  0.8017837257372732]

func MakeBasis

func MakeBasis(x Vec) (y, z Vec)

MakeBasis constructs an orthonormal basis. I.e. returns y and z so that x, y, and z are mutually orthogonal.

func TriangleNormal

func TriangleNormal(a, b, c Vec) Vec

TriangleNormal returns the normal vector of the triangle with vertices a, b, c.

Example
a := Vec{1, 0, 0}
b := Vec{2, 0, 0}
c := Vec{1, 1, 0}
fmt.Println(TriangleNormal(a, b, c))
Output:

[0 0 1]

func (Vec) Add

func (a Vec) Add(b Vec) Vec

Add returns a + b.

func (Vec) Cross

func (a Vec) Cross(b Vec) Vec

Cross returns the cross product of a and b, assuming a right-handed space. See https://en.wikipedia.org/wiki/Cross_product#Matrix_notation

func (Vec) Dot

func (a Vec) Dot(b Vec) float64

Dot returns the scalar product of a and b.

func (Vec) IsNaN

func (a Vec) IsNaN() bool

IsNaN returns true if at least one componet is NaN.

func (Vec) Len

func (a Vec) Len() float64

Len returns the length (norm).

func (Vec) Len2

func (a Vec) Len2() float64

Len2 returns the length squared

func (Vec) MAdd

func (a Vec) MAdd(s float64, b Vec) Vec

MAdd (multiply-add) returns a + s*b.

func (Vec) Mul

func (a Vec) Mul(s float64) Vec

Mul returns a scaled vector: s * a.

func (*Vec) Normalize

func (a *Vec) Normalize()

Normalize scales a to unit length, overwriting the original.

Example
a := Vec{3, 4, 0}
a.Normalize()
fmt.Printf("% .1f\n", a)
Output:

[ 0.6  0.8  0.0]

func (Vec) Normalized

func (a Vec) Normalized() Vec

Normalized returns a copy of a that is scaled to unit length.

func (Vec) Sub

func (a Vec) Sub(b Vec) Vec

Sub returns a - b.

type Vec2

type Vec2 [2]float64

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL