From 7db319f3fdc3be3c0cdcb47c99b8d89bb7cb90cd Mon Sep 17 00:00:00 2001 From: guille Date: Thu, 3 Mar 2022 16:52:01 -0500 Subject: [PATCH] Partial implementation for the greenery catalog integration --- catalogs/catalog.py | 33 ++ .../ecore_greenery/greenerycatalog.ecore | 268 +++++++++++++++ .../ecore_greenery/greenerycatalog.py | 318 ++++++++++++++++++ .../greenerycatalog_no_quantities.ecore | 268 +++++++++++++++ catalogs/greenery/greenery_catalog.py | 41 +++ catalogs/greenery_catalog_factory.py | 44 +++ data/greenery/ecore_greenery_catalog.xml | 59 ++++ imports/geometry/rhino.py | 1 + 8 files changed, 1032 insertions(+) create mode 100644 catalogs/catalog.py create mode 100644 catalogs/greenery/ecore_greenery/greenerycatalog.ecore create mode 100644 catalogs/greenery/ecore_greenery/greenerycatalog.py create mode 100644 catalogs/greenery/ecore_greenery/greenerycatalog_no_quantities.ecore create mode 100644 catalogs/greenery/greenery_catalog.py create mode 100644 catalogs/greenery_catalog_factory.py create mode 100644 data/greenery/ecore_greenery_catalog.xml diff --git a/catalogs/catalog.py b/catalogs/catalog.py new file mode 100644 index 00000000..ed272383 --- /dev/null +++ b/catalogs/catalog.py @@ -0,0 +1,33 @@ +""" +Catalog base class +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca +""" + +class Catalog: + """ + Catalog name + """ + + @property + def names(self): + """ + Base property to return the catalog entries names + :return: not implemented error + """ + raise NotImplementedError + + @property + def entries(self): + """ + Base property to return the catalog entries + :return: not implemented error + """ + raise NotImplementedError + + def get_entry(self, name): + """ + Base property to return the catalog entry matching the given name + :return: not implemented error + """ + raise NotImplementedError diff --git a/catalogs/greenery/ecore_greenery/greenerycatalog.ecore b/catalogs/greenery/ecore_greenery/greenerycatalog.ecore new file mode 100644 index 00000000..5c3bb85d --- /dev/null +++ b/catalogs/greenery/ecore_greenery/greenerycatalog.ecore @@ -0,0 +1,268 @@ + + + + +
+ + + + +
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ + + + +
+
+ + + + + + + + + +
+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + diff --git a/catalogs/greenery/ecore_greenery/greenerycatalog.py b/catalogs/greenery/ecore_greenery/greenerycatalog.py new file mode 100644 index 00000000..30ac116c --- /dev/null +++ b/catalogs/greenery/ecore_greenery/greenerycatalog.py @@ -0,0 +1,318 @@ +"""Definition of meta model 'greenerycatalog'.""" +from functools import partial +import pyecore.ecore as Ecore +from pyecore.ecore import * + + +name = 'greenerycatalog' +nsURI = 'http://ca.concordia/greenerycatalog' +nsPrefix = 'greenery' + +eClass = EPackage(name=name, nsURI=nsURI, nsPrefix=nsPrefix) + +eClassifiers = {} +getEClassifier = partial(Ecore.getEClassifier, searchspace=eClassifiers) +Management = EEnum('Management', literals=['Intensive', 'Extensive', 'SemiIntensive', 'NA']) + +Roughness = EEnum('Roughness', literals=['VeryRough', 'Rough', + 'MediumRough', 'MediumSmooth', 'Smooth', 'VerySmooth']) + + +class Soil(EObject, metaclass=MetaEClass): + + name = EAttribute(eType=EString, unique=True, derived=False, changeable=True) + roughness = EAttribute(eType=Roughness, unique=True, derived=False, + changeable=True, default_value=Roughness.MediumRough) + conductivityOfDrySoil = EAttribute( + eType=EString, unique=True, derived=False, changeable=True, default_value='1.0 W/(m*K)') + densityOfDrySoil = EAttribute(eType=EString, unique=True, derived=False, + changeable=True, default_value='1100 kg/m³') + specificHeatOfDrySoil = EAttribute( + eType=EString, unique=True, derived=False, changeable=True, default_value='1200 J/(kg*K)') + thermalAbsorptance = EAttribute(eType=EString, unique=True, + derived=False, changeable=True, default_value='0.9') + solarAbsorptance = EAttribute(eType=EString, unique=True, + derived=False, changeable=True, default_value='0.7') + visibleAbsorptance = EAttribute(eType=EString, unique=True, + derived=False, changeable=True, default_value='0.75') + saturationVolumetricMoistureContent = EAttribute( + eType=EString, unique=True, derived=False, changeable=True, default_value='0.0') + residualVolumetricMoistureContent = EAttribute( + eType=EString, unique=True, derived=False, changeable=True, default_value='0.05') + initialVolumetricMoistureContent = EAttribute( + eType=EString, unique=True, derived=False, changeable=True, default_value='0.1') + + def __init__(self, *, name=None, roughness=None, conductivityOfDrySoil=None, densityOfDrySoil=None, specificHeatOfDrySoil=None, thermalAbsorptance=None, solarAbsorptance=None, visibleAbsorptance=None, saturationVolumetricMoistureContent=None, residualVolumetricMoistureContent=None, initialVolumetricMoistureContent=None): + # if kwargs: + # raise AttributeError('unexpected arguments: {}'.format(kwargs)) + + super().__init__() + + if name is not None: + self.name = name + + if roughness is not None: + self.roughness = roughness + + if conductivityOfDrySoil is not None: + self.conductivityOfDrySoil = conductivityOfDrySoil + + if densityOfDrySoil is not None: + self.densityOfDrySoil = densityOfDrySoil + + if specificHeatOfDrySoil is not None: + self.specificHeatOfDrySoil = specificHeatOfDrySoil + + if thermalAbsorptance is not None: + self.thermalAbsorptance = thermalAbsorptance + + if solarAbsorptance is not None: + self.solarAbsorptance = solarAbsorptance + + if visibleAbsorptance is not None: + self.visibleAbsorptance = visibleAbsorptance + + if saturationVolumetricMoistureContent is not None: + self.saturationVolumetricMoistureContent = saturationVolumetricMoistureContent + + if residualVolumetricMoistureContent is not None: + self.residualVolumetricMoistureContent = residualVolumetricMoistureContent + + if initialVolumetricMoistureContent is not None: + self.initialVolumetricMoistureContent = initialVolumetricMoistureContent + + +class Plant(EObject, metaclass=MetaEClass): + + name = EAttribute(eType=EString, unique=True, derived=False, changeable=True) + height = EAttribute(eType=EString, unique=True, derived=False, + changeable=True, default_value='0.1 m') + leafAreaIndex = EAttribute(eType=EString, unique=True, derived=False, + changeable=True, default_value='2.5') + leafReflectivity = EAttribute(eType=EString, unique=True, + derived=False, changeable=True, default_value='0.1') + leafEmissivity = EAttribute(eType=EString, unique=True, derived=False, + changeable=True, default_value='0.9') + minimalStomatalResistance = EAttribute( + eType=EString, unique=True, derived=False, changeable=True, default_value='100.0 s/m') + co2Sequestration = EAttribute(eType=EString, unique=True, derived=False, + changeable=True, default_value='kgCO₂eq') + growsOn = EReference(ordered=True, unique=True, containment=False, derived=False, upper=-1) + + def __init__(self, *, name=None, height=None, leafAreaIndex=None, leafReflectivity=None, leafEmissivity=None, minimalStomatalResistance=None, growsOn=None, co2Sequestration=None): + # if kwargs: + # raise AttributeError('unexpected arguments: {}'.format(kwargs)) + + super().__init__() + + if name is not None: + self.name = name + + if height is not None: + self.height = height + + if leafAreaIndex is not None: + self.leafAreaIndex = leafAreaIndex + + if leafReflectivity is not None: + self.leafReflectivity = leafReflectivity + + if leafEmissivity is not None: + self.leafEmissivity = leafEmissivity + + if minimalStomatalResistance is not None: + self.minimalStomatalResistance = minimalStomatalResistance + + if co2Sequestration is not None: + self.co2Sequestration = co2Sequestration + + if growsOn: + self.growsOn.extend(growsOn) + + +class SupportEnvelope(EObject, metaclass=MetaEClass): + + roughness = EAttribute(eType=Roughness, unique=True, derived=False, + changeable=True, default_value=Roughness.MediumRough) + solarAbsorptance = EAttribute(eType=EDouble, unique=True, + derived=False, changeable=True, default_value=0.0) + conductivity = EAttribute(eType=EDouble, unique=True, derived=False, + changeable=True, default_value=0.0) + visibleAbsorptance = EAttribute(eType=EDouble, unique=True, + derived=False, changeable=True, default_value=0.0) + specificHeat = EAttribute(eType=EDouble, unique=True, derived=False, + changeable=True, default_value=0.0) + density = EAttribute(eType=EDouble, unique=True, derived=False, + changeable=True, default_value=0.0) + thermalAbsorptance = EAttribute(eType=EDouble, unique=True, + derived=False, changeable=True, default_value=0.0) + + def __init__(self, *, roughness=None, solarAbsorptance=None, conductivity=None, visibleAbsorptance=None, specificHeat=None, density=None, thermalAbsorptance=None): + # if kwargs: + # raise AttributeError('unexpected arguments: {}'.format(kwargs)) + + super().__init__() + + if roughness is not None: + self.roughness = roughness + + if solarAbsorptance is not None: + self.solarAbsorptance = solarAbsorptance + + if conductivity is not None: + self.conductivity = conductivity + + if visibleAbsorptance is not None: + self.visibleAbsorptance = visibleAbsorptance + + if specificHeat is not None: + self.specificHeat = specificHeat + + if density is not None: + self.density = density + + if thermalAbsorptance is not None: + self.thermalAbsorptance = thermalAbsorptance + + +class GreeneryCatalog(EObject, metaclass=MetaEClass): + + name = EAttribute(eType=EString, unique=True, derived=False, changeable=True) + description = EAttribute(eType=EString, unique=True, derived=False, changeable=True) + source = EAttribute(eType=EString, unique=True, derived=False, changeable=True) + plantCategories = EReference(ordered=True, unique=True, + containment=True, derived=False, upper=-1) + vegetationCategories = EReference(ordered=True, unique=True, + containment=True, derived=False, upper=-1) + soils = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1) + + def __init__(self, *, name=None, description=None, source=None, plantCategories=None, vegetationCategories=None, soils=None): + # if kwargs: + # raise AttributeError('unexpected arguments: {}'.format(kwargs)) + + super().__init__() + + if name is not None: + self.name = name + + if description is not None: + self.description = description + + if source is not None: + self.source = source + + if plantCategories: + self.plantCategories.extend(plantCategories) + + if vegetationCategories: + self.vegetationCategories.extend(vegetationCategories) + + if soils: + self.soils.extend(soils) + + +class PlantCategory(EObject, metaclass=MetaEClass): + """Excluding (that is non-overlapping) categories like Trees, Hedeges, Grasses that help users finding a specific biol. plant species.""" + name = EAttribute(eType=EString, unique=True, derived=False, changeable=True) + plants = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1) + + def __init__(self, *, name=None, plants=None): + # if kwargs: + # raise AttributeError('unexpected arguments: {}'.format(kwargs)) + + super().__init__() + + if name is not None: + self.name = name + + if plants: + self.plants.extend(plants) + + +class IrrigationSchedule(EObject, metaclass=MetaEClass): + + name = EAttribute(eType=EString, unique=True, derived=False, changeable=True) + + def __init__(self, *, name=None): + # if kwargs: + # raise AttributeError('unexpected arguments: {}'.format(kwargs)) + + super().__init__() + + if name is not None: + self.name = name + + +class Vegetation(EObject, metaclass=MetaEClass): + """Plant life or total plant cover (as of an area)""" + name = EAttribute(eType=EString, unique=True, derived=False, changeable=True) + thicknessOfSoil = EAttribute(eType=EString, unique=True, derived=False, + changeable=True, default_value='20 cm') + management = EAttribute(eType=Management, unique=True, derived=False, + changeable=True, default_value=Management.NA) + airGap = EAttribute(eType=EString, unique=True, derived=False, + changeable=True, default_value='0.0 cm') + soil = EReference(ordered=True, unique=True, containment=False, derived=False) + plants = EReference(ordered=True, unique=True, containment=True, derived=False, upper=-1) + + def __init__(self, *, name=None, thicknessOfSoil=None, soil=None, plants=None, management=None, airGap=None): + # if kwargs: + # raise AttributeError('unexpected arguments: {}'.format(kwargs)) + + super().__init__() + + if name is not None: + self.name = name + + if thicknessOfSoil is not None: + self.thicknessOfSoil = thicknessOfSoil + + if management is not None: + self.management = management + + if airGap is not None: + self.airGap = airGap + + if soil is not None: + self.soil = soil + + if plants: + self.plants.extend(plants) + + +class VegetationCategory(EObject, metaclass=MetaEClass): + """Excluding (that is non-overlapping) categories to help users finding a specific vegetation template.""" + name = EAttribute(eType=EString, unique=True, derived=False, changeable=True) + vegetationTemplates = EReference(ordered=True, unique=True, + containment=True, derived=False, upper=-1) + + def __init__(self, *, vegetationTemplates=None, name=None): + # if kwargs: + # raise AttributeError('unexpected arguments: {}'.format(kwargs)) + + super().__init__() + + if name is not None: + self.name = name + + if vegetationTemplates: + self.vegetationTemplates.extend(vegetationTemplates) + + +class PlantPercentage(EObject, metaclass=MetaEClass): + + percentage = EAttribute(eType=EString, unique=True, derived=False, + changeable=True, default_value='100') + plant = EReference(ordered=True, unique=True, containment=False, derived=False) + + def __init__(self, *, percentage=None, plant=None): + # if kwargs: + # raise AttributeError('unexpected arguments: {}'.format(kwargs)) + + super().__init__() + + if percentage is not None: + self.percentage = percentage + + if plant is not None: + self.plant = plant diff --git a/catalogs/greenery/ecore_greenery/greenerycatalog_no_quantities.ecore b/catalogs/greenery/ecore_greenery/greenerycatalog_no_quantities.ecore new file mode 100644 index 00000000..db58a9c0 --- /dev/null +++ b/catalogs/greenery/ecore_greenery/greenerycatalog_no_quantities.ecore @@ -0,0 +1,268 @@ + + + + +
+ + + + +
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ + + + +
+
+ + + + + + + + + +
+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + diff --git a/catalogs/greenery/greenery_catalog.py b/catalogs/greenery/greenery_catalog.py new file mode 100644 index 00000000..3ede5ab9 --- /dev/null +++ b/catalogs/greenery/greenery_catalog.py @@ -0,0 +1,41 @@ +""" +Greenery catalog +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca +""" + +from pyecore.resources import ResourceSet, URI +from catalogs.greenery.ecore_greenery.greenerycatalog import GreeneryCatalog as gc +from catalogs.catalog import Catalog +from pathlib import Path + + +class GreeneryCatalog(Catalog): + + def __init__(self, path): + base_path = Path(Path(__file__).parent / 'ecore_greenery' / 'greenerycatalog_no_quantities.ecore') + resource_set = ResourceSet() + data_model = resource_set.get_resource(URI(str(base_path))) + data_model_root = data_model.contents[0] + resource_set.metamodel_registry[data_model_root.nsURI] = data_model_root + resource = resource_set.get_resource(URI(str(path))) + catalog_data: gc = resource.contents[0] + self._data = {'vegetation': []} + vegetation = [] + for vegetation_category in catalog_data.vegetationCategories: + vegetation.append({vegetation_category.name: []}) + self._data['vegetation'] = vegetation + + @property + def names(self): + """ + :parm: + """ + _names = [] + for category in self._data: + for value in self._data[category]: + for key in value.keys(): + _names.append(key) + return _names + + diff --git a/catalogs/greenery_catalog_factory.py b/catalogs/greenery_catalog_factory.py new file mode 100644 index 00000000..8e7dfe29 --- /dev/null +++ b/catalogs/greenery_catalog_factory.py @@ -0,0 +1,44 @@ +""" +Greenery catalog publish the greenery information +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2022 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca +""" + +from pathlib import Path +from catalogs.greenery.greenery_catalog import GreeneryCatalog + + +class GreeneryCatalogFactory: + """ + GeometryFactory class + """ + def __init__(self, file_type, base_path=None): + if base_path is None: + base_path = Path(Path(__file__).parent.parent / 'data/greenery') + self._file_type = '_' + file_type.lower() + self._path = base_path + + @property + def _nrel(self) -> GreeneryCatalog: + """ + Return a greenery catalog using ecore as datasource + :return: GreeneryCatalog + """ + print('greenery') + return GreeneryCatalog((self._path / 'ecore_greenery_catalog.xml').resolve()) + + @property + def catalog(self) -> GreeneryCatalog: + """ + Enrich the city given to the class using the class given handler + :return: City + """ + return getattr(self, self._file_type, lambda: None) + + @property + def catalog_debug(self) -> GreeneryCatalog: + """ + Enrich the city given to the class using the class given handler + :return: City + """ + return GreeneryCatalog((self._path / 'ecore_greenery_catalog.xml').resolve()) \ No newline at end of file diff --git a/data/greenery/ecore_greenery_catalog.xml b/data/greenery/ecore_greenery_catalog.xml new file mode 100644 index 00000000..41b7801c --- /dev/null +++ b/data/greenery/ecore_greenery_catalog.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/imports/geometry/rhino.py b/imports/geometry/rhino.py index 23df7202..38c350f0 100644 --- a/imports/geometry/rhino.py +++ b/imports/geometry/rhino.py @@ -3,6 +3,7 @@ Rhino module parses rhino files and import the geometry into the city model stru SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca """ +import numpy as np from numpy import inf from rhino3dm import * from rhino3dm._rhino3dm import MeshType