Python

Enumerate Complex Elements using MicroStation Python

Q How do I enumerate a complex element using MicroStation Python?

A Here's a small Python program that enumerates a complex element using ChildElemIter.

Python Implementation

Elements in a DGN model can be classified as primitive or complex. A primitive element is simple and atomic: it can't be broken into smaller elements. Examples include line, ellipse and shape elements.

A complex DGN element is a container. It usually contains primitive elements, but may include nested complex elements. Examples include complex strings, complex shapes, cells and grouped holes.

This article focuses on complex elements and how to enumerate their contents programmatically using Python.

Complex Element Structure

A complex element stores a chain of elements. The first element is always a complex header. Subsequent elements may be primitive DGN elements or other complex DGN elements. MicroStation Python provides the ChildElemIter class to assist us.

ChildElemIter is tricky to use. It's not properly documented (at least in the first release of MicroStation Python) and is not Pythonic. The documentation fails to mention a vital precursor to using ChildElemIter: the values of related class ExposeChildrenReason. Without a valid ExposeChildrenReason, ChildElemIter doesn't work. Here's how …

ExposeChildrenCount = ExposeChildrenReason(100)
ExposeChildrenQuery = ExposeChildrenReason(200)
ExposeChildrenEdit  = ExposeChildrenReason(300)

eh = ElementHandle()
# Get eh from somewhere
component = ChildElemIter(eh, ExposeChildrenCount)

while component.IsValid():
    n += 1
    description = getElementDescription(component)
    MessageCenter.ShowDebugMessage(f"[{n}] Found component {description}", f"[{n}] Found component {description}", False)
    component = component.ToNext()

Function getElementDescription() is provided in the code example you can download.

The Python source code to enumerate a complex element is available for download.

Nested Cells

A cell element may be nested: it contains not only primitive elements, but also further complex elements. It's commonplace to find one cell nested in another. One way to analyse nested cells is to pass through its structure recursively.

Here's a recursive version of the above code …

def AnalyseNestedCell (eh, nestDepth = 0):
    # Step through the components of a grouped hole or normal cell.
    # If the cell contains nested components, this function calls
    # itself recursively
    n = 0
    component = ChildElemIter(eh, ExposeChildrenCount)
    while component.IsValid():
        n += 1
        description = getElementDescription(component)
        MessageCenter.ShowDebugMessage(f"[{nestDepth}.{n}] Found component {description}",
        	f"[{nestDepth}.{n}] Found component {description}", False)
        # If this cell contains one or more nested cells, then analyse them recursively
        if  isinstance (component.GetHandler(), ComplexElementHandlers):
            AnalyseNestedCell (component, nestDepth + 1)
        else:
            # Analyse primitive element
            pass

        component = component.ToNext()

Usage

ChildElemIter is intended to demonstrate how to use the ChildElemIter class. It has no practical purpose, but you can steal the code for your own Python projects.

You can test it as stand-alone code from the MicroStation Python manager. You'll find these lines in the project …

if __name__ == "__main__":  # check if this script is being run directly (not imported as a module)

Everything after those lines will be executed from a Python prompt or in MicroStation's Python Manager.

Download la_solutions_child_elem_iter.zip

Unpack the ZIP file and copy the Python file into a folder that MicroStation knows about.

Python Manager

Use MicroStation's Python Manager to find and execute the script.

Questions

Post questions about MicroStation programming to the MicroStation Programming Forum.