Questions similar to this appear on the Bentley Discussion Groups. This question appeared in the MicroStation discussion group.

Q

A A line is straight when all its vertices are colinear. MicroStation provides a simple line element (VBA msdElementTypeLine) that has two vertices: start and end. A simple line element is always colinear. The line-string element (VBA msdElementTypeLineString) has from 2 to 5,000 vertices. A colinear line-string requires that each set of three consecutive vertices are colinear.

Colinear and Non-Colinear (bent) Lines

The screenshot shows three lines …

Borrow an MDL Function

We can test a line-string to determine if is straight. To implement that test, we borrow a function from the MDL library: mdlVec_colinear.

When we use an MDL function we must declare it in our VBA module. The declaration looks like this …


' ---------------------------------------------------------------------
'   Declare MDL functions at top of your VBA module, before any procedures
'   mdlVec_colinear tests whether three points are colinear
' ---------------------------------------------------------------------
Declare PtrSafe Function mdlVec_colinear Lib "stdmdlbltin.dll" (ByRef pointArrayP As Point3d) As Long

Write a VBA Wrapper around an MDL Function

Here's a VBA wrapper around that function …

' ---------------------------------------------------------------------
'   PointsColinear
'   Wrapper around MDL function mdlVec_colinear.  Most MDL functions work
'   with Units-of-Resolution (UORs).  We need to convert VBA's units,
'   which are DGN master units, to UORs so that function works as
'   expected.
'   Returns True if three points are colinear
' ---------------------------------------------------------------------
Private Function PointsColinear(ByRef points() As Point3d) As Boolean
  Dim uors(0 To 2)    As Point3d
  Dim uorPerMaster    As Double
  uorPerMaster = ActiveModelReference.UORsPerMasterUnit
  Dim i               As Integer
  For i = 0 To 2
    uors(i) = Point3dScale(points(i), uorPerMaster)
  Next i
  Dim status          As Long
  status = mdlVec_colinear(uors(0))
  If 0 = status Then
    PointsColinear = False
  Else
    PointsColinear = True
  End If
End Function

Test VBA Function

Here's a VBA procedure to test that function …

Sub TestPointsColinear()
  Debug.Print "+ TestPointsColinear"
  Dim points(0 To 2) As Point3d
  points(0) = Point3dFromXYZ(0.315503012863086, 0.440172369410825, 0)
  points(1) = Point3dFromXYZ(0.60622419153676, 0.308341356545869, 0)
  points(2) = Point3dFromXYZ(0.85221903502987, 0.492407299036562, 0)
  If PointsColinear(points) Then
    Debug.Print "Points are colinear"
  Else
    Debug.Print "Points are not colinear"
  End If
End Sub

Get Information from DGN Elements

And here's a VBA procedure that will extract vertices from a LineElement. It relies on known Element IDs for the line elements — you'll have to modify those IDs to match your DGN model.

Public Sub Main()
  Debug.Print "+ Example of PointsColinear"
  Dim msg    As String
  Dim lineId      As DLong
  '   Change these to the element IDs of lines or line-strings in your DGN model
  Const SingleLineID      As Long = 1016
  Const BentLineID      As Long = 1017
  Const StraightLineID      As Long = 1018
  lineId = DLongFromLong(BentLineID)
  Dim oLine                               As LineElement
  Set oLine = ActiveModelReference.GetElementByID(lineId)
  oLine.IsHighlighted = True
  Select Case oLine.Type
  Case msdElementTypeLine
     msg = "Line element is always colinear"
    ShowMessage msg, msg
      Debug.Print msg
  Case msdElementTypeLineString
    If (3 = oLine.VerticesCount) Then
      If PointsColinear(oLine.GetVertices) Then
              msg = "Line-string element ID " & DLongToString(lineId) & " is colinear"
              ShowMessage msg, msg, msdMessageCenterPriorityWarning
              Debug.Print msg
      Else
              msg = "Line-string element ID " & DLongToString(lineId) & " is not colinear"
              ShowMessage msg, msg, msdMessageCenterPriorityInfo
              Debug.Print msg
      End If
    Else
          msg = "This example requires a line-string having exactly 3 vertices"
          ShowMessage msg, msg, msdMessageCenterPriorityWarning
          Debug.Print msg
    End If
  Case Else
    msg = "Can't determine colinearity of element type " & CStr(oLine.Type)
    ShowMessage msg, msg, msdMessageCenterPriorityWarning
    Debug.Print msg
  End Select
  '   Release memory
  Set oLine = Nothing
End Sub