diff --git a/src/blenderbim/blenderbim/bim/module/model/mep.py b/src/blenderbim/blenderbim/bim/module/model/mep.py new file mode 100644 index 0000000000..14784936d4 --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/model/mep.py @@ -0,0 +1,109 @@ +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2020, 2021 Dion Moult +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + +import bpy +import math +import bmesh +import ifcopenshell +import ifcopenshell.api +import ifcopenshell.util.unit +import ifcopenshell.util.element +import ifcopenshell.util.representation +import mathutils.geometry +import blenderbim.bim.handler +import blenderbim.core.type +import blenderbim.core.root +import blenderbim.core.geometry +import blenderbim.tool as tool +from math import pi, degrees +from mathutils import Vector, Matrix + + + +class MepGenerator: + def __init__(self, relating_type): + self.relating_type = relating_type + + def generate(self): + self.file = tool.Ifc.get() + self.collection = bpy.context.view_layer.active_layer_collection.collection + + if self.relating_type.is_a("IfcCableCarrierSegmentType"): + pass + elif self.relating_type.is_a("IfcCableSegmentType"): + pass + elif self.relating_type.is_a("IfcDuctSegmentType"): + dimensions = ifcopenshell.util.element.get_psets(self.relating_type).get("Pset_DuctSegmentTypeCommon") or {} + shape = dimensions.get("Shape") or dimensions.get("CrossSectionShape") + + if shape == "RECTANGULAR": + self.width = dimensions.get("NominalDiameterOrWidth") + self.height = dimensions.get("NominalHeight") + self.length = 1 + self.rotation = 0 + + return self.derive_from_cursor() + elif self.relating_type.is_a("IfcPipeSegmentType"): + pass + + def derive_from_cursor(self): + self.location = bpy.context.scene.cursor.location + return self.create_rectangle_segment() + + def create_rectangle_segment(self): + verts = [ + Vector((0, self.width, 0)), + Vector((0, 0, 0)), + Vector((0, self.width, self.height)), + Vector((0, 0, self.height)), + Vector((self.length, self.width, 0)), + Vector((self.length, 0, 0)), + Vector((self.length, self.width, self.height)), + Vector((self.length, 0, self.height)), + ] + faces = [ + [1, 3, 2, 0], + [4, 6, 7, 5], + [1, 0, 4, 5], + [3, 7, 6, 2], + [0, 2, 6, 4], + [1, 5, 7, 3], + ] + mesh = bpy.data.meshes.new(name="Segment") + mesh.from_pydata(verts, [], faces) + + ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema) + ifc_class = ifc_classes[0] + + obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(self.relating_type, ifc_class), mesh) + obj.location = self.location + obj.rotation_euler[2] = self.rotation + self.collection.objects.link(obj) + + bpy.ops.bim.assign_class( + obj=obj.name, + ifc_class=ifc_class, + ifc_representation_class="IfcExtrudedAreaSolid/IfcRectangleProfileDef", + ) + + blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=tool.Ifc.get_entity(obj), type=self.relating_type) + element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) + pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="EPset_Parametric") + ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Engine": "BlenderBIM.Mep"}) + obj.select_set(True) + return obj diff --git a/src/blenderbim/blenderbim/bim/module/model/product.py b/src/blenderbim/blenderbim/bim/module/model/product.py index 76a743105e..ab47a6866c 100644 --- a/src/blenderbim/blenderbim/bim/module/model/product.py +++ b/src/blenderbim/blenderbim/bim/module/model/product.py @@ -25,7 +25,7 @@ import ifcopenshell.util.representation import blenderbim.tool as tool import blenderbim.core.type import blenderbim.core.geometry -from . import wall, slab, profile +from . import wall, slab, profile, mep from blenderbim.bim.ifc import IfcStore from ifcopenshell.api.pset.data import Data as PsetData from mathutils import Vector, Matrix @@ -81,6 +81,9 @@ class AddTypeInstance(bpy.types.Operator): elif material and material.is_a("IfcMaterialLayerSet"): if self.generate_layered_element(ifc_class, relating_type): return {"FINISHED"} + if relating_type.is_a("IfcFlowSegmentType"): + if mep.MepGenerator(relating_type).generate(): + return {"FINISHED"} building_obj = None if len(context.selected_objects) == 1 and context.active_object: