mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 17:21:05 +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 bpy
|
||||||
|
import ifcopenshell.util.schema
|
||||||
import blenderbim.bim.module.aggregate.assign_object as assign_object
|
import blenderbim.bim.module.aggregate.assign_object as assign_object
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from blenderbim.bim.module.aggregate.data import Data
|
from blenderbim.bim.module.aggregate.data import Data
|
||||||
@@ -12,22 +13,44 @@ class AssignObject(bpy.types.Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
self.file = IfcStore.get_file()
|
self.file = IfcStore.get_file()
|
||||||
obj = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object
|
related_object = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object
|
||||||
props = obj.BIMObjectProperties
|
props = related_object.BIMObjectProperties
|
||||||
relating_object = bpy.data.objects.get(self.relating_object) if self.relating_object else props.relating_object
|
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:
|
if not relating_object or not relating_object.BIMObjectProperties.ifc_definition_id:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
product = self.file.by_id(props.ifc_definition_id)
|
||||||
assign_object.Usecase(
|
assign_object.Usecase(
|
||||||
self.file,
|
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),
|
"relating_object": self.file.by_id(relating_object.BIMObjectProperties.ifc_definition_id),
|
||||||
},
|
},
|
||||||
).execute()
|
).execute()
|
||||||
Data.load(props.ifc_definition_id)
|
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"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
def remove_collection(self, parent, child):
|
||||||
|
try:
|
||||||
|
parent.children.unlink(child)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingAggregate(bpy.types.Operator):
|
class EnableEditingAggregate(bpy.types.Operator):
|
||||||
bl_idname = "bim.enable_editing_aggregate"
|
bl_idname = "bim.enable_editing_aggregate"
|
||||||
|
|||||||
@@ -119,6 +119,25 @@ class Usecase:
|
|||||||
items,
|
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):
|
def create_vertices(self, is_2d=False):
|
||||||
if is_2d:
|
if is_2d:
|
||||||
for v in self.settings["geometry"].vertices:
|
for v in self.settings["geometry"].vertices:
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class Data:
|
|||||||
return
|
return
|
||||||
cls.products[product_id] = []
|
cls.products[product_id] = []
|
||||||
product = file.by_id(product_id)
|
product = file.by_id(product_id)
|
||||||
if not product.Representation:
|
if not hasattr(product, "Representation") or not product.Representation:
|
||||||
return
|
return
|
||||||
for representation in product.Representation.Representations:
|
for representation in product.Representation.Representations:
|
||||||
c = representation.ContextOfItems
|
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()
|
IfcStore.file = create_file.Usecase({"version": bpy.context.scene.BIMProperties.export_schema}).execute()
|
||||||
self.file = IfcStore.get_file()
|
self.file = IfcStore.get_file()
|
||||||
|
|
||||||
project = bpy.data.collections.new("My Project")
|
project = bpy.data.objects.new("My Project", None)
|
||||||
site = bpy.data.collections.new("My Site")
|
site = bpy.data.objects.new("My Site", None)
|
||||||
building = bpy.data.collections.new("My Building")
|
building = bpy.data.objects.new("My Building", None)
|
||||||
building_storey = bpy.data.collections.new("Ground Floor")
|
building_storey = bpy.data.objects.new("Ground Floor", None)
|
||||||
|
|
||||||
project_obj = bpy.data.objects.new("My Project", None)
|
bpy.ops.bim.assign_class(obj=project.name, ifc_class="IfcProject")
|
||||||
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_unit()
|
bpy.ops.bim.assign_unit()
|
||||||
bpy.ops.bim.add_subcontext(context="Model")
|
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="Body", target_view="MODEL_VIEW")
|
||||||
bpy.ops.bim.add_subcontext(context="Model", subcontext="Box", 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")
|
||||||
bpy.ops.bim.add_subcontext(context="Plan", subcontext="Annotation", target_view="PLAN_VIEW")
|
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")
|
for subcontext in self.file.by_type("IfcGeometricRepresentationSubContext"):
|
||||||
bpy.ops.bim.assign_class(obj=building_storey_obj.name, ifc_class="IfcBuildingStorey")
|
if subcontext.ContextIdentifier == "Body":
|
||||||
bpy.ops.bim.assign_object(related_object=site_obj.name, relating_object=project_obj.name)
|
bpy.context.scene.BIMProperties.contexts = str(subcontext.id())
|
||||||
bpy.ops.bim.assign_object(related_object=building_obj.name, relating_object=site_obj.name)
|
break
|
||||||
bpy.ops.bim.assign_object(related_object=building_storey_obj.name, relating_object=building_obj.name)
|
|
||||||
|
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()
|
# Data.load()
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.util.schema
|
||||||
import blenderbim.bim.module.root.create_product as create_product
|
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.remove_product as remove_product
|
||||||
import blenderbim.bim.module.root.reassign_class as reassign_class
|
import blenderbim.bim.module.root.reassign_class as reassign_class
|
||||||
@@ -19,7 +20,8 @@ class EnableReassignClass(bpy.types.Operator):
|
|||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
obj = bpy.context.active_object
|
obj = bpy.context.active_object
|
||||||
ifc_class = obj.name.split("/")[0]
|
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
|
bpy.context.active_object.BIMObjectProperties.is_reassigning_class = True
|
||||||
ifc_products = [
|
ifc_products = [
|
||||||
"IfcElement",
|
"IfcElement",
|
||||||
@@ -85,49 +87,39 @@ class AssignClass(bpy.types.Operator):
|
|||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
objects = [bpy.data.objects.get(self.obj)] if self.obj else bpy.context.selected_objects
|
objects = [bpy.data.objects.get(self.obj)] if self.obj else bpy.context.selected_objects
|
||||||
self.file = IfcStore.get_file()
|
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:
|
for obj in objects:
|
||||||
if obj.BIMObjectProperties.ifc_definition_id:
|
self.assign_class(obj)
|
||||||
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)
|
|
||||||
return {"FINISHED"}
|
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):
|
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]:
|
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]:
|
if not [c for c in project.children if "Types" in c.name]:
|
||||||
@@ -140,6 +132,29 @@ class AssignClass(bpy.types.Operator):
|
|||||||
break
|
break
|
||||||
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):
|
class UnassignClass(bpy.types.Operator):
|
||||||
bl_idname = "bim.unassign_class"
|
bl_idname = "bim.unassign_class"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from . import ifc
|
|||||||
from . import annotation
|
from . import annotation
|
||||||
from . import decoration
|
from . import decoration
|
||||||
import bpy
|
import bpy
|
||||||
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from bpy.types import PropertyGroup
|
from bpy.types import PropertyGroup
|
||||||
from bpy.app.handlers import persistent
|
from bpy.app.handlers import persistent
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
@@ -125,14 +126,14 @@ def setDefaultProperties(scene):
|
|||||||
|
|
||||||
def getIfcPredefinedTypes(self, context):
|
def getIfcPredefinedTypes(self, context):
|
||||||
global types_enum
|
global types_enum
|
||||||
if len(types_enum) < 1:
|
file = IfcStore.get_file()
|
||||||
for name, data in schema.ifc.elements.items():
|
if len(types_enum) < 1 and file:
|
||||||
if name != self.ifc_class.strip():
|
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema)
|
||||||
continue
|
declaration = ifc_schema.declaration_by_name(self.ifc_class)
|
||||||
for attribute in data["attributes"]:
|
for attribute in declaration.attributes():
|
||||||
if attribute["name"] != "PredefinedType":
|
if attribute.name() == "PredefinedType":
|
||||||
continue
|
types_enum.extend([(e, e, "") for e in attribute.type_of_attribute().declared_type().enumeration_items()])
|
||||||
types_enum.extend([(e, e, "") for e in attribute["enum_values"]])
|
break
|
||||||
return types_enum
|
return types_enum
|
||||||
|
|
||||||
|
|
||||||
@@ -257,8 +258,7 @@ def getIfcProducts(self, context):
|
|||||||
"IfcElementType",
|
"IfcElementType",
|
||||||
"IfcSpatialElement",
|
"IfcSpatialElement",
|
||||||
"IfcGroup",
|
"IfcGroup",
|
||||||
"IfcStructural",
|
"IfcStructuralItem",
|
||||||
"IfcPositioningElement",
|
|
||||||
"IfcContext",
|
"IfcContext",
|
||||||
"IfcAnnotation",
|
"IfcAnnotation",
|
||||||
]
|
]
|
||||||
@@ -269,8 +269,19 @@ def getIfcProducts(self, context):
|
|||||||
|
|
||||||
def getIfcClasses(self, context):
|
def getIfcClasses(self, context):
|
||||||
global classes_enum
|
global classes_enum
|
||||||
if len(classes_enum) < 1:
|
file = IfcStore.get_file()
|
||||||
classes_enum.extend([(e, e, "") for e in getattr(schema.ifc, self.ifc_product)])
|
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
|
return classes_enum
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user