From 56f4b721617259d4eee2f015b291c26f6e48c35c Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 24 Sep 2022 15:42:50 +1000 Subject: [PATCH] Reimplement profile cardinal points 1-9 with new profile engine --- .../blenderbim/bim/module/model/profile.py | 22 ++--- .../geometry/add_profile_representation.py | 86 ++++++++++++++++++- 2 files changed, 91 insertions(+), 17 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/model/profile.py b/src/blenderbim/blenderbim/bim/module/model/profile.py index 621fa79baa..ae4fec3a4a 100644 --- a/src/blenderbim/blenderbim/bim/module/model/profile.py +++ b/src/blenderbim/blenderbim/bim/module/model/profile.py @@ -417,9 +417,12 @@ class DumbProfileJoiner: axis = body = self.get_profile_axis(obj) self.axis = copy.deepcopy(axis) self.body = copy.deepcopy(body) - material = ifcopenshell.util.element.get_material(element, should_skip_usage=True) + material = ifcopenshell.util.element.get_material(element, should_skip_usage=False) + usage = None + if material.is_a("IfcMaterialProfileSetUsage"): + usage = material + material = material.ForProfileSet self.profile = material.CompositeProfile or material.MaterialProfiles[0].Profile - height = self.get_height(tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_definition_id)) self.clippings = [] for rel in element.ConnectedTo: @@ -467,6 +470,7 @@ class DumbProfileJoiner: context=self.body_context, profile=self.profile, depth=depth, + cardinal_point=usage.CardinalPoint if usage else None, clippings=self.clippings, ) @@ -769,20 +773,6 @@ class DumbProfileJoiner: (obj.matrix_world @ Vector((0.0, 0.0, max(z_values)))), ] - # TODO - def get_height(self, representation): - height = 3.0 - item = representation.Items[0] - while True: - if item.is_a("IfcExtrudedAreaSolid"): - height = item.Depth * self.unit_scale - break - elif item.is_a("IfcBooleanClippingResult"): - item = item.FirstOperand - else: - break - return height - # An extension of a profile is determined by casting a ray from the cardinal # point of either extreme along the profiles local Z axis to a target # object. The nearest result from this raycast will be the target extension diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_profile_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_profile_representation.py index 840df4a716..fef68cce0f 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_profile_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_profile_representation.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell.geom import ifcopenshell.util.unit @@ -43,10 +44,11 @@ class Usecase: ) def create_item(self): + point = self.get_point() extrusion = self.file.createIfcExtrudedAreaSolid( self.settings["profile"], self.file.createIfcAxis2Placement3D( - self.file.createIfcCartesianPoint((0.0, 0.0, 0.0)), + point, self.file.createIfcDirection((0.0, 0.0, 1.0)), self.file.createIfcDirection((1.0, 0.0, 0.0)), ), @@ -81,3 +83,85 @@ class Usecase: def convert_si_to_unit(self, co): return co / self.settings["unit_scale"] + + def get_point(self): + if not self.settings["cardinal_point"]: + return self.file.createIfcCartesianPoint((0.0, 0.0, 0.0)) + elif self.settings["cardinal_point"] == 1: + return self.file.createIfcCartesianPoint((-self.get_x() / 2, self.get_y() / 2, 0.0)) + elif self.settings["cardinal_point"] == 2: + return self.file.createIfcCartesianPoint((0.0, self.get_y() / 2, 0.0)) + elif self.settings["cardinal_point"] == 3: + return self.file.createIfcCartesianPoint((self.get_x() / 2, self.get_y() / 2, 0.0)) + elif self.settings["cardinal_point"] == 4: + return self.file.createIfcCartesianPoint((-self.get_x() / 2, 0.0, 0.0)) + elif self.settings["cardinal_point"] == 5: + return self.file.createIfcCartesianPoint((0.0, 0.0, 0.0)) + elif self.settings["cardinal_point"] == 6: + return self.file.createIfcCartesianPoint((self.get_x() / 2, 0.0, 0.0)) + elif self.settings["cardinal_point"] == 7: + return self.file.createIfcCartesianPoint((-self.get_x() / 2, -self.get_y() / 2, 0.0)) + elif self.settings["cardinal_point"] == 8: + return self.file.createIfcCartesianPoint((0.0, -self.get_y() / 2, 0.0)) + elif self.settings["cardinal_point"] == 9: + return self.file.createIfcCartesianPoint((self.get_x() / 2, -self.get_y() / 2, 0.0)) + # TODO other cardinal points + return self.file.createIfcCartesianPoint((0.0, 0.0, 0.0)) + + def get_x(self): + if self.settings["profile"].is_a("IfcAsymmetricIShapeProfileDef"): + return self.settings["profile"].OverallWidth + elif self.settings["profile"].is_a("IfcCShapeProfileDef"): + return self.settings["profile"].Width + elif self.settings["profile"].is_a("IfcCircleProfileDef"): + return self.settings["profile"].Radius * 2 + elif self.settings["profile"].is_a("IfcEllipseProfileDef"): + return self.settings["profile"].SemiAxis1 * 2 + elif self.settings["profile"].is_a("IfcIShapeProfileDef"): + return self.settings["profile"].OverallWidth + elif self.settings["profile"].is_a("IfcLShapeProfileDef"): + return self.settings["profile"].Width + elif self.settings["profile"].is_a("IfcRectangleProfileDef"): + return self.settings["profile"].XDim + elif self.settings["profile"].is_a("IfcTShapeProfileDef"): + return self.settings["profile"].FlangeWidth + elif self.settings["profile"].is_a("IfcUShapeProfileDef"): + return self.settings["profile"].FlangeWidth + elif self.settings["profile"].is_a("IfcZShapeProfileDef"): + return (self.settings["profile"].FlangeWidth * 2) - self.settings["profile"].WebThickness + else: + settings = ifcopenshell.geom.settings() + settings.set(settings.INCLUDE_CURVES, True) + shape = ifcopenshell.geom.create_shape(settings, element) + x = [verts[i] for i in range(0, len(shape.verts), 3)] + return self.convert_si_to_unit(max(x) - min(x)) + return 0.0 + + def get_y(self): + if self.settings["profile"].is_a("IfcAsymmetricIShapeProfileDef"): + return self.settings["profile"].OverallDepth + elif self.settings["profile"].is_a("IfcCShapeProfileDef"): + return self.settings["profile"].Depth + elif self.settings["profile"].is_a("IfcCircleProfileDef"): + return self.settings["profile"].Radius * 2 + elif self.settings["profile"].is_a("IfcEllipseProfileDef"): + return self.settings["profile"].SemiAxis2 * 2 + elif self.settings["profile"].is_a("IfcIShapeProfileDef"): + return self.settings["profile"].OverallDepth + elif self.settings["profile"].is_a("IfcLShapeProfileDef"): + return self.settings["profile"].Depth + elif self.settings["profile"].is_a("IfcRectangleProfileDef"): + return self.settings["profile"].YDim + elif self.settings["profile"].is_a("IfcTShapeProfileDef"): + return self.settings["profile"].Depth + elif self.settings["profile"].is_a("IfcUShapeProfileDef"): + return self.settings["profile"].Depth + elif self.settings["profile"].is_a("IfcZShapeProfileDef"): + return self.settings["profile"].Depth + else: + settings = ifcopenshell.geom.settings() + settings.set(settings.INCLUDE_CURVES, True) + shape = ifcopenshell.geom.create_shape(settings, element) + y = [verts[i + 1] for i in range(0, len(shape.verts), 3)] + return self.convert_si_to_unit(max(y) - min(y)) + return 0.0