From 80dccfeb5498cec87a183df8c156075ef2a32770 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 8 Nov 2019 12:39:34 +1100 Subject: [PATCH] Add support for inner curves in mesh extrusions and fix position bug --- .../io_export_ifc/__init__.py | 3 +- .../io_export_ifc/export_ifc.py | 62 ++++++++++++++----- .../io_export_ifc/operator.py | 21 +++++-- src/ifcblenderexport/io_export_ifc/ui.py | 4 +- 4 files changed, 66 insertions(+), 24 deletions(-) diff --git a/src/ifcblenderexport/io_export_ifc/__init__.py b/src/ifcblenderexport/io_export_ifc/__init__.py index c5b971cdc1..a070c26a55 100644 --- a/src/ifcblenderexport/io_export_ifc/__init__.py +++ b/src/ifcblenderexport/io_export_ifc/__init__.py @@ -31,7 +31,8 @@ classes = ( operator.SelectAudited, operator.RejectElement, operator.SelectExternalMaterialDir, - operator.AssignSweptSolidProfile, + operator.AssignSweptSolidOuterCurve, + operator.AddSweptSolidInnerCurve, operator.AssignSweptSolidExtrusion, operator.AssignPset, operator.UnassignPset, diff --git a/src/ifcblenderexport/io_export_ifc/export_ifc.py b/src/ifcblenderexport/io_export_ifc/export_ifc.py index 157f944043..925e8c94aa 100644 --- a/src/ifcblenderexport/io_export_ifc/export_ifc.py +++ b/src/ifcblenderexport/io_export_ifc/export_ifc.py @@ -1383,36 +1383,64 @@ class IfcExporter(): def create_swept_solid_representation(self, representation): object = representation['raw_object'] mesh = representation['raw'] - profile_index = None + outer_curve_index = None + inner_curve_indices = [] extrusion_index = None + for index, vg in enumerate(object.vertex_groups): - if vg.name == 'profile': - profile_index = index + if vg.name == 'outer-curve': + outer_curve_index = index + elif 'inner-curve' in vg.name: + inner_curve_indices.append(index) elif vg.name == 'extrusion': extrusion_index = index - profile_edges = self.get_edges_in_vg_index(object, profile_index) + extrusion_edge = self.get_edges_in_vg_index(object, extrusion_index)[0] - loop = self.get_loop_from_edges(profile_edges) - points = [] - for point in loop: - points.append(self.create_cartesian_point( - mesh.vertices[point].co.x, - mesh.vertices[point].co.y, - mesh.vertices[point].co.z)) - points.append(points[0]) - curve = self.file.createIfcArbitraryClosedProfileDef('AREA', None, - self.file.createIfcPolyline(points)) - start, end = self.get_start_and_end_of_extrusion(points, extrusion_edge) + + inner_curves = [] + for index in inner_curve_indices: + inner_curves.append( + self.file.createIfcPolyline( + self.get_polyline_points_from_vg_index(object, index))) + + outer_curve_points = self.get_polyline_points_from_vg_index(object, outer_curve_index) + outer_curve = self.file.createIfcPolyline(outer_curve_points) + + if inner_curves: + curve = self.file.createIfcArbitraryProfileDefWithVoids('AREA', None, + outer_curve, inner_curves) + else: + curve = self.file.createIfcArbitraryClosedProfileDef('AREA', None, outer_curve) + + start, end = self.get_start_and_end_of_extrusion(outer_curve_points, extrusion_edge) direction = self.get_extrusion_direction(mesh, start, end) unit_direction = direction.normalized() - extruded_area_solid = self.file.createIfcExtrudedAreaSolid(curve, self.origin, - self.file.createIfcDirection((unit_direction.x, unit_direction.y, unit_direction.z)), + x_axis = object.matrix_world.to_quaternion() @ Vector((1, 0, 0)) + position = self.create_ifc_axis_2_placement_3d( + mesh.vertices[start].co, unit_direction, x_axis) + + self.file.createIfcDirection((unit_direction.x, unit_direction.y, unit_direction.z)) + + extruded_area_solid = self.file.createIfcExtrudedAreaSolid( + curve, position, self.file.createIfcDirection((0., 0., 1.)), self.convert_si_to_unit(direction.length)) return self.file.createIfcShapeRepresentation( self.ifc_rep_context[representation['context']][representation['subcontext']][representation['target_view']]['ifc'], representation['subcontext'], 'SweptSolid', [extruded_area_solid]) + def get_polyline_points_from_vg_index(self, object, vg_index): + outer_curve_edges = self.get_edges_in_vg_index(object, vg_index) + outer_curve_loop = self.get_loop_from_edges(outer_curve_edges) + outer_curve_points = [] + for point in outer_curve_loop: + outer_curve_points.append(self.create_cartesian_point( + object.data.vertices[point].co.x, + object.data.vertices[point].co.y, + object.data.vertices[point].co.z)) + outer_curve_points.append(outer_curve_points[0]) + return outer_curve_points + def get_start_and_end_of_extrusion(self, profile_points, extrusion_edge): if extrusion_edge.vertices[0] in profile_points: return (extrusion_edge.vertices[0], extrusion_edge.vertices[1]) diff --git a/src/ifcblenderexport/io_export_ifc/operator.py b/src/ifcblenderexport/io_export_ifc/operator.py index 73c0036ff6..931851475f 100644 --- a/src/ifcblenderexport/io_export_ifc/operator.py +++ b/src/ifcblenderexport/io_export_ifc/operator.py @@ -339,20 +339,31 @@ class RemoveAttribute(bpy.types.Operator): bpy.context.active_object.BIMObjectProperties.attributes.remove(self.attribute_index) return {'FINISHED'} -class AssignSweptSolidProfile(bpy.types.Operator): - bl_idname = 'bim.assign_swept_solid_profile' - bl_label = 'Assign Profile' +class AssignSweptSolidOuterCurve(bpy.types.Operator): + bl_idname = 'bim.assign_swept_solid_outer_curve' + bl_label = 'Assign Outer Curve' def execute(self, context): if bpy.context.mode != 'EDIT_MESH': return {'FINISHED'} for vg in bpy.context.active_object.vertex_groups: - if vg.name == 'profile': + if vg.name == 'outer-curve': bpy.ops.object.vertex_group_set_active(group=vg.name) bpy.ops.object.vertex_group_remove() break bpy.ops.object.vertex_group_assign_new() - bpy.context.active_object.vertex_groups[bpy.context.active_object.vertex_groups[-1].name].name = 'profile' + bpy.context.active_object.vertex_groups[bpy.context.active_object.vertex_groups[-1].name].name = 'outer-curve' + return {'FINISHED'} + +class AddSweptSolidInnerCurve(bpy.types.Operator): + bl_idname = 'bim.add_swept_solid_inner_curve' + bl_label = 'Add Inner Curve' + + def execute(self, context): + if bpy.context.mode != 'EDIT_MESH': + return {'FINISHED'} + bpy.ops.object.vertex_group_assign_new() + bpy.context.active_object.vertex_groups[bpy.context.active_object.vertex_groups[-1].name].name = 'inner-curve' return {'FINISHED'} class AssignSweptSolidExtrusion(bpy.types.Operator): diff --git a/src/ifcblenderexport/io_export_ifc/ui.py b/src/ifcblenderexport/io_export_ifc/ui.py index ad1f4353a9..d763d4391f 100644 --- a/src/ifcblenderexport/io_export_ifc/ui.py +++ b/src/ifcblenderexport/io_export_ifc/ui.py @@ -226,7 +226,9 @@ class MeshPanel(bpy.types.Panel): row = layout.row() row.prop(bpy.context.active_object.data.BIMMeshProperties, 'is_swept_solid') row = layout.row(align=True) - row.operator('bim.assign_swept_solid_profile') + row.operator('bim.assign_swept_solid_outer_curve') + row.operator('bim.add_swept_solid_inner_curve') + row = layout.row() row.operator('bim.assign_swept_solid_extrusion') class MaterialPanel(bpy.types.Panel):