MicroStation® is Bentley Systems flagship product for 3D computer-aided-design (CAD). Questions similar to this appear on the Be Community Forums. This problem appeared in the MicroStation Programming Forum.

Q How do I simplify an element using MicroStation VBA?

Simplify an Element

First, what sort of element needs to be simplified? The question arose when a user noticed redundant points in a shape element. The extra points don't affect the shape visually, but might cause problems in other areas. Here's a rectangle drawn as a DGN ShapeElement having the expected number of four vertices …

Rectangle with 4 Vertices

Here's a similar rectangle, but this time there's an extra vertex in the top side …

Rectangle with 5 Vertices

A similar occurence is a duplicate vertex, where two adjacent vertices share identical coordinates. I can't illustrate that here, because the rectangle would look no different to the first screenshot. However, a duplicate vertex can cause problems just as a redundant vertex can cause problems.

Our goal in this article is to show, programmatically, how to remove those redundant or duplicate vertices using MicroStation VBA.

VertexList Object

The key to understanding the following code is the MicroStation VBA VertexList Object. If an element, such as a ShapeElement, implements the VertexList interface, then we can obtain a list of that element's coordinates. With a list of coordinates, we can examine adjacent coordinate pairs or triplets …

The code to obtain a VertexList is simple …

Dim vertices                            As VertexList
Set vertices = oElement.AsVertexList
Dim points()                            As Point3d
points = vertices.GetVertices()

Iteration Tips: Removing Items from a List or Array

As an observant programmer, you'll notice that in the following examples we iterate the list of vertices starting at the end. The iteration step is -1, so we look at the items in decreasing order.

The reason for this backwards approach is that we anticipate removing items from the list. If we iterate the list from the start, then removing items may have invalidated the index we are about to consider: in fact, we may have removed the item! Starting from the end and decrementing the index ensures that we are always considering a valid index.

Find Duplicate Vertices

Iterate the array of points, starting at the end. Examine each point pair: if the points are coincident, remove one point from the VertexList …

Dim nVertices                           As Long
nVertices = vertices.VerticesCount
Dim n                                   As Long
For n = nVertices - 1 To 1 Step -1
    If Point3dEqual(points(n), points(n - 1)) Then
        vertices.RemoveVertex (n)
    End If
Next n

Method Point3dEqual is part of MicroStation VBA.

Find Redundant Vertices

Iterate the array of points, starting at the end. Examine each point triplet: if the points are colinear, remove one point from the VertexList …

Dim nVertices                           As Long
nVertices = vertices.VerticesCount
Dim n                                   As Long
For n = nVertices - 1 To 1 Step -1
    If PointsColinear(points(n), points(n - 1), points(n - 2)) Then
        vertices.RemoveVertex (n - 1)
    End If
Next n

There's no function provided by MicroStation VBA to determine if points are colinear. Here's one suggestion for a method PointsColinear …

' ---------------------------------------------------------------------
'   PointsColinear
'   Test three points to see whether they are colinear.  This is just
'   a suggestion.
'   It works by constructing two rays, then testing to find their intersection.
'   If they don't intersect, then they must be parallel.  Since one point is
'   common to both rays, parallel implies colinear.
'   Returns:    True if points are colinear
' ---------------------------------------------------------------------
Function PointsColinear( _
        ByRef point1 As Point3d, _
        ByRef point2 As Point3d, _
        ByRef point3 As Point3d) As Boolean
    PointsColinear = False
    Dim ray1 As Ray3d
    ray1 = Ray3dFromPoint3dStartEnd(point2, point1)
    Dim ray2 As Ray3d
    ray2 = Ray3dFromPoint3dStartEnd(point3, point1)
    '   The following variables are required to call Ray3dRay3dIntersectXY
    '   because it doesn't have default parameters
    Dim p0 As Point3d
    Dim p1 As Point3d
    Dim f0 As Double
    Dim f1 As Double
    '   If the rays don't intersect, they must be parallel,
    '   and hence the point triplet is colinear
    PointsColinear = Not Ray3dRay3dIntersectXY(ray1, ray2, p0, f0, p1, f1)
End Function

Download

Download VBA Project

Download the Simplify Element VBA Project.

Once you've downloaded the ZIP archive, unpack it and copy the VBA project Simplify.mvba to a well-known location. A suitable place is ..\Workspace\Standards\vba