mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-29 03:37:21 +00:00
Revisiting dumb walls - typed dumb walls now auto derive wall thickness from the type material
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user