bcf + bbim - set/get selected/visible elements #4857

1) added more high level api for getting/setting selected/visible elements in bcf
2) in bbim when you add a new viewpoint it will remember currently selected and visible objects:
https://imgur.com/a/2pZ79Z2
This commit is contained in:
Andrej730
2024-08-09 18:58:34 +05:00
parent de14e92720
commit 73e5985777
3 changed files with 217 additions and 5 deletions
+100 -2
View File
@@ -1,6 +1,6 @@
import uuid import uuid
import zipfile import zipfile
from typing import Any, Iterable, Optional from typing import Any, Iterable, Optional, Literal, Union
import numpy as np import numpy as np
from ifcopenshell import entity_instance from ifcopenshell import entity_instance
@@ -204,6 +204,104 @@ class VisualizationInfoHandler:
visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler
) )
def get_selected_guids(self) -> Union[list[str], None]:
"""
Return viewpoint selected elements IFC guids.
Returns:
If viewpoint has no selection settings, return `None`.
Otherwise return a list of selected elements IFC guids.
"""
visualization_info = self.visualization_info
components = visualization_info.components
if not components:
return None
selection = components.selection
if not selection:
return None
return [guid for c in selection.component if (guid := c.ifc_guid)]
def set_selected_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
visualization_info = self.visualization_info
guids = [e.GlobalId for e in elements]
components = visualization_info.components
if not components:
visibility = mdl.ComponentVisibility(default_visibility=True)
components = mdl.Components(visibility=visibility)
visualization_info.components = components
selection = components.selection
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
if not selection:
selection = mdl.ComponentSelection()
components.selection = selection
selection.component = components_list
def set_visible_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
self.set_visibility(elements, elements_visibility="VISIBLE")
def set_hidden_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
self.set_visibility(elements, elements_visibility="HIDDEN")
def set_visibility(
self, elements: list[ifcopenshell.entity_instance], elements_visibility: Literal["VISIBLE", "HIDDEN"]
) -> None:
visualization_info = self.visualization_info
default_visibility = elements_visibility == "HIDDEN"
guids = [e.GlobalId for e in elements]
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
components = visualization_info.components
if not components:
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
components = mdl.Components(visibility=visibility)
visualization_info.components = components
visibility = components.visibility
if not visibility:
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
components.visibility = visibility
elif visibility.default_visibility != default_visibility:
visibility.default_visibility = default_visibility
exceptions = visibility.exceptions
if not exceptions:
exceptions = mdl.ComponentVisibilityExceptions()
visibility.exceptions = exceptions
exceptions.component = components_list
def get_elements_visibility(self) -> Union[tuple[bool, list[str]], None]:
"""
Return viewpoint elements visibility settings.
Returns:
If viewpoint has no visibility settings, return `None`.
Otherwise return a tuple containing the default visibility
and a list of IFC element GUIDs listed as exceptions.
If default visibility is `True`, all elements are visible except the exceptions.
If default visibility is `False`, all elements are hidden except the exceptions.
"""
visualization_info = self.visualization_info
components = visualization_info.components
if not components:
return None
visibility = components.visibility
if not visibility:
return None
default_visibility = visibility.default_visibility or False
exceptions = visibility.exceptions
if not exceptions:
return default_visibility, []
guids = [guid for c in exceptions.component if (guid := c.ifc_guid)]
return default_visibility, guids
def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo: def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
""" """
@@ -256,7 +354,7 @@ def build_components(*guids: str) -> mdl.Components:
Return the BCF components from an IFC element GUID. Return the BCF components from an IFC element GUID.
Args: Args:
*guids: One or more IFC element GUID. *guids: One or more selected IFC element GUID.
Returns: Returns:
The BCF components definition. The BCF components definition.
+100 -2
View File
@@ -1,6 +1,6 @@
import uuid import uuid
import zipfile import zipfile
from typing import Any, Iterable, Optional from typing import Any, Iterable, Optional, Literal, Union
import numpy as np import numpy as np
from ifcopenshell import entity_instance from ifcopenshell import entity_instance
@@ -204,6 +204,104 @@ class VisualizationInfoHandler:
visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler
) )
def get_selected_guids(self) -> Union[list[str], None]:
"""
Return viewpoint selected elements IFC guids.
Returns:
If viewpoint has no selection settings, return `None`.
Otherwise return a list of selected elements IFC guids.
"""
visualization_info = self.visualization_info
components = visualization_info.components
if not components:
return None
selection = components.selection
if not selection:
return None
return [guid for c in selection.component if (guid := c.ifc_guid)]
def set_selected_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
visualization_info = self.visualization_info
guids = [e.GlobalId for e in elements]
components = visualization_info.components
if not components:
visibility = mdl.ComponentVisibility(default_visibility=True)
components = mdl.Components(visibility=visibility)
visualization_info.components = components
selection = components.selection
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
if not selection:
selection = mdl.ComponentSelection()
components.selection = selection
selection.component = components_list
def set_visible_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
self.set_visibility(elements, elements_visibility="VISIBLE")
def set_hidden_elements(self, elements: list[ifcopenshell.entity_instance]) -> None:
self.set_visibility(elements, elements_visibility="HIDDEN")
def set_visibility(
self, elements: list[ifcopenshell.entity_instance], elements_visibility: Literal["VISIBLE", "HIDDEN"]
) -> None:
visualization_info = self.visualization_info
default_visibility = elements_visibility == "HIDDEN"
guids = [e.GlobalId for e in elements]
components_list = [mdl.Component(ifc_guid=guid) for guid in guids]
components = visualization_info.components
if not components:
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
components = mdl.Components(visibility=visibility)
visualization_info.components = components
visibility = components.visibility
if not visibility:
visibility = mdl.ComponentVisibility(default_visibility=default_visibility)
components.visibility = visibility
elif visibility.default_visibility != default_visibility:
visibility.default_visibility = default_visibility
exceptions = visibility.exceptions
if not exceptions:
exceptions = mdl.ComponentVisibilityExceptions()
visibility.exceptions = exceptions
exceptions.component = components_list
def get_elements_visibility(self) -> Union[tuple[bool, list[str]], None]:
"""
Return viewpoint elements visibility settings.
Returns:
If viewpoint has no visibility settings, return `None`.
Otherwise return a tuple containing the default visibility
and a list of IFC element GUIDs listed as exceptions.
If default visibility is `True`, all elements are visible except the exceptions.
If default visibility is `False`, all elements are hidden except the exceptions.
"""
visualization_info = self.visualization_info
components = visualization_info.components
if not components:
return None
visibility = components.visibility
if not visibility:
return None
default_visibility = visibility.default_visibility or False
exceptions = visibility.exceptions
if not exceptions:
return default_visibility, []
guids = [guid for c in exceptions.component if (guid := c.ifc_guid)]
return default_visibility, guids
def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo: def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
""" """
@@ -256,7 +354,7 @@ def build_components(*guids: str) -> mdl.Components:
Return the BCF components from an IFC element GUID. Return the BCF components from an IFC element GUID.
Args: Args:
*guids: One or more IFC element GUID. *guids: One or more selected IFC element GUID.
Returns: Returns:
The BCF components definition. The BCF components definition.
@@ -31,6 +31,7 @@ import webbrowser
import ifcopenshell import ifcopenshell
import ifcopenshell.util.geolocation import ifcopenshell.util.geolocation
import ifcopenshell.util.unit import ifcopenshell.util.unit
import blenderbim.tool as tool
import blenderbim.bim.module.bcf.prop as bcf_prop import blenderbim.bim.module.bcf.prop as bcf_prop
import blenderbim.bim.module.bcf.bcfstore as bcfstore import blenderbim.bim.module.bcf.bcfstore as bcfstore
from pathlib import Path from pathlib import Path
@@ -453,6 +454,7 @@ class AddBcfViewpoint(bpy.types.Operator):
def execute(self, context): def execute(self, context):
bcfxml = bcfstore.BcfStore.get_bcfxml() bcfxml = bcfstore.BcfStore.get_bcfxml()
blender_camera = context.scene.camera blender_camera = context.scene.camera
assert blender_camera
props = context.scene.BCFProperties props = context.scene.BCFProperties
blender_topic = props.active_topic blender_topic = props.active_topic
topic = bcfxml.topics[blender_topic.name] topic = bcfxml.topics[blender_topic.name]
@@ -495,13 +497,27 @@ class AddBcfViewpoint(bpy.types.Operator):
snapshot = f.read() snapshot = f.read()
# viewpoint.snapshot = blender_render.filepath # viewpoint.snapshot = blender_render.filepath
# TODO we should handle selection and visibility state
vizinfo = bcf.v2.visinfo.VisualizationInfoHandler(visualization_info=visualization_info, snapshot=snapshot) vizinfo = bcf.v2.visinfo.VisualizationInfoHandler(visualization_info=visualization_info, snapshot=snapshot)
topic.viewpoints[vizinfo.guid + ".bcfv"] = vizinfo topic.viewpoints[vizinfo.guid + ".bcfv"] = vizinfo
topic.markup.viewpoints.append( topic.markup.viewpoints.append(
bcf.v2.model.ViewPoint(viewpoint=vizinfo.guid + ".bcfv", guid=vizinfo.guid, snapshot=vizinfo.guid + ".png") bcf.v2.model.ViewPoint(viewpoint=vizinfo.guid + ".bcfv", guid=vizinfo.guid, snapshot=vizinfo.guid + ".png")
) )
def get_ifc_elements(objs: list[bpy.types.Object]) -> list[ifcopenshell.entity_instance]:
elements = []
for obj in objs:
if e := tool.Ifc.get_entity(obj):
elements.append(e)
return elements
selected_elements = get_ifc_elements(context.selected_objects)
if selected_elements:
vizinfo.set_selected_elements(selected_elements)
visible_elements = get_ifc_elements(context.visible_objects)
if visible_elements:
vizinfo.set_visible_elements(visible_elements)
blender_render.filepath = old_filepath blender_render.filepath = old_filepath
blender_render.image_settings.file_format = old_file_format blender_render.image_settings.file_format = old_file_format
props.refresh_topic(context) props.refresh_topic(context)