mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
WIP class dropdowns are now schema version specific and generated. See #1222.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import bpy
|
||||
import ifcopenshell.util.schema
|
||||
import blenderbim.bim.module.aggregate.assign_object as assign_object
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.aggregate.data import Data
|
||||
@@ -12,22 +13,44 @@ class AssignObject(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
obj = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object
|
||||
props = obj.BIMObjectProperties
|
||||
related_object = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object
|
||||
props = related_object.BIMObjectProperties
|
||||
relating_object = bpy.data.objects.get(self.relating_object) if self.relating_object else props.relating_object
|
||||
if not relating_object or not relating_object.BIMObjectProperties.ifc_definition_id:
|
||||
return {"FINISHED"}
|
||||
product = self.file.by_id(props.ifc_definition_id)
|
||||
assign_object.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"product": self.file.by_id(props.ifc_definition_id),
|
||||
"product": product,
|
||||
"relating_object": self.file.by_id(relating_object.BIMObjectProperties.ifc_definition_id),
|
||||
},
|
||||
).execute()
|
||||
Data.load(props.ifc_definition_id)
|
||||
bpy.ops.bim.disable_editing_aggregate(obj=self.related_object)
|
||||
bpy.ops.bim.disable_editing_aggregate(obj=related_object.name)
|
||||
|
||||
file = IfcStore.get_file()
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema)
|
||||
declaration = ifc_schema.declaration_by_name(product.is_a())
|
||||
|
||||
# TODO: we may not need this conditional if aggregates stop using collection instances
|
||||
if ifcopenshell.util.schema.is_a(declaration, "IfcSpatialElement"):
|
||||
related_collection = related_object.users_collection[0]
|
||||
relating_collection = relating_object.users_collection[0]
|
||||
self.remove_collection(bpy.context.scene.collection, related_collection)
|
||||
for collection in bpy.data.collections:
|
||||
if collection == relating_collection:
|
||||
collection.children.link(related_collection)
|
||||
continue
|
||||
self.remove_collection(collection, related_collection)
|
||||
return {"FINISHED"}
|
||||
|
||||
def remove_collection(self, parent, child):
|
||||
try:
|
||||
parent.children.unlink(child)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
class EnableEditingAggregate(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_aggregate"
|
||||
|
||||
@@ -119,6 +119,25 @@ class Usecase:
|
||||
items,
|
||||
)
|
||||
|
||||
def create_polygonal_face_set(self):
|
||||
ifc_raw_items = [None] * self.settings["total_items"]
|
||||
for i, value in enumerate(ifc_raw_items):
|
||||
ifc_raw_items[i] = []
|
||||
for polygon in self.settings["geometry"].polygons:
|
||||
ifc_raw_items[polygon.material_index % self.settings["total_items"]].append(
|
||||
self.file.createIfcIndexedPolygonalFace([v + 1 for v in polygon.vertices])
|
||||
)
|
||||
coordinates = self.file.createIfcCartesianPointList3D(
|
||||
[self.convert_si_to_unit(v.co) for v in self.settings["geometry"].vertices]
|
||||
)
|
||||
items = [self.file.createIfcPolygonalFaceSet(coordinates, None, i) for i in ifc_raw_items if i]
|
||||
return self.file.createIfcShapeRepresentation(
|
||||
self.settings["context"],
|
||||
self.settings["context"].ContextIdentifier,
|
||||
"Tessellation",
|
||||
items,
|
||||
)
|
||||
|
||||
def create_vertices(self, is_2d=False):
|
||||
if is_2d:
|
||||
for v in self.settings["geometry"].vertices:
|
||||
|
||||
@@ -12,7 +12,7 @@ class Data:
|
||||
return
|
||||
cls.products[product_id] = []
|
||||
product = file.by_id(product_id)
|
||||
if not product.Representation:
|
||||
if not hasattr(product, "Representation") or not product.Representation:
|
||||
return
|
||||
for representation in product.Representation.Representations:
|
||||
c = representation.ContextOfItems
|
||||
|
||||
@@ -22,39 +22,30 @@ class CreateProject(bpy.types.Operator):
|
||||
IfcStore.file = create_file.Usecase({"version": bpy.context.scene.BIMProperties.export_schema}).execute()
|
||||
self.file = IfcStore.get_file()
|
||||
|
||||
project = bpy.data.collections.new("My Project")
|
||||
site = bpy.data.collections.new("My Site")
|
||||
building = bpy.data.collections.new("My Building")
|
||||
building_storey = bpy.data.collections.new("Ground Floor")
|
||||
project = bpy.data.objects.new("My Project", None)
|
||||
site = bpy.data.objects.new("My Site", None)
|
||||
building = bpy.data.objects.new("My Building", None)
|
||||
building_storey = bpy.data.objects.new("Ground Floor", None)
|
||||
|
||||
project_obj = bpy.data.objects.new("My Project", None)
|
||||
site_obj = bpy.data.objects.new("My Site", None)
|
||||
building_obj = bpy.data.objects.new("My Building", None)
|
||||
building_storey_obj = bpy.data.objects.new("Ground Floor", None)
|
||||
|
||||
bpy.context.scene.collection.children.link(project)
|
||||
project.children.link(site)
|
||||
site.children.link(building)
|
||||
building.children.link(building_storey)
|
||||
|
||||
project.objects.link(project_obj)
|
||||
site.objects.link(site_obj)
|
||||
building.objects.link(building_obj)
|
||||
building_storey.objects.link(building_storey_obj)
|
||||
|
||||
bpy.ops.bim.assign_class(obj=project_obj.name, ifc_class="IfcProject")
|
||||
bpy.ops.bim.assign_class(obj=project.name, ifc_class="IfcProject")
|
||||
bpy.ops.bim.assign_unit()
|
||||
bpy.ops.bim.add_subcontext(context="Model")
|
||||
bpy.ops.bim.add_subcontext(context="Model", subcontext="Body", target_view="MODEL_VIEW")
|
||||
bpy.ops.bim.add_subcontext(context="Model", subcontext="Box", target_view="MODEL_VIEW")
|
||||
bpy.ops.bim.add_subcontext(context="Plan")
|
||||
bpy.ops.bim.add_subcontext(context="Plan", subcontext="Annotation", target_view="PLAN_VIEW")
|
||||
bpy.ops.bim.assign_class(obj=site_obj.name, ifc_class="IfcSite")
|
||||
bpy.ops.bim.assign_class(obj=building_obj.name, ifc_class="IfcBuilding")
|
||||
bpy.ops.bim.assign_class(obj=building_storey_obj.name, ifc_class="IfcBuildingStorey")
|
||||
bpy.ops.bim.assign_object(related_object=site_obj.name, relating_object=project_obj.name)
|
||||
bpy.ops.bim.assign_object(related_object=building_obj.name, relating_object=site_obj.name)
|
||||
bpy.ops.bim.assign_object(related_object=building_storey_obj.name, relating_object=building_obj.name)
|
||||
|
||||
for subcontext in self.file.by_type("IfcGeometricRepresentationSubContext"):
|
||||
if subcontext.ContextIdentifier == "Body":
|
||||
bpy.context.scene.BIMProperties.contexts = str(subcontext.id())
|
||||
break
|
||||
|
||||
bpy.ops.bim.assign_class(obj=site.name, ifc_class="IfcSite")
|
||||
bpy.ops.bim.assign_class(obj=building.name, ifc_class="IfcBuilding")
|
||||
bpy.ops.bim.assign_class(obj=building_storey.name, ifc_class="IfcBuildingStorey")
|
||||
bpy.ops.bim.assign_object(related_object=site.name, relating_object=project.name)
|
||||
bpy.ops.bim.assign_object(related_object=building.name, relating_object=site.name)
|
||||
bpy.ops.bim.assign_object(related_object=building_storey.name, relating_object=building.name)
|
||||
# Data.load()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import bpy
|
||||
import numpy as np
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.schema
|
||||
import blenderbim.bim.module.root.create_product as create_product
|
||||
import blenderbim.bim.module.root.remove_product as remove_product
|
||||
import blenderbim.bim.module.root.reassign_class as reassign_class
|
||||
@@ -19,7 +20,8 @@ class EnableReassignClass(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
obj = bpy.context.active_object
|
||||
ifc_class = obj.name.split("/")[0]
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(bpy.context.scene.BIMProperties.export_schema)
|
||||
file = IfcStore.get_file()
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema)
|
||||
bpy.context.active_object.BIMObjectProperties.is_reassigning_class = True
|
||||
ifc_products = [
|
||||
"IfcElement",
|
||||
@@ -85,49 +87,39 @@ class AssignClass(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
objects = [bpy.data.objects.get(self.obj)] if self.obj else bpy.context.selected_objects
|
||||
self.file = IfcStore.get_file()
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(self.file.schema)
|
||||
self.declaration = ifc_schema.declaration_by_name(self.ifc_class)
|
||||
if self.predefined_type == "USERDEFINED":
|
||||
self.predefined_type = self.ifc_userdefined_type
|
||||
elif self.predefined_type == "":
|
||||
predefined_type = None
|
||||
for obj in objects:
|
||||
if obj.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
if self.predefined_type == "USERDEFINED":
|
||||
predefined_type = self.ifc_userdefined_type
|
||||
elif self.predefined_type == "":
|
||||
predefined_type = None
|
||||
else:
|
||||
predefined_type = self.predefined_type
|
||||
product = create_product.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"ifc_class": self.ifc_class,
|
||||
"predefined_type": predefined_type,
|
||||
"name": obj.name,
|
||||
},
|
||||
).execute()
|
||||
obj.name = "{}/{}".format(product.is_a(), obj.name)
|
||||
obj.BIMObjectProperties.ifc_definition_id = int(product.id())
|
||||
|
||||
bpy.ops.bim.add_representation(obj=obj.name)
|
||||
|
||||
relating_structure = None
|
||||
for collection in obj.users_collection:
|
||||
if "Ifc" in collection.name:
|
||||
relating_structure = self.file.by_id(
|
||||
bpy.data.objects.get(collection.name).BIMObjectProperties.ifc_definition_id
|
||||
)
|
||||
break
|
||||
|
||||
if relating_structure:
|
||||
assign_container.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"product": product,
|
||||
"relating_structure": relating_structure,
|
||||
},
|
||||
).execute()
|
||||
|
||||
if bpy.context.scene.BIMProperties.ifc_product == "IfcElementType":
|
||||
self.place_in_types_collection(obj)
|
||||
self.assign_class(obj)
|
||||
return {"FINISHED"}
|
||||
|
||||
def assign_class(self, obj):
|
||||
if obj.BIMObjectProperties.ifc_definition_id:
|
||||
return
|
||||
product = create_product.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"ifc_class": self.ifc_class,
|
||||
"predefined_type": self.predefined_type,
|
||||
"name": obj.name,
|
||||
},
|
||||
).execute()
|
||||
obj.name = "{}/{}".format(product.is_a(), obj.name)
|
||||
obj.BIMObjectProperties.ifc_definition_id = int(product.id())
|
||||
|
||||
bpy.ops.bim.add_representation(obj=obj.name)
|
||||
|
||||
if ifcopenshell.util.schema.is_a(self.declaration, "IfcElementType"):
|
||||
self.place_in_types_collection(obj)
|
||||
elif ifcopenshell.util.schema.is_a(self.declaration, "IfcSpatialElement") or self.ifc_class == "IfcProject":
|
||||
self.place_in_spatial_collection(obj)
|
||||
else:
|
||||
self.assign_potential_spatial_container(obj)
|
||||
|
||||
def place_in_types_collection(self, obj):
|
||||
for project in [c for c in bpy.context.view_layer.layer_collection.children if "IfcProject" in c.name]:
|
||||
if not [c for c in project.children if "Types" in c.name]:
|
||||
@@ -140,6 +132,29 @@ class AssignClass(bpy.types.Operator):
|
||||
break
|
||||
break
|
||||
|
||||
def place_in_spatial_collection(self, obj):
|
||||
for collection in obj.users_collection:
|
||||
if collection.name == obj.name:
|
||||
return
|
||||
parent_collection = None
|
||||
for collection in obj.users_collection:
|
||||
collection.objects.unlink(obj)
|
||||
if "Ifc" in collection.name:
|
||||
parent_collection = collection
|
||||
collection = bpy.data.collections.new(obj.name)
|
||||
collection.objects.link(obj)
|
||||
if parent_collection:
|
||||
parent_collection.children.link(collection)
|
||||
else:
|
||||
bpy.context.scene.collection.children.link(collection)
|
||||
|
||||
def assign_potential_spatial_container(self, obj):
|
||||
for collection in obj.users_collection:
|
||||
if "Ifc" not in collection.name:
|
||||
continue
|
||||
bpy.ops.bim.assign_container(relating_structure=collection.name, related_element=obj.name)
|
||||
break
|
||||
|
||||
|
||||
class UnassignClass(bpy.types.Operator):
|
||||
bl_idname = "bim.unassign_class"
|
||||
|
||||
@@ -8,6 +8,7 @@ from . import ifc
|
||||
from . import annotation
|
||||
from . import decoration
|
||||
import bpy
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.app.handlers import persistent
|
||||
from bpy.props import (
|
||||
@@ -125,14 +126,14 @@ def setDefaultProperties(scene):
|
||||
|
||||
def getIfcPredefinedTypes(self, context):
|
||||
global types_enum
|
||||
if len(types_enum) < 1:
|
||||
for name, data in schema.ifc.elements.items():
|
||||
if name != self.ifc_class.strip():
|
||||
continue
|
||||
for attribute in data["attributes"]:
|
||||
if attribute["name"] != "PredefinedType":
|
||||
continue
|
||||
types_enum.extend([(e, e, "") for e in attribute["enum_values"]])
|
||||
file = IfcStore.get_file()
|
||||
if len(types_enum) < 1 and file:
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema)
|
||||
declaration = ifc_schema.declaration_by_name(self.ifc_class)
|
||||
for attribute in declaration.attributes():
|
||||
if attribute.name() == "PredefinedType":
|
||||
types_enum.extend([(e, e, "") for e in attribute.type_of_attribute().declared_type().enumeration_items()])
|
||||
break
|
||||
return types_enum
|
||||
|
||||
|
||||
@@ -257,8 +258,7 @@ def getIfcProducts(self, context):
|
||||
"IfcElementType",
|
||||
"IfcSpatialElement",
|
||||
"IfcGroup",
|
||||
"IfcStructural",
|
||||
"IfcPositioningElement",
|
||||
"IfcStructuralItem",
|
||||
"IfcContext",
|
||||
"IfcAnnotation",
|
||||
]
|
||||
@@ -269,8 +269,19 @@ def getIfcProducts(self, context):
|
||||
|
||||
def getIfcClasses(self, context):
|
||||
global classes_enum
|
||||
if len(classes_enum) < 1:
|
||||
classes_enum.extend([(e, e, "") for e in getattr(schema.ifc, self.ifc_product)])
|
||||
file = IfcStore.get_file()
|
||||
if len(classes_enum) < 1 and file:
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema)
|
||||
declaration = ifc_schema.declaration_by_name(self.ifc_product)
|
||||
def get_classes(declaration):
|
||||
results = []
|
||||
if not declaration.is_abstract():
|
||||
results.append(declaration.name())
|
||||
for subtype in declaration.subtypes():
|
||||
results.extend(get_classes(subtype))
|
||||
return results
|
||||
classes = get_classes(declaration)
|
||||
classes_enum.extend([(c, c, "") for c in sorted(classes)])
|
||||
return classes_enum
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user