Python

Introduction

As a MicroStation user, you are familiar with the idioms of view control. It's common to want to focus on an element by changing a view to centre that element at a good size for examination. In MicroStation, that's termed Fit to Element Range. The idea of drawing a temporary rectangle to identify an area of interest becomes intuitive.

As a developer, you may want to offer your users a similar idiom. Having created or modified an object through your code, you want to offer the ability to focus visually on an element, or set of elements.

Methodology

All DGN graphic elements have a range (Python DRange3d). In 3D, the range is a block that encloses the element. In 2D, the range is a rectangle that encloses the element.

To zoom in on element, write code to perform the following …

Caution

Bentley staffer YongAn Fu commented: If the current view is in an ISO view, the extents of the acquired element cannot be used as an accurate basis for Zoom Element. The scenario becomes more complex when the view’s camera is on.

Implementation

Element Range

Every graphical DGN element has a range, and it also has a display handler. The DisplayHandler provides method CalcElementRange, which does what you would expect. Here's a function to get the range of any graphical DGN element …

def get_element_range (eh: ElementHandle)->[bool, DRange3d]:
    handler = eh.GetDisplayHandler()
    if handler is not None:
        range = DRange3d()
        transform = Transform()
        transform.InitIdentity()
        handler.CalcElementRange(eh, range, transform)
        return True, range
    return False, None

Convert to View Parameters

A MicroStation view has dimensions specified by a block. The block starts at the lower left back corner of the view and continues to the upper right front corner. The extent is the 3D vector that connects those corners. We convert the element range to view parameters, like this …

def convert_range_to_view(range: DRange3d)->[DPoint3d, DPoint3d]:
    # Make deep copies of the range coordinates
    low = DPoint3d(range.low.x, range.low.y, range.low.z)
    high = DPoint3d(range.high.x, range.high.y, range.high.z )
    # Calculate view range box (delta)
    high.Subtract(low)
    delta = high
    return low, delta

Assign the View Parameters

To set the view parameters, first get a ViewInfo reference for the desired view number …

def get_view_info(view_num: int)->ViewInfo:
    '''
    Helper function to get ViewInfo for the specified view number.
    '''
    view_set: IndexedViewSet = IViewManager.GetActiveViewSet()
    view_port: IndexedViewport = view_set.GetViewport(view_num)
    view_info: ViewInfo = view_port.GetViewInfo()
    return view_info

Using the range, adjust the specified view parameters. Scale the view extent and adjust its origin so that the element doesn't completely fill the view …

def zoom_to_range(view_num: int, range: DRange3d, expand: float = 2)->None:

    lower_left, delta = convert_range_to_view(range)
    delta.Scale(expand)

    rotation = RotMatrix()
    rotation.InitIdentity()
    # Move lower-left by a fraction of delta
    offset = DPoint3d(delta.x, delta.y, delta.z)
    offset.Scale(0.25)
    lower_left.Subtract(offset)
    view_info = get_view_info(view_num)
    view_info.SetGeometry(lower_left, delta, rotation)

    update_view(view_num)

Finally, here's the main function that stitches all those components together. You'll need to change TEXT_NODE_ELEMENT_ID or RECTANGLE_ELEMENT_ID to the Element ID of a DGN element in your DGN model …

if __name__ == "__main__":  # check if this script is being run directly (not imported as a module)
    vinfo = VersionInfo("Zoom to Element", 2026, 5, 6, "Zoom to Element")
    MessageCenter.ShowInfoMessage(vinfo.brief, vinfo.verbose, False)
    dgn_model: DgnModel = ISessionMgr.ActiveDgnModelRef.GetDgnModel()

    RECTANGLE_ELEMENT_ID = 2481
    TEXT_NODE_ELEMENT_ID = 1490
    status, eh = GetElementById(TEXT_NODE_ELEMENT_ID)
    if status:
        status, range = get_element_range(eh)
        if status:
            VIEW_NUMBER = 1
            zoom_to_range(VIEW_NUMBER, range)

Download Zoom to Element

Download la_solutions_zoom_element.zip

Download la_solutions_zoom_element.zip.

The ZIP file contains the main module la_solutions_zoom_element.py and supporting Python files in folder la_solutions.

├── la_solutions_zoom_element.py
└── la_solutions
    ├── dgn_elements.py
    ├── version_info.py
    └── __init__.py

Questions

Post questions about MicroStation programming to the MicroStation Programming Forum.