mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +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):
|
||||
tprops = context.scene.BIMTypeProperties
|
||||
ifc_class = self.ifc_class or tprops.ifc_class
|
||||
relating_type = self.relating_type or tprops.relating_type
|
||||
if not ifc_class or not relating_type:
|
||||
relating_type_id = self.relating_type or tprops.relating_type
|
||||
if not ifc_class or not relating_type_id:
|
||||
return {"FINISHED"}
|
||||
self.file = IfcStore.get_file()
|
||||
instance_class = ifcopenshell.util.type.get_applicable_entities(ifc_class, self.file.schema)[0]
|
||||
if ifc_class == "IfcWallType":
|
||||
obj = wall.DumbWallGenerator(self.file.by_id(int(relating_type))).generate()
|
||||
relating_type = self.file.by_id(int(relating_type_id))
|
||||
material = ifcopenshell.util.element.get_material(relating_type)
|
||||
if material.is_a("IfcMaterialProfileSet"):
|
||||
obj = profile.DumbProfileGenerator(relating_type).generate()
|
||||
if obj:
|
||||
return {"FINISHED"}
|
||||
elif ifc_class == "IfcSlabType":
|
||||
obj = slab.DumbSlabGenerator(self.file.by_id(int(relating_type))).generate()
|
||||
if obj:
|
||||
return {"FINISHED"}
|
||||
elif ifc_class in ["IfcColumnType", "IfcBeamType", "IfcMemberType"]:
|
||||
obj = profile.DumbProfileGenerator(self.file.by_id(int(relating_type))).generate()
|
||||
elif material.is_a("IfcMaterialLayerSet"):
|
||||
if ifc_class in ["IfcSlabType", "IfcRoofType", "IfcRampType", "IfcPlateType"]:
|
||||
obj = slab.DumbSlabGenerator(relating_type).generate()
|
||||
else:
|
||||
obj = wall.DumbWallGenerator(relating_type).generate()
|
||||
if obj:
|
||||
return {"FINISHED"}
|
||||
# A cube
|
||||
|
||||
@@ -137,25 +137,17 @@ class DumbProfileGenerator:
|
||||
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)
|
||||
if self.relating_type.is_a("IfcColumnType"):
|
||||
obj.name = "Column"
|
||||
bpy.ops.bim.assign_class(
|
||||
obj=obj.name, ifc_class="IfcColumn", predefined_type="COLUMN", should_add_representation=False
|
||||
)
|
||||
elif self.relating_type.is_a("IfcBeamType"):
|
||||
obj.name = "Beam"
|
||||
|
||||
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:]
|
||||
bpy.ops.bim.assign_class(obj=obj.name, ifc_class=ifc_class, should_add_representation=False)
|
||||
|
||||
if self.relating_type.is_a() in ["IfcBeamType", "IfcMemberType"]:
|
||||
obj.rotation_euler[0] = 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)
|
||||
bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name)
|
||||
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:
|
||||
return {"FINISHED"}
|
||||
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
|
||||
raycast = slab_obj.closest_point_on_mesh(local_location, distance=0.01)
|
||||
if not raycast[0]:
|
||||
@@ -280,7 +278,12 @@ class DumbSlabGenerator:
|
||||
modifier.use_even_offset = True
|
||||
modifier.offset = 1
|
||||
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
|
||||
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
|
||||
obj.location[2] = self.collection_obj.location[2] - self.depth
|
||||
@@ -289,8 +292,7 @@ class DumbSlabGenerator:
|
||||
self.collection.objects.link(obj)
|
||||
bpy.ops.bim.assign_class(
|
||||
obj=obj.name,
|
||||
ifc_class="IfcSlab",
|
||||
predefined_type="FLOOR",
|
||||
ifc_class=ifc_class,
|
||||
ifc_representation_class="IfcExtrudedAreaSolid/IfcArbitraryProfileDefWithVoids",
|
||||
)
|
||||
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:
|
||||
return {"FINISHED"}
|
||||
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
|
||||
raycast = wall_obj.closest_point_on_mesh(local_location, distance=0.01)
|
||||
if not raycast[0]:
|
||||
@@ -773,17 +771,24 @@ class DumbWallGenerator:
|
||||
]
|
||||
mesh = bpy.data.meshes.new(name="Wall")
|
||||
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.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",
|
||||
ifc_class=ifc_class,
|
||||
ifc_representation_class="IfcExtrudedAreaSolid/IfcArbitraryClosedProfileDef",
|
||||
)
|
||||
|
||||
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)
|
||||
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", "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", "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:
|
||||
entity_to_type_map["IFC4"] = json.load(f)
|
||||
|
||||
type_to_entity_map["IFC2X3"] = {
|
||||
value: [key] for key in entity_to_type_map["IFC2X3"] for value in entity_to_type_map["IFC2X3"][key]
|
||||
}
|
||||
|
||||
type_to_entity_map["IFC4"] = {
|
||||
value: [key] for key in entity_to_type_map["IFC4"] for value in entity_to_type_map["IFC4"][key]
|
||||
}
|
||||
for schema in ["IFC2X3", "IFC4"]:
|
||||
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[schema].setdefault(element_type, []).append(element)
|
||||
# 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"):
|
||||
|
||||
Reference in New Issue
Block a user