From 6a10c65068b122c85ed574ad21c916458dbc6506 Mon Sep 17 00:00:00 2001 From: Licini Date: Wed, 17 Jul 2024 19:37:34 +0200 Subject: [PATCH] add unit getter setter --- CHANGELOG.md | 2 + scripts/4.2_create_new.py | 12 +++-- .../entities/extensions/IfcProject.py | 16 +++---- src/compas_ifc/file.py | 1 - src/compas_ifc/model.py | 45 ++++++++++++------- 5 files changed, 42 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aca5e3b..9585d5a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added `export` method to `IFCFile` and `Model` to export selected list of entities. * Added `update_linear_deflection` to `Model`. +* Added `unit` attribute to `Model`. +* Added `unit` keyword argument to `Model.template()`. ### Changed diff --git a/scripts/4.2_create_new.py b/scripts/4.2_create_new.py index 4885e473..15020247 100644 --- a/scripts/4.2_create_new.py +++ b/scripts/4.2_create_new.py @@ -6,19 +6,17 @@ from compas_ifc.model import Model -model = Model.template(storey_count=1) +model = Model.template(storey_count=1, unit="m") -# Default unit is mm -box = Box.from_width_height_depth(5000, 5000, 50) -sphere = Sphere(2000) +box = Box.from_width_height_depth(5, 5, 0.05) +sphere = Sphere(2) mesh = Mesh.from_obj(compas.get("tubemesh.obj")) -mesh.scale(1000) storey = model.building_storeys[0] element1 = model.create("IfcWall", geometry=box, frame=Frame([0, 0, 0]), name="Wall", parent=storey) -element2 = model.create("IfcRoof", geometry=mesh, frame=Frame([0, 0, 5000]), name="Roof", parent=storey) -element3 = model.create(geometry=sphere, frame=Frame([0, 5000, 0]), name="Sphere", parent=storey, properties={"Custom_Pset": {"Custom_Property": "Custom Value"}}) +element2 = model.create("IfcRoof", geometry=mesh, frame=Frame([0, 0, 5]), name="Roof", parent=storey) +element3 = model.create(geometry=sphere, frame=Frame([0, 5, 0]), name="Sphere", parent=storey, properties={"Custom_Pset": {"Custom_Property": "Custom Value"}}) model.print_spatial_hierarchy(max_depth=5) model.show() diff --git a/src/compas_ifc/entities/extensions/IfcProject.py b/src/compas_ifc/entities/extensions/IfcProject.py index 5fd70ab5..03a430d0 100644 --- a/src/compas_ifc/entities/extensions/IfcProject.py +++ b/src/compas_ifc/entities/extensions/IfcProject.py @@ -52,30 +52,24 @@ def units(self): units_in_context = self.UnitsInContext or self.file.get_entities_by_type("IfcUnitAssignment")[0] for unit in units_in_context.Units: if unit.is_a("IfcSIUnit"): - units.append( - { - "type": unit.UnitType, - "name": unit.Name, - "prefix": unit.Prefix, - } - ) + units.append(unit) return units @property def length_unit(self): for unit in self.units: - if unit["type"] == "LENGTHUNIT": + if unit["UnitType"] == "LENGTHUNIT": return unit @property def length_scale(self): unit = self.length_unit if unit: - if unit["name"] == "METRE" and not unit["prefix"]: + if unit.Name == "METRE" and not unit.Prefix: return 1.0 - if unit["name"] == "METRE" and unit["prefix"] == "CENTI": + if unit.Name == "METRE" and unit.Prefix == "CENTI": return 1e-2 - if unit["name"] == "METRE" and unit["prefix"] == "MILLI": + if unit.Name == "METRE" and unit.Prefix == "MILLI": return 1e-3 return 1.0 diff --git a/src/compas_ifc/file.py b/src/compas_ifc/file.py index 17ba3076..04a42877 100644 --- a/src/compas_ifc/file.py +++ b/src/compas_ifc/file.py @@ -34,7 +34,6 @@ def __init__(self, model, filepath=None, schema="IFC4", use_occ=False, load_geom else: self._file = ifcopenshell.open(filepath) print("IFC file loaded: {}".format(filepath)) - self.model.update_linear_deflection() self._schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(self._file.schema) diff --git a/src/compas_ifc/model.py b/src/compas_ifc/model.py index e4ac4f42..865cb812 100644 --- a/src/compas_ifc/model.py +++ b/src/compas_ifc/model.py @@ -19,6 +19,8 @@ class Model(Data): def __init__(self, filepath=None, schema=None, use_occ=False, load_geometries=True): self.file = IFCFile(self, filepath=filepath, schema=schema, use_occ=use_occ, load_geometries=load_geometries) + if filepath: + self.update_linear_deflection() @property def schema(self): @@ -53,6 +55,27 @@ def building_storeys(self) -> list["IfcBuildingStorey"]: def building_elements(self) -> list["IfcBuildingElement"]: return self.file.get_entities_by_type("IfcBuildingElement") + @property + def unit(self): + length_unit = self.project.length_unit + if length_unit.Name == "METRE" and length_unit.Prefix == "MILLI": + return "mm" + elif length_unit.Name == "METRE" and length_unit.Prefix == "CENTI": + return "cm" + elif length_unit.Name == "METRE" and not length_unit.Prefix: + return "m" + + @unit.setter + def unit(self, value): + if value == "mm": + self.project.length_unit.Prefix = "MILLI" + elif value == "cm": + self.project.length_unit.Prefix = "CENTI" + elif value == "m": + self.project.length_unit.Prefix = None + else: + raise ValueError("Invalid unit. Use 'mm', 'cm', or 'm'.") + def get_entities_by_type(self, type_name) -> list["Base"]: return self.file.get_entities_by_type(type_name) @@ -103,16 +126,8 @@ def show(self, entity=None): raise ImportError("The show method requires compas_viewer to be installed.") viewer = Viewer() - length_unit = self.project.length_unit - print(f"Using length unit: {length_unit}") - if length_unit["name"] == "METRE" and length_unit["prefix"] == "MILLI": - viewer.unit = "mm" - elif length_unit["name"] == "METRE" and length_unit["prefix"] == "CENTI": - viewer.unit = "cm" - elif length_unit["name"] == "METRE" and not length_unit["prefix"]: - viewer.unit = "m" - else: - raise ValueError(f"Unsupported length unit: {length_unit}") + print(f"Unit: {self.unit}") + viewer.unit = self.unit entity_map = {} @@ -151,16 +166,15 @@ def create(self, cls="IfcBuildingElementProxy", parent=None, geometry=None, fram return self.file.create(cls=cls, parent=parent, geometry=geometry, frame=frame, properties=properties, **kwargs) def update_linear_deflection(self): - length_unit = self.project.length_unit - if length_unit["name"] == "METRE" and length_unit["prefix"] == "MILLI": + if self.unit == "mm": TOL.lineardeflection = 1 - elif length_unit["name"] == "METRE" and length_unit["prefix"] == "CENTI": + elif self.unit == "cm": TOL.lineardeflection = 1e-1 - elif length_unit["name"] == "METRE" and not length_unit["prefix"]: + elif self.unit == "m": TOL.lineardeflection = 1e-3 @classmethod - def template(cls, schema="IFC4", building_count=1, storey_count=1): + def template(cls, schema="IFC4", building_count=1, storey_count=1, unit="mm"): model = cls(schema=schema) project = model.file.default_project site = model.create("IfcSite", parent=project, Name="Default Site") @@ -169,6 +183,7 @@ def template(cls, schema="IFC4", building_count=1, storey_count=1): for j in range(storey_count): model.create("IfcBuildingStorey", parent=building, Name=f"Default Storey {j+1}") + model.unit = unit model.update_linear_deflection() return model