|
@@ -0,0 +1,351 @@
|
|
|
|
+package main
|
|
|
|
+
|
|
|
|
+import (
|
|
|
|
+ "fmt"
|
|
|
|
+ "strconv"
|
|
|
|
+ "strings"
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+type Vec2 struct {
|
|
|
|
+ X int64
|
|
|
|
+ Y int64
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func NewVec2(axis ...int64) *Vec2 {
|
|
|
|
+ if len(axis) == 0 {
|
|
|
|
+ return &Vec2{X: 0, Y: 0}
|
|
|
|
+ } else if len(axis) == 1 {
|
|
|
|
+ return &Vec2{X: axis[0], Y: axis[0]}
|
|
|
|
+ } else {
|
|
|
|
+ return &Vec2{X: axis[0], Y: axis[1]}
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Clone() *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ return &Vec2{X: v.X, Y: v.Y}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Add(axis ...int64) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if len(axis) == 0 {
|
|
|
|
+ return v
|
|
|
|
+ } else if len(axis) == 1 {
|
|
|
|
+ v.X += axis[0]
|
|
|
|
+ v.Y += axis[0]
|
|
|
|
+ return v
|
|
|
|
+ } else {
|
|
|
|
+ v.X += axis[0]
|
|
|
|
+ v.Y += axis[1]
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Sub(axis ...int64) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if len(axis) == 0 {
|
|
|
|
+ return v
|
|
|
|
+ } else if len(axis) == 1 {
|
|
|
|
+ v.X -= axis[0]
|
|
|
|
+ v.Y -= axis[0]
|
|
|
|
+ return v
|
|
|
|
+ } else {
|
|
|
|
+ v.X -= axis[0]
|
|
|
|
+ v.Y -= axis[1]
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Mul(axis ...int64) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if len(axis) == 0 {
|
|
|
|
+ return v
|
|
|
|
+ } else if len(axis) == 1 {
|
|
|
|
+ v.X *= axis[0]
|
|
|
|
+ v.Y *= axis[0]
|
|
|
|
+ return v
|
|
|
|
+ } else {
|
|
|
|
+ v.X *= axis[0]
|
|
|
|
+ v.Y *= axis[1]
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Div(axis ...int64) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if len(axis) == 0 {
|
|
|
|
+ return v
|
|
|
|
+ } else if len(axis) == 1 {
|
|
|
|
+ v.X /= axis[0]
|
|
|
|
+ v.Y /= axis[0]
|
|
|
|
+ return v
|
|
|
|
+ } else {
|
|
|
|
+ v.X /= axis[0]
|
|
|
|
+ v.Y /= axis[1]
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Rem(axis ...int64) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if len(axis) == 0 {
|
|
|
|
+ return v
|
|
|
|
+ } else if len(axis) == 1 {
|
|
|
|
+ v.X %= axis[0]
|
|
|
|
+ v.Y %= axis[0]
|
|
|
|
+ return v
|
|
|
|
+ } else {
|
|
|
|
+ v.X %= axis[0]
|
|
|
|
+ v.Y %= axis[1]
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Set(axis ...int64) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if len(axis) == 0 {
|
|
|
|
+ v.X = 0
|
|
|
|
+ v.Y = 0
|
|
|
|
+ return v
|
|
|
|
+ } else if len(axis) == 1 {
|
|
|
|
+ v.X = axis[0]
|
|
|
|
+ v.Y = axis[0]
|
|
|
|
+ return v
|
|
|
|
+ } else {
|
|
|
|
+ v.X = axis[0]
|
|
|
|
+ v.Y = axis[1]
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) AddBy(o *Vec2) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if o == nil {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ v.X += o.X
|
|
|
|
+ v.Y += o.Y
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) SubBy(o *Vec2) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if o == nil {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ v.X -= o.X
|
|
|
|
+ v.Y -= o.Y
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) MulBy(o *Vec2) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if o == nil {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ v.X *= o.X
|
|
|
|
+ v.Y *= o.Y
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) DivBy(o *Vec2) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if o == nil {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ v.X /= o.X
|
|
|
|
+ v.Y /= o.Y
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) RemBy(o *Vec2) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if o == nil {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ v.X -= o.X
|
|
|
|
+ v.Y -= o.Y
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) SetTo(o *Vec2) *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if o == nil {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ v.X = o.X
|
|
|
|
+ v.Y = o.Y
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Abs() *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ v.X = I64Abs(v.X)
|
|
|
|
+ v.Y = I64Abs(v.Y)
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func I64Abs(i int64) int64 {
|
|
|
|
+ if i < 0 {
|
|
|
|
+ return -i
|
|
|
|
+ }
|
|
|
|
+ return i
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Negate() *Vec2 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ v.X = -v.X
|
|
|
|
+ v.Y = -v.Y
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Less(axis ...int64) bool {
|
|
|
|
+ if v == nil || len(axis) == 0 {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ if len(axis) == 1 {
|
|
|
|
+ return v.X < axis[0] && v.Y < axis[0]
|
|
|
|
+ } else {
|
|
|
|
+ return v.X < axis[0] && v.Y < axis[1]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Great(axis ...int64) bool {
|
|
|
|
+ if v == nil || len(axis) == 0 {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ if len(axis) == 1 {
|
|
|
|
+ return v.X > axis[0] && v.Y > axis[0]
|
|
|
|
+ } else {
|
|
|
|
+ return v.X > axis[0] && v.Y > axis[1]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Eq(axis ...int64) bool {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ if len(axis) == 0 {
|
|
|
|
+ return v.X == 0 && v.Y == 0
|
|
|
|
+ } else if len(axis) == 1 {
|
|
|
|
+ return v.X == axis[0] && v.Y == axis[0]
|
|
|
|
+ } else {
|
|
|
|
+ return v.X == axis[0] && v.Y == axis[1]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) LessThan(o *Vec2) bool {
|
|
|
|
+ if v == nil || o == nil {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ return v.X < o.X && v.Y < o.Y
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) GreatThan(o *Vec2) bool {
|
|
|
|
+ if v == nil || o == nil {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ return v.X > o.X && v.Y > o.Y
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) EqTo(o *Vec2) bool {
|
|
|
|
+ if v == nil || o == nil {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ return v.X == o.X && v.Y == o.Y
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) Dist(axis ...int64) int64 {
|
|
|
|
+ if v == nil {
|
|
|
|
+ return -1
|
|
|
|
+ }
|
|
|
|
+ if len(axis) == 0 {
|
|
|
|
+ return I64Abs(v.X) + I64Abs(v.Y)
|
|
|
|
+ } else if len(axis) == 1 {
|
|
|
|
+ a := I64Abs(v.X) + I64Abs(v.Y)
|
|
|
|
+ b := I64Abs(axis[0]) + I64Abs(axis[0])
|
|
|
|
+ return I64Abs(a - b)
|
|
|
|
+ } else {
|
|
|
|
+ a := I64Abs(v.X) + I64Abs(v.Y)
|
|
|
|
+ b := I64Abs(axis[0]) + I64Abs(axis[1])
|
|
|
|
+ return I64Abs(a - b)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) DistTo(o *Vec2) int64 {
|
|
|
|
+ if v == nil || o == nil {
|
|
|
|
+ return -1
|
|
|
|
+ }
|
|
|
|
+ a := I64Abs(v.X) + I64Abs(v.Y)
|
|
|
|
+ b := I64Abs(o.X) + I64Abs(o.Y)
|
|
|
|
+ return I64Abs(a - b)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (v *Vec2) String() string {
|
|
|
|
+ return fmt.Sprintf("(%d, %d)", v.X, v.Y)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+var (
|
|
|
|
+ ErrVec2Format error = fmt.Errorf("missing parentheses and/or comma")
|
|
|
|
+ ErrTooManyCommas error = fmt.Errorf("missing or too many commas")
|
|
|
|
+ ErrInvalidAxisX error = fmt.Errorf("missing or invalid X-axis")
|
|
|
|
+ ErrInvalidAxisY error = fmt.Errorf("missing or invalid Y-axis")
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+func StrToVec2(s string) (*Vec2, error) {
|
|
|
|
+ if !strings.Contains(s, "(") || !strings.Contains(s, ")") || !strings.Contains(s, ",") {
|
|
|
|
+ return nil, ErrVec2Format
|
|
|
|
+ }
|
|
|
|
+ work := strings.ReplaceAll(s, "(", "")
|
|
|
|
+ work = strings.ReplaceAll(work, ")", "")
|
|
|
|
+ commas := strings.Count(work, ",")
|
|
|
|
+ if commas != 1 {
|
|
|
|
+ return nil, ErrTooManyCommas
|
|
|
|
+ }
|
|
|
|
+ parts := strings.Split(work, ",")
|
|
|
|
+ for idx, part := range parts {
|
|
|
|
+ parts[idx] = strings.TrimSpace(part)
|
|
|
|
+ }
|
|
|
|
+ if len(parts) != 2 {
|
|
|
|
+ return nil, ErrTooManyCommas
|
|
|
|
+ }
|
|
|
|
+ x, err := strconv.ParseInt(parts[0], 10, 64)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, ErrInvalidAxisX
|
|
|
|
+ }
|
|
|
|
+ y, err := strconv.ParseInt(parts[1], 10, 64)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, ErrInvalidAxisY
|
|
|
|
+ }
|
|
|
|
+ return &Vec2{X: x, Y: y}, nil
|
|
|
|
+}
|