Error in Perpendicular Lines to ComplexStringElement (or ChainableElement) macro

Hi
I'm working in Microstation V8i Version 08.11.09.608 on a Windows 7 machine
I found the CrossingPerpendiculars macro by DanPaul at this location: https://communities.bentley.com/products/programming/microstation_programming/f/archived-microstation-v8-xm-edition-vba-forum/20356/perpendicular-lines-to-complexstringelement-or-chainableelement

The macro does not deal with segments of the line that are vertical when looked at in Top view. 

I'd be happy if a mathematically competent person could find a fix for the problem in the macro.

Sub sbExamineLine()
Dim esc As ElementScanCriteria
Set esc = New ElementScanCriteria
esc.ExcludeAllTypes
esc.IncludeType msdElementTypeLine
esc.IncludeType msdElementTypeBsplineCurve
esc.IncludeType msdElementTypeLineString
esc.IncludeType msdElementTypeComplexString
'esc.ExcludeAllLevels
'esc.IncludeLevel oLevel

Dim oEle As Element
Dim ee As ElementEnumerator
Dim dblSpan As Double



Set ee = ActiveModelReference.Scan(esc)
Dim Count As Long
dblSpan = 10
Do While ee.MoveNext
Set oEle = ee.Current
Count = Int(oEle.AsChainableElement.Length / dblSpan) + 1


CrossingPerpendiculars oEle, Count, 20
Loop

End Sub



' Side 0 means cross, 1 means left, -1 means right
Sub CrossingPerpendiculars(LinearElem As Element, Count As Long, Distance As Double, Optional Side As Integer = 0)
Dim bSpl As BsplineCurve
Set bSpl = New BsplineCurve

Dim FrenetFrame As Matrix3d, Param As Double, Curvature As Double, Torsion As Double
Dim Tangent As Point3d, Normal As Point3d, BiNormal As Point3d
Dim LinearNormal As Point3d: LinearNormal = Point3dFromXYZ(0, 1, 0)

Dim StartPoint As Point3d, EndPoint As Point3d, Length As Double
Dim oLine As LineElement
Dim halfDist As Double: halfDist = Distance * 0.5

If LinearElem.IsTraversableElement Then
bSpl.FromElement LinearElem
Length = bSpl.ComputeCurveLength

For Length = 0 To Length Step Length / (Count - 1)
bSpl.EvaluatePointAtDistance Param, Length
StartPoint = bSpl.EvaluatePointFrame(FrenetFrame, Curvature, Torsion, Param, LinearNormal)

' If UpVector is 0, 0, 1, then we know, that if Frenets UpVector's Z value is less than zero,
' it is up side down for us... So we can negate it's needed rows...
If FrenetFrame.RowZ.z < 0 Then
'' RowZ [Binormal/UpVector in 2D] is not needed negated now, so we can keep it unchanged
'FrenetFrame.RowZ = Point3dNegate(FrenetFrame.RowZ)

'' RowY [Normal/SideVector in 2D] is only needed on correct side
FrenetFrame.RowY = Point3dNegate(FrenetFrame.RowY)

'' RowX [Tangent/DirectionVector] is not needed negated now too...
'FrenetFrame.RowX = Point3dNegate(FrenetFrame.RowX)
End If

If Side = 0 Then
EndPoint = Point3dAddScaled(StartPoint, FrenetFrame.RowY, halfDist)
StartPoint = Point3dAddScaled(StartPoint, FrenetFrame.RowY, -halfDist)
Set oLine = CreateLineElement2(Nothing, StartPoint, EndPoint)
ActiveModelReference.AddElement oLine
oLine.Redraw
Else
EndPoint = Point3dAddScaled(StartPoint, FrenetFrame.RowY, Side * Distance)
Set oLine = CreateLineElement2(Nothing, StartPoint, EndPoint)
ActiveModelReference.AddElement oLine
oLine.Redraw
End If

Next Length
Else
Debug.Print "Element is not traversable!!!"
End If


End Sub

Parents
  • Any progress in this?

    I have ran into exactly the same problem. The crossing line is drawn perfectly on all other part of the complex, except for the lines running vertical in the y-axes.

    The lines where the different between the x-coordinate of the start and end point is zero.

    Regards,

     

    Finn Mejding

    CAD Manager

    Railway and Metro

    COWI

  • Hi,

    Did a little debug and came up with this work-around.

    Don't know if this gives me trouble later on in my program. But I'll take the change.

    StartPoint = m_oSpline.EvaluatePointFrame(FrenetFrame, Curvature, Torsion, Param, LinearNormal)
    If FrenetFrame.RowX.x = 0 And FrenetFrame.RowX.Y = 1 Then
      FrenetFrame.RowY.x = 1
    End If
    If FrenetFrame.RowX.x = 0 And 1 - FrenetFrame.RowX.Y = 2 Then
      FrenetFrame.RowY.x = -1
    End If
    EndPoint = Point3dAddScaled(StartPoint, FrenetFrame.RowY, -50)
    StartPoint = Point3dAddScaled(StartPoint, FrenetFrame.RowY, 50)
    Set Linelem = CreateLineElement2(Nothing, StartPoint, EndPoint)
    ActiveModelReference.AddElement
    Linelem Linelem.Rewrite

    The line: If FrenetFrame.RowX.x = 0 And 1 - FrenetFrame.RowX.Y = 2 Then

    looks odd, but I couldn't get this to work: If FrenetFrame.RowX.x = 0 And FrenetFrame.RowX.Y = -1 Then

    even though FrenetFrame.RowX.y was -1 it returned 'false'

    The above code is modifications to DanPauls original code.

    Regards,

     

    Finn Mejding

    CAD Manager

    Railway and Metro

    COWI

  • I was quite excited when I tested your modifications to the code, at first, but, further testing seems to indicate that it's not a complete solution. I admit that I do not have the maths capability to understand the problem, let alone find a solution. The attachment shows that, for most of the line, the modified macro worked well. The problem occurred at the 'end' of the line where 7 locations malfunctioned. The 7 yellow dots. Of course, it could be an error in my code (I'll have a look at DanPaul's original code with your modification when I get some time). It does seem strange that the code, with your modification, manages to perform perfectly on the other two 'vertical' legs. Your code is a huge improvement, without it 492 points are incorrectly calculated. Thanks for that. Regards. Paul Smith

  • You're welcome Paul

    As I wrote "I don't know if this gives me trouble later in the code". But for my macro it works right now.

    Hope you manage to figure out what wrong with the 7 points at the end of your string.

    Regards,

     

    Finn Mejding

    CAD Manager

    Railway and Metro

    COWI

  • Hi Finn

    In case you don't notice my reply to Jon (above) his macro works perfectly on my test line. Should you have any issues with your version, I would recommend that you have a look at Jon's macro .

    Regards

    Paul Smith

Reply Children
No Data