mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 03:10:56 +00:00
You can now parametrically create profile / layer based objects of any type, no longer limited to walls, slabs, etc.
This commit is contained in:
@@ -23,21 +23,22 @@ class AddTypeInstance(bpy.types.Operator):
|
|||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
tprops = context.scene.BIMTypeProperties
|
tprops = context.scene.BIMTypeProperties
|
||||||
ifc_class = self.ifc_class or tprops.ifc_class
|
ifc_class = self.ifc_class or tprops.ifc_class
|
||||||
relating_type = self.relating_type or tprops.relating_type
|
relating_type_id = self.relating_type or tprops.relating_type
|
||||||
if not ifc_class or not relating_type:
|
if not ifc_class or not relating_type_id:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
self.file = IfcStore.get_file()
|
self.file = IfcStore.get_file()
|
||||||
instance_class = ifcopenshell.util.type.get_applicable_entities(ifc_class, self.file.schema)[0]
|
instance_class = ifcopenshell.util.type.get_applicable_entities(ifc_class, self.file.schema)[0]
|
||||||
if ifc_class == "IfcWallType":
|
relating_type = self.file.by_id(int(relating_type_id))
|
||||||
obj = wall.DumbWallGenerator(self.file.by_id(int(relating_type))).generate()
|
material = ifcopenshell.util.element.get_material(relating_type)
|
||||||
|
if material.is_a("IfcMaterialProfileSet"):
|
||||||
|
obj = profile.DumbProfileGenerator(relating_type).generate()
|
||||||
if obj:
|
if obj:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
elif ifc_class == "IfcSlabType":
|
elif material.is_a("IfcMaterialLayerSet"):
|
||||||
obj = slab.DumbSlabGenerator(self.file.by_id(int(relating_type))).generate()
|
if ifc_class in ["IfcSlabType", "IfcRoofType", "IfcRampType", "IfcPlateType"]:
|
||||||
if obj:
|
obj = slab.DumbSlabGenerator(relating_type).generate()
|
||||||
return {"FINISHED"}
|
else:
|
||||||
elif ifc_class in ["IfcColumnType", "IfcBeamType", "IfcMemberType"]:
|
obj = wall.DumbWallGenerator(relating_type).generate()
|
||||||
obj = profile.DumbProfileGenerator(self.file.by_id(int(relating_type))).generate()
|
|
||||||
if obj:
|
if obj:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
# A cube
|
# A cube
|
||||||
|
|||||||
@@ -137,25 +137,17 @@ class DumbProfileGenerator:
|
|||||||
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
|
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
|
||||||
obj.location[2] = self.collection_obj.location[2]
|
obj.location[2] = self.collection_obj.location[2]
|
||||||
self.collection.objects.link(obj)
|
self.collection.objects.link(obj)
|
||||||
if self.relating_type.is_a("IfcColumnType"):
|
|
||||||
obj.name = "Column"
|
ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema)
|
||||||
bpy.ops.bim.assign_class(
|
# Standard cases are deprecated, so let's cull them
|
||||||
obj=obj.name, ifc_class="IfcColumn", predefined_type="COLUMN", should_add_representation=False
|
ifc_class = [c for c in ifc_classes if "StandardCase" not in c][0]
|
||||||
)
|
obj.name = ifc_class[3:]
|
||||||
elif self.relating_type.is_a("IfcBeamType"):
|
bpy.ops.bim.assign_class(obj=obj.name, ifc_class=ifc_class, should_add_representation=False)
|
||||||
obj.name = "Beam"
|
|
||||||
|
if self.relating_type.is_a() in ["IfcBeamType", "IfcMemberType"]:
|
||||||
obj.rotation_euler[0] = math.pi / 2
|
obj.rotation_euler[0] = math.pi / 2
|
||||||
obj.rotation_euler[2] = math.pi / 2
|
obj.rotation_euler[2] = math.pi / 2
|
||||||
bpy.ops.bim.assign_class(
|
|
||||||
obj=obj.name, ifc_class="IfcBeam", predefined_type="BEAM", should_add_representation=False
|
|
||||||
)
|
|
||||||
elif self.relating_type.is_a("IfcMemberType"):
|
|
||||||
obj.name = "Member"
|
|
||||||
obj.rotation_euler[0] = math.pi / 2
|
|
||||||
obj.rotation_euler[2] = math.pi / 2
|
|
||||||
bpy.ops.bim.assign_class(
|
|
||||||
obj=obj.name, ifc_class="IfcMember", predefined_type="MEMBER", should_add_representation=False
|
|
||||||
)
|
|
||||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name)
|
bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name)
|
||||||
profile_set_usage = ifcopenshell.util.element.get_material(element)
|
profile_set_usage = ifcopenshell.util.element.get_material(element)
|
||||||
|
|||||||
@@ -211,8 +211,6 @@ class AddSlabOpening(bpy.types.Operator):
|
|||||||
if not slab_obj.BIMObjectProperties.ifc_definition_id:
|
if not slab_obj.BIMObjectProperties.ifc_definition_id:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
slab = IfcStore.get_file().by_id(slab_obj.BIMObjectProperties.ifc_definition_id)
|
slab = IfcStore.get_file().by_id(slab_obj.BIMObjectProperties.ifc_definition_id)
|
||||||
if not slab.is_a("IfcSlab"):
|
|
||||||
return {"FINISHED"}
|
|
||||||
local_location = slab_obj.matrix_world.inverted() @ context.scene.cursor.location
|
local_location = slab_obj.matrix_world.inverted() @ context.scene.cursor.location
|
||||||
raycast = slab_obj.closest_point_on_mesh(local_location, distance=0.01)
|
raycast = slab_obj.closest_point_on_mesh(local_location, distance=0.01)
|
||||||
if not raycast[0]:
|
if not raycast[0]:
|
||||||
@@ -280,7 +278,12 @@ class DumbSlabGenerator:
|
|||||||
modifier.use_even_offset = True
|
modifier.use_even_offset = True
|
||||||
modifier.offset = 1
|
modifier.offset = 1
|
||||||
modifier.thickness = self.depth
|
modifier.thickness = self.depth
|
||||||
obj.name = "Slab"
|
|
||||||
|
ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema)
|
||||||
|
# Standard cases are deprecated, so let's cull them
|
||||||
|
ifc_class = [c for c in ifc_classes if "StandardCase" not in c][0]
|
||||||
|
|
||||||
|
obj.name = ifc_class[3:]
|
||||||
obj.location = self.location
|
obj.location = self.location
|
||||||
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
|
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
|
||||||
obj.location[2] = self.collection_obj.location[2] - self.depth
|
obj.location[2] = self.collection_obj.location[2] - self.depth
|
||||||
@@ -289,8 +292,7 @@ class DumbSlabGenerator:
|
|||||||
self.collection.objects.link(obj)
|
self.collection.objects.link(obj)
|
||||||
bpy.ops.bim.assign_class(
|
bpy.ops.bim.assign_class(
|
||||||
obj=obj.name,
|
obj=obj.name,
|
||||||
ifc_class="IfcSlab",
|
ifc_class=ifc_class,
|
||||||
predefined_type="FLOOR",
|
|
||||||
ifc_representation_class="IfcExtrudedAreaSolid/IfcArbitraryProfileDefWithVoids",
|
ifc_representation_class="IfcExtrudedAreaSolid/IfcArbitraryProfileDefWithVoids",
|
||||||
)
|
)
|
||||||
bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name)
|
bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name)
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ class AddWallOpening(bpy.types.Operator):
|
|||||||
if not wall_obj.BIMObjectProperties.ifc_definition_id:
|
if not wall_obj.BIMObjectProperties.ifc_definition_id:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
wall = IfcStore.get_file().by_id(wall_obj.BIMObjectProperties.ifc_definition_id)
|
wall = IfcStore.get_file().by_id(wall_obj.BIMObjectProperties.ifc_definition_id)
|
||||||
if not wall.is_a("IfcWall"):
|
|
||||||
return {"FINISHED"}
|
|
||||||
local_location = wall_obj.matrix_world.inverted() @ context.scene.cursor.location
|
local_location = wall_obj.matrix_world.inverted() @ context.scene.cursor.location
|
||||||
raycast = wall_obj.closest_point_on_mesh(local_location, distance=0.01)
|
raycast = wall_obj.closest_point_on_mesh(local_location, distance=0.01)
|
||||||
if not raycast[0]:
|
if not raycast[0]:
|
||||||
@@ -773,17 +771,24 @@ class DumbWallGenerator:
|
|||||||
]
|
]
|
||||||
mesh = bpy.data.meshes.new(name="Wall")
|
mesh = bpy.data.meshes.new(name="Wall")
|
||||||
mesh.from_pydata(verts, [], faces)
|
mesh.from_pydata(verts, [], faces)
|
||||||
obj = bpy.data.objects.new("Wall", mesh)
|
|
||||||
|
ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema)
|
||||||
|
# Standard cases are deprecated, so let's cull them
|
||||||
|
ifc_class = [c for c in ifc_classes if "StandardCase" not in c][0]
|
||||||
|
|
||||||
|
obj = bpy.data.objects.new(ifc_class[3:], mesh)
|
||||||
obj.location = self.location
|
obj.location = self.location
|
||||||
obj.rotation_euler[2] = self.rotation
|
obj.rotation_euler[2] = self.rotation
|
||||||
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
|
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
|
||||||
obj.location[2] = self.collection_obj.location[2]
|
obj.location[2] = self.collection_obj.location[2]
|
||||||
self.collection.objects.link(obj)
|
self.collection.objects.link(obj)
|
||||||
|
|
||||||
bpy.ops.bim.assign_class(
|
bpy.ops.bim.assign_class(
|
||||||
obj=obj.name,
|
obj=obj.name,
|
||||||
ifc_class="IfcWall",
|
ifc_class=ifc_class,
|
||||||
ifc_representation_class="IfcExtrudedAreaSolid/IfcArbitraryClosedProfileDef",
|
ifc_representation_class="IfcExtrudedAreaSolid/IfcArbitraryClosedProfileDef",
|
||||||
)
|
)
|
||||||
|
|
||||||
bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name)
|
bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name)
|
||||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="EPset_Parametric")
|
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="EPset_Parametric")
|
||||||
|
|||||||
@@ -17,6 +17,14 @@ class LibraryGenerator:
|
|||||||
self.create_layer_type("IfcWallType", "DEMO200", 0.2)
|
self.create_layer_type("IfcWallType", "DEMO200", 0.2)
|
||||||
self.create_layer_type("IfcWallType", "DEMO300", 0.3)
|
self.create_layer_type("IfcWallType", "DEMO300", 0.3)
|
||||||
|
|
||||||
|
self.create_layer_type("IfcCoveringType", "DEMO20", 0.02)
|
||||||
|
self.create_layer_type("IfcRampType", "DEMO200", 0.2)
|
||||||
|
|
||||||
|
profile = self.file.create_entity(
|
||||||
|
"IfcCircleProfileDef", ProfileType="AREA", Radius=0.3
|
||||||
|
)
|
||||||
|
self.create_profile_type("IfcPileType", "DEMO1", profile)
|
||||||
|
|
||||||
self.create_layer_type("IfcSlabType", "DEMO150", 0.2)
|
self.create_layer_type("IfcSlabType", "DEMO150", 0.2)
|
||||||
self.create_layer_type("IfcSlabType", "DEMO250", 0.3)
|
self.create_layer_type("IfcSlabType", "DEMO250", 0.3)
|
||||||
|
|
||||||
|
|||||||
@@ -12,13 +12,14 @@ with open(os.path.join(cwd, "entity_to_type_map_2x3.json")) as f:
|
|||||||
with open(os.path.join(cwd, "entity_to_type_map_4.json")) as f:
|
with open(os.path.join(cwd, "entity_to_type_map_4.json")) as f:
|
||||||
entity_to_type_map["IFC4"] = json.load(f)
|
entity_to_type_map["IFC4"] = json.load(f)
|
||||||
|
|
||||||
type_to_entity_map["IFC2X3"] = {
|
for schema in ["IFC2X3", "IFC4"]:
|
||||||
value: [key] for key in entity_to_type_map["IFC2X3"] for value in entity_to_type_map["IFC2X3"][key]
|
type_to_entity_map[schema] = {}
|
||||||
}
|
for element, element_types in entity_to_type_map[schema].items():
|
||||||
|
for element_type in element_types:
|
||||||
type_to_entity_map["IFC4"] = {
|
type_to_entity_map[schema].setdefault(element_type, []).append(element)
|
||||||
value: [key] for key in entity_to_type_map["IFC4"] for value in entity_to_type_map["IFC4"][key]
|
# TODO: this method just fails for IFC2X3 because 2X3 type mapping is just so broken.
|
||||||
}
|
# Uncomment the following line to see how bad it is.
|
||||||
|
# print(type_to_entity_map[schema])
|
||||||
|
|
||||||
|
|
||||||
def get_applicable_types(ifc_class, schema="IFC4"):
|
def get_applicable_types(ifc_class, schema="IFC4"):
|
||||||
|
|||||||
Reference in New Issue
Block a user