You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 line
4.1KB

  1. // Package vector is a simple 2D vector math package.
  2. package vector
  3. import (
  4. "fmt"
  5. "math"
  6. )
  7. // Vector represents a 2 dimensional Vector.
  8. type Vector struct {
  9. X, Y float64
  10. }
  11. // Values returns the x, y values of the Vector.
  12. func (v Vector) Values() (x, y float64) {
  13. return v.X, v.Y
  14. }
  15. // Abs returns a Vector with the absolute value of X and Y.
  16. // Should not be confused with Magnitude due to its notation ||A||.
  17. func (v Vector) Abs() Vector {
  18. return Vector{
  19. math.Abs(v.X),
  20. math.Abs(v.Y),
  21. }
  22. }
  23. // Add returns a Vector with the value of Vector p plus Vector q.
  24. func (v Vector) Add(q Vector) Vector {
  25. return Vector{
  26. v.X + q.X,
  27. v.Y + q.Y,
  28. }
  29. }
  30. // Subtract returns a Vector with the value of Vector p minus Vector q.
  31. func (v Vector) Subtract(q Vector) Vector {
  32. return Vector{
  33. X: v.X - q.X,
  34. Y: v.Y - q.Y,
  35. }
  36. }
  37. // Multiply returns a Vector with the value of Vector p multiplied by f.
  38. func (v Vector) Multiply(f float64) Vector {
  39. return Vector{X: v.X * f, Y: v.Y * f}
  40. }
  41. // Divide returns a Vector with the value of Vector p divided by f.
  42. func (v Vector) Divide(f float64) Vector {
  43. return Vector{X: v.X / f, Y: v.Y / f}
  44. }
  45. // Round returns a Vector with the rounded value of Vector p.
  46. func (v Vector) Round() Vector {
  47. return Vector{X: math.Round(v.X), Y: math.Round(v.Y)}
  48. }
  49. // Floor returns a Vector with the floored value of Vector p.
  50. func (v Vector) Floor() Vector {
  51. return Vector{X: math.Floor(v.X), Y: math.Floor(v.Y)}
  52. }
  53. // Ceil returns a Vector with the rounded up value of Vector p.
  54. func (v Vector) Ceil() Vector {
  55. return Vector{X: math.Ceil(v.X), Y: math.Ceil(v.Y)}
  56. }
  57. // Scale returns a Vector with the values of Vector p scaled up by the values of Vector q.
  58. func (v Vector) Scale(q Vector) Vector {
  59. return Vector{
  60. X: v.X * q.X,
  61. Y: v.Y * q.Y,
  62. }
  63. }
  64. // ScaleDown returns a Vector with the values of Vector p scaled down by the values of Vector q.
  65. func (v Vector) ScaleDown(q Vector) Vector {
  66. return Vector{
  67. X: v.X / q.X,
  68. Y: v.Y / q.Y,
  69. }
  70. }
  71. // Min returns a Vector with the smallest values of X and Y for Vector p and q.
  72. func (v Vector) Min(q Vector) Vector {
  73. return Vector{
  74. X: math.Min(v.X, q.X),
  75. Y: math.Min(v.Y, q.Y),
  76. }
  77. }
  78. // Max returns a Vector with the largest values of X and Y for Vector p and q.
  79. func (v Vector) Max(q Vector) Vector {
  80. return Vector{
  81. X: math.Max(v.X, q.X),
  82. Y: math.Max(v.Y, q.Y),
  83. }
  84. }
  85. // String returns a string with comma separated values of Vector p.
  86. func (v Vector) String() string {
  87. return fmt.Sprintf("%v,%v", v.X, v.Y)
  88. }
  89. // Magnitude returns a float64 with the length/magnitude of Vector p.
  90. func (v Vector) Magnitude() float64 {
  91. return math.Sqrt(math.Pow(v.X, 2) + math.Pow(v.Y, 2))
  92. }
  93. // Unit returns a vector with the same direction but with a length of 1.
  94. func (v Vector) Unit() Vector {
  95. m := v.Magnitude()
  96. if m == 0 {
  97. panic("Cannot create unit vector of a vector with length 0.")
  98. }
  99. return v.Divide(m)
  100. }
  101. // Rotate the vector with an angle in radians.
  102. func (v Vector) Rotate(a float64) Vector {
  103. return Vector{
  104. X: math.Cos(a)*v.X - math.Sin(a)*v.Y,
  105. Y: math.Sin(a)*v.X + math.Cos(a)*v.Y,
  106. }
  107. }
  108. // Span returns the difference between a vector and the rotated version of the vector.
  109. func (v Vector) Span(a float64) Vector {
  110. return v.Subtract(v.Rotate(a))
  111. }
  112. // Distance between two vectors.
  113. func (v Vector) Distance(q Vector) float64 {
  114. return v.Subtract(q).Magnitude()
  115. }
  116. // Angle of the vector.
  117. func (v Vector) Angle() float64 {
  118. return math.Atan2(v.Y, v.X)
  119. }
  120. // AngleBetween returns the angle of the line between to vector endpoints.
  121. func (v Vector) AngleBetween(q Vector) float64 {
  122. diff := q.Subtract(v)
  123. return diff.Angle()
  124. }
  125. // Above returns a vector that is length l above the existing vector.
  126. func (v Vector) Above(l float64) Vector {
  127. return v.Add(Vector{Y: l})
  128. }
  129. // Below returns a vector that is length l below the existing vector.
  130. func (v Vector) Below(l float64) Vector {
  131. return v.Subtract(Vector{Y: l})
  132. }
  133. // Right returns a vector that is length l right of the existing vector.
  134. func (v Vector) Right(l float64) Vector {
  135. return v.Add(Vector{X: l})
  136. }
  137. // Left returns a vector that is length l left of the existing vector.
  138. func (v Vector) Left(l float64) Vector {
  139. return v.Subtract(Vector{X: l})
  140. }