city_retrofit/city_model_structure/city.py

162 lines
3.9 KiB
Python
Raw Normal View History

2020-06-09 11:28:50 -04:00
"""
City module
SPDX - License - Identifier: LGPL - 3.0 - or -later
Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
"""
import sys
from typing import List, Union
import pyproj
import reverse_geocoder as rg
from pyproj import Transformer
from city_model_structure.building import Building
2020-06-09 11:28:50 -04:00
from city_model_structure.city_object import CityObject
2020-05-19 17:23:29 -04:00
class City:
2020-06-09 11:28:50 -04:00
"""
City class
"""
def __init__(self, lower_corner, upper_corner, srs_name, buildings=None):
self._buildings = None
self._name = None
self._lower_corner = lower_corner
self._upper_corner = upper_corner
self._buildings = buildings
self._srs_name = srs_name
# todo: right now extracted at city level, in the future should be extracted also at building level if exist
self._location = None
2020-06-09 11:28:50 -04:00
def _get_location(self):
if self._location is None:
gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth
try:
input_reference = pyproj.CRS(self.srs_name) # Projected coordinate system from input data
except pyproj.exceptions.CRSError:
print('Invalid projection reference system, please check the input data. (e.g. in CityGML files: srs_name)')
2020-06-09 11:28:50 -04:00
sys.exit()
2020-06-03 16:56:17 -04:00
transformer = Transformer.from_crs(input_reference, gps)
coordinates = transformer.transform(self.lower_corner[0], self.lower_corner[1])
self._location = rg.search(coordinates)
return self._location
@property
def country_code(self):
2020-06-09 11:28:50 -04:00
"""
City country code
:return: str
"""
return self._get_location()[0]['cc']
@property
def name(self):
2020-06-09 11:28:50 -04:00
"""
City name
:return: str
"""
if self._name is None:
2020-06-09 11:28:50 -04:00
self._name = self._get_location()[0]['name']
return self._name
@property
def city_objects(self) -> Union[List[CityObject], None]:
2020-06-09 11:28:50 -04:00
"""
City objects belonging to the city
:return: None or [CityObject]
2020-06-09 11:28:50 -04:00
"""
return self.buildings
@property
def buildings(self) -> Union[List[Building], None]:
"""
Buildings belonging to the city
:return: None or [Building]
"""
return self._buildings
@property
def trees(self) -> NotImplementedError:
"""
Trees belonging to the city
:return: NotImplementedError
"""
raise NotImplementedError
@property
def bixi_features(self) -> NotImplementedError:
"""
Bixi features belonging to the city
:return: NotImplementedError
"""
raise NotImplementedError
@property
def composting_plants(self) -> NotImplementedError:
"""
Composting plants belonging to the city
:return: NotImplementedError
"""
raise NotImplementedError
@property
def lower_corner(self):
2020-06-09 11:28:50 -04:00
"""
City lower corner
:return: [x,y,z]
"""
return self._lower_corner
@property
def upper_corner(self):
2020-06-09 11:28:50 -04:00
"""
City upper corner
:return: [x,y,z]
"""
return self._upper_corner
def city_object(self, name) -> Union[CityObject, None]:
2020-06-09 11:28:50 -04:00
"""
Retrieve the city CityObject with the given name
:param name:str
:return: None or CityObject
"""
for city_object in self.buildings:
2020-06-09 11:28:50 -04:00
if city_object.name == name:
return city_object
return None
def add_city_object(self, new_city_object):
2020-06-09 11:28:50 -04:00
"""
Add a CityObject to the city
:param new_city_object:CityObject
:return: None
"""
if new_city_object.type != 'building':
raise NotImplementedError(new_city_object.type)
if self._buildings is None:
self._buildings = []
for building in self.buildings:
for surface in building.surfaces:
for surface2 in new_city_object.surfaces:
surface.shared(surface2)
self._buildings.append(new_city_object)
@property
def srs_name(self):
2020-06-09 11:28:50 -04:00
"""
srs name
:return: str
"""
return self._srs_name
@name.setter
def name(self, value):
2020-06-09 11:28:50 -04:00
"""
Set the city name
2020-06-10 11:08:38 -04:00
:param value:str
2020-06-09 11:28:50 -04:00
:return: None
"""
self._name = value