Generate facilities from buildings in a city

This commit is contained in:
Ruben1729 2024-01-26 12:36:53 -05:00
parent e3108e08ad
commit 2baf9ec518
12 changed files with 254559 additions and 14 deletions

Binary file not shown.

View File

@ -0,0 +1,78 @@
import hub.helpers.constants as cte
class HubFunctionToMatsimActivity:
"""
Hub function to nrcan construction function class
"""
def __init__(self):
self._dictionary = {
cte.RESIDENTIAL: 'home',
cte.SINGLE_FAMILY_HOUSE: 'home',
cte.MULTI_FAMILY_HOUSE: 'home',
cte.ROW_HOUSE: 'home',
cte.MID_RISE_APARTMENT: 'home',
cte.HIGH_RISE_APARTMENT: 'home',
cte.OFFICE_AND_ADMINISTRATION: 'work',
cte.SMALL_OFFICE: 'work',
cte.MEDIUM_OFFICE: 'work',
cte.LARGE_OFFICE: 'work',
cte.COURTHOUSE: 'work',
cte.FIRE_STATION: 'work',
cte.PENITENTIARY: 'work',
cte.POLICE_STATION: 'work',
cte.POST_OFFICE: 'work',
cte.LIBRARY: 'edu',
cte.EDUCATION: 'edu',
cte.PRIMARY_SCHOOL: 'edu',
cte.PRIMARY_SCHOOL_WITH_SHOWER: 'edu',
cte.SECONDARY_SCHOOL: 'edu',
cte.UNIVERSITY: 'edu',
cte.LABORATORY_AND_RESEARCH_CENTER: 'edu',
cte.STAND_ALONE_RETAIL: 'secondary',
cte.HOSPITAL: 'work',
cte.OUT_PATIENT_HEALTH_CARE: 'work',
cte.HEALTH_CARE: 'work',
cte.RETIREMENT_HOME_OR_ORPHANAGE: 'home',
cte.COMMERCIAL: 'secondary',
cte.STRIP_MALL: 'secondary',
cte.SUPERMARKET: 'secondary',
cte.RETAIL_SHOP_WITHOUT_REFRIGERATED_FOOD: 'secondary',
cte.RETAIL_SHOP_WITH_REFRIGERATED_FOOD: 'secondary',
cte.RESTAURANT: 'secondary',
cte.QUICK_SERVICE_RESTAURANT: 'secondary',
cte.FULL_SERVICE_RESTAURANT: 'secondary',
cte.HOTEL: 'work',
cte.HOTEL_MEDIUM_CLASS: 'work',
cte.SMALL_HOTEL: 'work',
cte.LARGE_HOTEL: 'work',
cte.DORMITORY: 'work',
cte.EVENT_LOCATION: 'secondary',
cte.CONVENTION_CENTER: 'secondary',
cte.HALL: 'secondary',
cte.GREEN_HOUSE: 'secondary',
cte.INDUSTRY: 'work',
cte.WORKSHOP: 'work',
cte.WAREHOUSE: 'work',
cte.WAREHOUSE_REFRIGERATED: 'work',
cte.SPORTS_LOCATION: 'secondary',
cte.SPORTS_ARENA: 'secondary',
cte.GYMNASIUM: 'secondary',
cte.MOTION_PICTURE_THEATRE: 'secondary',
cte.MUSEUM: 'secondary',
cte.PERFORMING_ARTS_THEATRE: 'secondary',
cte.TRANSPORTATION: 'secondary',
cte.AUTOMOTIVE_FACILITY: 'work',
cte.PARKING_GARAGE: 'work',
cte.RELIGIOUS: 'secondary',
cte.NON_HEATED: 'secondary',
cte.DATACENTER: 'work',
cte.FARM: 'work'
}
@property
def dictionary(self) -> dict:
"""
Get the dictionary
:return: {}
"""
return self._dictionary

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,294 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": 12,
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-73.57945149010348,
45.49793915473101
],
[
-73.57945502047383,
45.497935600591106
],
[
-73.57945748913181,
45.49793681276347
],
[
-73.57945995778985,
45.49793802493576
],
[
-73.57946108986009,
45.49793688584562
],
[
-73.57946222064952,
45.49793574585649
],
[
-73.57946503164756,
45.497932909392325
],
[
-73.5794800321942,
45.497917804072586
],
[
-73.57949503273288,
45.49790269875081
],
[
-73.57950823165471,
45.49788939886833
],
[
-73.57952143057031,
45.497876098984314
],
[
-73.57952481016481,
45.49787269972034
],
[
-73.57952818975889,
45.49786930045622
],
[
-73.57963374256275,
45.49776298233438
],
[
-73.57963739684415,
45.497759299424665
],
[
-73.57956562282082,
45.49772405755894
],
[
-73.5795624921933,
45.497722521006246
],
[
-73.57955974509859,
45.4977252944393
],
[
-73.57953557695755,
45.497749634054365
],
[
-73.5795114087957,
45.497773973664174
],
[
-73.57945076790263,
45.49783505227953
],
[
-73.57939012687844,
45.49789613086214
],
[
-73.57938759058709,
45.49789868818189
],
[
-73.57938505429556,
45.49790124550157
],
[
-73.57941717242674,
45.49791701633786
],
[
-73.5794136407655,
45.497920563278754
],
[
-73.57943256542505,
45.497929854507255
],
[
-73.57944202776348,
45.49793450461953
],
[
-73.57945149010348,
45.49793915473101
]
]
]
},
"properties": {
"OBJECTID_12": 12,
"gml_id": 1340982,
"gml_parent": "fme-gen-5fa2a82b-c38e-4bf0-9e8f-10a47b9f64f7",
"citygml_ta": "http://www.opengis.net/citygml/building/2.0",
"citygml_fe": "cityObjectMember",
"citygml__1": " ",
"citygml__2": " ",
"gml_descri": " ",
"gml_name": " ",
"citygml_cr": " ",
"citygml_te": " ",
"externalRe": " ",
"external_1": " ",
"external_2": " ",
"citygml_ge": " ",
"citygml_re": " ",
"citygml__3": " ",
"citygml_ap": " ",
"citygml_cl": " ",
"citygml__4": " ",
"citygml_fu": " ",
"citygml__5": " ",
"citygml_us": " ",
"citygml__6": " ",
"citygml_ye": " ",
"citygml__7": " ",
"citygml_ro": " ",
"citygml__8": " ",
"citygml_me": 19.113,
"citygml__9": "#m",
"citygml_st": " ",
"citygml_10": " ",
"citygml_11": " ",
"citygml_12": " ",
"citygml_13": " ",
"citygml_14": " ",
"citygml_ou": " ",
"citygml_in": " ",
"citygml_bo": " ",
"citygml_le": " ",
"citygml_15": " ",
"citygml_co": " ",
"citygml_ad": " ",
"Volume": "2931.350",
"parcelle": " ",
"OBJECTID": 1056,
"gml_id_1": "384b2b1c-2e25-4f6a-b082-d272dba3453f",
"gml_pare_1": 1340982,
"citygml_16": "http://www.opengis.net/citygml/building/2.0",
"citygml_17": "boundedBy",
"citygml_18": " ",
"citygml_19": " ",
"gml_desc_1": " ",
"gml_name_1": " ",
"citygml_20": " ",
"citygml_21": " ",
"external_3": " ",
"external_4": " ",
"external_5": " ",
"citygml_22": " ",
"citygml_23": " ",
"citygml_24": " ",
"citygml_25": " ",
"citygml_26": " ",
"citygml_op": " ",
"Area": 191.404,
"FID_": 0,
"Join_Count": 2,
"TARGET_FID": 1058,
"gml_id_12": 1340982,
"gml_pare_2": "fme-gen-5fa2a82b-c38e-4bf0-9e8f-10a47b9f64f7",
"citygml_27": "http://www.opengis.net/citygml/building/2.0",
"citygml_28": "cityObjectMember",
"citygml_29": " ",
"citygml_30": " ",
"gml_desc_2": " ",
"gml_name_2": " ",
"citygml_31": " ",
"citygml_32": " ",
"external_6": " ",
"external_7": " ",
"external_8": " ",
"citygml_33": " ",
"citygml_34": " ",
"citygml_35": " ",
"citygml_36": " ",
"citygml_37": " ",
"citygml_38": " ",
"citygml_39": " ",
"citygml_40": " ",
"citygml_41": " ",
"citygml_42": " ",
"citygml_43": " ",
"citygml_44": " ",
"citygml_45": " ",
"citygml_46": " ",
"citygml_47": 19.113,
"citygml_48": "#m",
"citygml_49": " ",
"citygml_50": " ",
"citygml_51": " ",
"citygml_52": " ",
"citygml_53": " ",
"citygml_54": " ",
"citygml_55": " ",
"citygml_56": " ",
"citygml_57": " ",
"citygml_58": " ",
"citygml_59": " ",
"citygml_60": " ",
"citygml_61": " ",
"Volume_1": "2931.350",
"Field": 0,
"Field1": 0,
"OBJECTID_1": 1056,
"gml_id_12_": "384b2b1c-2e25-4f6a-b082-d272dba3453f",
"gml_pare_3": 1340982,
"citygml_62": "http://www.opengis.net/citygml/building/2.0",
"citygml_63": "boundedBy",
"citygml_64": " ",
"citygml_65": " ",
"gml_desc_3": " ",
"gml_name_3": " ",
"citygml_66": " ",
"citygml_67": " ",
"external_9": " ",
"externa_10": " ",
"externa_11": " ",
"citygml_68": " ",
"citygml_69": " ",
"citygml_70": " ",
"citygml_71": " ",
"citygml_72": " ",
"citygml_73": " ",
"Area_1": 191.404,
"cityGML_hi": 0,
"Z_Min": 46.1162,
"Z_Max": 64.399,
"Shape_Leng": 63.6906066955,
"ID_UEV": "01036804",
"CIVIQUE_DE": " 2170",
"CIVIQUE_FI": " 2170",
"NOM_RUE": "rue Bishop (MTL)",
"MUNICIPALI": 50,
"ETAGE_HORS": 3,
"NOMBRE_LOG": 1,
"ANNEE_CONS": 1900,
"CODE_UTILI": 6000,
"LIBELLE_UT": "Immeuble à bureaux",
"CATEGORIE_": "Régulier",
"MATRICULE8": "9839-57-7770-3-000-0000",
"SUPERFICIE": 259,
"SUPERFIC_1": 490,
"NO_ARROND_": "REM19",
"Shape_Le_1": 0.00093336765858,
"Shape_Ar_1": 3.0845126501e-8,
"Z_Min_1": null,
"Z_Max_1": null,
"Shape_Length": 63.69060669550123,
"Shape_Area": 174.69050030775531
}
}
]
}

File diff suppressed because it is too large Load Diff

45
main.py
View File

@ -1,20 +1,37 @@
import subprocess from pathlib import Path
import sys
def run_matsim(config_file_path=None): from hub.imports.geometry_factory import GeometryFactory
java_path = "java" from hub.imports.construction_factory import ConstructionFactory
jar_path = "matsim.jar" from hub.imports.usage_factory import UsageFactory
command = [java_path, "-jar", jar_path] from hub.helpers.dictionaries import Dictionaries
if config_file_path: from matsim_engine import MatSimEngine
command.append(config_file_path)
subprocess.run(command) try:
file_path = (Path(__file__).parent / 'input_files' / 'summerschool_all_buildings.geojson')
construction_format = 'nrcan'
usage_format = 'nrcan'
energy_systems_format = 'montreal_custom'
out_path = (Path(__file__).parent / 'output_files')
tmp_folder = (Path(__file__).parent / 'tmp')
if len(sys.argv) > 1: print('[simulation start]')
config_file = sys.argv[1] city = GeometryFactory('geojson',
else: path=file_path,
config_file = None height_field='citygml_me',
year_of_construction_field='ANNEE_CONS',
function_field='CODE_UTILI',
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
run_matsim(config_file) print(f'city created from {file_path}')
ConstructionFactory(construction_format, city).enrich()
print('enrich constructions... done')
UsageFactory(usage_format, city).enrich()
print('enrich usage... done')
MatSimEngine(city, 'output_files')
except Exception as ex:
print('error: ', ex)
print('[simulation abort]')

View File

@ -0,0 +1,19 @@
class MatsimActivityToMatsimSchedule:
"""
Hub function to nrcan construction function class
"""
def __init__(self):
self._dictionary = {
'work': '08:00:00-18:00:00',
'home': '00:00:00-30:00:00',
'edu': '08:00:00-18:00:00',
'secondary': '08:00:00-20:00:00'
}
@property
def dictionary(self) -> dict:
"""
Get the dictionary
:return: {}
"""
return self._dictionary

66
matsim_engine.py Normal file
View File

@ -0,0 +1,66 @@
import subprocess
import xmltodict
from matsim_activity_to_matsim_schedule import MatsimActivityToMatsimSchedule
from hub_function_to_matsim_activity import HubFunctionToMatsimActivity
class MatSimEngine:
def __init__(self, city, output_file_path):
self._city = city
self._output_file_path = output_file_path
facilities_dict = {
'facilities': {
'@name': 'Montreal Facilities',
'facility': []
}
}
hub_function_to_matsim = HubFunctionToMatsimActivity()
matsim_schedule = MatsimActivityToMatsimSchedule()
# 1- Facilities
# TODO: Add the ability for a building to have multiple activities
for building in city.buildings:
activity = hub_function_to_matsim.dictionary[building.function]
schedule = matsim_schedule.dictionary[activity]
start_time, end_time = schedule.split('-')
facility = {
'@id': building.name,
'@x': str(building.centroid[0]),
'@y': str(building.centroid[1]),
'activity': {
'@type': activity,
'capacity': {
'@value': '4.0' # TODO: Replace with a proper value taken from function
},
'opentime': {
'@day': 'wkday',
'@start_time': start_time,
'@end_time': end_time
}
}
}
facilities_dict['facilities']['facility'].append(facility)
# Convert the Python dictionary to an XML string
xml_content = xmltodict.unparse(facilities_dict, pretty=True)
# Write the XML to the file
with open(f"{output_file_path}/montreal_facilities.xml", 'w') as file:
file.write(xml_content)
# 2- Network
# 3- Population
# 4- Config Generation
def run(self):
java_path = "java"
jar_path = "matsim.jar"
command = [java_path, "-jar", jar_path]
# Must generate this config file first.
# command.append(config_file_path)
subprocess.run(command)

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<facilities name="Montreal Facilities">
<facility id="3" x="3854959.3147786935" y="6039970.256562924">
<activity type="secondary">
<capacity value="4.0"></capacity>
<opentime day="wkday" start_time="08:00:00" end_time="20:00:00"></opentime>
</activity>
</facility>
<facility id="5" x="3854967.9909430863" y="6039992.286574578">
<activity type="home">
<capacity value="4.0"></capacity>
<opentime day="wkday" start_time="00:00:00" end_time="30:00:00"></opentime>
</activity>
</facility>
<facility id="6" x="3854961.5685679" y="6039981.23266926">
<activity type="home">
<capacity value="4.0"></capacity>
<opentime day="wkday" start_time="00:00:00" end_time="30:00:00"></opentime>
</activity>
</facility>
<facility id="8" x="3854996.7269906714" y="6040014.087941397">
<activity type="work">
<capacity value="4.0"></capacity>
<opentime day="wkday" start_time="08:00:00" end_time="18:00:00"></opentime>
</activity>
</facility>
<facility id="9" x="3855012.732080259" y="6040010.546487992">
<activity type="work">
<capacity value="4.0"></capacity>
<opentime day="wkday" start_time="08:00:00" end_time="18:00:00"></opentime>
</activity>
</facility>
<facility id="12" x="3855004.9829044794" y="6040017.1087535">
<activity type="work">
<capacity value="4.0"></capacity>
<opentime day="wkday" start_time="08:00:00" end_time="18:00:00"></opentime>
</activity>
</facility>
<facility id="67" x="3854967.5354593457" y="6040000.320902303">
<activity type="work">
<capacity value="4.0"></capacity>
<opentime day="wkday" start_time="08:00:00" end_time="18:00:00"></opentime>
</activity>
</facility>
<facility id="68" x="3854966.6880635563" y="6040020.215150922">
<activity type="work">
<capacity value="4.0"></capacity>
<opentime day="wkday" start_time="08:00:00" end_time="18:00:00"></opentime>
</activity>
</facility>
</facilities>

File diff suppressed because it is too large Load Diff