Add Address.x and Address.y coordinates

- the Address.x and Address.y properties use the UTMCoordinate class
  behind the scenes
- x and y are simple coordinates in an x-y plane
- the (0, 0) origin is the southwest corner of Address.city.viewport
This commit is contained in:
Alexander Hess 2021-01-02 16:29:50 +01:00
commit 6cb4be80f6
Signed by: alexander
GPG key ID: 344EA5AB10D868E0
5 changed files with 69 additions and 1 deletions

View file

@ -1,11 +1,14 @@
"""Provide the ORM's `Address` model."""
from typing import Any
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.dialects import postgresql
from sqlalchemy.ext import hybrid
from urban_meal_delivery.db import meta
from urban_meal_delivery.db import utils
class Address(meta.Base):
@ -64,6 +67,15 @@ class Address(meta.Base):
foreign_keys='[Order._delivery_address_id]',
)
def __init__(self, *args: Any, **kwargs: Any) -> None:
"""Create a new address."""
# Call SQLAlchemy's default `.__init__()` method.
super().__init__(*args, **kwargs)
self._utm_coordinates = utils.UTMCoordinate(
self.latitude, self.longitude, relative_to=self.city.as_origin,
)
def __repr__(self) -> str:
"""Non-literal text representation."""
return '<{cls}({street} in {city})>'.format(
@ -80,3 +92,13 @@ class Address(meta.Base):
`.is_primary` indicates the first in a group of `Address` objects.
"""
return self.id == self._primary_id
@property
def x(self) -> int: # noqa=WPS111
"""The `.easting` of the address in meters, relative to the `.city`."""
return self._utm_coordinates.x
@property
def y(self) -> int: # noqa=WPS111
"""The `.northing` of the address in meters, relative to the `.city`."""
return self._utm_coordinates.y

View file

@ -1,12 +1,13 @@
"""Provide the ORM's `City` model."""
from typing import Dict
from typing import Any, Dict
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.dialects import postgresql
from urban_meal_delivery.db import meta
from urban_meal_delivery.db import utils
class City(meta.Base):
@ -45,6 +46,18 @@ class City(meta.Base):
# Relationships
addresses = orm.relationship('Address', back_populates='city')
def __init__(self, *args: Any, **kwargs: Any) -> None:
"""Create a new city."""
# Call SQLAlchemy's default `.__init__()` method.
super().__init__(*args, **kwargs)
# Take the "lower left" of the viewport as the origin
# of a Cartesian coordinate system.
lower_left = self.viewport['southwest']
self._origin = utils.UTMCoordinate(
lower_left['latitude'], lower_left['longitude'],
)
def __repr__(self) -> str:
"""Non-literal text representation."""
return '<{cls}({name})>'.format(cls=self.__class__.__name__, name=self.name)
@ -81,3 +94,12 @@ class City(meta.Base):
'longitude': self._southwest_longitude,
},
}
@property
def as_origin(self) -> utils.UTMCoordinate:
"""The lower left corner of the `.viewport` in UTM coordinates.
This property serves as the `relative_to` argument to the
`UTMConstructor` when representing an `Address` in the x-y plane.
"""
return self._origin