feat: add csv handler to geometry factory

This commit is contained in:
Majid Rezaei 2024-10-03 18:27:21 -04:00
parent ad630027b6
commit a84ba4725e
2 changed files with 106 additions and 1 deletions

View File

@ -0,0 +1,85 @@
import csv
import uuid
from decimal import Decimal, InvalidOperation
from hub.city_model_structure.simplified_building import SimplifiedBuilding
from hub.city_model_structure.simplified_city import SimplifiedCity
class Csv:
"""
CSV class
"""
def __init__(self,
path,
year_of_construction_field=None,
function_field=None,
function_to_hub=None,
total_floor_area_field=None):
self._simplified_city = None
self._year_of_construction_field = year_of_construction_field
self._function_field = function_field
self._function_to_hub = function_to_hub
self._total_floor_area_field = total_floor_area_field
with open(path, 'r', encoding='utf8') as csv_file:
reader = csv.DictReader(csv_file)
self._csv_data = [row for row in reader]
def safe_int(self, value):
if value in ('NULL', '', None):
return None
try:
return int(value)
except ValueError:
return None
def safe_float(self, value):
if value in ('NULL', '', None):
return None
try:
return float(value)
except ValueError:
return None
def safe_decimal(self, value):
if value in ('NULL', '', None):
return None
try:
return Decimal(value)
except InvalidOperation:
return None
@property
def city(self) -> SimplifiedCity:
if self._simplified_city is None:
self._simplified_city = SimplifiedCity()
for row in self._csv_data:
year_of_construction = None
if self._year_of_construction_field:
year_of_construction = self.safe_int(row[self._year_of_construction_field])
function = None
if self._function_field:
function = row[self._function_field]
if self._function_to_hub:
function = self._function_to_hub.get(function, function)
total_floor_area = None
if self._total_floor_area_field:
total_floor_area = self.safe_float(row[self._total_floor_area_field])
if 'id_provinc' in row and row['id_provinc']:
building_name = str(self.safe_decimal(row['id_provinc']))
else:
building_name = str(uuid.uuid4())
building = SimplifiedBuilding(
name=building_name,
total_floor_area=total_floor_area,
year_of_construction=year_of_construction,
function=function
)
if building.total_floor_area is not None and building.total_floor_area >= 25:
self._simplified_city.add_city_object(building)
return self._simplified_city

View File

@ -6,10 +6,12 @@ Project Coder Guille Gutierrez guillermo.gutierrezmorote@concordia.ca
""" """
from hub.city_model_structure.city import City from hub.city_model_structure.city import City
from hub.city_model_structure.simplified_city import SimplifiedCity
from hub.helpers.utils import validate_import_export_type from hub.helpers.utils import validate_import_export_type
from hub.imports.geometry.citygml import CityGml from hub.imports.geometry.citygml import CityGml
from hub.imports.geometry.geojson import Geojson from hub.imports.geometry.geojson import Geojson
from hub.imports.geometry.obj import Obj from hub.imports.geometry.obj import Obj
from hub.imports.geometry.csv import Csv
class GeometryFactory: class GeometryFactory:
@ -23,7 +25,8 @@ class GeometryFactory:
year_of_construction_field=None, year_of_construction_field=None,
function_field=None, function_field=None,
function_to_hub=None, function_to_hub=None,
hub_crs=None): hub_crs=None,
total_floor_area_field=None):
self._file_type = '_' + file_type.lower() self._file_type = '_' + file_type.lower()
validate_import_export_type(GeometryFactory, file_type) validate_import_export_type(GeometryFactory, file_type)
self._path = path self._path = path
@ -33,6 +36,7 @@ class GeometryFactory:
self._function_field = function_field self._function_field = function_field
self._function_to_hub = function_to_hub self._function_to_hub = function_to_hub
self._hub_crs = hub_crs self._hub_crs = hub_crs
self._total_floor_area_field = total_floor_area_field
@property @property
def _citygml(self) -> City: def _citygml(self) -> City:
@ -68,6 +72,14 @@ class GeometryFactory:
self._function_to_hub, self._function_to_hub,
self._hub_crs).city self._hub_crs).city
@property
def _csv(self) -> SimplifiedCity:
return Csv(self._path,
self._year_of_construction_field,
self._function_field,
self._function_to_hub,
self._total_floor_area_field).city
@property @property
def city(self) -> City: def city(self) -> City:
""" """
@ -75,3 +87,11 @@ class GeometryFactory:
:return: City :return: City
""" """
return getattr(self, self._file_type, lambda: None) return getattr(self, self._file_type, lambda: None)
@property
def simplified_city(self) -> SimplifiedCity:
"""
Enrich the city given to the class using the class given handler
:return: SimplifiedCity
"""
return getattr(self, self._file_type, lambda: None)