mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
create new shape aspects from UI
example - https://i.imgur.com/BJJZWrC.png
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user