icon

Support Forum

Create assemblies


Dear all,

I am currently trying to create a set of specifically named assemblies using "AllplanPrecast.AssemblyGroupElement" after selecting multiple components of an imported .ifc model using "MultiElementSelectInteractor()"

Unfortunately, I have not been able to do it. I am currently trying to follow the script example "AssemblyGroupPlacement". Please check the enclosed script . The script runs without throwing an error, but the created assembly is not listed in the objects palette.

Is this achievable with AllplanPrecast.AssemblyGroupElement?
Is the fact that I am working with an ifc model an issue here?

Looking forward to hearing from you

Cheers,

Attachments (1)

CreateAssembly.py
Extension of this Attachment is wrong!
Type: text/x-script.python
Downloaded 0 times
Size: 5,16 KiB

Show most helpful answer Hide most helpful answer

Hi,

attaching scripts is not allowed, you have to change the extension to .txt for example.

Since I cannot look into the script, IDK what you are trying to put into the assembly. AFAIK, AssemblyGroup requires three lists:

  • one consisting of FixtureElement objects
  • one consisting of ReinforcementElement objects
  • one consisting of LibraryElement objects

What you get from the selection is a BaseElementAdapterList. You would need to extract all these objects from BaseElementAdapterList using GetElements. But:

  • You cannot get a LibraryElement from an BaseElementAdapter. LibraryElements can only be created new based on path to a .sym file
  • I think you can get a FixtureElement, but I am not sure if all the information are read
  • Getting a BarPlacement (which is ReinforcementElement) object is possible but tricky

So please provide more information. Maybe example drawing file would be helpful.

Cheers,
Bart

Hi,

attaching scripts is not allowed, you have to change the extension to .txt for example.

Since I cannot look into the script, IDK what you are trying to put into the assembly. AFAIK, AssemblyGroup requires three lists:

  • one consisting of FixtureElement objects
  • one consisting of ReinforcementElement objects
  • one consisting of LibraryElement objects

What you get from the selection is a BaseElementAdapterList. You would need to extract all these objects from BaseElementAdapterList using GetElements. But:

  • You cannot get a LibraryElement from an BaseElementAdapter. LibraryElements can only be created new based on path to a .sym file
  • I think you can get a FixtureElement, but I am not sure if all the information are read
  • Getting a BarPlacement (which is ReinforcementElement) object is possible but tricky

So please provide more information. Maybe example drawing file would be helpful.

Cheers,
Bart

Hi,

Much appreciated for the timely reply. My apologies for the uploaded .py file. Please find enclosed the script in a .txt file format.

Please let me know what your thoughts are on the enclosed script.

In the meantime, I will take a look at the information you provided, and I'll see if I can create an assembly using multi-element select interactor.

Cheers.

Attachments (1)

CreateAssembly.txt
Extension of this Attachment is wrong!
Type: text/x-script.python
Downloaded 0 times
Size: 5,53 KiB

Hi Bart,

Since the .txt file format is not working as well, please find below the script I trying to use to create assemblies.

Currently I am able to create an assembly, but it comes empty without any child element. This is achieved after I the script throws some error that I am currently investigating.

Additionally, the selected elements are being moved and displaced relative to each other after selection... which is something I don't actually want.

#===================================================================================
from __future__ import annotations

from typing import TYPE_CHECKING
from enum import IntEnum


import NemAll_Python_Utility as AllplanUtil
import NemAll_Python_BaseElements as AllplanBaseElements


import NemAll_Python_Precast as AllplanPrecast
from BaseScriptObject import BaseScriptObject, BaseScriptObjectData
from CreateElementResult import CreateElementResult
from ScriptObjectInteractors.MultiElementSelectInteractor import (
    MultiElementSelectInteractor,
    MultiElementSelectInteractorResult,
)
from PythonPart import PythonPart, View2D3D

if TYPE_CHECKING:
    from __BuildingElementStubFiles.InputInteractorBuildingElement import (
        InputInteractorBuildingElement as BuildingElement,
    )  # type: ignore
else:
    from BuildingElement import BuildingElement




def check_allplan_version(_build_ele: BuildingElement,
                          _version  : str) -> bool:
    """ Check the current Allplan version

    Args:
        _build_ele: building element with the parameter properties
        _version:   the current Allplan version

    Returns:
        True
    """

    # Support all versions
    return True



def create_script_object(
    build_ele: BuildingElement,
    script_object_data: BaseScriptObjectData) -> BaseScriptObject:


    return AssemblyGroupScript(build_ele, script_object_data)



class InputStep(IntEnum):
    """Input step for the input sequence"""
    Undefined = 0
    SelectElements  = 1
    Done = 2


class AssemblyGroupScript(BaseScriptObject):
    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()
        self.current_input_step = InputStep.Undefined
        self.generated_elements: list = []

    def start_input(self):
        # Prompt user to select elements to group
        self.script_object_interactor = MultiElementSelectInteractor(
            self.multi_select_result,
            prompt_msg="Select elements to group")
        self.current_input_step = InputStep.SelectElements

    def start_next_input(self):


        if self.current_input_step == InputStep.SelectElements:
            # End selection
            self.script_object_interactor = None

            # Collect valid adapters
            adapters = self.multi_select_result.sel_elements
            print(adapters)
            adaptersList = AllplanBaseElements.GetElements(adapters)
            print(adaptersList)



            valid_adapters = [a for a in adapters if a.IsValid()]
            print("Valid adapters", valid_adapters)






            if not valid_adapters:
                AllplanUtil.ShowMessageBox(
                    "No valid elements selected.", AllplanUtil.MB_OK
                )
                # restart selection
                self.current_input_step = InputStep.SelectElements
                return


            asg_element = AllplanPrecast.AssemblyGroupElement()
            asg_element.Name = "Assembly_XY"
            asg_element.Number = 12
            asg_element.ReinforcementList=[]
            asg_element.FixtureElementsList=adaptersList
            # clear out any existing entries (if needed)
            asg_element.LibraryElementsList = []
            print("TEST_C")




            # keep a reference for execute()
            self.assembly_group = asg_element
            print("Assembly Elements", asg_element.LibraryElementsList)


            attr_list = [
                AllplanBaseElements.AttributeString(1444, "ASSEMBLYGROUP"),
                AllplanBaseElements.AttributeString(684, "IfcElementAssembly")
            ]
            attr_set_list = [AllplanBaseElements.AttributeSet(attr_list)]
            attributes = AllplanBaseElements.Attributes(attr_set_list)
            asg_element.SetAttributes(attributes)



            AllplanUtil.ShowMessageBox(
                "Assembly_AB group created", AllplanUtil.MB_OK)

            self.current_input_step = InputStep.Done
            return

        if self.current_input_step == InputStep.Done:
            # end interaction
            self.script_object_interactor = None
            return

        # Default: start selection
        self.start_input()

    def execute(self) -> CreateElementResult:

        views = [View2D3D([])]  # Add 3D geometry list if available
        common_props = AllplanBaseElements.CommonProperties()
        common_props.GetGlobalProperties()
        self.assembly_group.SetCommonProperties(common_props)

        pp = PythonPart("AssemblyGroup",
                parameter_list=self.build_ele.get_params_list(),
                hash_value=self.build_ele.get_hash(),
                python_file=self.build_ele.pyp_file_name,
                views=views,
                reinforcement=[],
                common_props=common_props,
                library_elements=[],
                fixture_elements=[],
                assembly_elements=[self.assembly_group],
                mws_elements=[],
                type_display_name="Assembly Group",
                type_uuid="3f2504e0-4f89-11d3-9a0c-0305e82c3301",
                )

        print("Execute was runned")

        result_elements = pp.create()
        print(f"Created {len(result_elements)} elements.")

        return CreateElementResult(elements=result_elements)
#===================================================================================

Cheers,

Hi Bart

Any help here?

Cheers.

Quote by uid-446051
Hi Bart
Any help here?
Cheers.

Hi,

creating ElementAssembly with Python API is possible only out of newly created elements and not existing ones.

You are starting a multiple elements selection and a result of such selection is a list of element adapters (BaseElementAdapterList). As shown in this example, to create an assembly group you need a list of FixturePlacementElement and/or a list of rebar placements (BarPlacement) (see these lines of code).

The problem is extracting pythnon objects from BaseElementAdapter. You can do it e.g. for BarPlacement in ALLPLAN 2025, but the result is not "complete". And even if it were (which is the case in the upcoming 2026 version of ALLPLAN), you need to create the group together with the rebars. Which means you have now duplicated rebars: one in the group, and the old one, ungrouped. You need to delete the old one which means, loosing all the labels you potentially have.

You would need a constructor for AssemblyGroupElement, that takes a list of BaseElementAdapter (existing elements) as input. This is currently not offered by the API.

Can you describe more to us, WHY you want to group the elements with the API?

Best,
Bart

Quote by uid-446051
Hi Bart
Any help here?
Cheers.

To my Previous post, here's the script creating a new assembly group out of existing rebars. You can see, that it recreates the rebars. Also, because the incompleteness of BarPlacement object in 2025, it may "move" the rebars around:

class AssemblyGroupScript(BaseScriptObject):
    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):
        valid_types = [AllplanElementAdapter.BarsRepresentationLine_TypeUUID]

        self.script_object_interactor = MultiElementSelectInteractor(
            self.multi_select_result,
            ele_filter = valid_types,
            prompt_msg = "Select elements to group")


    def start_next_input(self):


        # Collect valid adapters
        bar_placements = AllplanBaseElements.GetElements(self.multi_select_result.sel_elements)

        asg_element = AllplanPrecast.AssemblyGroupElement()
        asg_element.Name              = "Assembly_XY"
        asg_element.Number            = 12
        asg_element.ReinforcementList = bar_placements

        pyp_transaction = PythonPartTransaction(self.document)

        pyp_transaction.execute(AllplanGeo.Matrix3D(), 
                                self.coord_input.GetViewWorldProjection(),
                                [asg_element], 
                                self.modification_ele_list,
                                elements_to_delete=self.multi_select_result.sel_elements)

    def execute(self) -> CreateElementResult:

        return CreateElementResult()