icon

Support Forum

[Frage] Mapping 3D Objects to 2D Section Views


Hello,

I’m trying to figure out how 3D object coordinates can be mapped to their representation in 2D sections, essentially, I want to map from the 3D (global) space to the 2D (local) space of a section (see figure below). However, I’m struggling to achieve this.

When I implement a simple MultiElementSelectInteractor and select the section, I receive an object of type AllplanEleAdapter.ClippingPathBody_TypeUUID. The problem is that I cannot convert this to a PythonParts object, and it doesn’t seem to have any useful child or parent objects.

Is the section object even accessible with PythonParts, or is there another, better approach to work with sections?

Thanks in advance for your help!

Anhänge (1)

Typ: image/jpeg
11-mal heruntergeladen
Größe: 46,04 KiB

Hilfreichste Antwort anzeigen Hilfreichste Antwort verbergen

Hi,

You will need to implement your own element selection interactor (or extend the MultiElementSelectInteractor, not sure what will work best for your case). In your custom interactor, directly after performing an element selection (literally directly after calling SelectElement), you need to call GetSelectedElementAssocView. If the element that was found, was found in a view/section, this will return a AssocViewElementAdapter with the transformation matrix. This matrix can be get with GetTransformationMatrix and it mapps your element from the global coordinate system to local coordinate system of the view.
If the element was not found in a section, calling IsNull() on the returned AssocViewAdapter will return True.

Hope that helps.

Cheers,
Bart

Hi,

You will need to implement your own element selection interactor (or extend the MultiElementSelectInteractor, not sure what will work best for your case). In your custom interactor, directly after performing an element selection (literally directly after calling SelectElement), you need to call GetSelectedElementAssocView. If the element that was found, was found in a view/section, this will return a AssocViewElementAdapter with the transformation matrix. This matrix can be get with GetTransformationMatrix and it mapps your element from the global coordinate system to local coordinate system of the view.
If the element was not found in a section, calling IsNull() on the returned AssocViewAdapter will return True.

Hope that helps.

Cheers,
Bart

Thank you for your quick response.
From your explanation, I now understand that if I can select the architectural elements through a CoordinateInput object, I can retrieve the transformation matrix using:

coordinate_input.GetSelectedElementAssocView().GetTransformationMatrix() -> Matrix3D

So, if I understand correctly, with this Matrix3D, calculating the 2D representation of any 3D point should be straightforward

However, a few points are still unclear:

1. Element selection
So far, I have been using the MultiElementSelectInteractor class to handle element selection:

self.selection_result = MultiElementSelectInteractorResult()
self.script_object_interactor = MultiElementSelectInteractor(
    self.selection_result,
    [AllplanEleAdapter.WallTier_TypeUUID],
    "Select walls"
) 

This approach provides the selection behavior I need, but it does not appear to expose its internal CoordinateInput object (Calling "self.script_object_interactor.__coord_input" draws an error). I attempted to subclass it; however, the API documentation only lists function names and arguments, making it difficult to understand how the selection is handled internally. More generally, it remains unclear how CoordinateInput operates within MultiElementSelectInteractor.
Is the source code for the Python API available by any chance?

2. Multiple associative views
Assuming I can select the desired architectural elements via a CoordinateInput class, how can I control which associative view is used?

For example, if the same wall appears in multiple sections (e.g., four different views), I would like to choose among those views. However, GetSelectedElementAssocView() only returns a single AssocViewElementAdapter, and it is not clear how that specific view is determined or how to influence the selection.

Thank you in advance for your help.

Oh. Well, MultiElementSelection is different. In that case, it is not possible to unambiguously tell, whether an element was selected in a section or not. This is because you select multiple elements: one element is in a section, the other is not. What you get as a result of that type of selection is solely a list of elements, without the information, where they were selected.

Also, during this selection, the process_mouse_msg event is overloaded. In other words, your logic implemented in this event is not called.

The bottom line: you can only establish the AssocViewAdapter only in the single selection. My explanation is then only valid, if you will override/extend the SingleElementSelectInteractor
If you need to select multiple elements, you will need an additional step before that -> picking up a reference element (with single selection). The AssocViewAdapter of that element will be then applied later, regardless whether the subsequently selected elements are in a section or not.

Since in the original post, you already talked about "selecting a section", maybe that can be the first step. In this case, in the first step you would implement a single element selection and ask the user to pick up a section. Although, I don't know if an AssocViewAdapter can be read from the section element itself.

IMPORTANT: when picking the section, apply a filter to consider only UnifiedView_TypeUUID or UnifiedSection_TypeUUID types of adapters. The ClippingPathBody_TypeUUID is the clipping path and I don't expect it holds the information about the transformation matrix.

Cheers,
Bart

Thank you for the informative response.

Thanks to your help I was able to get the script working by implementing a custom interactor. By clicking on the architectural element inside the associated view, I can access the BaseElementAdapter of the section (with type UnifiedSection_TypeUUID) and perform the 3D-to-2D mapping using the TransformationMatrix property. This works well.

However, this led to another question. I would like to identify which architectural elements lie within the selected section (inside the box defined by the section bounds, see figure). This information does not appear to be directly accessible from the BaseElementAdapter that I previously accessed.
Is the geometry of the section's bounding box defined by a ClippingPathBody_TypeUUID object? If so, how can I access the ClippingPathBody_TypeUUID associated with a given UnifiedSection_TypeUUID?

Thank you for your help in advance.

Anhänge (1)

Typ: image/png
10-mal heruntergeladen
Größe: 13,26 KiB

Zitiert von: uid-487586
...how can I access the ClippingPathBody_TypeUUID associated with a given UnifiedSection_TypeUUID?

The answer is partially in your question: "associated with..." -> you need to use association framework.

A user asked the same quesion in german forum not that long ago. In case this link doesn't work, here's my anser:

Hi Christian,

I just found this function in one of my projects:

    @staticmethod
    def _find_clipping_box_uuid(uvs: AllplanElementAdapter.AssocViewElementAdapter) -> uuid.UUID:
        """Find the clipping box UUID associated with the given UVS using the associative framework

        Args:
            uvs: UVS element

        Returns:
            UUID of the clipping box
        """
        filter_clipping_path = ElementFilter([AllplanElementAdapter.ClippingPath_TypeUUID])
        uuid_gen = (uuid.UUID(str(ele.GetElementUUID())) for ele
                    in AllplanBaseElements.AssociationService.GetObservedElements(uvs.GetDocument(), uvs.GetElementUUID())
                    if filter_clipping_path(ele))

        return next(uuid_gen, uuid.UUID(int=0))

Cheers,
Bart