Python

Count Elements using MicroStation Python

Q How do I count elements using MicroStation Python?

Q How do I count elements by type (e.g. lines, line-strings) using MicroStation Python?

A Here's a small Python program that uses type-matching to count elements by type.

Python Implementation

The Count Elements by Type example borrows from Python articles and examples delivered with MicroStation Python.

We get a list of DGN elements (as elementRef) in a DGN model using DgnModel.GetGraphicElements(). Next we enumerate the list and analyse each elementRef. In this example, we filter the list by element type (e.g. MicroStation classes LineHandler, LineStringHandler etc) …

Function IsInteresting() analyses an element to see if it is interesting for our purposes …

Element Handlers

Count Elements filters the element list by examining the element's handler. Element handlers are classes in MicroStation Python that provide type-specific methods. For example, you can use a LineHandler to create a DGN line element.

Here, we supply a list of handlers used by Count Elements. For example, here's a Python tuple of handlers for lines and line-strings …

LineHandlers = (LineHandler, LineStringHandler, )

You'll find more examples of handler lists in the project's source code.

Here's the Python class DgnElementCounter used to get a list of elements and analyse each one in method CountElements …

class DgnElementCounter:
    """A class to count DGN elements in a DGN model for one or more element types.
    """
    def __init__(self, dgnModel: DgnModel = ISessionMgr.ActiveDgnModelRef.GetDgnModel()):
        self._dgnModel = dgnModel
        self._elementCount = 0
        self._searchName = ""

    def CountElements(self, handlers: namedtuple)->int:
        # Pass a namedtuple of DGN element classes (e.g. LineHandler et alia).
        # The class name of the namedtuple is our search name
        self._searchName = type(handlers).__name__
        # Execute the element test to produce a new list of elements from a
        # Python list comprehension
        matchedElements = [elemRef for elemRef in self._dgnModel.GetGraphicElements() if IsInteresting(elemRef, self._dgnModel, handlers)]
        return len(matchedElements)

    @property
    def ElementCount (self):
        # Get the element count
        return self._elementCount

    @property
    def DgnModelName (self):
        # Get the name of the DGN model that contains elements to be counted
        if (self._dgnModel is None):
            return "unknown"
        else:
            return self._dgnModel.GetModelName()

    @property
    def SearchName(self):
        # Get the name of the search criteria supplied in the namedtuple
        return self._searchName

    def __str__(self):
        return f"Element count {self._elementCount} in model '{self.DgnModelName()}'"

    def __repr__(self):
        return 'CountElements(Handler List)'

Function IsInteresting() provides a boolean test to determine whether a particular DGN element is interesting for our purposes. In this example the element is interesting if it is one of MicroStation's element types, indicated by a list of ElementHandler. Here's function IsInteresting() …

def IsInteresting (elemRef: PersistentElementRef, dgnModel: DgnModel, handlers: namedtuple):
    """Function tests whether a DGN element is interesting, whatever that means"""
    # Create an element handle and get its Handler
    eh = ElementHandle (elemRef, dgnModel)
    handler = eh.GetHandler()
    if isinstance (handler, handlers):
        return True
    #else
    return False

The Python source code of Count Elements is available for download.

Python namedtuple

Here's a Python tuple of element handlers: (LineHandler, LineStringHandler, ). We prefer to use a namedtuple because it has a name. Otherwise, namedtuple behaves just like a tuple.

In this example, there's a function MakeNamedTupleFromHandlerList that accepts a name and a tuple of ElementHandlers. It analyses the tuple and converts it to a namedtuple. Subsequently, you can get the name like this …

searchName = type(handlers).__name__

Usage

Count Elements is intended to be used by your Python code. Import it as a module …

import la_solutions_elements_count_by_type

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)
    counter = DgnElementCounter()

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

Download la_solutions_count_elements_by_type.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.