mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-19 11:43:53 +00:00
Modernize zone and type table mappings for COBie 2.4 with Emma Hooper
This commit is contained in:
+76
-137
@@ -66,22 +66,6 @@ def get_zones(ifc_file):
|
|||||||
has_space = True
|
has_space = True
|
||||||
if not has_space:
|
if not has_space:
|
||||||
results.append((zone, None))
|
results.append((zone, None))
|
||||||
if zones:
|
|
||||||
return results
|
|
||||||
|
|
||||||
zone_spaces = {}
|
|
||||||
for space in ifc_file.by_type("IfcSpace"):
|
|
||||||
for _, props in ifcopenshell.util.element.get_psets(space).items():
|
|
||||||
for name, value in props.items():
|
|
||||||
if "ZoneName" in name:
|
|
||||||
zone_name = val(value)
|
|
||||||
space_name = val(space.Name)
|
|
||||||
category = name
|
|
||||||
zone_key = str(name) + "," + str(category)
|
|
||||||
zone_spaces.setdefault(zone_key, [])
|
|
||||||
if space_name not in zone_spaces[zone_key]:
|
|
||||||
zone_spaces[zone_key].append(space_name)
|
|
||||||
results.append(((zone_name, category), space_name))
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
@@ -443,21 +427,6 @@ def get_space_data(ifc_file, element):
|
|||||||
def get_zone_data(ifc_file, element):
|
def get_zone_data(ifc_file, element):
|
||||||
zone, space = element
|
zone, space = element
|
||||||
|
|
||||||
if isinstance(zone, tuple):
|
|
||||||
name, category = zone
|
|
||||||
history = get_history(ifc_file)
|
|
||||||
return {
|
|
||||||
"Name": name,
|
|
||||||
"CreatedBy": get_email_from_history(history) if history else None,
|
|
||||||
"CreatedOn": ifcopenshell.util.date.ifc2datetime(history.CreationDate).isoformat() if history else None,
|
|
||||||
"Category": category,
|
|
||||||
"SpaceNames": space,
|
|
||||||
"ExternalSystem": history.OwningApplication.ApplicationFullName if history else None,
|
|
||||||
"ExternalObject": "IfcPropertySingleValue",
|
|
||||||
"ExternalIdentifier": None,
|
|
||||||
"Description": val(name) or val(category),
|
|
||||||
}
|
|
||||||
|
|
||||||
name = zone.Name
|
name = zone.Name
|
||||||
parent = ifcopenshell.util.element.get_aggregate(zone)
|
parent = ifcopenshell.util.element.get_aggregate(zone)
|
||||||
if parent and val(parent.Name):
|
if parent and val(parent.Name):
|
||||||
@@ -480,136 +449,106 @@ def get_zone_data(ifc_file, element):
|
|||||||
|
|
||||||
|
|
||||||
def get_type_data(ifc_file, element):
|
def get_type_data(ifc_file, element):
|
||||||
pset_metadata = {}
|
|
||||||
pset_mapping = {
|
|
||||||
"manufacturer": {"Manufacturer"},
|
|
||||||
"model_number": {"ModelNumber", "ArticleNumber", "ModelReference"},
|
|
||||||
"warranty_guarantor_parts": {"WarrantyGuarantorParts", "PointOfContact"},
|
|
||||||
"warranty_guarantor_labor": {"WarrantyGuarantorLabor", "PointOfContact"},
|
|
||||||
"warranty_description": {"WarrantyDescription", "WarrantyIdentifier"},
|
|
||||||
"replacement_cost": {"ReplacementCost", "Replacement Cost", "Replacement", "Cost"},
|
|
||||||
"nominal_length": {"NominalLength", "OverallLength", "Length"},
|
|
||||||
"nominal_width": {"NominalWidth", "OverallWidth", "Width"},
|
|
||||||
# https://github.com/opensourceBIM/COBie-plugins/blob/master/COBiePlugins/lib/IfcToCobieConfig.xml#L104
|
|
||||||
"nominal_height": {"NominalHeight", "Height"}, # Original has a typo "Heght"
|
|
||||||
"model_reference": {"ModelLabel"}, # I believe this is what the intention was, not "ModelReference".
|
|
||||||
"shape": {"Shape"},
|
|
||||||
"size": {"Size"},
|
|
||||||
"color": {"Color", "Colour"},
|
|
||||||
"finish": {"Finish"},
|
|
||||||
"grade": {"Grade"},
|
|
||||||
"material": {"Material"},
|
|
||||||
"constituents": {"Constituents", "Parts"},
|
|
||||||
"features": {"Features"},
|
|
||||||
"accessibility_performance": {"AccessibilityPerformance", "Access"},
|
|
||||||
"code_performance": {"CodePerformance", "Regulation"},
|
|
||||||
"sustainability_performance": {"SustainabilityPerformance", "Environmental"},
|
|
||||||
}
|
|
||||||
asset_type = None
|
asset_type = None
|
||||||
asset_type_names = {"AssetType", "AssetAccountingType"}
|
manufacturer = None
|
||||||
|
model_number = None
|
||||||
warranty_duration_parts = None
|
warranty_duration_parts = None
|
||||||
warranty_duration_parts_names = {"WarrantyDurationParts", "WarrantyPeriod"}
|
|
||||||
warranty_duration_labor = None
|
warranty_duration_labor = None
|
||||||
warranty_duration_labor_names = {"WarrantyDurationLabor", "WarrantyPeriod"}
|
|
||||||
warranty_duration_unit = None
|
warranty_duration_unit = None
|
||||||
|
replacement_cost = None
|
||||||
expected_life = None
|
expected_life = None
|
||||||
expected_life_names = {"ExpectedLife", "Expected Life", "ServiceLifeDuration", "Expected"}
|
|
||||||
duration_unit = None
|
duration_unit = None
|
||||||
|
warranty_description = None
|
||||||
|
nominal_length = None
|
||||||
|
nominal_width = None
|
||||||
|
nominal_height = None
|
||||||
|
model_reference = None
|
||||||
|
shape = None
|
||||||
|
size = None
|
||||||
|
color = None
|
||||||
|
finish = None
|
||||||
|
grade = None
|
||||||
|
material = None
|
||||||
|
constituents = None
|
||||||
|
features = None
|
||||||
|
accessibility_performance = None
|
||||||
|
code_performance = None
|
||||||
|
sustainability_performance = None
|
||||||
|
|
||||||
for pset_name, props in ifcopenshell.util.element.get_psets(element).items():
|
for pset_name, props in ifcopenshell.util.element.get_psets(element).items():
|
||||||
pset_warranty_type = None
|
pset_warranty_type = None
|
||||||
if pset_name == "Pset_Warranty":
|
if pset_name == "COBie_Warranty":
|
||||||
if "parts" in (props.get("WarrantyIdentifier", "") or "").lower():
|
warranty_guarantor_parts = props.get("WarrantyGuarantorParts", None)
|
||||||
pset_warranty_type = "parts"
|
warranty_guarantor_labor = props.get("WarrantyGuarantorLabor", None)
|
||||||
elif "labor" in (props.get("WarrantyIdentifier", "") or "").lower():
|
warranty_duration_parts = props.get("WarrantyDurationParts", None)
|
||||||
pset_warranty_type = "labor"
|
warranty_duration_labor = props.get("WarrantyDurationLabor", None)
|
||||||
|
warranty_duration_unit = props.get("WarrantyDurationUnit", None)
|
||||||
pset = ifc_file.by_id(props["id"])
|
warranty_description = props.get("WarrantyDescription", None)
|
||||||
|
elif pset_name == "COBie_Asset":
|
||||||
for name, value in props.items():
|
asset_type = props.get("AssetType", None)
|
||||||
for key, prop_names in pset_mapping.items():
|
elif pset_name == "COBie_EconomicImpactValues":
|
||||||
if not pset_metadata.get(key, None) and name in prop_names and val(value):
|
replacement_cost = props.get("ReplacementCost", None)
|
||||||
pset_metadata[key] = str(value)
|
elif pset_name == "COBie_ServiceLife":
|
||||||
|
duration_unit = props.get("DurationUnit", None)
|
||||||
if not asset_type and name in asset_type_names and val(value):
|
duration_unit = props.get("ServiceLifeDuration", props.get("ExpectedLife", None))
|
||||||
value = value.strip().lower()
|
elif pset_name == "COBie_Specification":
|
||||||
if value in ("moveable", "nonfixed"):
|
nominal_length = props.get("NominalLength", None)
|
||||||
asset_type = "Moveable"
|
nominal_width = props.get("NominalWidth", None)
|
||||||
elif value == "fixed":
|
nominal_height = props.get("NominalHeight", None)
|
||||||
asset_type = "Fixed"
|
shape = props.get("Shape", None)
|
||||||
if not warranty_duration_parts and name in warranty_duration_parts_names and val(value):
|
size = props.get("Size", None)
|
||||||
warranty_duration_parts = str(value)
|
color = props.get("Color", None)
|
||||||
if not warranty_duration_unit:
|
finish = props.get("Finish", None)
|
||||||
warranty_duration_unit = get_property_unit(pset, name)
|
grade = props.get("Grade", None)
|
||||||
if not warranty_duration_labor and name in warranty_duration_labor_names and val(value):
|
material = props.get("Material", None)
|
||||||
warranty_duration_labor = str(value)
|
constituents = props.get("Constituents", None)
|
||||||
if not warranty_duration_unit:
|
features = props.get("Features", None)
|
||||||
warranty_duration_unit = get_property_unit(pset, name)
|
accessibility_performance = props.get("AccessibilityPerformance", None)
|
||||||
if not expected_life and name in expected_life_names and val(value):
|
code_performance = props.get("CodePerformance", None)
|
||||||
expected_life = str(value)
|
sustainability_performance = props.get("SustainabilityPerformance", None)
|
||||||
if not duration_unit:
|
elif pset_name == "Pset_ServiceLife":
|
||||||
duration_unit = get_property_unit(pset, name)
|
duration_unit = props.get("ServiceLifeDuration", None)
|
||||||
|
elif pset_name == "Pset_ManufacturerTypeInformation":
|
||||||
if pset_warranty_type == "parts" and val(value):
|
manufacturer = props.get("Manufacturer", None)
|
||||||
if name == "PointOfContact":
|
model_number = props.get("ModelLabel", None)
|
||||||
# https://github.com/buildingSMART/IFC4.3.x-development/issues/698
|
model_reference = props.get("ModelReference", None)
|
||||||
warranty_guarantor_parts = str(value)
|
|
||||||
elif name == "WarrantyPeriod":
|
|
||||||
warranty_duration_parts = str(value)
|
|
||||||
unit = get_property_unit(pset, name)
|
|
||||||
warranty_duration_unit = unit or warranty_duration_unit
|
|
||||||
elif pset_warranty_type == "labor" and val(value):
|
|
||||||
if name == "PointOfContact":
|
|
||||||
# https://github.com/buildingSMART/IFC4.3.x-development/issues/698
|
|
||||||
warranty_guarantor_labor = str(value)
|
|
||||||
elif name == "WarrantyPeriod":
|
|
||||||
warranty_duration_labor = str(value)
|
|
||||||
unit = get_property_unit(pset, name)
|
|
||||||
warranty_duration_unit = unit or warranty_duration_unit
|
|
||||||
|
|
||||||
if warranty_duration_parts or warranty_duration_labor:
|
|
||||||
if not warranty_duration_unit:
|
|
||||||
warranty_duration_unit = get_unit_type_name(ifc_file, "TIMEUNIT")
|
|
||||||
|
|
||||||
if not asset_type and element.is_a("IfcFurnitureType"):
|
|
||||||
asset_type = "Moveable"
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"Name": val(element.Name),
|
"Name": val(element.Name),
|
||||||
"CreatedBy": get_created_by(element),
|
"CreatedBy": get_created_by(element),
|
||||||
"CreatedOn": get_created_on(element),
|
"CreatedOn": get_created_on(element),
|
||||||
"Category": get_category(element),
|
"Category": get_category(element),
|
||||||
"Description": val(element.Description) or val(element.Name),
|
"Description": val(element.Description),
|
||||||
"AssetType": asset_type,
|
"AssetType": asset_type,
|
||||||
"Manufacturer": pset_metadata.get("manufacturer", None),
|
"Manufacturer": manufacturer,
|
||||||
"ModelNumber": pset_metadata.get("model_number", None),
|
"ModelNumber": model_number,
|
||||||
"WarrantyGuarantorParts": pset_metadata.get("warranty_guarantor_parts", None),
|
"WarrantyGuarantorParts": warranty_guarantor_parts,
|
||||||
"WarrantyDurationParts": warranty_duration_parts,
|
"WarrantyDurationParts": warranty_duration_parts,
|
||||||
"WarrantyGuarantorLabor": pset_metadata.get("warranty_guarantor_labor", None),
|
"WarrantyGuarantorLabor": warranty_guarantor_labor,
|
||||||
"WarrantyDurationLabor": warranty_duration_labor,
|
"WarrantyDurationLabor": warranty_duration_labor,
|
||||||
"WarrantyDurationUnit": warranty_duration_unit,
|
"WarrantyDurationUnit": warranty_duration_unit,
|
||||||
"ExternalSystem": get_external_system(element),
|
"ExternalSystem": get_external_system(element),
|
||||||
"ExternalObject": element.is_a(),
|
"ExternalObject": element.is_a(),
|
||||||
"ExternalIdentifier": element.GlobalId,
|
"ExternalIdentifier": element.GlobalId,
|
||||||
"ReplacementCost": pset_metadata.get("replacement_cost", None),
|
"ReplacementCost": replacement_cost,
|
||||||
"ExpectedLife": expected_life,
|
"ExpectedLife": expected_life,
|
||||||
"DurationUnit": duration_unit,
|
"DurationUnit": duration_unit,
|
||||||
"WarrantyDescription": pset_metadata.get("warranty_description", None),
|
"WarrantyDescription": warranty_description,
|
||||||
"NominalLength": pset_metadata.get("nominal_length", None),
|
"NominalLength": nominal_length,
|
||||||
"NominalWidth": pset_metadata.get("nominal_width", None),
|
"NominalWidth": nominal_width,
|
||||||
"NominalHeight": pset_metadata.get("nominal_height", None),
|
"NominalHeight": nominal_height,
|
||||||
"ModelReference": pset_metadata.get("model_reference", None),
|
"ModelReference": model_reference,
|
||||||
"Shape": pset_metadata.get("shape", None),
|
"Shape": shape,
|
||||||
"Size": pset_metadata.get("size", None),
|
"Size": size,
|
||||||
"Color": pset_metadata.get("color", None),
|
"Color": color,
|
||||||
"Finish": pset_metadata.get("finish", None),
|
"Finish": finish,
|
||||||
"Grade": pset_metadata.get("grade", None),
|
"Grade": grade,
|
||||||
"Material": pset_metadata.get("material", None),
|
"Material": material,
|
||||||
"Constituents": pset_metadata.get("constituents", None),
|
"Constituents": constituents,
|
||||||
"Features": pset_metadata.get("features", None),
|
"Features": features,
|
||||||
"AccessibilityPerformance": pset_metadata.get("accessibility_performance", None),
|
"AccessibilityPerformance": accessibility_performance,
|
||||||
"CodePerformance": pset_metadata.get("code_performance", None),
|
"CodePerformance": code_performance,
|
||||||
"SustainabilityPerformance": pset_metadata.get("sustainability_performance", None),
|
"SustainabilityPerformance": sustainability_performance,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -496,7 +496,7 @@ def get_type_data(ifc_file, element):
|
|||||||
pset_metadata = {}
|
pset_metadata = {}
|
||||||
pset_mapping = {
|
pset_mapping = {
|
||||||
"manufacturer": {"Manufacturer"},
|
"manufacturer": {"Manufacturer"},
|
||||||
"model_number": {"ModelNumber", "ArticleNumber", "ModelReference"},
|
"model_number": {"ModelNumber", "ArticleNumber", "ModelLabel"},
|
||||||
"warranty_guarantor_parts": {"WarrantyGuarantorParts", "PointOfContact"},
|
"warranty_guarantor_parts": {"WarrantyGuarantorParts", "PointOfContact"},
|
||||||
"warranty_guarantor_labor": {"WarrantyGuarantorLabor", "PointOfContact"},
|
"warranty_guarantor_labor": {"WarrantyGuarantorLabor", "PointOfContact"},
|
||||||
"warranty_description": {"WarrantyDescription", "WarrantyIdentifier"},
|
"warranty_description": {"WarrantyDescription", "WarrantyIdentifier"},
|
||||||
@@ -505,7 +505,7 @@ def get_type_data(ifc_file, element):
|
|||||||
"nominal_width": {"NominalWidth", "OverallWidth", "Width"},
|
"nominal_width": {"NominalWidth", "OverallWidth", "Width"},
|
||||||
# https://github.com/opensourceBIM/COBie-plugins/blob/master/COBiePlugins/lib/IfcToCobieConfig.xml#L104
|
# https://github.com/opensourceBIM/COBie-plugins/blob/master/COBiePlugins/lib/IfcToCobieConfig.xml#L104
|
||||||
"nominal_height": {"NominalHeight", "Height"}, # Original has a typo "Heght"
|
"nominal_height": {"NominalHeight", "Height"}, # Original has a typo "Heght"
|
||||||
"model_reference": {"ModelLabel"}, # I believe this is what the intention was, not "ModelReference".
|
"model_reference": {"ModelReference"},
|
||||||
"shape": {"Shape"},
|
"shape": {"Shape"},
|
||||||
"size": {"Size"},
|
"size": {"Size"},
|
||||||
"color": {"Color", "Colour"},
|
"color": {"Color", "Colour"},
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ What makes IfcOpenShell special?
|
|||||||
IfcOpenShell has a huge amount of unique features and capabilities not found in any other technology.
|
IfcOpenShell has a huge amount of unique features and capabilities not found in any other technology.
|
||||||
|
|
||||||
- IfcOpenShell is the oldest and most mature open source IFC library available. It's developed since 2011 by a community of hundreds of developers and trusted to deliver many AEC technologies that power our industry. IfcOpenShell is also taught in numerous universities and cited in hundreds of academic publications.
|
- IfcOpenShell is the oldest and most mature open source IFC library available. It's developed since 2011 by a community of hundreds of developers and trusted to deliver many AEC technologies that power our industry. IfcOpenShell is also taught in numerous universities and cited in hundreds of academic publications.
|
||||||
- Lots of platforms and package management options are available: Windows, Mac, Mac ARM (M1, M2), Linux, Web Assembly (WASM), Docker, AWS Lambda, Google Colab, and more.
|
- Lots of platforms and package management options are available: Windows, Mac Intel, Mac Silicon (M1, M2), Linux, Web Assembly (WASM), Docker, AWS Lambda, Google Colab, and more.
|
||||||
- Develop in C++, Python, or JavaScript via Pyodide.
|
- Develop in C++, Python, or JavaScript via Pyodide.
|
||||||
- All tools can be used either as a developer library, through a command line interface, or using a rich graphical interface. Whether you're deploy headless server tools for your own pipeline, writing your own apps, or an end-user, there's something for you.
|
- All tools can be used either as a developer library, through a command line interface, or using a rich graphical interface. Whether you're deploying headless server tools for your own pipeline, writing your own apps, or an end-user, there's something for you.
|
||||||
- Supports IFC2X3, IFC4, and IFC4.3. Custom schemas (such as experimental or draft schemas) may be loaded at run-time instead of having to recompile.
|
- Supports IFC2X3, IFC4, and IFC4.3. Custom schemas (such as experimental or draft schemas) may be loaded at run-time instead of having to recompile.
|
||||||
- Built-in IFC validation is possible from basic syntax validation to more detailed "Where Rule" checks. This is the same validation that powers the official buildingSMART validation engine.
|
- Built-in IFC validation is possible from basic syntax validation to more detailed "Where Rule" checks. This is the same validation that powers the official buildingSMART validation engine.
|
||||||
- Read and write IFC-SPF, IFCJSON, IFCXML, IFCHDF5, MySQL, and SQLite.
|
- Read and write IFC-SPF, IFCJSON, IFCXML, IFCHDF5, MySQL, and SQLite.
|
||||||
@@ -57,7 +57,7 @@ IfcOpenShell is a modular ecosystem of tools that work together, where each tool
|
|||||||
"**IfcOpenShell**", "The core library for C++ developers. The library includes the ability to parse schemas, tessellate and process implicit geometry."
|
"**IfcOpenShell**", "The core library for C++ developers. The library includes the ability to parse schemas, tessellate and process implicit geometry."
|
||||||
"**IfcOpenShell-Python**", "Python bindings to the core IfcOpenShell C++ system, as well as high level analysis and authoring functions."
|
"**IfcOpenShell-Python**", "Python bindings to the core IfcOpenShell C++ system, as well as high level analysis and authoring functions."
|
||||||
"**IfcConvert**", "A command-line application for converting IFC geometry into file formats such as OBJ, DAE, GLB, STP, IGS, XML, SVG, H5, and IFC itself."
|
"**IfcConvert**", "A command-line application for converting IFC geometry into file formats such as OBJ, DAE, GLB, STP, IGS, XML, SVG, H5, and IFC itself."
|
||||||
"**BlenderBIM Add-on**", "A graphical add-on that lets you analyse, author, and modify IFC with Blender."
|
"**BlenderBIM Add-on**", "A graphical add-on that lets you analyse, author, and modify IFC with Blender. Graphically create BIM models from scratch!"
|
||||||
"**BCF**", "BIM Collaboration Format (BCF) is a standard to manage and exchange coordination topics between disciplines collaborating on a project by changing XML files or querying an API."
|
"**BCF**", "BIM Collaboration Format (BCF) is a standard to manage and exchange coordination topics between disciplines collaborating on a project by changing XML files or querying an API."
|
||||||
"**BIMServer-Plugin**", "A plugin to the open source BIMServer CDE to allow you to use IfcOpenShell to parse, view, and audit models."
|
"**BIMServer-Plugin**", "A plugin to the open source BIMServer CDE to allow you to use IfcOpenShell to parse, view, and audit models."
|
||||||
"**BIMTester**", "A utility that allows you to write Gherkin-based tests for models."
|
"**BIMTester**", "A utility that allows you to write Gherkin-based tests for models."
|
||||||
|
|||||||
Reference in New Issue
Block a user