python-package/lets_plot/geo_data/gis/geometry.py (65 lines of code) (raw):

from typing import List from ..type_assertion import assert_list_type class GeometryBase: pass class GeoPoint(GeometryBase): def __init__(self, lon: float, lat: float): self.lon: float = lon self.lat: float = lat def __eq__(self, other): return isinstance(other, GeoPoint) \ and self.lon == other.lon \ and self.lat == other.lat def __ne__(self, other): return not self == other class GeoRect(GeometryBase): def __init__(self, start_lon: float, min_lat: float, end_lon: float, max_lat: float): self.start_lon: float = start_lon self.min_lat: float = min_lat self.end_lon: float = end_lon self.max_lat: float = max_lat def crosses_antimeridian(self): return self.start_lon > self.end_lon def __eq__(self, other): return isinstance(other, GeoRect) \ and self.start_lon == other.start_lon \ and self.min_lat == other.min_lat \ and self.end_lon == other.end_lon \ and self.max_lat == other.max_lat def __ne__(self, other): return not self == other class Ring(GeometryBase): def __init__(self, points: List[GeoPoint]): assert_list_type(points, GeoPoint) self.points: List[GeoPoint] = points def __eq__(self, other): return isinstance(other, Ring) \ and self.points == other.points def __ne__(self, other): return not self == other class Polygon(GeometryBase): def __init__(self, rings: List[Ring]): assert_list_type(rings, Ring) self.rings: List[Ring] = rings def __eq__(self, other): if not isinstance(other, Polygon): return False for r, o in zip(self.rings, other.rings): if r != o: return False return True def __ne__(self, other): return not self == other class Multipolygon(GeometryBase): def __init__(self, polygons: List[Polygon]): assert_list_type(polygons, Polygon) self.polygons: List[Polygon] = polygons def __eq__(self, other): if not isinstance(other, Multipolygon): return False for p, o in zip(self.polygons, other.polygons): if p != o: return False return True def __ne__(self, other): return not self == other