github.com/richardwilkes/toolbox@v1.121.0/xmath/geom/point.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package geom 11 12 import ( 13 "fmt" 14 15 "github.com/richardwilkes/toolbox/xmath" 16 ) 17 18 // Point defines a location. 19 type Point[T xmath.Numeric] struct { 20 X T `json:"x"` 21 Y T `json:"y"` 22 } 23 24 // NewPoint returns a new Point. 25 func NewPoint[T xmath.Numeric](x, y T) Point[T] { 26 return Point[T]{X: x, Y: y} 27 } 28 29 // ConvertPoint converts a Point of type F into one of type T. 30 func ConvertPoint[T, F xmath.Numeric](pt Point[F]) Point[T] { 31 return NewPoint(T(pt.X), T(pt.Y)) 32 } 33 34 // Add returns a new Point which is the result of adding this Point with the provided Point. 35 func (p Point[T]) Add(pt Point[T]) Point[T] { 36 return Point[T]{X: p.X + pt.X, Y: p.Y + pt.Y} 37 } 38 39 // Sub returns a new Point which is the result of subtracting the provided Point from this Point. 40 func (p Point[T]) Sub(pt Point[T]) Point[T] { 41 return Point[T]{X: p.X - pt.X, Y: p.Y - pt.Y} 42 } 43 44 // Mul returns a new Point which is the result of multiplying the coordinates of this point by the value. 45 func (p Point[T]) Mul(value T) Point[T] { 46 return Point[T]{X: p.X * value, Y: p.Y * value} 47 } 48 49 // Div returns a new Point which is the result of dividing the coordinates of this point by the value. 50 func (p Point[T]) Div(value T) Point[T] { 51 return Point[T]{X: p.X / value, Y: p.Y / value} 52 } 53 54 // Neg returns a new Point that holds the negated coordinates of this Point. 55 func (p Point[T]) Neg() Point[T] { 56 return Point[T]{X: -p.X, Y: -p.Y} 57 } 58 59 // Floor returns a new Point which is aligned to integer coordinates by using Floor on them. 60 func (p Point[T]) Floor() Point[T] { 61 return Point[T]{X: xmath.Floor(p.X), Y: xmath.Floor(p.Y)} 62 } 63 64 // Ceil returns a new Point which is aligned to integer coordinates by using Ceil() on them. 65 func (p Point[T]) Ceil() Point[T] { 66 return Point[T]{X: xmath.Ceil(p.X), Y: xmath.Ceil(p.Y)} 67 } 68 69 // Dot returns the dot product of the two Points. 70 func (p Point[T]) Dot(pt Point[T]) T { 71 return p.X*pt.X + p.Y*pt.Y 72 } 73 74 // Cross returns the cross product of the two Points. 75 func (p Point[T]) Cross(pt Point[T]) T { 76 return p.X*pt.Y - p.Y*pt.X 77 } 78 79 // In returns true if this Point is within the Rect. 80 func (p Point[T]) In(r Rect[T]) bool { 81 if r.Empty() { 82 return false 83 } 84 return r.X <= p.X && r.Y <= p.Y && p.X < r.Right() && p.Y < r.Bottom() 85 } 86 87 // EqualWithin returns true if the two points are within the given tolerance of each other. 88 func (p Point[T]) EqualWithin(pt Point[T], tolerance T) bool { 89 return xmath.EqualWithin(p.X, pt.X, tolerance) && xmath.EqualWithin(p.Y, pt.Y, tolerance) 90 } 91 92 // String implements the fmt.Stringer interface. 93 func (p Point[T]) String() string { 94 return fmt.Sprintf("%#v,%#v", p.X, p.Y) 95 }