// Package vector is a simple 2D vector math package. package vector import ( "fmt" "math" ) // Vector represents a 2 dimensional Vector. type Vector struct { X, Y float64 } // Values returns the x, y values of the Vector. func (v Vector) Values() (x, y float64) { return v.X, v.Y } // Abs returns a Vector with the absolute value of X and Y. // Should not be confused with Magnitude due to its notation ||A||. func (v Vector) Abs() Vector { return Vector{ math.Abs(v.X), math.Abs(v.Y), } } // Add returns a Vector with the value of Vector p plus Vector q. func (v Vector) Add(q Vector) Vector { return Vector{ v.X + q.X, v.Y + q.Y, } } // Subtract returns a Vector with the value of Vector p minus Vector q. func (v Vector) Subtract(q Vector) Vector { return Vector{ X: v.X - q.X, Y: v.Y - q.Y, } } // Multiply returns a Vector with the value of Vector p multiplied by f. func (v Vector) Multiply(f float64) Vector { return Vector{X: v.X * f, Y: v.Y * f} } // Divide returns a Vector with the value of Vector p divided by f. func (v Vector) Divide(f float64) Vector { return Vector{X: v.X / f, Y: v.Y / f} } // Round returns a Vector with the rounded value of Vector p. func (v Vector) Round() Vector { return Vector{X: math.Round(v.X), Y: math.Round(v.Y)} } // Floor returns a Vector with the floored value of Vector p. func (v Vector) Floor() Vector { return Vector{X: math.Floor(v.X), Y: math.Floor(v.Y)} } // Ceil returns a Vector with the rounded up value of Vector p. func (v Vector) Ceil() Vector { return Vector{X: math.Ceil(v.X), Y: math.Ceil(v.Y)} } // Scale returns a Vector with the values of Vector p scaled up by the values of Vector q. func (v Vector) Scale(q Vector) Vector { return Vector{ X: v.X * q.X, Y: v.Y * q.Y, } } // ScaleDown returns a Vector with the values of Vector p scaled down by the values of Vector q. func (v Vector) ScaleDown(q Vector) Vector { return Vector{ X: v.X / q.X, Y: v.Y / q.Y, } } // Min returns a Vector with the smallest values of X and Y for Vector p and q. func (v Vector) Min(q Vector) Vector { return Vector{ X: math.Min(v.X, q.X), Y: math.Min(v.Y, q.Y), } } // Max returns a Vector with the largest values of X and Y for Vector p and q. func (v Vector) Max(q Vector) Vector { return Vector{ X: math.Max(v.X, q.X), Y: math.Max(v.Y, q.Y), } } // String returns a string with comma separated values of Vector p. func (v Vector) String() string { return fmt.Sprintf("%v,%v", v.X, v.Y) } // Magnitude returns a float64 with the length/magnitude of Vector p. func (v Vector) Magnitude() float64 { return math.Sqrt(math.Pow(v.X, 2) + math.Pow(v.Y, 2)) } // Unit returns a vector with the same direction but with a length of 1. func (v Vector) Unit() Vector { m := v.Magnitude() if m == 0 { panic("Cannot create unit vector of a vector with length 0.") } return v.Divide(m) } // Rotate the vector with an angle in radians. func (v Vector) Rotate(a float64) Vector { return Vector{ X: math.Cos(a)*v.X - math.Sin(a)*v.Y, Y: math.Sin(a)*v.X + math.Cos(a)*v.Y, } } // Span returns the difference between a vector and the rotated version of the vector. func (v Vector) Span(a float64) Vector { return v.Subtract(v.Rotate(a)) } // Distance between two vectors. func (v Vector) Distance(q Vector) float64 { return v.Subtract(q).Magnitude() } // Angle of the vector. func (v Vector) Angle() float64 { return math.Atan2(v.Y, v.X) } // AngleBetween returns the angle of the line between to vector endpoints. func (v Vector) AngleBetween(q Vector) float64 { diff := q.Subtract(v) return diff.Angle() } // Above returns a vector that is length l above the existing vector. func (v Vector) Above(l float64) Vector { return v.Add(Vector{Y: l}) } // Below returns a vector that is length l below the existing vector. func (v Vector) Below(l float64) Vector { return v.Subtract(Vector{Y: l}) } // Right returns a vector that is length l right of the existing vector. func (v Vector) Right(l float64) Vector { return v.Add(Vector{X: l}) } // Left returns a vector that is length l left of the existing vector. func (v Vector) Left(l float64) Vector { return v.Subtract(Vector{X: l}) }