Module datatap.geometry.polygon
Expand source code
from __future__ import annotations
from typing import Generator, Sequence, Tuple, Union
from .point import Point, PointJson
from ..utils import basic_repr
PolygonJson = Sequence[PointJson]
class Polygon:
"""
A polygon in 2D space.
"""
points: Sequence[Point]
"""
The vertices of this polygon.
"""
@staticmethod
def from_json(json: PolygonJson) -> Polygon:
"""
Creates a `Polygon` from a `PolygonJson`.
"""
return Polygon([Point.from_json(pt) for pt in json])
def __init__(self, points: Sequence[Point]):
self.points = points
if len(self.points) < 3:
raise ValueError(f"A polygon must have at least three points; failed on polygon {repr(self)}")
def scale(self, factor: Union[float, int, Tuple[float, float], Point]) -> Polygon:
"""
Resizes the polygon according to `factor`. The scaling factor can either
be a scalar (`int` or `float`), in which case the polygon will be scaled
by the same factor on both axes, or a point-like (`Tuple[float, float]`
or `Point`), in which case the polygon will be scaled independently on
each axis.
"""
return Polygon([p.scale(factor) for p in self.points])
def to_json(self) -> PolygonJson:
"""
Serializes this object as a `PolygonJson`.
"""
return [point.to_json() for point in self.points]
def assert_valid(self) -> None:
"""
Ensures that this polygon is valid on the unit plane.
"""
for point in self.points:
point.assert_valid()
# TODO(mdsavage): check for self-intersection?
def __repr__(self) -> str:
return basic_repr("Polygon", self.points)
def __eq__(self, other: object) -> bool:
# TODO(mdsavage): currently, this requires the points to be in the same order, not just represent the same polygon
if not isinstance(other, Polygon):
return NotImplemented
return self.points == other.points
def __mul__(self, o: Union[int, float]) -> Polygon:
if not isinstance(o, (int, float)): # type: ignore - pyright complains about the isinstance check being redundant
return NotImplemented
return Polygon([p * o for p in self.points])
def __iter__(self) -> Generator[Point, None, None]:
yield from self.points
Classes
class Polygon (points: Sequence[Point])
-
A polygon in 2D space.
Expand source code
class Polygon: """ A polygon in 2D space. """ points: Sequence[Point] """ The vertices of this polygon. """ @staticmethod def from_json(json: PolygonJson) -> Polygon: """ Creates a `Polygon` from a `PolygonJson`. """ return Polygon([Point.from_json(pt) for pt in json]) def __init__(self, points: Sequence[Point]): self.points = points if len(self.points) < 3: raise ValueError(f"A polygon must have at least three points; failed on polygon {repr(self)}") def scale(self, factor: Union[float, int, Tuple[float, float], Point]) -> Polygon: """ Resizes the polygon according to `factor`. The scaling factor can either be a scalar (`int` or `float`), in which case the polygon will be scaled by the same factor on both axes, or a point-like (`Tuple[float, float]` or `Point`), in which case the polygon will be scaled independently on each axis. """ return Polygon([p.scale(factor) for p in self.points]) def to_json(self) -> PolygonJson: """ Serializes this object as a `PolygonJson`. """ return [point.to_json() for point in self.points] def assert_valid(self) -> None: """ Ensures that this polygon is valid on the unit plane. """ for point in self.points: point.assert_valid() # TODO(mdsavage): check for self-intersection? def __repr__(self) -> str: return basic_repr("Polygon", self.points) def __eq__(self, other: object) -> bool: # TODO(mdsavage): currently, this requires the points to be in the same order, not just represent the same polygon if not isinstance(other, Polygon): return NotImplemented return self.points == other.points def __mul__(self, o: Union[int, float]) -> Polygon: if not isinstance(o, (int, float)): # type: ignore - pyright complains about the isinstance check being redundant return NotImplemented return Polygon([p * o for p in self.points]) def __iter__(self) -> Generator[Point, None, None]: yield from self.points
Class variables
var points : Sequence[Point]
-
The vertices of this polygon.
Static methods
def from_json(json: PolygonJson) ‑> Polygon
-
Creates a
Polygon
from aPolygonJson
.Expand source code
@staticmethod def from_json(json: PolygonJson) -> Polygon: """ Creates a `Polygon` from a `PolygonJson`. """ return Polygon([Point.from_json(pt) for pt in json])
Methods
def assert_valid(self) ‑> None
-
Ensures that this polygon is valid on the unit plane.
Expand source code
def assert_valid(self) -> None: """ Ensures that this polygon is valid on the unit plane. """ for point in self.points: point.assert_valid() # TODO(mdsavage): check for self-intersection?
def scale(self, factor: Union[float, int, Tuple[float, float], Point]) ‑> Polygon
-
Resizes the polygon according to
factor
. The scaling factor can either be a scalar (int
orfloat
), in which case the polygon will be scaled by the same factor on both axes, or a point-like (Tuple[float, float]
orPoint
), in which case the polygon will be scaled independently on each axis.Expand source code
def scale(self, factor: Union[float, int, Tuple[float, float], Point]) -> Polygon: """ Resizes the polygon according to `factor`. The scaling factor can either be a scalar (`int` or `float`), in which case the polygon will be scaled by the same factor on both axes, or a point-like (`Tuple[float, float]` or `Point`), in which case the polygon will be scaled independently on each axis. """ return Polygon([p.scale(factor) for p in self.points])
def to_json(self) ‑> Sequence[Tuple[float, float]]
-
Serializes this object as a
PolygonJson
.Expand source code
def to_json(self) -> PolygonJson: """ Serializes this object as a `PolygonJson`. """ return [point.to_json() for point in self.points]