package unit import ( "math" "strconv" ) // Vec2 is a 2D vector of values with the unit of T. type Vec2[T UnitConstraint] struct { X T `json:"x"` Y T `json:"y"` } // NewVec2FromVec2 takes an arbitrary Vec2 and returns it as a new vector with the type T. func NewVec2FromVec2[I, T UnitConstraint](a Vec2[I]) Vec2[T] { return Vec2[T]{T(a.X), T(a.Y)} } func (a Vec2[T]) String() string { return "(" + strconv.FormatFloat(float64(a.X), 'f', -1, 64) + ", " + strconv.FormatFloat(float64(a.Y), 'f', -1, 64) + ")\u00A0" + T.UnitSymbol(0) } func (a Vec2[T]) EqualWithPrecision(b Vec2[T], precision T) bool { if math.Abs(float64(a.X-b.X)) > float64(precision) { return false } if math.Abs(float64(a.Y-b.Y)) > float64(precision) { return false } return true } func (a Vec2[T]) Unitless() Vec2[Unitless] { return Vec2[Unitless]{Unitless(a.X), Unitless(a.Y)} } func (a Vec2[T]) Added(b Vec2[T]) Vec2[T] { return Vec2[T]{a.X + b.X, a.Y + b.Y} } func (a Vec2[T]) Subed(b Vec2[T]) Vec2[T] { return Vec2[T]{a.X - b.X, a.Y - b.Y} } func (a Vec2[T]) Scaled(s float64) Vec2[T] { return Vec2[T]{a.X * T(s), a.Y * T(s)} } func (a Vec2[T]) Normalized() Vec2[Unitless] { return a.Scaled(1 / float64(a.Length())).Unitless() } func (a Vec2[T]) LengthSqr() T { return a.X*a.X + a.Y*a.Y } func (a Vec2[T]) Length() T { return T(math.Abs(float64(a.LengthSqr()))) }