diff --git a/vector/README.md b/vector/README.md new file mode 100644 index 0000000..02a335b --- /dev/null +++ b/vector/README.md @@ -0,0 +1,5 @@ +# vector + +Package vector provides a simple 3D vector class. + +For documentation, see [pkg.go.dev](https://pkg.go.dev/github.com/vaibhav11s/gopkgs/vector) diff --git a/vector/doc.md b/vector/doc.md new file mode 100644 index 0000000..1290686 --- /dev/null +++ b/vector/doc.md @@ -0,0 +1,338 @@ + + +# vector + +```go +import "github.com/vaibhav11s/gopkgs/vector" +``` + +Package vector provides a simple 3D vector class. + +## Index + +- [type Vector](#type-vector) + - [func Add(v1, v2 *Vector) *Vector](#func-add) + - [func Copy(v *Vector) *Vector](#func-copy) + - [func Cross(v1, v2 *Vector) *Vector](#func-cross) + - [func FromAngles(thetha, phi float32, length ...float32) \*Vector](#func-fromangles) + - [func Lerp(v1, v2 *Vector, t float32) *Vector](#func-lerp) + - [func Lerp2(v1, v2 *Vector, n, i int) *Vector](#func-lerp2) + - [func New(x, y, z float32) \*Vector](#func-new) + - [func Random(length ...float32) \*Vector](#func-random) + - [func ReflectThroughPlane(v, normal *Vector) *Vector](#func-reflectthroughplane) + - [func RotateAlongAxis(v, axis *Vector, angle float32) *Vector](#func-rotatealongaxis) + - [func Sub(v1, v2 *Vector) *Vector](#func-sub) + - [func Unit(v *Vector) *Vector](#func-unit) + - [func Angle(v1, v2 \*Vector) float32](#func-angle) + - [func Dist(v1, v2 \*Vector) float32](#func-dist) + - [func Dot(v1, v2 \*Vector) float32](#func-dot) + - [func (v *Vector) Add(v2 *Vector) \*Vector](#func-vector-add) + - [func (v *Vector) Angle(v2 *Vector) float32](#func-vector-angle) + - [func (v1 *Vector) Assign(v2 *Vector) \*Vector](#func-vector-assign) + - [func (v *Vector) Component(axis *Vector) (parallel, perpendicular \*Vector)](#func-vector-component) + - [func (v *Vector) Copy() *Vector](#func-vector-copy) + - [func (v *Vector) Cross(v2 *Vector) \*Vector](#func-vector-cross) + - [func (v *Vector) Dist(v2 *Vector) float32](#func-vector-dist) + - [func (v *Vector) Dot(v2 *Vector) float32](#func-vector-dot) + - [func (v *Vector) Equal(v2 *Vector, tolerance ...float32) bool](#func-vector-equal) + - [func (v \*Vector) Heading() (theta, phi float32)](#func-vector-heading) + - [func (v \*Vector) Mag() float32](#func-vector-mag) + - [func (v \*Vector) MagSq() float32](#func-vector-magsq) + - [func (v *Vector) Mult(scalar float32) *Vector](#func-vector-mult) + - [func (v *Vector) Normalize() *Vector](#func-vector-normalize) + - [func (v *Vector) ReflectThroughPlane(normal *Vector) \*Vector](#func-vector-reflectthroughplane) + - [func (v *Vector) Resize(mag float32) *Vector](#func-vector-resize) + - [func (v *Vector) RotateAlongAxis(axis *Vector, angle float32) \*Vector](#func-vector-rotatealongaxis) + - [func (v *Vector) SetHeading(thetha, phi float32) *Vector](#func-vector-setheading) + - [func (v \*Vector) String() string](#func-vector-string) + - [func (v *Vector) Sub(v2 *Vector) \*Vector](#func-vector-sub) + +## type Vector + +```go +type Vector struct { + X, Y, Z float32 +} +``` + +### func Add + +```go +func Add(v1, v2 *Vector) *Vector +``` + +returns the sum of two vectors + +### func Copy + +```go +func Copy(v *Vector) *Vector +``` + +Gets a copy of the vector + +### func Cross + +```go +func Cross(v1, v2 *Vector) *Vector +``` + +Calculates the cross product of two vectors + +### func FromAngles + +```go +func FromAngles(thetha, phi float32, length ...float32) *Vector +``` + +Make a new 3D vector from a pair of azimuth and zenith angles\. https://en.wikipedia.org/wiki/Spherical_coordinate_system + +### func Lerp + +```go +func Lerp(v1, v2 *Vector, t float32) *Vector +``` + +Linear interpolate the vector to another vector + +### func Lerp2 + +```go +func Lerp2(v1, v2 *Vector, n, i int) *Vector +``` + +Linear interpolate the vector to another vector\. i/n = t + +### func New + +```go +func New(x, y, z float32) *Vector +``` + +Creates a new 3D vector\. Three dimensional Euclidean vector\. + +### func Random + +```go +func Random(length ...float32) *Vector +``` + +Makes a random 3D vector of given lenght \(default 1\) + +### func ReflectThroughPlane + +```go +func ReflectThroughPlane(v, normal *Vector) *Vector +``` + +Gives the reflection of vector from the given plane\(normal vector\) + +### func RotateAlongAxis + +```go +func RotateAlongAxis(v, axis *Vector, angle float32) *Vector +``` + +Rotates the given vector around the axis by given angle + +### func Sub + +```go +func Sub(v1, v2 *Vector) *Vector +``` + +returns the difference of two vectors + +### func Unit + +```go +func Unit(v *Vector) *Vector +``` + +Gives a unit vector in dirction of the vector + +### func Angle + +```go +func Angle(v1, v2 *Vector) float32 +``` + +Calculates and returns the angle between two vectors\. Returns NaN if any vector is a zero vector + +### func Dist + +```go +func Dist(v1, v2 *Vector) float32 +``` + +Calculates the Euclidean distance between two points \(considering a point as a vector object\) + +### func Dot + +```go +func Dot(v1, v2 *Vector) float32 +``` + +### func \(\*Vector\) Add + +```go +func (v *Vector) Add(v2 *Vector) *Vector +``` + +add a vector to the current vector\. Modify \+ Returns self + +### func \(\*Vector\) Angle + +```go +func (v *Vector) Angle(v2 *Vector) float32 +``` + +Calculates and returns the angle with another vector Returns NaN if any vector is a zero vector + +### func \(\*Vector\) Assign + +```go +func (v1 *Vector) Assign(v2 *Vector) *Vector +``` + +Assigns the values of given vector to the vector\. Similar to copy\, but no new vector is create + +### func \(\*Vector\) Component + +```go +func (v *Vector) Component(axis *Vector) (parallel, perpendicular *Vector) +``` + +Give the component of the given vector parallel and perpendicular to the axis + +### func \(\*Vector\) Copy + +```go +func (v *Vector) Copy() *Vector +``` + +Gets a copy of the vector + +### func \(\*Vector\) Cross + +```go +func (v *Vector) Cross(v2 *Vector) *Vector +``` + +Calculates the cross product with another vector + +### func \(\*Vector\) Dist + +```go +func (v *Vector) Dist(v2 *Vector) float32 +``` + +Calculates the Euclidean distance between two points \(considering a point as a vector object\) + +### func \(\*Vector\) Dot + +```go +func (v *Vector) Dot(v2 *Vector) float32 +``` + +Calculates the dot product with another vector + +### func \(\*Vector\) Equal + +```go +func (v *Vector) Equal(v2 *Vector, tolerance ...float32) bool +``` + +Checks whether two vectors are equal\. optional tolerence value can be passed as a parameter to check for equality within a tolerance\. abs\(v\.x \- v2\.x\) \< tolerance && abs\(v\.y \- v2\.y\) \< tolerance && abs\(v\.z \- v2\.z\) \< tolerance + +### func \(\*Vector\) Heading + +```go +func (v *Vector) Heading() (theta, phi float32) +``` + +Calculate the azimuth and zenith angles\. https://en.wikipedia.org/wiki/Spherical_coordinate_system + +### func \(\*Vector\) Mag + +```go +func (v *Vector) Mag() float32 +``` + +Calculates the magnitude \(length\) of the vector and returns the result as a float this is simply the equation sqrt\(x\*x \+ y\*y \+ z\*z\) + +### func \(\*Vector\) MagSq + +```go +func (v *Vector) MagSq() float32 +``` + +Calculates the squared magnitude of the vector and returns the result as a float this is simply the equation \(x\*x \+ y\*y \+ z\*z\) + +### func \(\*Vector\) Mult + +```go +func (v *Vector) Mult(scalar float32) *Vector +``` + +Multiplies the vector by a scalar\. Modify \+ Returns self + +### func \(\*Vector\) Normalize + +```go +func (v *Vector) Normalize() *Vector +``` + +Normalize the vector to length 1 \(make it a unit vector\)\. Modify \+ Returns self + +### func \(\*Vector\) ReflectThroughPlane + +```go +func (v *Vector) ReflectThroughPlane(normal *Vector) *Vector +``` + +Gives the reflection of vector from the given plane\(normal vector\) + +### func \(\*Vector\) Resize + +```go +func (v *Vector) Resize(mag float32) *Vector +``` + +Set the magnitude of the vector to the given value\. Modify \+ Returns self + +### func \(\*Vector\) RotateAlongAxis + +```go +func (v *Vector) RotateAlongAxis(axis *Vector, angle float32) *Vector +``` + +Rotates the given vector around the axis by given angle https://math.stackexchange.com/questions/511370/how-to-rotate-one-vector-about-another + +### func \(\*Vector\) SetHeading + +```go +func (v *Vector) SetHeading(thetha, phi float32) *Vector +``` + +Rotate the vector to a specific angle\. magnitude remains the same\. Modify \+ Returns self https://en.wikipedia.org/wiki/Spherical_coordinate_system + +### func \(\*Vector\) String + +```go +func (v *Vector) String() string +``` + +String representation of vector + +### func \(\*Vector\) Sub + +```go +func (v *Vector) Sub(v2 *Vector) *Vector +``` + +subtract a vector from the current vector\. Modify \+ Returns self + +Calculates the dot product of two vectors + +Generated by [gomarkdoc](https://github.com/princjef/gomarkdoc) diff --git a/vector/vector.go b/vector/vector.go new file mode 100644 index 0000000..15abd02 --- /dev/null +++ b/vector/vector.go @@ -0,0 +1,347 @@ +// Package vector provides a simple 3D vector class. +package vector + +import ( + "fmt" + "math" + "math/rand" + "time" +) + +type Vector struct { + X, Y, Z float32 +} + +func init() { + rand.Seed(time.Now().UnixNano()) +} + +// Creates a new 3D vector. +// Three dimensional Euclidean vector. +func New(x, y, z float32) *Vector { + return &Vector{x, y, z} +} + +func x() *Vector { + return &Vector{1, 0, 0} +} + +func y() *Vector { + return &Vector{0, 1, 0} +} + +func z() *Vector { + return &Vector{0, 0, 1} +} + +func zero() *Vector { + return &Vector{0, 0, 0} +} + +// Make a new 3D vector from a pair of azimuth and zenith angles. +// https://en.wikipedia.org/wiki/Spherical_coordinate_system +func FromAngles(thetha, phi float32, length ...float32) *Vector { + var l float64 = 1 + if len(length) >= 1 { + l = float64(length[0]) + } + cosPhi := math.Cos(float64(phi)) + sinPhi := math.Sin(float64(phi)) + cosTheta := math.Cos(float64(thetha)) + sinTheta := math.Sin(float64(thetha)) + return &Vector{ + X: float32(l * cosTheta * sinPhi), + Y: float32(l * sinTheta * sinPhi), + Z: float32(l * cosPhi), + } +} + +// Makes a random 3D vector of given lenght (default 1) +func Random(length ...float32) *Vector { + var l float32 = 1 + if len(length) >= 1 { + l = length[0] + } + thetha := rand.Float32() * 2 * math.Pi + phi := rand.Float32() * 2 * math.Pi + return FromAngles(thetha, phi, l) +} + +// String representation of vector +func (v *Vector) String() string { + return fmt.Sprintf("{X: %v, Y: %v, Z: %v}", v.X, v.Y, v.Z) +} + +// Checks whether two vectors are equal. +// optional tolerence value can be passed as a parameter to check for equality +// within a tolerance. +// abs(v.x - v2.x) < tolerance && abs(v.y - v2.y) < tolerance && abs(v.z - v2.z) < tolerance +func (v *Vector) Equal(v2 *Vector, tolerance ...float32) bool { + var t float32 = 1e-7 + if len(tolerance) >= 1 { + t += tolerance[0] + } + if diff := float32(math.Abs(float64(v.X - v2.X))); diff > t { + return false + } + if math.Abs(float64(v.Y-v2.Y)) > float64(t) { + return false + } + if math.Abs(float64(v.Z-v2.Z)) > float64(t) { + return false + } + return true +} + +func isZero(v *Vector) bool { + return v.X == 0 && v.Y == 0 && v.Z == 0 +} + +// Gets a copy of the vector +func (v *Vector) Copy() *Vector { + return &Vector{v.X, v.Y, v.Z} +} + +// Gets a copy of the vector +func Copy(v *Vector) *Vector { + return &Vector{v.X, v.Y, v.Z} +} + +// Assigns the values of given vector to the vector. +// Similar to copy, but no new vector is create +func (v1 *Vector) Assign(v2 *Vector) *Vector { + v1.X = v2.X + v1.Y = v2.Y + v1.Z = v2.Z + return v1 +} + +// Calculates the magnitude (length) of the vector and returns the result as a float +// this is simply the equation sqrt(x*x + y*y + z*z) +func (v *Vector) Mag() float32 { + return float32(math.Sqrt(float64(v.X*v.X + v.Y*v.Y + v.Z*v.Z))) +} + +// Calculates the squared magnitude of the vector and returns the result as a float +// this is simply the equation (x*x + y*y + z*z) +func (v *Vector) MagSq() float32 { + return v.X*v.X + v.Y*v.Y + v.Z*v.Z +} + +// Normalize the vector to length 1 (make it a unit vector). +// Modify + Returns self +func (v *Vector) Normalize() *Vector { + mag := v.Mag() + if mag != 0 { + v.X /= mag + v.Y /= mag + v.Z /= mag + } + return v +} + +// Gives a unit vector in dirction of the vector +func Unit(v *Vector) *Vector { + m := v.Mag() + if m == 0 { + return &Vector{0, 0, 0} + } + return &Vector{v.X / m, v.Y / m, v.Z / m} +} + +// Set the magnitude of the vector to the given value. +// Modify + Returns self +func (v *Vector) Resize(mag float32) *Vector { + v.Normalize() + v.Mult(mag) + return v +} + +// add a vector to the current vector. +// Modify + Returns self +func (v *Vector) Add(v2 *Vector) *Vector { + v.X += v2.X + v.Y += v2.Y + v.Z += v2.Z + return v +} + +// returns the sum of two vectors +func Add(v1, v2 *Vector) *Vector { + return &Vector{v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z} +} + +// subtract a vector from the current vector. +// Modify + Returns self +func (v *Vector) Sub(v2 *Vector) *Vector { + v.X -= v2.X + v.Y -= v2.Y + v.Z -= v2.Z + return v +} + +// returns the difference of two vectors +func Sub(v1, v2 *Vector) *Vector { + return &Vector{v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z} +} + +// Multiplies the vector by a scalar. +// Modify + Returns self +func (v *Vector) Mult(scalar float32) *Vector { + v.X *= scalar + v.Y *= scalar + v.Z *= scalar + return v +} + +// Calculates the Euclidean distance between two points +// (considering a point as a vector object) +func (v *Vector) Dist(v2 *Vector) float32 { + return Dist(v, v2) +} + +// Calculates the Euclidean distance between two points +// (considering a point as a vector object) +func Dist(v1, v2 *Vector) float32 { + return Sub(v1, v2).Mag() +} + +// Calculates the dot product with another vector +func (v *Vector) Dot(v2 *Vector) float32 { + return Dot(v, v2) +} + +// Calculates the dot product of two vectors +func Dot(v1, v2 *Vector) float32 { + return v1.X*v2.X + v1.Y*v2.Y + v1.Z*v2.Z +} + +// Calculates the cross product with another vector +func (v *Vector) Cross(v2 *Vector) *Vector { + return Cross(v, v2) +} + +// Calculates the cross product of two vectors +func Cross(v1, v2 *Vector) *Vector { + return &Vector{v1.Y*v2.Z - v1.Z*v2.Y, v1.Z*v2.X - v1.X*v2.Z, v1.X*v2.Y - v1.Y*v2.X} +} + +// Calculates and returns the angle with another vector +// Returns NaN if any vector is a zero vector +func (v *Vector) Angle(v2 *Vector) float32 { + return Angle(v, v2) +} + +// Calculates and returns the angle between two vectors. +// Returns NaN if any vector is a zero vector +func Angle(v1, v2 *Vector) float32 { + m1 := v1.Mag() + m2 := v2.Mag() + if m1 == 0 || m2 == 0 { + return float32(math.NaN()) + } + return float32(math.Acos(float64(Dot(v1, v2) / (m1 * m2)))) +} + +// Calculate the azimuth and zenith angles. +// https://en.wikipedia.org/wiki/Spherical_coordinate_system +func (v *Vector) Heading() (theta, phi float32) { + m := v.Mag() + theta = float32(math.Atan2(float64(v.Y), float64(v.X))) + if m == 0 { + phi = float32(math.NaN()) + return + } + phi = float32(math.Acos(float64(v.Z / m))) + return +} + +// Rotate the vector to a specific angle. magnitude remains the same. +// Modify + Returns self +// https://en.wikipedia.org/wiki/Spherical_coordinate_system +func (v *Vector) SetHeading(thetha, phi float32) *Vector { + l := float64(v.Mag()) + cosPhi := math.Cos(float64(phi)) + sinPhi := math.Sin(float64(phi)) + cosTheta := math.Cos(float64(thetha)) + sinTheta := math.Sin(float64(thetha)) + v.X = float32(l * cosTheta * sinPhi) + v.Y = float32(l * sinTheta * sinPhi) + v.Z = float32(l * cosPhi) + return v +} + +func rotateOnPlane(v, normal *Vector, angle float32) *Vector { + // v dot n = 0 + sin := float32(math.Sin(float64(angle))) + cos := float32(math.Cos(float64(angle))) + nv := Cross(Unit(normal), v) + nv.Mult(sin) + V := v.Copy().Mult(cos) + V.Add(nv) + return V +} + +func (v *Vector) rotateOnPlane(normal *Vector, angle float32) *Vector { + v.Assign(rotateOnPlane(v, normal, angle)) + return v +} + +// Give the component of the given vector parallel and perpendicular to the axis +func (v *Vector) Component(axis *Vector) (parallel, perpendicular *Vector) { + if isZero(axis) { + return zero(), zero() + } + parallel = axis.Copy().Normalize() + parallel.Mult(Dot(v, parallel)) + perpendicular = Sub(v, parallel) + return +} + +// Rotates the given vector around the axis by given angle +func RotateAlongAxis(v, axis *Vector, angle float32) *Vector { + if isZero(axis) { + return v + } + parallel, perpendicular := v.Component(axis) + perpendicular.rotateOnPlane(axis, angle) + parallel.Add(perpendicular) + return parallel +} + +// Rotates the given vector around the axis by given angle +// https://math.stackexchange.com/questions/511370/how-to-rotate-one-vector-about-another +func (v *Vector) RotateAlongAxis(axis *Vector, angle float32) *Vector { + v.Assign(RotateAlongAxis(v, axis, angle)) + return v +} + +// Gives the reflection of vector from the given plane(normal vector) +func ReflectThroughPlane(v, normal *Vector) *Vector { + if isZero(normal) { + return v + } + n := normal.Copy().Normalize() + return Sub(v, n.Mult(2*Dot(v, n))) +} + +// Gives the reflection of vector from the given plane(normal vector) +func (v *Vector) ReflectThroughPlane(normal *Vector) *Vector { + v.Assign(ReflectThroughPlane(v, normal)) + return v +} + +func lerpf(a, b, t float32) float32 { + return a + (b-a)*t +} + +// Linear interpolate the vector to another vector +func Lerp(v1, v2 *Vector, t float32) *Vector { + return &Vector{lerpf(v1.X, v2.X, t), lerpf(v1.Y, v2.Y, t), lerpf(v1.Z, v2.Z, t)} +} + +// Linear interpolate the vector to another vector. i/n = t +func Lerp2(v1, v2 *Vector, n, i int) *Vector { + r := float32(i) / float32(n) + return Lerp(v1, v2, r) +} diff --git a/vector/vector_test.go b/vector/vector_test.go new file mode 100644 index 0000000..c71b6f7 --- /dev/null +++ b/vector/vector_test.go @@ -0,0 +1,642 @@ +package vector + +import ( + "math" + "math/rand" + "testing" + + "github.com/google/go-cmp/cmp" +) + +func getComparer(tolerance float64) cmp.Option { + return cmp.Comparer(func(x, y float32) bool { + diff := math.Abs(float64(x - y)) + return diff <= tolerance + }) +} + +func TestFromAngles(t *testing.T) { + P4 := float32(math.Pi / 4) + P2 := float32(math.Pi / 2) + tests := []struct { + theta, phi float32 + length []float32 + want *Vector + }{ + {P4, 0.9553166, []float32{}, New(1, 1, 1).Normalize()}, + {P4, 0.9553166, []float32{2}, New(1, 1, 1).Normalize().Mult(2)}, + {rand.Float32() * 4 * P2, 0, []float32{}, New(0, 0, 1)}, + {rand.Float32() * 4 * P2, math.Pi, []float32{}, New(0, 0, -1)}, + // + {0 * P2, P4, []float32{}, New(1, 0, 1).Normalize()}, + {1 * P2, P4, []float32{}, New(0, 1, 1).Normalize()}, + {2 * P2, P4, []float32{}, New(-1, 0, 1).Normalize()}, + {3 * P2, P4, []float32{}, New(0, -1, 1).Normalize()}, + // + {0 * P2, 3 * P4, []float32{}, New(1, 0, -1).Normalize()}, + {1 * P2, 3 * P4, []float32{}, New(0, 1, -1).Normalize()}, + {2 * P2, 3 * P4, []float32{}, New(-1, 0, -1).Normalize()}, + {3 * P2, 3 * P4, []float32{}, New(0, -1, -1).Normalize()}, + // + {1 * P4, P2, []float32{}, New(1, 1, 0).Normalize()}, + {3 * P4, P2, []float32{}, New(-1, 1, 0).Normalize()}, + {5 * P4, P2, []float32{}, New(-1, -1, 0).Normalize()}, + {7 * P4, P2, []float32{}, New(1, -1, 0).Normalize()}, + // + {1 * P4, 3 * P2, []float32{}, New(-1, -1, 0).Normalize()}, + {3 * P4, 3 * P2, []float32{}, New(1, -1, 0).Normalize()}, + {5 * P4, 3 * P2, []float32{}, New(1, 1, 0).Normalize()}, + {7 * P4, 3 * P2, []float32{}, New(-1, 1, 0).Normalize()}, + // + {0 * P2, P2, []float32{}, New(1, 0, 0)}, + {1 * P2, P2, []float32{}, New(0, 1, 0)}, + {2 * P2, P2, []float32{}, New(-1, 0, 0)}, + {3 * P2, P2, []float32{}, New(0, -1, 0)}, + // + {1 * P4, P4, []float32{}, New(1, 1, 1.4142131).Normalize()}, + } + opt := getComparer(.00001) + for _, test := range tests { + for i := 0; i < 4; i += 1 { + + if v := FromAngles(test.theta+4*P2*float32(i), test.phi+4*P2*float32(i), test.length...); !cmp.Equal(v, test.want, opt) { + t.Errorf("FromAngles(%v, %v, %v) = %v, want %v", test.theta, test.phi, test.length, v, test.want) + } + } + } +} + +func TestRandom(t *testing.T) { + opt := getComparer(.00001) + // Mag = 1 + for i := 0; i < 100; i += 1 { + v := Random() + x := v.Copy() + X := Unit(v) + if !cmp.Equal(x, X, opt) { + t.Errorf("got %v, want %v", x, X) + } + } + // Mag = i + for i := float32(1); i < 100; i += 1 { + v := Random(i) + x := v.Copy() + X := v.Copy().Resize(i) + if !cmp.Equal(x, X, opt) { + t.Errorf("got %v, want %v", x, X) + } + } +} + +func TestString(t *testing.T) { + tests := []struct { + v *Vector + want string + }{ + {zero(), "{X: 0, Y: 0, Z: 0}"}, + {New(1.232, 0, 64.0), "{X: 1.232, Y: 0, Z: 64}"}, + } + for _, test := range tests { + if got := test.v.String(); got != test.want { + t.Errorf("%v.String() = %v, want %v", test.v, got, test.want) + } + } +} + +func TestEqual(t *testing.T) { + tests := []struct { + a, b *Vector + tolerance []float32 + want bool + }{ + {New(1, 2, 3), New(1, 2, 3), []float32{}, true}, + {New(1, 2, 3), New(1, 2.1, 3), []float32{}, false}, + {New(1.1, 2.3, 3.2), New(1.1, 2.3, 3.2), []float32{0.1}, true}, + {New(1.1, 2.4, 3.2), New(1.0, 2.5, 3.2), []float32{0.1}, true}, + {New(1.1, 2.4, 3.2), New(1.0, 2.5, 3.5), []float32{0.1}, false}, + {New(1.4, 2.2, 3.2), New(1.0, 2.21, 3.4), []float32{0.01}, false}, + {New(1.41, 2.2, 3.2), New(1.4, 2.22, 3.19), []float32{0.01}, false}, + {New(1.41, 2.2, 3.2), New(1.4, 2.20, 3.19), []float32{0.01}, true}, + } + for _, test := range tests { + if got := test.a.Equal(test.b, test.tolerance...); got != test.want { + t.Errorf("%v.Equal(%v, %v...) = %v, want %v", test.a, test.b, test.tolerance, got, test.want) + } + } +} + +func TestVCopy(t *testing.T) { + tests := []struct { + v1 *Vector + want *Vector + }{ + {New(1, 2, 3), New(1, 2, 3)}, + {New(2, 5, 8), New(2, 5, 8)}, + {New(12, 19, 6), New(12, 19, 6)}, + } + for _, test := range tests { + copy := test.v1.Copy() + if !cmp.Equal(copy, test.want) { + t.Errorf("%v.Copy() = %v, want %v", test.v1, copy, test.want) + } + if copy == test.v1 { + t.Errorf("%v.Copy() = %v, want a copy", test.v1, copy) + } + copy.X = 32 + if cmp.Equal(copy, test.v1) { + t.Errorf("changing copy also changed original %v", test.v1) + } + test.v1.Y = 43 + if cmp.Equal(test.v1, copy) { + t.Errorf("changing original also changed copy %v", copy) + } + } +} + +func TestCopyV(t *testing.T) { + tests := []struct { + v1 *Vector + want *Vector + }{ + {New(1, 2, 3), New(1, 2, 3)}, + {New(2, 5, 8), New(2, 5, 8)}, + {New(12, 19, 6), New(12, 19, 6)}, + } + for _, test := range tests { + copy := Copy(test.v1) + if !cmp.Equal(copy, test.want) { + t.Errorf("Copy(%v) = %v, want %v", test.v1, copy, test.want) + } + if copy == test.v1 { + t.Errorf("Copy(%v) = %v, want a copy", test.v1, copy) + } + copy.X = 32 + if cmp.Equal(copy, test.v1) { + t.Errorf("changing copy also changed original %v", test.v1) + } + test.v1.Y = 43 + if cmp.Equal(test.v1, copy) { + t.Errorf("changing original also changed copy %v", copy) + } + } +} + +func TestAssign(t *testing.T) { + tests := []struct { + want *Vector + }{ + {New(1, 2, 3)}, + {New(2, 5, 8)}, + {New(12, 19, 6)}, + } + for _, test := range tests { + v := zero() + v.Assign(test.want) + if !cmp.Equal(v, test.want) { + t.Errorf("%v.Assign(%v) = %v, want %v", v, test.want, v, test.want) + } + if v == test.want { + t.Errorf("%v.Assign(%v) = %v, want a copy", v, test.want, v) + } + v.X = 32 + if cmp.Equal(v, test.want) { + t.Errorf("changing copy also changed original %v", test.want) + } + test.want.Y = 43 + if cmp.Equal(test.want, v) { + t.Errorf("changing original also changed copy %v", v) + } + } +} + +func TestMag(t *testing.T) { + tests := []struct { + v *Vector + want float32 + }{ + {New(0.26726, 0.53452, 0.80178), 1}, + {New(1, 2, 3), float32(math.Sqrt(14))}, + {New(3, 4, 12), 13}, + {New(2, 5, 8), float32(math.Sqrt(93))}, + {New(12, 19, 6), float32(math.Sqrt(541))}, + {New(312.1511574, 2259.344174, 321.9829745), 2303.4208207624088}, + } + opt := getComparer(.00001) + for _, test := range tests { + if got := test.v.Mag(); !cmp.Equal(got, test.want, opt) { + t.Errorf("%v.Mag() = %v, want %v", test.v, got, test.want) + } + } +} + +func TestMagSq(t *testing.T) { + tests := []struct { + v *Vector + want float32 + }{ + {New(0.26726, 0.53452, 0.80178), 1}, + {New(1, 2, 3), 14}, + {New(3, 4, 12), 169}, + {New(2, 5, 8), 93}, + {New(12, 19, 6), 541}, + {New(12.15, 59.34, 21.92), 4149.3445}, + } + opt := getComparer(.00001) + for _, test := range tests { + if got := test.v.MagSq(); !cmp.Equal(got, test.want, opt) { + t.Errorf("%v.MagSq() = %v, want %v", test.v, got, test.want) + } + } +} + +func TestNormalizeUnit(t *testing.T) { + tests := []struct { + v *Vector + want *Vector + }{ + {zero(), zero()}, + {New(1, 2, 3), New(0.26726, 0.53452, 0.80178)}, + {New(2, 5, 8), New(float32(2/math.Sqrt(93)), float32(5/math.Sqrt(93)), float32(8/math.Sqrt(93)))}, + {New(3, 4, 12), New(3/13.0, 4/13.0, 12/13.0)}, + } + opt := getComparer(.00001) + // Unit + for _, test := range tests { + if got := Unit(test.v); !cmp.Equal(got, test.want, opt) { + t.Errorf("Unit(%v) = %v, want %v", test.v, got, test.want) + } + } + // Normalize + for _, test := range tests { + if test.v.Normalize(); !cmp.Equal(test.v, test.want, opt) { + t.Errorf("%v.Normalize() = %v, want %v", test.v, test.v, test.want) + } + } +} + +func TestResize(t *testing.T) { + tests := []struct { + v *Vector + fl float32 + want *Vector + }{ + {New(3, 4, 12), 26, New(6, 8, 24)}, + {New(2, 5, 8), 3, New(0.622171, 1.555427, 2.48868)}, + } + opt := getComparer(.00001) + for _, test := range tests { + if test.v.Resize(test.fl); !cmp.Equal(test.v, test.want, opt) { + t.Errorf("%v.Resize(%v) = %v, want %v", test.v, test.fl, test.v, test.want) + } + } +} + +func TestAdd(t *testing.T) { + tests := []struct { + v1, v2 *Vector + want *Vector + }{ + {New(1, 2, 3), New(2, 3, 4), New(3, 5, 7)}, + {New(2, 5, 8), New(12, 19, 6), New(14, 24, 14)}, + {New(8.5, 2, 9.5), New(17.8, 96.0, 3.90), New(26.3, 98.0, 13.4)}, + {New(-68.8, 7.47, 15.9), New(54.5, 48.2, -6.50), New(-14.3, 55.67, 9.4)}, + } + opt := getComparer(.00001) + // Add(v1,v2) + for _, test := range tests { + if got := Add(test.v1, test.v2); !cmp.Equal(got, test.want, opt) { + t.Errorf("Add(%v, %v) = %v, want %v", test.v1, test.v2, got, test.want) + } + } + // v1.Add(v2) + for _, test := range tests { + if test.v1.Add(test.v2); !cmp.Equal(test.v1, test.want, opt) { + t.Errorf("%v.Add(%v) = %v, want %v", test.v1, test.v2, test.v1, test.want) + } + } +} + +func TestSub(t *testing.T) { + tests := []struct { + v1, v2 *Vector + want *Vector + }{ + {New(1, 2, 3), New(2, 3, 4), New(-1, -1, -1)}, + {New(2, 5, 8), New(12, 19, 6), New(-10, -14, 2)}, + {New(3, 4, 12), New(12, 19, 6), New(-9, -15, 6)}, + {New(3, 4, 12), New(-9, -15, 6), New(12, 19, 6)}, + {New(12, 19, 6), New(3, 4, 12), New(9, 15, -6)}, + } + opt := getComparer(.00001) + // Sub(v1,v2) + for _, test := range tests { + if got := Sub(test.v1, test.v2); !cmp.Equal(got, test.want, opt) { + t.Errorf("Sub(%v, %v) = %v, want %v", test.v1, test.v2, got, test.want) + } + } + // v1.Sub(v2) + for _, test := range tests { + if test.v1.Sub(test.v2); !cmp.Equal(test.v1, test.want, opt) { + t.Errorf("%v.Sub(%v) = %v, want %v", test.v1, test.v2, test.v1, test.want) + } + } +} + +func TestMult(t *testing.T) { + tests := []struct { + v1 *Vector + fl float32 + want *Vector + }{ + {New(1, 2, 3), 2, New(2, 4, 6)}, + {New(2, 5, 8), 12, New(24, 60, 96)}, + {New(3, 4, 12), -2, New(-6, -8, -24)}, + {New(12, 19, 6), 0.5, New(6, 9.5, 3)}, + } + opt := getComparer(.00001) + for _, test := range tests { + if test.v1.Mult(test.fl); !cmp.Equal(test.v1, test.want, opt) { + t.Errorf("%v.Mul(%v) = %v, want %v", test.v1, test.fl, test.v1, test.want) + } + } +} + +func TestDist(t *testing.T) { + tests := []struct { + v1, v2 *Vector + want float32 + }{ + {zero(), zero(), 0}, + {New(1, 2, 3), New(2, 3, 4), 1.732050}, + {New(2, 5, 8), New(12, 19, 6), 17.320508}, + } + opt := getComparer(.00001) + // Dist(v1,v2) + for _, test := range tests { + if got := Dist(test.v1, test.v2); !cmp.Equal(got, test.want, opt) { + t.Errorf("Dist(%v, %v) = %v, want %v", test.v1, test.v2, got, test.want) + } + } + // v1.Dist(v2) + for _, test := range tests { + if got := test.v1.Dist(test.v2); !cmp.Equal(got, test.want, opt) { + t.Errorf("%v.Dist(%v) = %v, want %v", test.v1, test.v2, got, test.want) + } + } +} + +func TestDot(t *testing.T) { + tests := []struct { + v1, v2 *Vector + want float32 + }{ + {New(1, 1, 1), New(1, 1, 1), 3}, + {New(2, 5, 8), New(12, 19, 6), 167}, + {New(1, 1, 1), New(2, -2, 0), 0}, + } + opt := getComparer(.00001) + // Dot(v1,v2) + for _, test := range tests { + if got := Dot(test.v1, test.v2); !cmp.Equal(got, test.want, opt) { + t.Errorf("Dot(%v, %v) = %v, want %v", test.v1, test.v2, got, test.want) + } + } + // v1.Dot(v2) + for _, test := range tests { + if got := test.v1.Dot(test.v2); !cmp.Equal(got, test.want, opt) { + t.Errorf("%v.Dot(%v) = %v, want %v", test.v1, test.v2, got, test.want) + } + } +} + +func TestCross(t *testing.T) { + tests := []struct { + v1 *Vector + v2 *Vector + want *Vector + }{ + {New(1, 1, 1), New(1, 1, 1), zero()}, + {New(21, 31.2, 12.1), New(4.0, 2.1, 15), New(442.59, -266.6, -80.7)}, + {New(-18, 12.4, -6), New(2.2, -12, 1.2), New(-57.12, 8.4, 188.72)}, + {New(12, 19, 0), New(6, 9, 0), New(0, 0, -6)}, + } + opt := getComparer(.00001) + // Cross(v1,v2) + for _, test := range tests { + if got := Cross(test.v1, test.v2); !cmp.Equal(got, test.want, opt) { + t.Errorf("Cross(%v, %v) = %v, want %v", test.v1, test.v2, got, test.want) + } + } + // v1.Cross(v2) + for _, test := range tests { + if got := test.v1.Cross(test.v2); !cmp.Equal(got, test.want, opt) { + t.Errorf("%v.Cross(%v) = %v, want %v", test.v1, test.v2, got, test.want) + } + } +} + +func TestAngle(t *testing.T) { + tests := []struct { + v1, v2 *Vector + want float32 + }{ + {New(1, 0, 0), New(0, 1, 0), math.Pi / 2}, + {New(8, 16, 7), New(19, 3, 8), 0.8766778}, + {New(3.2, 2.2, 2.8), New(3.3, 5, 4.2), 0.3135}, + } + opt := getComparer(.00001) + // Angle(v1,v2) + for _, test := range tests { + if got := Angle(test.v1, test.v2); !cmp.Equal(got, test.want, opt) { + t.Errorf("Angle(%v, %v) = %v, want %v", test.v1, test.v2, got, test.want) + } + } + v := zero() + v2 := Random() + if got := Angle(v, v2); !math.IsNaN(float64(got)) { + t.Errorf("Angle(%v, %v) = %v, want %v", v, v2, got, math.NaN()) + } + // v1.Angle(v2) + for _, test := range tests { + if got := test.v1.Angle(test.v2); !cmp.Equal(got, test.want, opt) { + t.Errorf("%v.Angle(%v) = %v, want %v", test.v1, test.v2, got, test.want) + } + } + v = zero() + v2 = Random() + if got := v.Angle(v2); !math.IsNaN(float64(got)) { + t.Errorf("%v.Angle(%v) = %v, want %v", v, v2, got, math.NaN()) + } +} + +func TestHeading(t *testing.T) { + tests := []struct { + v1 *Vector + theta, phi float32 + }{ + {New(1, 0, 0), 0, math.Pi / 2}, + {New(0, 1, 0), math.Pi / 2, math.Pi / 2}, + {New(0, 0, 1), 0, 0}, + {New(1, 1, 1), math.Pi / 4, 0.9553166}, + {New(1, -1, 1), -math.Pi / 4, 0.9553166}, + {New(1, 1, -1), math.Pi / 4, math.Pi - 0.9553166}, + } + opt := getComparer(.00001) + for _, test := range tests { + th, p := test.v1.Heading() + if !cmp.Equal(th, test.theta, opt) { + t.Errorf("%v.Heading()(thetha) = %v, want %v", test.v1, th, test.theta) + } + if !cmp.Equal(p, test.phi, opt) { + t.Errorf("%v.Heading()(phi) = %v, want %v", test.v1, p, test.phi) + } + } + v := zero() + thetha := float32(0) + phi := float32(math.NaN()) + th, p := v.Heading() + if math.IsNaN(float64(phi)) && math.IsNaN(float64(p)) { + + } else { + t.Errorf("%v.Heading()(phi) = %v, want %v", v, p, phi) + } + if !cmp.Equal(th, thetha) { + t.Errorf("%v.Heading()(thetha) = %v, want %v", v, th, thetha) + } +} + +func TestSetHeading(t *testing.T) { + test := []struct { + v1 *Vector + theta, phi float32 + }{ + {New(1, 0, 0), 0, math.Pi / 2}, + {New(0, 1, 0), math.Pi / 2, math.Pi / 2}, + {New(0, 0, 1), 0, 0}, + {New(1, 1, 1), math.Pi / 4, 0.9553166}, + {New(1, -1, 1), -math.Pi / 4, 0.9553166}, + {New(1, 1, -1), math.Pi / 4, math.Pi - 0.9553166}, + } + opt := getComparer(.00001) + for _, test := range test { + for i := 0; i < 5; i += 1 { + m := rand.Float32() * 100 + v := Random(m) + v.SetHeading(test.theta, test.phi) + test.v1.Resize(m) + if !cmp.Equal(v, test.v1, opt) { + t.Errorf("%v.SetHeading(%v, %v) = %v, want %v", v, test.theta, test.phi, v, test.v1) + } + } + } +} + +func TestComponent(t *testing.T) { + tests := []struct { + v, axis *Vector + pll, pr *Vector + }{ + {New(1, 0, 0), New(1, 0, 0), New(1, 0, 0), zero()}, + {New(1, 0, 0), New(0, 1, 0), zero(), New(1, 0, 0)}, + {New(2, 1, 2), zero(), zero(), zero()}, + } + opt := getComparer(.00001) + for _, test := range tests { + pl, pr := test.v.Component(test.axis) + if !cmp.Equal(pr, test.pr, opt) { + t.Errorf("%v.Component(%v)(perpendicular) = %v, want %v", test.v, test.axis, pr, test.pr) + } + if !cmp.Equal(pl, test.pll, opt) { + t.Errorf("%v.Component(%v)(paraller) = %v, want %v", test.v, test.axis, pl, test.pll) + } + } +} + +func TestRotatateAlongAxis(t *testing.T) { + tests := []struct { + v, axis *Vector + theta float32 + want *Vector + }{ + {x(), x(), 0, x()}, + {x(), x(), math.Pi / 2, x()}, + {x(), x(), math.Pi, x()}, + {x(), z(), math.Pi / 2, y()}, + {x(), z().Mult(-1), math.Pi / 2, y().Mult(-1)}, + {x(), z(), math.Pi, x().Mult(-1)}, + {x(), z().Mult(-1), math.Pi, x().Mult(-1)}, + {x(), z(), math.Pi / 4, New(1, 1, 0).Normalize()}, + {x(), y(), math.Pi / 2, z().Mult(-1)}, + {x(), y(), math.Pi, x().Mult(-1)}, + {x(), y(), math.Pi / 4, New(1, 0, -1).Normalize()}, + {New(1, 1, 1), New(1, 1, 1), math.Pi / 4, New(1, 1, 1)}, + {New(1, 1, 1), x(), math.Pi / 4, New(1, 0, math.Sqrt2)}, + {New(1, 1, 1), y(), math.Pi / 4, New(math.Sqrt2, 1, 0)}, + {New(1, 1, 1), z(), math.Pi / 4, New(0, math.Sqrt2, 1)}, + {New(1, 1, 1), New(-1, 1, 0), -0.9553166, New(0, 0, float32(math.Sqrt(3)))}, + {New(1, 1, 1), zero(), 0.9553166, New(1, 1, 1)}, + {zero(), Random(), 0.9553166, zero()}, + } + opt := getComparer(.00001) + // RotateAlongAxis(v1,ax,th) + for _, test := range tests { + v := RotateAlongAxis(test.v, test.axis, test.theta) + if !cmp.Equal(v, test.want, opt) { + t.Errorf("RotateAlongAxis(%v, %v, %v) = %v, want %v", test.v, test.axis, test.theta, v, test.want) + } + } + // v1.RotateAlongAxis(ax,th) + for _, test := range tests { + test.v.RotateAlongAxis(test.axis, test.theta) + if !cmp.Equal(test.v, test.want, opt) { + t.Errorf("%v.RotateAlongAxis(%v, %v) = %v, want %v", test.v, test.axis, test.theta, test.v, test.want) + } + } +} + +func TestReflectThroughPlane(t *testing.T) { + tests := []struct { + v, normal *Vector + want *Vector + }{ + {New(1, 1, 1), New(0, 0, 1), New(1, 1, -1)}, + {zero(), Random(), zero()}, + {New(1, 1, 1), zero(), New(1, 1, 1)}, + } + opt := getComparer(.00001) + // ReflectThroughPlane(v,n) + for _, test := range tests { + if got := ReflectThroughPlane(test.v, test.normal); !cmp.Equal(got, test.want, opt) { + t.Errorf("ReflectThroughPlane(%v, %v) = %v, want %v", test.v, test.normal, got, test.want) + } + } + // v.ReflectThroughPlane(n) + for _, test := range tests { + if got := test.v.ReflectThroughPlane(test.normal); !cmp.Equal(got, test.want, opt) { + t.Errorf("%v.ReflectThroughPlane(%v) = %v, want %v", test.v, test.normal, got, test.want) + } + } +} + +func TestLerp(t *testing.T) { + tests := []struct { + v1, v2 *Vector + n, i int + want *Vector + }{ + {zero(), New(1, 1, 1), 2, 0, zero()}, + {zero(), New(1, 1, 1), 2, 1, New(0.5, 0.5, 0.5)}, + {zero(), New(1, 1, 1), 2, 2, New(1, 1, 1)}, + } + opt := getComparer(.00001) + for _, test := range tests { + if got := Lerp(test.v1, test.v2, float32(test.i)/float32(test.n)); !cmp.Equal(got, test.want, opt) { + t.Errorf("Lerp(%v, %v, %v) = %v, want %v", test.v1, test.v2, float32(test.i)/float32(test.n), got, test.want) + } + } + for _, test := range tests { + if got := Lerp2(test.v1, test.v2, test.n, test.i); !cmp.Equal(got, test.want, opt) { + t.Errorf("Lerp(%v, %v, %v) = %v, want %v", test.v1, test.v2, test.i/test.n, got, test.want) + } + } +} diff --git a/vector2d-generic/README.md b/vector2d-generic/README.md new file mode 100644 index 0000000..7bef0b9 --- /dev/null +++ b/vector2d-generic/README.md @@ -0,0 +1,5 @@ +# vector2d-generic + +Package vector2d provides a simple 2D vector type on cartesian plane + +For documentation, see [pkg.go.dev](https://pkg.go.dev/github.com/vaibhav11s/gopkgs/vector2d-generic) diff --git a/vector2d-generic/doc.md b/vector2d-generic/doc.md index 13f28af..3bf6a6a 100644 --- a/vector2d-generic/doc.md +++ b/vector2d-generic/doc.md @@ -40,7 +40,7 @@ Package vector provides a simple 2D vector type on cartesian plane - [func Sub(v1, v2 Vector2D) Vector2D](#func-sub) - [func Unit(v Vector2D) Vector2D](#func-unit) -# type Vector2D +## type Vector2D ```go type Vector2D struct { @@ -48,7 +48,7 @@ type Vector2D struct { } ``` -## func New +### func New ```go func New(x, y interface{}) (Vector2D, error) @@ -56,7 +56,7 @@ func New(x, y interface{}) (Vector2D, error) Creates a new 2D vector\. Two dimensional Euclidean vector\. -## func FromAngle +### func FromAngle ```go func FromAngle(angle interface{}, length ...interface{}) (Vector2D, error) @@ -64,7 +64,7 @@ func FromAngle(angle interface{}, length ...interface{}) (Vector2D, error) Make a new 2D vector from an angle -## func Random +### func Random ```go func Random(length ...interface{}) (Vector2D, error) @@ -72,7 +72,7 @@ func Random(length ...interface{}) (Vector2D, error) Make a new 2D vector from a random angle of length 1 \(default\) or a given length -## func \(\*Vector2D\) Add +### func \(\*Vector2D\) Add ```go func (v *Vector2D) Add(v2 Vector2D) error @@ -80,7 +80,7 @@ func (v *Vector2D) Add(v2 Vector2D) error add a vector to the current vector -## func Add +### func Add ```go func Add(v1, v2 Vector2D) Vector2D @@ -88,7 +88,7 @@ func Add(v1, v2 Vector2D) Vector2D returns the sum of two vectors -## func \(Vector2D\) AngleBetween +### func \(Vector2D\) AngleBetween ```go func (v Vector2D) AngleBetween(v2 Vector2D) (float32, error) @@ -96,7 +96,7 @@ func (v Vector2D) AngleBetween(v2 Vector2D) (float32, error) Calculates and returns the angle with another vector Return error if the vectors any vector is zero vector -## func AngleBetween +### func AngleBetween ```go func AngleBetween(v1, v2 Vector2D) (float32, error) @@ -104,7 +104,7 @@ func AngleBetween(v1, v2 Vector2D) (float32, error) Calculates and returns the angle between two vectors\. Return error if the vectors any vector is zero vector -## func \(Vector2D\) Copy +### func \(Vector2D\) Copy ```go func (v Vector2D) Copy() Vector2D @@ -112,7 +112,7 @@ func (v Vector2D) Copy() Vector2D Gets a copy of the vector -## func Copy +### func Copy ```go func Copy(v Vector2D) Vector2D @@ -120,7 +120,7 @@ func Copy(v Vector2D) Vector2D Gets a copy of the vector -## func \(Vector2D\) Cross +### func \(Vector2D\) Cross ```go func (v Vector2D) Cross(v2 Vector2D) float32 @@ -128,7 +128,7 @@ func (v Vector2D) Cross(v2 Vector2D) float32 Calculates the cross product with another vector \~ give the value of the z axis component \(in 2D space\, the cross product is a vector perpendicular to the two input vectors\) -## func Cross +### func Cross ```go func Cross(v1, v2 Vector2D) float32 @@ -136,7 +136,7 @@ func Cross(v1, v2 Vector2D) float32 Calculates the cross product of two vectors \~ give the value of the z axis component \(in 2D space\, the cross product is a vector perpendicular to the two input vectors\) -## func \(Vector2D\) Dist +### func \(Vector2D\) Dist ```go func (v Vector2D) Dist(v2 Vector2D) float32 @@ -144,7 +144,7 @@ func (v Vector2D) Dist(v2 Vector2D) float32 Calculates the Euclidean distance between two points \(considering a point as a vector object\) -## func \(\*Vector2D\) Div +### func \(\*Vector2D\) Div ```go func (v *Vector2D) Div(scalar interface{}) error @@ -152,7 +152,7 @@ func (v *Vector2D) Div(scalar interface{}) error Divides the vector by a scalar -## func \(Vector2D\) Dot +### func \(Vector2D\) Dot ```go func (v Vector2D) Dot(v2 Vector2D) float32 @@ -160,7 +160,7 @@ func (v Vector2D) Dot(v2 Vector2D) float32 Calculates the dot product with another vector -## func Dot +### func Dot ```go func Dot(v1, v2 Vector2D) float32 @@ -168,7 +168,7 @@ func Dot(v1, v2 Vector2D) float32 Calculates the dot product of two vectors -## func \(Vector2D\) Equal +### func \(Vector2D\) Equal ```go func (v Vector2D) Equal(v2 Vector2D, tolerance ...interface{}) (bool, error) @@ -176,7 +176,7 @@ func (v Vector2D) Equal(v2 Vector2D, tolerance ...interface{}) (bool, error) Checks whether two vectors are equal\. optional tolerence value can be passed as a parameter to check for equality within a tolerance\, abs\(v\.x \- v2\.x\) \< tolerance and abs\(v\.y \- v2\.y\) \< tolerance -## func \(Vector2D\) Heading +### func \(Vector2D\) Heading ```go func (v Vector2D) Heading() float32 @@ -184,7 +184,7 @@ func (v Vector2D) Heading() float32 Calculate the angle of rotation for the vector -## func \(Vector2D\) Mag +### func \(Vector2D\) Mag ```go func (v Vector2D) Mag() float32 @@ -192,7 +192,7 @@ func (v Vector2D) Mag() float32 Calculates the magnitude \(length\) of the vector and returns the result as a float this is simply the equation sqrt\(x\*x \+ y\*y\) -## func \(Vector2D\) MagSq +### func \(Vector2D\) MagSq ```go func (v Vector2D) MagSq() float32 @@ -200,7 +200,7 @@ func (v Vector2D) MagSq() float32 Calculates the squared magnitude of the vector and returns the result as a float this is simply the equation \(x\*x \+ y\*y \+ z\*z\) -## func \(\*Vector2D\) Mult +### func \(\*Vector2D\) Mult ```go func (v *Vector2D) Mult(scalar interface{}) error @@ -208,7 +208,7 @@ func (v *Vector2D) Mult(scalar interface{}) error Multiplies the vector by a scalar -## func \(\*Vector2D\) Normalize +### func \(\*Vector2D\) Normalize ```go func (v *Vector2D) Normalize() @@ -216,7 +216,7 @@ func (v *Vector2D) Normalize() Normalize the vector to length 1 \(make it a unit vector\) -## func \(\*Vector2D\) Resize +### func \(\*Vector2D\) Resize ```go func (v *Vector2D) Resize(len interface{}) error @@ -224,7 +224,7 @@ func (v *Vector2D) Resize(len interface{}) error Set the length of this vector to the value used for the len parameter -## func \(\*Vector2D\) Rotate +### func \(\*Vector2D\) Rotate ```go func (v *Vector2D) Rotate(angle interface{}) error @@ -232,7 +232,7 @@ func (v *Vector2D) Rotate(angle interface{}) error rotate the vector in the direction of the angle -## func \(\*Vector2D\) SetHeading +### func \(\*Vector2D\) SetHeading ```go func (v *Vector2D) SetHeading(angle interface{}) error @@ -240,7 +240,7 @@ func (v *Vector2D) SetHeading(angle interface{}) error Rotate the vector to a specific angle\, magnitude remains the same -## func \(Vector2D\) String +### func \(Vector2D\) String ```go func (v Vector2D) String() string @@ -248,7 +248,7 @@ func (v Vector2D) String() string Returns a string representation of the vector -## func \(\*Vector2D\) Sub +### func \(\*Vector2D\) Sub ```go func (v *Vector2D) Sub(v2 Vector2D) error @@ -256,7 +256,7 @@ func (v *Vector2D) Sub(v2 Vector2D) error subtract a vector from the current vector -## func Sub +### func Sub ```go func Sub(v1, v2 Vector2D) Vector2D @@ -264,7 +264,7 @@ func Sub(v1, v2 Vector2D) Vector2D returns the difference of two vectors -## func Unit +### func Unit ```go func Unit(v Vector2D) Vector2D diff --git a/vector2d/README.md b/vector2d/README.md index b68b422..27a9113 100644 --- a/vector2d/README.md +++ b/vector2d/README.md @@ -1,269 +1,5 @@ - - # vector2d -```go -import "github.com/vaibhav11s/gopkgs/vector2d" -``` - -Package vector provides a simple 2D vector type on cartesian plane - -## Index - -- [func AngleBetween(v1, v2 *Vector2D) float32](<#func-anglebetween>) -- [func Cross(v1, v2 *Vector2D) float32](<#func-cross>) -- [func Dot(v1, v2 *Vector2D) float32](<#func-dot>) -- [type Vector2D](<#type-vector2d>) - - [func Add(v1, v2 *Vector2D) *Vector2D](<#func-add>) - - [func Copy(v *Vector2D) *Vector2D](<#func-copy>) - - [func FromAngle(angle float32, length ...float32) *Vector2D](<#func-fromangle>) - - [func New(x, y float32) *Vector2D](<#func-new>) - - [func Random(length ...float32) *Vector2D](<#func-random>) - - [func Sub(v1, v2 *Vector2D) *Vector2D](<#func-sub>) - - [func Unit(v *Vector2D) *Vector2D](<#func-unit>) - - [func (v *Vector2D) Add(v2 *Vector2D) *Vector2D](<#func-vector2d-add>) - - [func (v *Vector2D) AngleBetween(v2 *Vector2D) float32](<#func-vector2d-anglebetween>) - - [func (v *Vector2D) Copy() *Vector2D](<#func-vector2d-copy>) - - [func (v *Vector2D) Cross(v2 *Vector2D) float32](<#func-vector2d-cross>) - - [func (v *Vector2D) Dist(v2 *Vector2D) float32](<#func-vector2d-dist>) - - [func (v *Vector2D) Dot(v2 *Vector2D) float32](<#func-vector2d-dot>) - - [func (v *Vector2D) Equal(v2 *Vector2D, tolerance ...float32) bool](<#func-vector2d-equal>) - - [func (v *Vector2D) Heading() float32](<#func-vector2d-heading>) - - [func (v *Vector2D) Mag() float32](<#func-vector2d-mag>) - - [func (v *Vector2D) MagSq() float32](<#func-vector2d-magsq>) - - [func (v *Vector2D) Mult(scalar float32) *Vector2D](<#func-vector2d-mult>) - - [func (v *Vector2D) Normalize() *Vector2D](<#func-vector2d-normalize>) - - [func (v *Vector2D) Resize(mag float32) *Vector2D](<#func-vector2d-resize>) - - [func (v *Vector2D) Rotate(angle float32) *Vector2D](<#func-vector2d-rotate>) - - [func (v *Vector2D) SetHeading(angle float32) *Vector2D](<#func-vector2d-setheading>) - - [func (v *Vector2D) String() string](<#func-vector2d-string>) - - [func (v *Vector2D) Sub(v2 *Vector2D) *Vector2D](<#func-vector2d-sub>) - - -## func AngleBetween - -```go -func AngleBetween(v1, v2 *Vector2D) float32 -``` - -Calculates and returns the angle between two vectors\. Returns NaN if any vector is a zero vector - -## func Cross - -```go -func Cross(v1, v2 *Vector2D) float32 -``` - -Calculates the cross product of two vectors \~ give the value of the z axis component \(in 2D space\, the cross product is a vector perpendicular to the two input vectors\) - -## func Dot - -```go -func Dot(v1, v2 *Vector2D) float32 -``` - -Calculates the dot product of two vectors - -## type Vector2D - -```go -type Vector2D struct { - X, Y float32 -} -``` - -### func Add - -```go -func Add(v1, v2 *Vector2D) *Vector2D -``` - -returns the sum of two vectors - -### func Copy - -```go -func Copy(v *Vector2D) *Vector2D -``` - -Gets a copy of the vector - -### func FromAngle - -```go -func FromAngle(angle float32, length ...float32) *Vector2D -``` - -Make a new 2D vector from an angle - -### func New - -```go -func New(x, y float32) *Vector2D -``` - -Creates a new 2D vector\. Two dimensional Euclidean vector\. - -### func Random - -```go -func Random(length ...float32) *Vector2D -``` - -Make a new 2D vector from a random angle of length 1 \(default\) or a given length - -### func Sub - -```go -func Sub(v1, v2 *Vector2D) *Vector2D -``` - -returns the difference of two vectors - -### func Unit - -```go -func Unit(v *Vector2D) *Vector2D -``` - -Gives a unit vector in dirction of the vector - -### func \(\*Vector2D\) Add - -```go -func (v *Vector2D) Add(v2 *Vector2D) *Vector2D -``` - -add a vector to the current vector\. Modify \+ Returns self - -### func \(\*Vector2D\) AngleBetween - -```go -func (v *Vector2D) AngleBetween(v2 *Vector2D) float32 -``` - -Calculates and returns the angle with another vector Returns NaN if any vector is a zero vector - -### func \(\*Vector2D\) Copy - -```go -func (v *Vector2D) Copy() *Vector2D -``` - -Gets a copy of the vector - -### func \(\*Vector2D\) Cross - -```go -func (v *Vector2D) Cross(v2 *Vector2D) float32 -``` - -Calculates the cross product with another vector \~ give the value of the z axis component \(in 2D space\, the cross product is a vector perpendicular to the two input vectors\) - -### func \(\*Vector2D\) Dist - -```go -func (v *Vector2D) Dist(v2 *Vector2D) float32 -``` - -Calculates the Euclidean distance between two points \(considering a point as a vector object\) - -### func \(\*Vector2D\) Dot - -```go -func (v *Vector2D) Dot(v2 *Vector2D) float32 -``` - -Calculates the dot product with another vector - -### func \(\*Vector2D\) Equal - -```go -func (v *Vector2D) Equal(v2 *Vector2D, tolerance ...float32) bool -``` - -Checks whether two vectors are equal\. optional tolerence value can be passed as a parameter to check for equality within a tolerance\, abs\(v\.x \- v2\.x\) \< tolerance and abs\(v\.y \- v2\.y\) \< tolerance - -### func \(\*Vector2D\) Heading - -```go -func (v *Vector2D) Heading() float32 -``` - -Calculate the angle of rotation for the vector - -### func \(\*Vector2D\) Mag - -```go -func (v *Vector2D) Mag() float32 -``` - -Calculates the magnitude \(length\) of the vector and returns the result as a float this is simply the equation sqrt\(x\*x \+ y\*y\) - -### func \(\*Vector2D\) MagSq - -```go -func (v *Vector2D) MagSq() float32 -``` - -Calculates the squared magnitude of the vector and returns the result as a float this is simply the equation \(x\*x \+ y\*y \+ z\*z\) - -### func \(\*Vector2D\) Mult - -```go -func (v *Vector2D) Mult(scalar float32) *Vector2D -``` - -Multiplies the vector by a scalar\. Modify \+ Returns self - -### func \(\*Vector2D\) Normalize - -```go -func (v *Vector2D) Normalize() *Vector2D -``` - -Normalize the vector to length 1 \(make it a unit vector\)\. Modify \+ Returns self - -### func \(\*Vector2D\) Resize - -```go -func (v *Vector2D) Resize(mag float32) *Vector2D -``` - -Set the magnitude of this vector to the value used for the len parameter\. Modify \+ Returns self - -### func \(\*Vector2D\) Rotate - -```go -func (v *Vector2D) Rotate(angle float32) *Vector2D -``` - -rotate the vector in the direction of the angle\. Modify \+ Returns self - -### func \(\*Vector2D\) SetHeading - -```go -func (v *Vector2D) SetHeading(angle float32) *Vector2D -``` - -Rotate the vector to a specific angle\, magnitude remains the same\. Modify \+ Returns self - -### func \(\*Vector2D\) String - -```go -func (v *Vector2D) String() string -``` - -Returns a string representation of the vector - -### func \(\*Vector2D\) Sub - -```go -func (v *Vector2D) Sub(v2 *Vector2D) *Vector2D -``` - -subtract a vector from the current vector\. Modify \+ Returns self - - +Package vector2d provides a simple 2D vector type on cartesian plane -Generated by [gomarkdoc]() +For documentation, see [pkg.go.dev](https://pkg.go.dev/github.com/vaibhav11s/gopkgs/vector2d) diff --git a/vector2d/doc.md b/vector2d/doc.md new file mode 100644 index 0000000..3f69c99 --- /dev/null +++ b/vector2d/doc.md @@ -0,0 +1,266 @@ + + +# vector2d + +```go +import "github.com/vaibhav11s/gopkgs/vector2d" +``` + +Package vector2d provides a simple 2D vector type on cartesian plane + +## Index + +- [type Vector2D](#type-vector2d) + - [func Add(v1, v2 *Vector2D) *Vector2D](#func-add) + - [func Copy(v *Vector2D) *Vector2D](#func-copy) + - [func FromAngle(angle float32, length ...float32) \*Vector2D](#func-fromangle) + - [func New(x, y float32) \*Vector2D](#func-new) + - [func Random(length ...float32) \*Vector2D](#func-random) + - [func Sub(v1, v2 *Vector2D) *Vector2D](#func-sub) + - [func Unit(v *Vector2D) *Vector2D](#func-unit) + - [func AngleBetween(v1, v2 \*Vector2D) float32](#func-anglebetween) + - [func Cross(v1, v2 \*Vector2D) float32](#func-cross) + - [func Dot(v1, v2 \*Vector2D) float32](#func-dot) + - [func (v *Vector2D) Add(v2 *Vector2D) \*Vector2D](#func-vector2d-add) + - [func (v *Vector2D) AngleBetween(v2 *Vector2D) float32](#func-vector2d-anglebetween) + - [func (v *Vector2D) Copy() *Vector2D](#func-vector2d-copy) + - [func (v *Vector2D) Cross(v2 *Vector2D) float32](#func-vector2d-cross) + - [func (v *Vector2D) Dist(v2 *Vector2D) float32](#func-vector2d-dist) + - [func (v *Vector2D) Dot(v2 *Vector2D) float32](#func-vector2d-dot) + - [func (v *Vector2D) Equal(v2 *Vector2D, tolerance ...float32) bool](#func-vector2d-equal) + - [func (v \*Vector2D) Heading() float32](#func-vector2d-heading) + - [func (v \*Vector2D) Mag() float32](#func-vector2d-mag) + - [func (v \*Vector2D) MagSq() float32](#func-vector2d-magsq) + - [func (v *Vector2D) Mult(scalar float32) *Vector2D](#func-vector2d-mult) + - [func (v *Vector2D) Normalize() *Vector2D](#func-vector2d-normalize) + - [func (v *Vector2D) Resize(mag float32) *Vector2D](#func-vector2d-resize) + - [func (v *Vector2D) Rotate(angle float32) *Vector2D](#func-vector2d-rotate) + - [func (v *Vector2D) SetHeading(angle float32) *Vector2D](#func-vector2d-setheading) + - [func (v \*Vector2D) String() string](#func-vector2d-string) + - [func (v *Vector2D) Sub(v2 *Vector2D) \*Vector2D](#func-vector2d-sub) + +## type Vector2D + +```go +type Vector2D struct { + X, Y float32 +} +``` + +### func Add + +```go +func Add(v1, v2 *Vector2D) *Vector2D +``` + +returns the sum of two vectors + +### func Copy + +```go +func Copy(v *Vector2D) *Vector2D +``` + +Gets a copy of the vector + +### func FromAngle + +```go +func FromAngle(angle float32, length ...float32) *Vector2D +``` + +Make a new 2D vector from an angle + +### func New + +```go +func New(x, y float32) *Vector2D +``` + +Creates a new 2D vector\. Two dimensional Euclidean vector\. + +### func Random + +```go +func Random(length ...float32) *Vector2D +``` + +Make a new 2D vector from a random angle of length 1 \(default\) or a given length + +### func Sub + +```go +func Sub(v1, v2 *Vector2D) *Vector2D +``` + +returns the difference of two vectors + +### func Unit + +```go +func Unit(v *Vector2D) *Vector2D +``` + +Gives a unit vector in dirction of the vector + +### func AngleBetween + +```go +func AngleBetween(v1, v2 *Vector2D) float32 +``` + +Calculates and returns the angle between two vectors\. Returns NaN if any vector is a zero vector + +### func Cross + +```go +func Cross(v1, v2 *Vector2D) float32 +``` + +Calculates the cross product of two vectors \~ give the value of the z axis component \(in 2D space\, the cross product is a vector perpendicular to the two input vectors\) + +### func Dot + +```go +func Dot(v1, v2 *Vector2D) float32 +``` + +Calculates the dot product of two vectors + +### func \(\*Vector2D\) Add + +```go +func (v *Vector2D) Add(v2 *Vector2D) *Vector2D +``` + +add a vector to the current vector\. Modify \+ Returns self + +### func \(\*Vector2D\) AngleBetween + +```go +func (v *Vector2D) AngleBetween(v2 *Vector2D) float32 +``` + +Calculates and returns the angle with another vector Returns NaN if any vector is a zero vector + +### func \(\*Vector2D\) Copy + +```go +func (v *Vector2D) Copy() *Vector2D +``` + +Gets a copy of the vector + +### func \(\*Vector2D\) Cross + +```go +func (v *Vector2D) Cross(v2 *Vector2D) float32 +``` + +Calculates the cross product with another vector \~ give the value of the z axis component \(in 2D space\, the cross product is a vector perpendicular to the two input vectors\) + +### func \(\*Vector2D\) Dist + +```go +func (v *Vector2D) Dist(v2 *Vector2D) float32 +``` + +Calculates the Euclidean distance between two points \(considering a point as a vector object\) + +### func \(\*Vector2D\) Dot + +```go +func (v *Vector2D) Dot(v2 *Vector2D) float32 +``` + +Calculates the dot product with another vector + +### func \(\*Vector2D\) Equal + +```go +func (v *Vector2D) Equal(v2 *Vector2D, tolerance ...float32) bool +``` + +Checks whether two vectors are equal\. optional tolerence value can be passed as a parameter to check for equality within a tolerance\, abs\(v\.x \- v2\.x\) \< tolerance and abs\(v\.y \- v2\.y\) \< tolerance + +### func \(\*Vector2D\) Heading + +```go +func (v *Vector2D) Heading() float32 +``` + +Calculate the angle of rotation for the vector + +### func \(\*Vector2D\) Mag + +```go +func (v *Vector2D) Mag() float32 +``` + +Calculates the magnitude \(length\) of the vector and returns the result as a float this is simply the equation sqrt\(x\*x \+ y\*y\) + +### func \(\*Vector2D\) MagSq + +```go +func (v *Vector2D) MagSq() float32 +``` + +Calculates the squared magnitude of the vector and returns the result as a float this is simply the equation \(x\*x \+ y\*y\) + +### func \(\*Vector2D\) Mult + +```go +func (v *Vector2D) Mult(scalar float32) *Vector2D +``` + +Multiplies the vector by a scalar\. Modify \+ Returns self + +### func \(\*Vector2D\) Normalize + +```go +func (v *Vector2D) Normalize() *Vector2D +``` + +Normalize the vector to length 1 \(make it a unit vector\)\. Modify \+ Returns self + +### func \(\*Vector2D\) Resize + +```go +func (v *Vector2D) Resize(mag float32) *Vector2D +``` + +Set the magnitude of this vector to the value used for the len parameter\. Modify \+ Returns self + +### func \(\*Vector2D\) Rotate + +```go +func (v *Vector2D) Rotate(angle float32) *Vector2D +``` + +rotate the vector in the direction of the angle\. Modify \+ Returns self + +### func \(\*Vector2D\) SetHeading + +```go +func (v *Vector2D) SetHeading(angle float32) *Vector2D +``` + +Rotate the vector to a specific angle\, magnitude remains the same\. Modify \+ Returns self + +### func \(\*Vector2D\) String + +```go +func (v *Vector2D) String() string +``` + +Returns a string representation of the vector + +### func \(\*Vector2D\) Sub + +```go +func (v *Vector2D) Sub(v2 *Vector2D) *Vector2D +``` + +subtract a vector from the current vector\. Modify \+ Returns self + +Generated by [gomarkdoc](https://github.com/princjef/gomarkdoc) diff --git a/vector2d/vector2d.go b/vector2d/vector2d.go index 4e87eeb..cb2fb74 100644 --- a/vector2d/vector2d.go +++ b/vector2d/vector2d.go @@ -1,4 +1,4 @@ -// Package vector provides a simple 2D vector type on cartesian plane +// Package vector2d provides a simple 2D vector type on cartesian plane package vector2d import ( @@ -75,7 +75,7 @@ func (v *Vector2D) Mag() float32 { } // Calculates the squared magnitude of the vector and returns the result as a float -// this is simply the equation (x*x + y*y + z*z) +// this is simply the equation (x*x + y*y) func (v *Vector2D) MagSq() float32 { return v.X*v.X + v.Y*v.Y }