city_retrofit/helpers/city_util.py

123 lines
4.2 KiB
Python

from persistence.models import Building
from city_model_structure.building_demand.surface import Surface
from typing import Dict, List, Union
import numpy as np
class CityUtil(object):
# holds a single instance of this class
_instance = None
def __init__(self):
pass
def __new__(cls):
"""
Implemented for a singleton pattern
"""
if cls._instance is None:
cls._instance = super(CityUtil, cls).__new__(cls)
return cls._instance
def _class_object_to_dict(self, class_obj) -> Union[Dict, None]:
"""
converts a class object to a dictionary
:param class_obj: the class object
:return:
"""
if class_obj is None:
return None
if type(class_obj) is not dict:
return vars(class_obj)
return class_obj
def _ndarray_to_list(self, key, building_dict) -> Union[Dict, None]:
"""
Converts a numpy array to dictionary
:param key: the key to the dictionary value
:param building_dict: the dictionary
:return:
"""
if dict is not None:
if type(building_dict[key]) is np.ndarray:
return building_dict[key].tolist()
else:
return building_dict[key]
return None
def object_list_to_dict_list(self, object_list):
"""
converts a list of objects to a list of dictionaries
:param object_list: a list of objects
:return:
"""
if object_list is None:
return []
return [self._class_object_to_dict(obj) for obj in object_list]
def _serialize_points(self, points) -> List:
"""
Deserializes arry of Point objects to array of dictionarier
:param points: a Point object
:return a list of points []:
"""
if points is None:
return None
serialized_points = []
for i in range(len(points)):
point = self._class_object_to_dict(points[i])
point['_coordinates'] = self._ndarray_to_list('_coordinates', point)
serialized_points.append(point)
return serialized_points
def extract_building_data(self, building: Building) -> Dict:
"""
Extracts various values from a building
:param building: the building object
:return: a dictionary {} of building attributes
"""
dict_building = {}
for key, value in vars(building).items():
if key in ['_name', '_year_of_construction', '_function', '_floor_area']:
continue
if type(value) is list:
if len(value) == 0:
dict_building[key] = []
elif len(value) > 0:
if type(value[0]) is Surface:
try:
surfaces = []
for surface in value:
surface_dict = vars(surface)
perimeter_polygon = self._class_object_to_dict(surface_dict['_perimeter_polygon'])
solid_polygon = self._class_object_to_dict(surface_dict['_solid_polygon'])
holes_polygon = self._class_object_to_dict(surface_dict['_holes_polygons'])
if perimeter_polygon is not None:
perimeter_polygon['_coordinates'] = self._ndarray_to_list('_coordinates', perimeter_polygon)
perimeter_polygon['_points'] = self._serialize_points(perimeter_polygon['_points'])
surface_dict['_perimeter_polygon'] = perimeter_polygon
if holes_polygon is not None:
holes_polygon['_coordinates'] = self._ndarray_to_list('_coordinates', holes_polygon)
holes_polygon['_points'] = self._serialize_points(holes_polygon['_points'])
surface_dict['_holes_polygons'] = holes_polygon
if solid_polygon is not None:
solid_polygon['_coordinates'] = self._ndarray_to_list('_coordinates', solid_polygon)
solid_polygon['_points'] = self._serialize_points(solid_polygon['_points'])
surface_dict['_solid_polygon'] = solid_polygon
surfaces.append(surface_dict)
dict_building[key] = surfaces
except KeyError as err:
print(f'Dictionary key error: {err}')
elif value is None:
dict_building[key] = None
elif type(value) in [str, int, dict, np.float64]:
dict_building[key] = value
elif type(value) is np.ndarray:
dict_building[key] = value.tolist()
return dict_building