Source code for gon.core.point

import math
from numbers import Real
from typing import Optional

from ground.hints import Scalar
from reprit.base import generate_repr
from symba.base import Expression

from .angle import Angle
from .geometry import Geometry


class Point(Geometry[Scalar]):
    __slots__ = '_coordinates', '_x', '_y'

[docs] def __init__(self, x: Scalar, y: Scalar) -> None: """ Initializes point. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` """ self._coordinates = self._x, self._y = x, y
__repr__ = generate_repr(__init__)
[docs] def __hash__(self) -> int: """ Returns hash value of the point. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` >>> from gon.base import Point >>> hash(Point(0, 0)) == hash(Point(0, 0)) True """ return hash(self._coordinates)
[docs] def __eq__(self, other: 'Point[Scalar]') -> bool: """ Checks if the point is equal to the other. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` >>> from gon.base import Point >>> Point(0, 0) == Point(0, 0) True >>> Point(0, 0) == Point(0, 1) False >>> Point(0, 0) == Point(1, 1) False >>> Point(0, 0) == Point(1, 0) False """ return (self.x == other.x and self.y == other.y if isinstance(other, Point) else NotImplemented)
[docs] def __le__(self, other: 'Point[Scalar]') -> bool: """ Checks if the point is less than or equal to the other. Compares points lexicographically, ``x`` coordinates first. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` Reference: https://en.wikipedia.org/wiki/Lexicographical_order >>> from gon.base import Point >>> Point(0, 0) <= Point(0, 0) True >>> Point(0, 0) <= Point(0, 1) True >>> Point(0, 0) <= Point(1, 1) True >>> Point(0, 0) <= Point(1, 0) True """ return (self._coordinates <= other._coordinates if isinstance(other, Point) else NotImplemented)
[docs] def __lt__(self, other: 'Point[Scalar]') -> bool: """ Checks if the point is less than the other. Compares points lexicographically, ``x`` coordinates first. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` Reference: https://en.wikipedia.org/wiki/Lexicographical_order >>> from gon.base import Point >>> Point(0, 0) < Point(0, 0) False >>> Point(0, 0) < Point(0, 1) True >>> Point(0, 0) < Point(1, 1) True >>> Point(0, 0) < Point(1, 0) True """ return (self._coordinates < other._coordinates if isinstance(other, Point) else NotImplemented)
@property def x(self) -> Scalar: """ Returns abscissa of the point. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` >>> from gon.base import Point >>> Point(1, 0).x == 1 True """ return self._x @property def y(self) -> Scalar: """ Returns ordinate of the point. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` >>> from gon.base import Point >>> Point(1, 0).y == 0 True """ return self._y
[docs] def distance_to(self, other: Geometry[Scalar]) -> Scalar: """ Returns distance between the point and the other geometry. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` >>> from gon.base import Point >>> point = Point(1, 0) >>> point.distance_to(point) == 0 True """ if isinstance(other, Point): return self._context.sqrt(self._context.points_squared_distance( self, other )) else: return other.distance_to(self)
[docs] def rotate(self, angle: Angle, point: Optional['Point[Scalar]'] = None) -> 'Point[Scalar]': """ Rotates the point by given angle around given point. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` >>> from gon.base import Angle, Point >>> point = Point(1, 0) >>> point.rotate(Angle(1, 0)) == point True >>> point.rotate(Angle(0, 1), Point(1, 1)) == Point(2, 1) True """ return (self._context.rotate_point_around_origin(self, angle.cosine, angle.sine) if point is None else self._context.rotate_point(self, angle.cosine, angle.sine, point))
[docs] def scale(self, factor_x: Scalar, factor_y: Optional[Scalar] = None) -> 'Point[Scalar]': """ Scales the point by given factor. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` >>> from gon.base import Point >>> point = Point(1, 0) >>> point.scale(1) == point.scale(1, 2) == point True """ return self._context.scale_point( self, factor_x, factor_x if factor_y is None else factor_y)
[docs] def translate(self, step_x: Scalar, step_y: Scalar) -> 'Point[Scalar]': """ Translates the point by given step. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` >>> from gon.base import Point >>> Point(1, 0).translate(1, 2) == Point(2, 2) True """ return self._context.translate_point(self, step_x, step_y)
[docs] def validate(self) -> None: """ Checks if coordinates are finite. Time complexity: ``O(1)`` Memory complexity: ``O(1)`` >>> from gon.base import Point >>> Point(0, 0).validate() """ if not (is_finite(self.x) and is_finite(self.y)): raise ValueError('NaN/infinity coordinates are not supported.')
def is_finite(value: Scalar) -> bool: return (math.isfinite(value) if isinstance(value, Real) else isinstance(value, Expression) and value.is_finite)