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  }