Introduction

The MicroStation Development Library (MDL) and MicroStationAPI provide APIs for developers wanting to create custom applications for MicroStation® from Bentley Systems. We create a MicroStation application as a DLL, written using C++ and built with the Microsoft C++ compiler and linker provided with Visual Studio.

When editing your source code, you can choose whether to use Microsoft Visual Studio, Microsoft Visual Studio Code, or one of your favourite text editors.

When building your app, you can use Visual Studio or the Bentley Systems make (bmake) tools.

Test an Element for Planarity

A MicroStation DGN model's primary purpose is to be a container of graphic elements. A user creates and manipulates elements in one of eight views of a DGN model.

In a 2D model, all elements are planar: they lie on the same XY plane. In a 3D model, elements may be planar and non-planar. If planar, they don't necessarily lie on the XY plane. How do we test for planarity?

The code shown below is encapsulated in a C++ project. You can download the project to examine the code and kick the tyres.

MicroStationAPI CurveVector

Test for Planarity

A CurveVector is a collection of lines, arcs and other elements that may form an open or closed loop. The CurveVector::IsPlanarWithDefaultNormal() method tests most elements for planarity. Here's some example code …

#include <DgnPlatform/CurveVector.h>
#include <DgnPlatform/ElementGeometry.h>
bool             IsPlanar (ElementHandleCR	eh) const
{
  bool           planar  { false };
  CurveVectorPtr curve   = ICurvePathQuery::ElementToCurveVector (eh);
  if (curve.IsValid ())
  {
    Transform    localToWorld;
    Transform    worldToLocal;
    DRange3d     range;
    if (curve->IsPlanarWithDefaultNormal (localToWorld, worldToLocal, range, nullptr))
    {
      planar = true;
    }
  }
  return planar;
}

Test for Flatness

The Flat Earth Society has a lot to answer for. What do we mean by 'flat'? To be flat, an object should first be planar. Additionally it should be aligned with something that we consider to be a datum. In other words, 'flatness' is a subjective concept.

Here, we attempt a deterministic approach to 'flatness'. First, define a plane to compare against. For example, suppose that we're testing for flatness compared to our current position on the globe. The plane that we want to compare is defined by the local Z axis [0,0,1].

Here's some example code. It builds on the above test for planarity, then compares the normal of the planar object to our axis …

bool   IsFlat    (ElementHandleCR  eh, DVec3dCP axis) const
{
  bool           flat  { false };
  CurveVectorPtr  curve = ICurvePathQuery::ElementToCurveVector (eh);
  if (curve.IsValid ())
  {
    Transform    localToWorld;
    Transform    worldToLocal;
    DRange3d     range;
    // Brien Bastings of Bentley Systems commented:
    // One suggestion I have for your flatness test is to supply the normal you are looking for to
    // IsPlanarWithDefaultNormal and not just use it to check the result.
    // The reason for this is to support line segments. A line may very well lie in the plane
    // defined by your desired normal, but the line by itself doesn't uniquely specify a single plane
    if (curve->IsPlanarWithDefaultNormal (localToWorld, worldToLocal, range, axis))
    {
      if (axis)
      {
        DPoint3d origin;
        DVec3d   v1, v2, v3;
        localToWorld.GetOriginAndVectors (origin, v1, v2, v3);
        flat = axis->IsParallelTo (v3);
      }
    }
  }
  return flat;
}

Usage …

ElementHandle 	eh ( /* get element from somewhere */ );
DVec3d          axis;
axis.Init ( 0., 0., 1. );	// Z axis
if (IsFlat (eh, &axis))
{
  WCharCP msg = L"Element is flat";
  mdlOutput_messageCenter (DgnPlatform::OutputMessagePriority::Debug, msg, msg, OutputMessageAlert::None);
}
else
{
  WCharCP msg = L"Element is not flat";
  mdlOutput_messageCenter (DgnPlatform::OutputMessagePriority::Debug, msg, msg, OutputMessageAlert::None);
}

Download IsElementPlanar Source Code

Download CSearchTypes Source Code

Download the IsElementPlanar Source Code. Unpack the ZIP file, retaining the folder structure. The pack includes a Bentley make (bmake) file.

In addition to the MicroStation SDK, you need the following to be installed on your development computer …

The ZIP file does not include the application. You must build the app. before loading it into MicroStation.

Load the app. using MicroStation key-in
mdl load IsElementPlanar
With the app. loaded, you have the following key-ins available …

IsElementPlanar Commands
Command Root Command Word 1
ISPLANAR PICK

Start picking elements. The app. tells you if a selected element is planar and, if it is planar, whether it is 'flat'. As delivered, the app. compares the element normal to the XY plane to determine 'flatness'.


Return to MicroStationAPI articles index.

Questions

Post questions about C++ and the MicroStationAPI to the MicroStation Programming Forum.