Hi there,
I am currently trying to create a script that allows me to unite different geometries from an imported IFC model. Nonetheless, my current script only works properly the first time it is called in Allplan. Let's say I have elements A and B in Position 1, and elements C and D in Position 2. When I select element A + B, the union is performed successfully and placed in Position 1. Once I try to use the same script to unite elements C + D, the union is performed and placed in position 1, instead of position 2. Furthermore, the shape of Element C + D now takes the shape of Element A + B. It seems like the initial position and the initially selected geometries cannot be overwritten once the script is restarted.
I must say that the situation remains the same when I run the script on the elements created within Allplan 2026.
Please let me know what is going on here. See my script below.
"""
Simple Element Union Script
Basic functionality:
- Select multiple elements
- Union their geometries
- Replace with single element
"""
from __future__ import annotations
from typing import TYPE_CHECKING, List
import NemAll_Python_BaseElements as AllplanBaseEle
import NemAll_Python_Utility as AllplanUtil
import NemAll_Python_Geometry as AllplanGeo
import NemAll_Python_IFW_ElementAdapter as AllplanEleAdapter
from BaseScriptObject import BaseScriptObject, BaseScriptObjectData
from CreateElementResult import CreateElementResult
from ScriptObjectInteractors.MultiElementSelectInteractor import (
MultiElementSelectInteractor,
MultiElementSelectInteractorResult,
)
from TypeCollections.ModelEleList import ModelEleList
from PythonPartUtil import PythonPartUtil
if TYPE_CHECKING:
from __BuildingElementStubFiles.InputInteractorBuildingElement import InputInteractorBuildingElement as BuildingElement
else:
from BuildingElement import BuildingElement
def check_allplan_version(_build_ele: BuildingElement, _version: str) -> bool:
return True
def create_script_object(build_ele: BuildingElement, script_object_data: BaseScriptObjectData) -> "UniteElementsScript":
return UniteElementsScript(build_ele, script_object_data)
class UniteElementsScript(BaseScriptObject):
"""Simple script object for uniting elements"""
def __init__(self, build_ele: BuildingElement, script_object_data: BaseScriptObjectData):
super().__init__(script_object_data)
self.build_ele = build_ele
self.multi_select_result = MultiElementSelectInteractorResult()
def start_input(self):
"""Start element selection"""
self.script_object_interactor = MultiElementSelectInteractor(
self.multi_select_result,
prompt_msg="Select elements to unite"
)
def start_next_input(self):
"""Process selected elements"""
self.script_object_interactor = None
selected_adapters = self.multi_select_result.sel_elements
valid_adapters = [adapter for adapter in selected_adapters if adapter.IsValid()]
if len(valid_adapters) < 2:
AllplanUtil.ShowMessageBox("Please select at least 2 elements.", AllplanUtil.MB_OK)
return None
success = self.unite_elements(valid_adapters)
if success:
AllplanUtil.ShowMessageBox("Union created successfully!", AllplanUtil.MB_OK)
else:
AllplanUtil.ShowMessageBox("Error creating union.", AllplanUtil.MB_OK)
return None
def unite_elements(self, adapters: List) -> bool:
"""Unite the selected elements"""
# Get geometries
geometries = []
base_properties = None
for adapter in adapters:
geom = adapter.GetGeometry()
print("MY GEOM",geom)
if geom is not None:
geometries.append(geom)
if base_properties is None:
base_properties = adapter.GetCommonProperties()
if len(geometries) < 2:
return False
print("MY GEOMETRIES", geometries)
# Perform union
united_geometry = self.perform_union(geometries)
if united_geometry is None:
return False
# Create new element
com_prop = base_properties or AllplanBaseEle.CommonProperties()
model_ele_list = ModelEleList(com_prop)
model_ele_list.append_geometry_3d(united_geometry)
# Delete original elements
delete_list = AllplanEleAdapter.BaseElementAdapterList()
for adapter in adapters:
delete_list.append(adapter)
AllplanBaseEle.DeleteElements(self.document, delete_list)
# Create new PythonPart
pyp_util = PythonPartUtil()
pyp_util.add_pythonpart_view_2d3d(model_ele_list)
pythonpart_elements = pyp_util.create_pythonpart(self.build_ele)
# Place in document
placement = AllplanGeo.Matrix3D()
AllplanBaseEle.CreateElements(self.document, placement, pythonpart_elements, [], [])
return True
def perform_union(self, geometries: List):
"""Perform geometry union operation"""
try:
polyhed_list = AllplanGeo.Polyhedron3DList()
for geometry in geometries:
if isinstance(geometry, AllplanGeo.Polyhedron3D):
polyhed_list.append(geometry)
print ("Geometry is Polyhedron 3D")
elif hasattr(geometry, 'ToPolyhedron3D'):
polyhed = geometry.ToPolyhedron3D()
if polyhed.IsValid():
polyhed_list.append(polyhed)
if len(polyhed_list) < 2:
return None
result, united_polyhed = AllplanGeo.MakeUnion(polyhed_list)
print("RESULTS", result)
print("UNITED POLYHED", united_polyhed)
if result and united_polyhed.IsValid():
print("COMPLETED")
return united_polyhed
else:
return None
except Exception:
return None
def execute(self) -> CreateElementResult:
"""Execute the script"""
return CreateElementResult()