MicroStation .NET: Focus on an Element

  • Products
  • Services
  • All Publications
  • CONNECT Publications
  • Links
  • WishList
  • LA Solutions
  • Home
LA Solutions
tel: +44 1398 361 800
DgnPlatformNet

Introduction

This article is for C# developers who want to write an application for MicroStation CONNECT. It describes a way to focus on an element in a DGN model view. Another way to think of that is zooming to an element. This is not a complete application: rather, it describes what might otherwise be a non-intuitive approach to solve a problem.

For a practical demonstration of the technique described here, see the article about Scanning for Tags.

Be Communities

If you want to ask questions about C# development for MicroStation CONNECT, post your question to the MicroStation Programming Forum.

Focussing on an Element

Suppose that your application (or AddIn, in Bentley Systems terminology) is interactive. Your app. works with MicroStation DGN elements in some way. When choosing, modifying or otherwise working with an element you want to show that element in greater detail.

Lots of Elements

The process of focussing on an element means to modify a view's display coordinates. The steps to focus on an element are …

  1. Get the element's range
  2. Calculate the view's new origin and extent from the range
  3. Apply the origin and extent to the view
  4. Update the view
Zoomed Element

A problem with this approach is the final step: the DgnPlatformNet offers no straightforward way to update or redraw a view. That's easy in a primitive command function because the dynamic event handler does that all for you. However, when operating outside a state function we have to take a devious route to view updates.

Here's a brief overview of the ElementLocator class …

  • The constructor takes an Element ID, which we use immediately to obtain an Element reference from the active DGN model
  • GetElementGeometry converts the element's range into an origin and extent used by the view classes. At the same time we scale the range to effect a zoom
  • GetViewGeometry uses the origin and extent calculate by GetElementGeometry, and sets data in the view's ViewInformation struct. After changing the ViewInformation data, we apply it to a ViewGroup
  • UpdateViews uses smoke and mirrors to update a view. We're compensating for the absence of IViewManager::UpdateView in the DgnPlatformNet
  • FocusInView is the public method that puts it all together

The DgnPlatformNet  and MicroStationAPI  help documents do a poor job in explaining the five or six view classes. We've written an article about MicroStation View Classes for Programmers. We may have misinterpreted Bentley Systems class design, for which error we admit guilt.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BM = Bentley.MstnPlatformNET;
using BD = Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Geometry = Bentley.GeometryNET;

namespace ElementLocatorExample
{
    /// Element Locator is used to focus a view on an object, generally a particular graphic DGN element
    class ElementLocator
    {
        readonly BD.ElementId id_;
        BD.Elements.DisplayableElement el_;
        double UORs_;
        /// Construct an ElementLocator supplying an Element ID.
        public ElementLocator(BD.ElementId id)
        {
            id_ = id;
            BD.DgnModel model = BM.Session.Instance.GetActiveDgnModel();
            UORs_ = 1.0 / model.GetModelInfo().UorPerMaster;
            el_ = (BD.Elements.DisplayableElement)model.FindElementById(id_);
        }
        /// Calculate view origin and extent from element range.
        /// Element range is expanded by scale.
        /// Element origin is adjusted for scale.
        private void GetElementGeometry(out Geometry.DPoint3d origin, out Geometry.DPoint3d delta, double scale)
        {
            Geometry.DRange3d range;
            el_.CalcElementRange(out range);
            Geometry.DPoint3d centre = Geometry.DPoint3d.Multiply(Geometry.DPoint3d.Add(range.Low, range.High), .5);
            Geometry.DPoint3d offset = Geometry.DPoint3d.Multiply(Geometry.DPoint3d.Subtract(range.Low, centre), scale);
            origin = Geometry.DPoint3d.Add(centre, offset);
            delta = Geometry.DPoint3d.Multiply (Geometry.DPoint3d.Subtract(range.High, range.Low), scale);
        }
        /// Get current view geometry.
        private void GetViewGeometry(BD.ViewGroup viewGroup, int nView, Geometry.DPoint3d origin,
                                        Geometry.DPoint3d elementDelta, BD.DgnModel model)
        {
            BD.ViewInformation viewInfo = viewGroup.GetViewInformation(nView);
            BD.ViewGeometryInformation geometry = viewInfo.GetGeometryInformation();

            Geometry.DMatrix3d rotation = Geometry.DMatrix3d.Identity;
            viewInfo.SetGeometry(origin, elementDelta, rotation);
            viewGroup.SetViewInformation(viewInfo, nView);
            //viewGroup.SaveChanges();
            //viewGroup.SynchViewDisplay(nView, false, true, false);
            UpdateViews(viewGroup, model, viewInfo, nView);
        }
        /// The DgnPlatformNet way to redraw a view.
        private void UpdateViews(BD.ViewGroup source, BD.DgnModel model, BD.ViewInformation viewInfo, int nView)
        {
            const bool Transient = true;
            const bool AddToCollection = true;
            BD.ViewGroup viewGroup = new BD.ViewGroup(model, Transient, "Transient View Group", !AddToCollection);
            BD.ViewGroupCopyOptions options = new BD.ViewGroupCopyOptions();
            options.NewName = "Transient View Group";
            viewGroup.From(source, options);
            viewGroup.SetViewInformation(viewInfo, nView);
            const bool DeferUpdate = true;
            BD.ViewGroupStatus status = model.GetDgnFile().GetViewGroups().MakeActive(viewGroup, !DeferUpdate);
        }
        /// Zoom to the element in the given view
        public void FocusInView(int nView)
        {
            BD.DgnModel model = BM.Session.Instance.GetActiveDgnModel();
            if (null != el_ && el_.IsGraphics)
            {
                BD.ViewGroupCollection viewGroups = BM.Session.Instance.GetActiveDgnFile().GetViewGroups();
                BD.ViewGroup viewGroup = viewGroups.GetActive();
                const int NoActiveView = -1;
                int v = NoActiveView;
                if (BD.ViewGroupStatus.Success == viewGroup.FindFirstOpenView(out v) && NoActiveView != v)
                {
                    Geometry.DPoint3d origin;
                    Geometry.DPoint3d delta;
                    const double scale = 4.0;
                    GetElementGeometry(out origin, out delta, scale);
                    GetViewGeometry(viewGroup, v, origin, delta, model);
                }
            }
        }
    }
}

You don't need to copy the above code. Instead, download the Tag Scanning project that includes the ElementLocator class.

Highlighting an Element

Another way to illuminate an element is to highlight it. We discuss highlighting an element elsewhere.

Highlighted Element
Download

Download the Tag Scanner Project

Rather than copy the code above, you can download a complete Visual Studio project. That project is TagScanning. It provides a link to download the project including source code.

The TagScanning example makes use of the ElementLocator class.

Questions

Post questions about MicroStation programming to the MicroStation Programming Forum.


Bentley Technology Partner

Trademarks

All trademarks are acknowledged. Trademarks may be registered in some jurisdictions.
e-mail Contact LA Solutions using this enquiry form.

Home
Home
Updated on 16-Feb-2020 Copyright © 2016…2025 Jon Summers