package main import ( "fmt" "strconv" "strings" ) type Vec2 struct { X int64 Y int64 } func NewVec2(axis ...int64) *Vec2 { if len(axis) == 0 { return &Vec2{} } else if len(axis) == 1 { return &Vec2{axis[0], axis[0]} } else { return &Vec2{axis[0], axis[1]} } } func (v *Vec2) Clone() *Vec2 { if v == nil { return nil } return &Vec2{v.X, v.Y} } func (v *Vec2) Translate(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) TranslateBy(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) Assign(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) AssignTo(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) Equal(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) EqualTo(o *Vec2) bool { if v == nil { return false } if o == nil { return v.X == 0 && v.Y == 0 } return v.X == o.X && v.Y == o.Y } func (v *Vec2) Less(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 { return false } if o == nil { return v.Less() } return v.X <= o.X && v.Y <= o.Y } func (v *Vec2) Greater(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) GreaterThan(o *Vec2) bool { if v == nil { return false } if o == nil { return v.Greater() } return v.X >= o.X && v.Y >= o.Y } func SortVec2(v1, v2 *Vec2) (*Vec2, *Vec2) { if v1.GreaterThan(v2) { return v2, v1 } return v1, v2 } func (v *Vec2) Within(v1, v2 *Vec2) bool { if v == nil || v1 == nil || v2 == nil { return false } if v1.EqualTo(v2) && !v.EqualTo(v1) { return false } v1, v2 = SortVec2(v1, v2) return v.GreaterThan(v1) && v.LessThan(v2) } func (v *Vec2) Distance(axis ...int64) int64 { if v == nil { return -1 } if len(axis) == 0 { return v.X + v.Y } else if len(axis) == 1 { x := v.X - axis[0] y := v.Y - axis[0] if x < 0 { x = -x } if y < 0 { y = -y } return x + y } else { x := v.X - axis[0] y := v.Y - axis[1] if x < 0 { x = -x } if y < 0 { y = -y } return x + y } } func (v *Vec2) DistanceTo(o *Vec2) int64 { if v == nil || o == nil { return -1 } x := v.X - o.X y := v.Y - o.Y if x < 0 { x = -x } if y < 0 { y = -y } return x + y } func (v *Vec2) Abs() *Vec2 { if v == nil { return nil } if v.X < 0 { v.X = -v.X } if v.Y < 0 { v.Y = -v.Y } return v } func (v *Vec2) NegAbs() *Vec2 { if v == nil { return nil } if v.X > 0 { v.X = -v.X } if v.Y > 0 { v.Y = -v.Y } return v } func (v *Vec2) Negate() *Vec2 { if v == nil { return nil } v.X = -v.X v.Y = -v.Y return v } func (v *Vec2) String() string { if v == nil { return "nil" } return fmt.Sprintf("(%d, %d)", v.X, v.Y) } func Vec2FromString(s string) (*Vec2, string) { if !strings.ContainsAny(s, "(),") { return nil, "missing '(),' characters" } work := strings.Split(strings.ReplaceAll(strings.ReplaceAll(s, ")", ""), "(", ""), ", ") if len(work) != 2 { return nil, fmt.Sprintf("missing parts, got %d, need 2", len(work)) } x, err := strconv.ParseInt(work[0], 10, 64) if err != nil { return nil, fmt.Sprintf("failed parsing x axis, %v", err) } y, err := strconv.ParseInt(work[1], 10, 64) if err != nil { return nil, fmt.Sprintf("failed parsing y axis, %v", err) } return NewVec2(x, y), "" }