diff --git a/src/bonsai/bonsai/bim/module/drawing/decoration.py b/src/bonsai/bonsai/bim/module/drawing/decoration.py index b9b4dd40cb..4aed1073d7 100644 --- a/src/bonsai/bonsai/bim/module/drawing/decoration.py +++ b/src/bonsai/bonsai/bim/module/drawing/decoration.py @@ -1898,6 +1898,13 @@ class CutDecorator: no = tool.Drawing.get_extrusion_vector(element).normalized() no = Vector([1.0, 0.0, 0.0]) no *= sense_factor + # Detect non-conformant exports (e.g. Revit) where DirectionSense=POSITIVE + # but the geometry extrudes in the negative direction. If the mesh centroid + # in object local space is on the wrong side of the starting plane, flip no. + bb = [Vector(v) for v in obj.bound_box] + mesh_centroid = sum(bb, Vector((0.0, 0.0, 0.0))) / 8 + if (mesh_centroid - co).dot(no) < 0: + no = -no last_i = len(layer_set.MaterialLayers) - 1 vert_map = {} diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index 58474d8ce5..35a933c406 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -729,6 +729,13 @@ class CreateDrawing(bpy.types.Operator): no = tool.Drawing.get_extrusion_vector(element).normalized() no = Vector([1.0, 0.0, 0.0]) no *= sense_factor + # Detect non-conformant exports (e.g. Revit) where DirectionSense=POSITIVE + # but the geometry extrudes in the negative direction. If the mesh centroid + # in object local space is on the wrong side of the starting plane, flip no. + bb = [Vector(v) for v in obj.bound_box] + mesh_centroid = sum(bb, Vector((0.0, 0.0, 0.0))) / 8 + if (mesh_centroid - co).dot(no) < 0: + no = -no last_i = len(layer_set.MaterialLayers) - 1 for i, layer in enumerate(layer_set.MaterialLayers): prev_co = co.copy() diff --git a/src/bonsai/bonsai/bim/module/model/slab.py b/src/bonsai/bonsai/bim/module/model/slab.py index 58a353ab28..c28ba920b7 100644 --- a/src/bonsai/bonsai/bim/module/model/slab.py +++ b/src/bonsai/bonsai/bim/module/model/slab.py @@ -248,7 +248,8 @@ class DumbSlabPlaner: def change_thickness(self, element: ifcopenshell.entity_instance, thickness: float) -> None: self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) - if tool.Model.get_usage_type(element) != "LAYER3": + usage_type = tool.Model.get_usage_type(element) + if usage_type != "LAYER3": return layer_params = tool.Model.get_material_layer_parameters(element) ifc_file = tool.Ifc.get() @@ -304,11 +305,15 @@ class DumbSlabPlaner: ifc_position = extrusion.Position position = offset_direction * perpendicular_offset material = ifcopenshell.util.element.get_material(element) - if material: - if material.is_a("IfcMaterialLayerSetUsage"): - material.OffsetFromReferenceLine = position.z if ifc_position: - ifc_position.Location.Coordinates = position + orig = Vector(ifc_position.Location.Coordinates) + layer_normal = offset_direction.normalized() + perp = orig - orig.dot(layer_normal) * layer_normal + new_coords = perp + layer_normal * perpendicular_offset + ifc_position.Location.Coordinates = new_coords + if material: + if material.is_a("IfcMaterialLayerSetUsage"): + material.OffsetFromReferenceLine = new_coords.z else: tool.Model.add_extrusion_position(extrusion, position) diff --git a/src/bonsai/bonsai/tool/loader.py b/src/bonsai/bonsai/tool/loader.py index 6d30192485..b6167cf993 100644 --- a/src/bonsai/bonsai/tool/loader.py +++ b/src/bonsai/bonsai/tool/loader.py @@ -1090,6 +1090,13 @@ class Loader(bonsai.core.tool.Loader): no = cls.get_extrusion_vector(element).normalized() no = Vector([1.0, 0.0, 0.0]) no *= sense_factor + # Detect non-conformant exports (e.g. Revit) where DirectionSense=POSITIVE + # but the geometry extrudes in the negative direction. If the mesh centroid + # in object local space is on the wrong side of the starting plane, flip no. + if bm.verts: + mesh_centroid = sum((v.co for v in bm.verts), Vector((0.0, 0.0, 0.0))) / len(bm.verts) + if (mesh_centroid - co).dot(no) < 0: + no = -no # Cache this body = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW") styles = {}