Module datatap.geometry.polygon
Expand source code
from __future__ import annotations
from typing import Any, 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 pointlike (`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 selfintersection?
def __repr__(self) > str:
return basic_repr("Polygon", self.points)
def __eq__(self, other: Any) > 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 pointlike (`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 selfintersection? def __repr__(self) > str: return basic_repr("Polygon", self.points) def __eq__(self, other: Any) > 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 selfintersection?
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 pointlike (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 pointlike (`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]