create new shape aspects from UI

example - https://i.imgur.com/BJJZWrC.png
This commit is contained in:
Andrej730
2024-01-29 12:29:15 +05:00
parent d8fa853308
commit 64a9f85f25
4 changed files with 70 additions and 20 deletions
@@ -108,7 +108,8 @@ class RepresentationsData:
matching_shape_aspects.append(shape_aspect)
# blender enum items
return [(str(s.id()), s.Name or "Unnamed", "") for s in matching_shape_aspects]
new_shape_aspect = [("NEW", "Create A New Shape Aspect", "")]
return new_shape_aspect + [(str(s.id()), s.Name or "Unnamed", "") for s in matching_shape_aspects]
class RepresentationItemsData:
@@ -1692,7 +1692,7 @@ class EnableEditingRepresentationItemShapeAspect(bpy.types.Operator, Operator):
props = context.active_object.BIMGeometryProperties
props.is_editing_item_shape_aspect = True
# set dropdown to currently active style
# set dropdown to currently active shape aspect
shape_aspect_id = props.items[props.active_item_index].shape_aspect_id
if shape_aspect_id != 0:
props.representation_item_shape_aspect = str(shape_aspect_id)
@@ -1705,21 +1705,36 @@ class EditRepresentationItemShapeAspect(bpy.types.Operator, Operator):
def _execute(self, context):
obj = context.active_object
element = tool.Ifc.get_entity(obj)
props = obj.BIMGeometryProperties
props.is_editing_item_shape_aspect = False
ifc_file = tool.Ifc.get()
shape_aspect = ifc_file.by_id(int(props.representation_item_shape_aspect))
representation_item_id = props.items[props.active_item_index].ifc_definition_id
representation_item = ifc_file.by_id(representation_item_id)
if props.representation_item_shape_aspect == "NEW":
active_representation = tool.Geometry.get_active_representation(obj)
# find IfcProductRepresentationSelect based on current representation
if hasattr(element, "Representation"): # IfcProduct
product_shape = element.Representation
else: # IfcTypeProduct
for representation_map in element.RepresentationMaps:
if representation_map.MappedRepresentation == active_representation:
product_shape = representation_map
previous_shape_aspect_id = props.items[props.active_item_index].shape_aspect_id
# will be None if item didn't had a shape aspect
previous_shape_aspect = tool.Ifc.get_entity_by_id(previous_shape_aspect_id)
shape_aspect = tool.Geometry.create_shape_aspect(product_shape, active_representation, [representation_item], previous_shape_aspect)
else:
shape_aspect = ifc_file.by_id(int(props.representation_item_shape_aspect))
tool.Geometry.add_representation_item_to_shape_aspect([representation_item], shape_aspect)
# set attributes from UI
shape_aspect_attrs = props.shape_aspect_attrs
shape_aspect.Name = shape_aspect_attrs.name
shape_aspect.Description = shape_aspect_attrs.description
representation_item_id = props.items[props.active_item_index].ifc_definition_id
representation_item = ifc_file.by_id(representation_item_id)
tool.Geometry.add_representation_item_to_shape_aspect(representation_item, shape_aspect)
# reload style ui
bpy.ops.bim.disable_editing_representation_items()
bpy.ops.bim.enable_editing_representation_items()
@@ -1749,7 +1764,7 @@ class RemoveRepresentationItemFromShapeAspect(bpy.types.Operator, Operator):
representation_item = ifc_file.by_id(representation_item_id)
shape_aspect = ifc_file.by_id(props.items[props.active_item_index].shape_aspect_id)
tool.Geometry.remove_representation_item_from_shape_aspect(representation_item, shape_aspect)
tool.Geometry.remove_representation_items_from_shape_aspect([representation_item], shape_aspect)
# reload style ui
bpy.ops.bim.disable_editing_representation_items()
bpy.ops.bim.enable_editing_representation_items()
@@ -72,9 +72,13 @@ def update_shape_aspect(self, context):
shape_aspect_id = self.representation_item_shape_aspect
attrs = self.shape_aspect_attrs
shape_aspect = tool.Ifc.get().by_id(int(shape_aspect_id))
attrs.name = shape_aspect.Name or ""
attrs.description = shape_aspect.Description or ""
if shape_aspect_id == "NEW": # new shape aspect
attrs.name = tool.Blender.get_blender_prop_default_value(attrs, "name")
attrs.description = tool.Blender.get_blender_prop_default_value(attrs, "description")
else:
shape_aspect = tool.Ifc.get().by_id(int(shape_aspect_id))
attrs.name = shape_aspect.Name or ""
attrs.description = shape_aspect.Description or ""
class RepresentationItem(PropertyGroup):
+39 -9
View File
@@ -299,6 +299,7 @@ class Geometry(blenderbim.core.tool.Geometry):
@classmethod
def get_active_representation(cls, obj):
"""< IfcShapeRepresentation or None"""
if obj.data and hasattr(obj.data, "BIMMeshProperties") and obj.data.BIMMeshProperties.ifc_definition_id:
return tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_definition_id)
@@ -744,31 +745,56 @@ class Geometry(blenderbim.core.tool.Geometry):
return shape_aspects
@classmethod
def remove_representation_item_from_shape_aspect(cls, representation_item, shape_aspect):
def create_shape_aspect(cls, product_shape, base_representation, items, previous_shape_aspect=None):
"""
> `product_shape` - IfcProductDefinitionShape or IfcRepresentationMap\n
> `base_representation` - base representation to get context attributes from\n
> `items` - representation items\n
> `previous_shape_aspect` - (optional) previous shape aspect, if provided\n
items will be removed the previous shape aspect first\n
< IfcShapeAspect
"""
if previous_shape_aspect is not None:
cls.remove_representation_items_from_shape_aspect(items, previous_shape_aspect)
shape_aspect = tool.Ifc.get().createIfcShapeAspect(
PartOfProductDefinitionShape=product_shape, ShapeRepresentations=()
)
# keep IfcShapeAspect and IfcShapeRepresentation valid
rep = tool.Geometry.add_shape_aspect_representation(shape_aspect, base_representation)
rep.Items = items
return shape_aspect
@classmethod
def remove_representation_items_from_shape_aspect(cls, representation_items, shape_aspect):
ifc_file = tool.Ifc.get()
# as shape aspect might have multiple representations
# it's easier to find it from the item
for inverse in ifc_file.get_inverse(representation_item):
for inverse in ifc_file.get_inverse(representation_items[0]):
if inverse.is_a("IfcShapeRepresentation") and shape_aspect in inverse.OfShapeAspect:
representation = inverse
break
# removing last item would make representation invalid
if len(representation.Items) == 1:
if len(representation.Items) == len(representation_items):
# removing last representation would make shape aspect invalid.
# remove shape aspect first otherwise remove_representation won't remove it because of the inverse
if len(shape_aspect.ShapeRepresentations) == 1:
ifc_file.remove(shape_aspect)
tool.Ifc.run("geometry.remove_representation", representation=representation)
else:
items = set(representation.Items) - {representation_item}
items = set(representation.Items) - set(representation_items)
representation.Items = tuple(items)
@classmethod
def add_representation_item_to_shape_aspect(cls, representation_item, shape_aspect):
def add_representation_item_to_shape_aspect(cls, representation_items, shape_aspect):
"""NOTE: we assume that all items belonged to the same representation and to the same shape aspect"""
ifc_file = tool.Ifc.get()
previous_shape_aspect = None
for inverse in ifc_file.get_inverse(representation_item):
for inverse in ifc_file.get_inverse(representation_items[0]):
if inverse.is_a("IfcShapeRepresentation"):
if inverse.OfShapeAspect:
# item is already added to the shape aspect
@@ -780,11 +806,11 @@ class Geometry(blenderbim.core.tool.Geometry):
# remove item from previous shape aspect
if previous_shape_aspect:
cls.remove_representation_item_from_shape_aspect(representation_item, previous_shape_aspect)
cls.remove_representation_items_from_shape_aspect(representation_items, previous_shape_aspect)
shape_aspect_representation = cls.get_shape_aspect_representation(
shape_aspect, base_representation, create_new=True
)
shape_aspect_representation.Items = shape_aspect_representation.Items + (representation_item,)
shape_aspect_representation.Items = shape_aspect_representation.Items + tuple(representation_items)
@classmethod
def get_shape_aspect_representation(cls, shape_aspect, base_representation, create_new=False):
@@ -799,11 +825,15 @@ class Geometry(blenderbim.core.tool.Geometry):
if not create_new:
return None
return cls.add_shape_aspect_representation(shape_aspect, base_representation)
@classmethod
def add_shape_aspect_representation(cls, shape_aspect, base_representation):
shape_aspect_representation = tool.Ifc.get().createIfcShapeRepresentation(
ContextOfItems=base_representation.ContextOfItems,
RepresentationIdentifier=base_representation.RepresentationIdentifier,
RepresentationType=base_representation.RepresentationType,
)
shape_aspect.ShapeRepresentations = shape_aspect.ShapeRepresentations + (shape_aspect_representation,)
return shape_aspect_representation