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