Revisiting dumb walls - typed dumb walls now auto derive wall thickness from the type material

This commit is contained in:
Dion Moult
2021-05-20 12:53:40 +10:00
parent 1541cbbbb8
commit 97244d1919
@@ -1,6 +1,9 @@
import bpy import bpy
import math
import ifcopenshell import ifcopenshell
import ifcopenshell.util.type import ifcopenshell.util.type
import ifcopenshell.util.unit
import mathutils.geometry
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from mathutils import Vector from mathutils import Vector
@@ -13,6 +16,12 @@ class AddTypeInstance(bpy.types.Operator):
tprops = context.scene.BIMTypeProperties tprops = context.scene.BIMTypeProperties
if not tprops.ifc_class or not tprops.relating_type: if not tprops.ifc_class or not tprops.relating_type:
return {"FINISHED"} return {"FINISHED"}
self.file = IfcStore.get_file()
instance_class = ifcopenshell.util.type.get_applicable_entities(tprops.ifc_class, self.file.schema)[0]
if instance_class in ["IfcWall", "IfcWallStandardCase"]:
obj = DumbWallGenerator(self.file.by_id(int(tprops.relating_type))).generate()
if obj:
return {"FINISHED"}
# A cube # A cube
verts = [ verts = [
Vector((-1, -1, -1)), Vector((-1, -1, -1)),
@@ -40,8 +49,93 @@ class AddTypeInstance(bpy.types.Operator):
collection = bpy.context.view_layer.active_layer_collection.collection collection = bpy.context.view_layer.active_layer_collection.collection
collection.objects.link(obj) collection.objects.link(obj)
collection_obj = bpy.data.objects.get(collection.name) collection_obj = bpy.data.objects.get(collection.name)
if collection_obj:
obj.location[2] = collection_obj.location[2] - min(v[2] for v in obj.bound_box)
bpy.ops.bim.assign_class(obj=obj.name, ifc_class=instance_class) bpy.ops.bim.assign_class(obj=obj.name, ifc_class=instance_class)
bpy.ops.bim.assign_type(relating_type=int(tprops.relating_type), related_object=obj.name) bpy.ops.bim.assign_type(relating_type=int(tprops.relating_type), related_object=obj.name)
if collection_obj and collection_obj.BIMObjectProperties.ifc_definition_id:
obj.location[2] = collection_obj.location[2] - min([v[2] for v in obj.bound_box])
return {"FINISHED"} return {"FINISHED"}
class DumbWallGenerator:
def __init__(self, relating_type):
self.relating_type = relating_type
def generate(self):
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(IfcStore.get_file())
thicknesses = []
for rel in self.relating_type.HasAssociations:
if rel.is_a("IfcRelAssociatesMaterial"):
material = rel.RelatingMaterial
if material.is_a("IfcMaterialLayerSet"):
thicknesses = [l.LayerThickness for l in material.MaterialLayers]
break
if not thicknesses:
return
self.collection = bpy.context.view_layer.active_layer_collection.collection
self.collection_obj = bpy.data.objects.get(self.collection.name)
self.width = sum(thicknesses) * unit_scale
self.height = 3
self.length = 1
self.rotation = 0
self.location = Vector((0, 0, 0))
if self.has_sketch():
return self.derive_from_sketch()
return self.derive_from_cursor()
def has_sketch(self):
return (
len(bpy.context.scene.grease_pencil.layers) == 1
and bpy.context.scene.grease_pencil.layers[0].active_frame.strokes
)
def derive_from_cursor(self):
self.location = bpy.context.scene.cursor.location
if self.collection:
for sibling_obj in self.collection.objects:
if not isinstance(sibling_obj.data, bpy.types.Mesh):
continue
if "IfcWall" not in sibling_obj.name:
continue
print("checking sibling", sibling_obj)
raycast = sibling_obj.closest_point_on_mesh(bpy.context.scene.cursor.location, distance=0.05)
print(raycast)
if raycast[0]:
print("GOT IT!")
print(raycast)
# Rotate the wall in the direction of the face normal
self.rotation = math.atan2(raycast[2][1], raycast[2][0])
break
self.create_wall()
def create_wall(self):
verts = [
Vector((0, self.width / 2, 0)),
Vector((0, -self.width / 2, 0)),
Vector((0, self.width / 2, self.height)),
Vector((0, -self.width / 2, self.height)),
Vector((self.length, self.width / 2, 0)),
Vector((self.length, -self.width / 2, 0)),
Vector((self.length, self.width / 2, self.height)),
Vector((self.length, -self.width / 2, 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="Wall")
mesh.from_pydata(verts, [], faces)
obj = bpy.data.objects.new("Wall", mesh)
obj.location = self.location
obj.rotation_euler[2] = self.rotation
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
obj.location[2] = self.collection_obj.location[2]
self.collection.objects.link(obj)
bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcWall")
bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name)
return obj