DgnPlatformNet |
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.
If you want to ask questions about C# development for MicroStation CONNECT, post your question to the MicroStation Programming Forum.
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.
The process of focussing on an element means to modify a view's display coordinates. The steps to focus on an element are …
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 …
GetElementGeometry
,
and sets data in the view's ViewInformation
struct.
After changing the ViewInformation
data, we apply it to a ViewGroup
IViewManager::UpdateView
in the DgnPlatformNet
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.
Another way to illuminate an element is to highlight it. We discuss highlighting an element elsewhere.
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.
Post questions about MicroStation programming to the MicroStation Programming Forum.