Skip to content

Commit 47f1a9b

Browse files
committed
initial setup, supports mesh hole fixing and bulk property assignment
1 parent 58e14df commit 47f1a9b

File tree

5 files changed

+215
-0
lines changed

5 files changed

+215
-0
lines changed

__init__.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# This program is free software; you can redistribute it and/or modify
2+
# it under the terms of the GNU General Public License as published by
3+
# the Free Software Foundation; either version 3 of the License, or
4+
# (at your option) any later version.
5+
#
6+
# This program is distributed in the hope that it will be useful, but
7+
# WITHOUT ANY WARRANTY; without even the implied warranty of
8+
# MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9+
# General Public License for more details.
10+
#
11+
# You should have received a copy of the GNU General Public License
12+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
13+
14+
bl_info = {
15+
"name" : "BII Blender Tools",
16+
"author" : "bii",
17+
"description" : "",
18+
"blender" : (2, 80, 0),
19+
"version" : (0, 0, 1),
20+
"location" : "",
21+
"warning" : "",
22+
"category" : "BII Tools"
23+
}
24+
25+
from . import close_mesh_holes
26+
from . import bii_functions_panel
27+
from . import bulk_assign_ifc_class
28+
from . import bulk_material_dropdown
29+
30+
def register():
31+
close_mesh_holes.register()
32+
bii_functions_panel.register()
33+
bulk_assign_ifc_class.register()
34+
bulk_material_dropdown.register()
35+
36+
def unregister():
37+
close_mesh_holes.unregister()
38+
bii_functions_panel.unregister()
39+
bulk_assign_ifc_class.unregister()
40+
bulk_material_dropdown.unregister()
41+
42+
if __name__ == "__main__":
43+
register()

bii_functions_panel.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import bpy
2+
3+
class BiiFunctionsPanel(bpy.types.Panel):
4+
"""Creates a Panel in the Object properties window"""
5+
bl_label = "BII IFC Tools"
6+
bl_idname = "OBJECT_PT_mesh_cleanup_tools"
7+
bl_space_type = 'VIEW_3D'
8+
bl_region_type = 'UI'
9+
bl_category = 'BII Tools'
10+
11+
def draw(self, context):
12+
layout = self.layout
13+
14+
# Add a short description of the panel
15+
row1 = layout.row(align = True)
16+
row1.alignment = 'EXPAND'
17+
row1.label(text="Default", icon='INFO')
18+
19+
layout.operator("object.close_mesh_holes_operator")
20+
21+
layout.prop(context.scene, "bulk_material", text="Bulk Material")
22+
23+
layout.operator("object.set_ifc_class_for_bulk_operator")
24+
25+
26+
def register():
27+
bpy.utils.register_class(BiiFunctionsPanel)
28+
29+
def unregister():
30+
bpy.utils.unregister_class(BiiFunctionsPanel)

bulk_assign_ifc_class.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import bpy
2+
import ifcopenshell
3+
import blenderbim
4+
from blenderbim.bim.ifc import IfcStore
5+
import blenderbim.tool as tool
6+
from blenderbim.bim.module.pset.data import Data as PsetData
7+
import bmesh
8+
9+
def calculate_volume(obj):
10+
bm = bmesh.new()
11+
bm.from_mesh(obj.data)
12+
volume = bm.calc_volume(signed=True)
13+
bm.free()
14+
return volume
15+
16+
def calculate_height(obj):
17+
# Example calculation - adjust as needed
18+
z_coords = [v.co.z for v in obj.data.vertices]
19+
height = max(z_coords) - min(z_coords)
20+
return height
21+
22+
def set_ifc_class_for_bulk(self, context, material):
23+
# Get the active IFC file
24+
ifc_file = IfcStore.get_file()
25+
if not ifc_file:
26+
print("No IFC file found. Ensure you're working in a BlenderBIM project.")
27+
return
28+
29+
# Create a new Pset template file and the Pset template for Bulk
30+
pset_template = ifcopenshell.api.run("pset_template.add_pset_template", ifc_file, name="dProB_Bulk")
31+
ifcopenshell.api.run("pset_template.add_prop_template", ifc_file, pset_template=pset_template, name="BulkMaterial", description="Limited to what dProB is able to interpret!")
32+
ifcopenshell.api.run("pset_template.add_prop_template", ifc_file, pset_template=pset_template, name="BulkVolume", primary_measure_type="IfcVolumeMeasure")
33+
ifcopenshell.api.run("pset_template.add_prop_template", ifc_file, pset_template=pset_template, name="BulkHeight", primary_measure_type="IfcLengthMeasure")
34+
blenderbim.bim.handler.refresh_ui_data()
35+
blenderbim.bim.schema.reload(tool.Ifc.get().schema)
36+
37+
# Loop through all selected objects
38+
for obj in bpy.context.selected_objects:
39+
if obj.type == 'MESH':
40+
41+
# Set the active object
42+
bpy.context.view_layer.objects.active = obj
43+
# Assign the IFC class
44+
bpy.ops.bim.assign_class(ifc_class="IfcBuilding")
45+
# get the ifc object
46+
ifc_obj = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
47+
# check if the object is valid
48+
if not ifc_obj:
49+
print(f"Object {obj.name} has no IFC object.")
50+
continue
51+
pset = ifcopenshell.api.run("pset.add_pset", ifc_file, product=ifc_obj, name="dProB_Bulk")
52+
53+
volume = calculate_volume(obj)
54+
height = calculate_height(obj)
55+
56+
# Set the properties of the Pset
57+
new_values = {
58+
"BulkMaterial": material,
59+
"BulkVolume": volume,
60+
"BulkHeight": height
61+
}
62+
ifcopenshell.api.run("pset.edit_pset", ifc_file, pset=pset, properties=new_values)
63+
64+
print(f"Assigned IfcBuilding and custom Pset to {obj.name}.")
65+
66+
67+
class SetIfcClassForBulkOperator(bpy.types.Operator):
68+
"""Set IFC Class of selected Objects for custom dProB-Bulk"""
69+
bl_idname = "object.set_ifc_class_for_bulk_operator"
70+
bl_label = "Set IFC Class for Bulk"
71+
72+
def execute(self, context):
73+
material = context.scene.bulk_material
74+
set_ifc_class_for_bulk(self, context, material)
75+
return {'FINISHED'}
76+
77+
78+
def register():
79+
bpy.utils.register_class(SetIfcClassForBulkOperator)
80+
81+
def unregister():
82+
bpy.utils.unregister_class(SetIfcClassForBulkOperator)

bulk_material_dropdown.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import bpy
2+
3+
def get_material_options(self, context):
4+
return [
5+
("Gleisschotter (Verschmutzt)", "Gleisschotter (Verschmutzt)", "Description for Option 1"),
6+
("Gleisschotter (Neu)", "Gleisschotter (Neu)", "Description for Option 2"),
7+
("Asphalt", "Asphalt", "Description for Option 3"),
8+
("Frostschutzschicht", "Frostschutzschicht", "Description for Option 4"),
9+
("Gleisunterbau", "Gleisunterbau", "Description for Option 5"),
10+
("Beton", "Beton", "Description for Option 6"),
11+
# Add more options as needed
12+
]
13+
14+
def register():
15+
bpy.types.Scene.bulk_material = bpy.props.EnumProperty(
16+
name="Bulk Material",
17+
items=get_material_options,
18+
description="Select the material for the bulk",
19+
)
20+
21+
def unregister():
22+
del bpy.types.Scene.bulk_material
23+

close_mesh_holes.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import bpy
2+
3+
def close_mesh_holes(self, context):
4+
# Loop through all selected objects
5+
for obj in bpy.context.selected_objects:
6+
# Check if the object is a mesh
7+
if obj.type == 'MESH':
8+
# Switch to Object Mode (required to perform some operations)
9+
bpy.ops.object.mode_set(mode='OBJECT')
10+
# Make the current object the active object
11+
bpy.context.view_layer.objects.active = obj
12+
# Switch to Edit Mode
13+
bpy.ops.object.mode_set(mode='EDIT')
14+
# Select all vertices
15+
bpy.ops.mesh.select_all(action='SELECT')
16+
# Fill holes
17+
# Here, sides=0 means it will fill holes of any size. Adjust as needed.
18+
bpy.ops.mesh.fill_holes(sides=0)
19+
# Switch back to Object Mode
20+
bpy.ops.object.mode_set(mode='OBJECT')
21+
22+
# Deselect all to clean up selection after operation
23+
24+
class CloseMeshHolesOperator(bpy.types.Operator):
25+
"""Print Hello World"""
26+
bl_idname = "object.close_mesh_holes_operator"
27+
bl_label = "Close Selected Mesh Holes"
28+
29+
def execute(self, context):
30+
close_mesh_holes(self, context)
31+
return {'FINISHED'}
32+
33+
def register():
34+
bpy.utils.register_class(CloseMeshHolesOperator)
35+
36+
def unregister():
37+
bpy.utils.unregister_class(CloseMeshHolesOperator)

0 commit comments

Comments
 (0)