Support Forum

[Frage] Can you find examples of modifying or deleting an existing model? [Gelöst]


Hello everyone,
Most of the Python examples are those that create new models or read information from existing models.
Can you find examples of modifying or deleting an existing model?

Lösung anzeigen Lösung verbergen

Hello sahoon1,

Depending on what kind of modification you would like to apply to an object, there are two ways:

  • Working with Adapters
  • Working directly with AllplanElements like ModelElement3D or WallElement

The first object, BaseElementAdapter, is the result of an element selection. To be more specific: BaseElementAdapterList. It is mainly there for reading the properties of an element, but in some cases it can be used for modifying objects:

  • Modifying Attributes using NemAll_Python_BaseElements.ElementsAttributeService
  • Since Allplan 2023-1-1: copying and moving model elements (documentation is in preparation)

If you however would like to get full access to an object, e.g. to modify its geometry o Common Properties, you have to get the AllplanElement from the ElementAdapter. You can do it using the function:

NemAll_Python_BaseElements.GetElements()

Depending on what element you become (Wall, Beam, Room, 3D solid etc...) you can perform different operations on it. When you are done, you write the results back to the drawing file using the function:
NemAll_Python_BaseElements.ModifyElements()

Here's a small example that trims a 2D line by 10 cm:
objects = self.post_element_selection.GetSelectedElements(self.coord_input.GetInputViewDocument())
allplan_elements = AllplanBaseElements.GetElements(objects)
if isinstance(allplan_elements[0], AllplanBasisElements.ModelElement2D):
    geo = allplan_elements[0].GetGeometryObject()
    if isinstance(geo, AllplanGeo.Line2D):
        geo.TrimEnd(100)
    allplan_elements[0].SetGeometryObject(geo)
    AllplanBaseElements.ModifyElements(self.coord_input.GetInputViewDocument(), allplan_elements)

Refer to the example SelectObjectsWith3DGeometry, to see how to get an BaseElementAdapterList from selected objects. Then use the code above. The variable "objects" is a BaseElementAdapterList

I hope this would help you.

Hello sahoon1,

Depending on what kind of modification you would like to apply to an object, there are two ways:

  • Working with Adapters
  • Working directly with AllplanElements like ModelElement3D or WallElement

The first object, BaseElementAdapter, is the result of an element selection. To be more specific: BaseElementAdapterList. It is mainly there for reading the properties of an element, but in some cases it can be used for modifying objects:

  • Modifying Attributes using NemAll_Python_BaseElements.ElementsAttributeService
  • Since Allplan 2023-1-1: copying and moving model elements (documentation is in preparation)

If you however would like to get full access to an object, e.g. to modify its geometry o Common Properties, you have to get the AllplanElement from the ElementAdapter. You can do it using the function:

NemAll_Python_BaseElements.GetElements()

Depending on what element you become (Wall, Beam, Room, 3D solid etc...) you can perform different operations on it. When you are done, you write the results back to the drawing file using the function:
NemAll_Python_BaseElements.ModifyElements()

Here's a small example that trims a 2D line by 10 cm:
objects = self.post_element_selection.GetSelectedElements(self.coord_input.GetInputViewDocument())
allplan_elements = AllplanBaseElements.GetElements(objects)
if isinstance(allplan_elements[0], AllplanBasisElements.ModelElement2D):
    geo = allplan_elements[0].GetGeometryObject()
    if isinstance(geo, AllplanGeo.Line2D):
        geo.TrimEnd(100)
    allplan_elements[0].SetGeometryObject(geo)
    AllplanBaseElements.ModifyElements(self.coord_input.GetInputViewDocument(), allplan_elements)

Refer to the example SelectObjectsWith3DGeometry, to see how to get an BaseElementAdapterList from selected objects. Then use the code above. The variable "objects" is a BaseElementAdapterList

I hope this would help you.

Thank you for answer.
I solved the problem thanks.

Hello bmarciniec,

Thank you for your sharing. I am also trying to access the existing model element and move it. I found your answer and try to adapt it to use it in my situation. But unfortunately it did not work. Do you might have some time to help me?

I want to move a column element and here is the main code snippet:

doc = self.coord_input.GetInputViewDocument()
sel_elements = self.post_element_selection.GetSelectedElements(doc)
allplan_elements = AllplanBaseElements.GetElements(sel_elements)
geo = sel_elements[0].GetModelGeometry()
translation_vector = AllplanGeo.Vector3D(1000, 700, 500)
translated_geometry = AllplanGeo.Move(geo, translation_vector)
allplan_elements[0].SetGeometryObject(translated_geometry)
AllplanBaseElements.ModifyElements(doc, allplan_elements)

The other part of the code was copied from the official example SelectObjectsWith3DGeometry like you suggest. After run the interactor pythonpart, the chosen element did not move, nothing happened. In order to check where is the error, I tried to print all variable's type and geometry after each line. And it seems like the NemAll_Python_BaseElements.ModifyElements() did not work.

All the types corresponding what you wrote in your example. The geometry was successfully moved. If I print the allplan_elements[0]after
allplan_elements[0].SetGeometryObject(translated_geometry)
it would be a polyhedron3D with translated vertices.

I used
geo = sel_elements[0].GetModelGeometry()
instead of your
geo = allplan_elements[0].GetGeometryObject()
to get the Geometry object. Because if I use the latter one, the result would be a point2d, which is also quite weird to me. Would that causes the problem?

Besides, if I add these code after the ModifyElements:
doc = AllplanEleAdapter.DocumentAdapter()
uuid = "d94da6e8-b830-4acf-945f-8c391258a0e6"
guid = AllplanEleAdapter.GUID.FromString(uuid)
element_after_modify = AllplanEleAdapter.BaseElementAdapter.FromGUID(guid, doc)
print('element_after_move type is {}'.format(type(element_after_modify)))
print(element_after_modify)
print(element_after_modify.GetModelGeometry)

It shows:
elemen_after_move type is <class 'NemAll_Python_IFW_ElementAdapter.BaseElementAdapter'>
null element
<bound method GetModelGeometry of null element>

Therefore, I thought the problem is the ModifyElements function. But I also cannot find more detail abour this funciton. Do you happen to know the answer or maybe have some advices?

Thank you in advance.

Hi!

Fist of all, you are trying to modify a geometry of an architectural element: a column. These kind of elements are represented differently in the data base, as general elements (e.g. a line, for which I made the example in my previous post).

The geometry of a column is really just a 2D point. This information is stored in the database. Also other properties, like:

  • cross-section's width and depth
  • height constraints, represented by PlaneReferences)

And based on that properties, the the columns appearance is generated on the run, as you open the drawing file and view the model. This appearance is the model geometry. You cannot modify it freely. Otherwise you could define a sphere as a geometry of a column, and Allplan does not support that.

What you want to do is to modify the placement point, not the model geometry. I found out, that doing that is not possible in the current API other than deleting the old column and creating a new one in new place. This result in a new ID of the column, so that is probably not what you want, but anyway here are the steps:

Find the script attached.

To recognize, whether an element is a general element, call IsGeneralElement

Or to check, if the selected element is an architecture element, you can call GetArchElementType

I hope that helps.

Best!
Bart

Anhänge (1)

Typ: application/zip
387-mal heruntergeladen
Größe: 3,49 KiB

Zitiert von: YuyeJiang
Besides, if I add these code after the ModifyElements:

doc = AllplanEleAdapter.DocumentAdapter()
uuid = "d94da6e8-b830-4acf-945f-8c391258a0e6"
guid = AllplanEleAdapter.GUID.FromString(uuid)
element_after_modify = AllplanEleAdapter.BaseElementAdapter.FromGUID(guid, doc)
print('element_after_move type is {}'.format(type(element_after_modify)))
print(element_after_modify)
print(element_after_modify.GetModelGeometry)

It shows:

elemen_after_move type is <class 'NemAll_Python_IFW_ElementAdapter.BaseElementAdapter'>

null element

<bound method GetModelGeometry of null element>
Therefore, I thought the problem is the ModifyElements function. But I also cannot find more detail abour this funciton. Do you happen to know the answer or maybe have some advices?
Thank you in advance.


Hi again,
I forgot to answer to the above. Do not instantiate a DocumentAdapter. By doing that you just create an empty document with no objects in it.
ModifyElements should however work, when it comes to modifying the column properties. Here is an example function:

    def modify_column(self,
                      column_adapter: AllplanElementAdapter.BaseElementAdapter,
                      document: AllplanElementAdapter.DocumentAdapter):
        if column_adapter.GetElementAdapterType().GetGuid() != AllplanElementAdapter.Column_TypeUUID:
            return
        column = AllplanBaseElements.GetElements(AllplanElementAdapter.BaseElementAdapterList([column_adapter]))[0]
        column = cast(AllplanArchElements.ColumnElement, column)

        # doing some modification
        column_props = column.GetProperties()
        column_props.Width = 300
        column_props.Depth = 700
        column_props.Angle = AllplanGeometry.Angle.FromDeg(45)

        # apply the modified properties
        column.SetProperties(column_props)
        AllplanBaseElements.ModifyElements(document,[column])

After that, to the modified column points the same BaseElementAdapter, as before the modification.

Hope it helps.

Best!
Bart

Zitiert von: bmarciniec
Hi!
Fist of all, you are trying to modify a geometry of an architectural element: a column. These kind of elements are represented differently in the data base, as general elements (e.g. a line, for which I made the example in my previous post).
The geometry of a column is really just a 2D point. This information is stored in the database. Also other properties, like:
cross-section's width and depth
height constraints, represented by PlaneReferences)
And based on that properties, the the columns appearance is generated on the run, as you open the drawing file and view the model. This appearance is the model geometry. You cannot modify it freely. Otherwise you could define a sphere as a geometry of a column, and Allplan does not support that.
What you want to do is to modify the placement point, not the model geometry. I found out, that doing that is not possible in the current API other than deleting the old column and creating a new one in new place. This result in a new ID of the column, so that is probably not what you want, but anyway here are the steps:
get the ColumnElement from the adapter with GetElements
apply the translation on the GeometryObject property of the ColumnElement (this is the placement point)
delete the old column with DeleteElements
create new column with CreateElements
Find the script attached.
To recognize, whether an element is a general element, call IsGeneralElement
Or to check, if the selected element is an architecture element, you can call GetArchElementType
I hope that helps.
Best!

Bart

Hi Bart,

Thank you so so much for your reply! WOW, I can't believe that you wrote a complete pythonpart! I'm not really familiar with the Allplan API so I have a lot to learn. I will read your code carefully.

And yes...I actually want to move an element continuously, I hope I could figure something out in the future.

Your explanation of the Point2D and Why it's a null element was also very helpful and understandable. Thanks again for your patience

Have a nice week!

Best regards,
Yuye

Hi Marciniec
Thank you very much for the help getting full access to an object using the function "NemAll_Python_BaseElements.GetElements()". This is very helpfull for generals elements.
Is there also a way to get full access to reinforcement objects and labels?
I have an existing reinforcement and I want to get full access to the reinforcement-elements and also label-elements in order to perform changes using python.

Best regards,
Diego

Hello Diego,

currently it is not possible to access a BarPlacement or ReinforcementLabel objects, that already exists in the drawing file, through the Python API. This feature is however already on our roadmap. Specifically I am talking about the BarPlacement object.

Best,
Bart