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?
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 …
Here's a similar rectangle, but this time there's an extra vertex in the top side …
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.
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()
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.
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.
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 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
vba run [Simplify]modMain.Main