Rotation and transformation matrix

Hi,

I'm struggling with placing a cell along an arc in VBA.

I have a Complex Chain where I will place a cell along the whol chain with a fixed distance.

I have solved the rotation on the "Line" part of the chainm but having trouble with the arc.

The rotation is almost correct, but almost doesn't count :-)

Any one have a suggestion?

The code snippet for placing the cell:

Sub showLineElm(LinElm As ComplexStringElement)
  Dim elm As ElementEnumerator
  Dim aelm As ArcElement
  Dim lelm As LineElement
  Dim oPH As PropertyHandler
  Dim lastsegment As String
  Dim streng As String, streng1 As String
  Dim start As Point3d
  Dim skala As Point3d
  Dim oCell As CellElement
  Dim z As Integer
  Dim ant_cell As Double, distance As Double
  Dim vinkel As Double
  Dim mtrxRotation As Matrix3d
 
  skala.X = 1
  skala.Y = 1
  skala.z = 1
  If LinElm.Type = msdElementTypeComplexString Then
    If LinElm.IsTraversableElement Then
      Set elm = LinElm.GetSubElements
      Do While elm.MoveNext

        Select Case elm.Current.Type
          Case msdElementTypeLine
            Set lelm = elm.Current.AsLineElement
            lastsegment = "Segments[" & (lelm.VerticesCount - 2) & "]."
            Set oPH = CreatePropertyHandler(lelm)
            oPH.SelectByAccessString (lastsegment & "Start")
            start = oPH.GetValueAsPoint3d
            oPH.SelectByAccessString (lastsegment & "Direction")
            streng = oPH.GetValue
            vinkel = Degrees(CDbl(streng))
            mtrxRotation = Matrix3dFromAxisAndRotationAngle(2, CDbl(streng))
            Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
            ActiveModelReference.AddElement oCell
            ant_cell = lelm.Length / 0.854
            ant_cell = ant_cell \ 1
            distance = 0
            For z = 1 To ant_cell
              distance = distance + 0.854
              If distance > lelm.Length Then
                Exit For
              End If
              start = lelm.PointAtDistance(distance)
              Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
              ActiveModelReference.AddElement oCell
            Next z

          Case msdElementTypeArc
            Set aelm = elm.Current.AsArcElement
            Set oPH = CreatePropertyHandler(aelm)
            oPH.SelectByAccessString ("SweepAngle")
            vinkel = oPH.GetValue
            mtrxRotation = Matrix3dFromAxisAndRotationAngle(2, vinkel)
            start = aelm.StartPoint
            Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
            distance = 0
            oCell.Transform Transform3dFromMatrix3dAndFixedPoint3d(mtrxRotation, start)
            ActiveModelReference.AddElement oCell
            ant_cell = aelm.Length / 0.854
            ant_cell = ant_cell \ 1
            For z = 1 To ant_cell
              distance = distance + 0.854
              If distance > aelm.Length Then
                Exit For
              End If
              start = aelm.PointAtDistance(distance)
              Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
              oCell.Transform Transform3dFromMatrix3dAndFixedPoint3d(mtrxRotation, start)
              ActiveModelReference.AddElement oCell
            Next z
        End Select
      Loop
    End If
  End If
errExit:
End Sub    'showLineElm

Parents
  • Hi Finn,

    please read and follow MicroStation Programming forum best practices and to share required information like what MicroStation version do you use. Also some example file would be nice.

    Also please edit your post and use Insert > Insert Code tool to share your code in a proper form. Personally, long time ago I decided to don't read any code formatted as plain text, because it's ugly, hardly readable and time consuming.

    The rotation is almost correct

    What does it mean. Why you don't provide better explanation?

    Any one have a suggestion?

    Split your code into more functions with exactly specified responsibility (at least to process linear and arc elements). Approach "one function will do everything" always leads to dirty and buggy code.

    Why do you use PropertyHandler object here? It's "the last chance" tool, but I am pretty sure to use it in any code processing elements is wrong. It's not only much slower than direct access to element properties, but I am also not quite sure about a precision of values returned.

    With regards,

      Jan

  • Jan,

    Thought I was OK by tagging the post with MicroStation V8i Open mouth

    My version is: 08.11.09.459 (SelectSeries 3).

    This is what I mean by "Close, but no cigar", the blue ones are placed manually with the correct rotation, the black cells are drawn by my program.

    The code:

    Sub showLineElm(LinElm As ComplexStringElement)
      Dim elm As ElementEnumerator
      Dim aelm As ArcElement
      Dim lelm As LineElement
      Dim oPH As PropertyHandler
      Dim lastsegment As String
      Dim streng As String, streng1 As String
      Dim start As Point3d
      Dim skala As Point3d
      Dim oCell As CellElement
      Dim z As Integer
      Dim ant_cell As Double, distance As Double
      Dim vinkel As Double
      Dim mtrxRotation As Matrix3d
      
      skala.X = 1
      skala.Y = 1
      skala.z = 1
      If LinElm.Type = msdElementTypeComplexString Then
        If LinElm.IsTraversableElement Then
          Set elm = LinElm.GetSubElements
          Do While elm.MoveNext
            Select Case elm.Current.Type
              Case msdElementTypeLine
                Set lelm = elm.Current.AsLineElement
                lastsegment = "Segments[" & (lelm.VerticesCount - 2) & "]."
                Set oPH = CreatePropertyHandler(lelm)
                oPH.SelectByAccessString (lastsegment & "Start")
                start = oPH.GetValueAsPoint3d
                oPH.SelectByAccessString (lastsegment & "Direction")
                streng = oPH.GetValue
                vinkel = Degrees(CDbl(streng))
                mtrxRotation = Matrix3dFromAxisAndRotationAngle(2, CDbl(streng))
                Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
    '            oCell.GraphicGroup = ggNum
                ActiveModelReference.AddElement oCell
                ant_cell = lelm.Length / 0.854
                ant_cell = ant_cell \ 1
                distance = 0
                For z = 1 To ant_cell
                  distance = distance + 0.854
                  If distance > lelm.Length Then
                    Exit For
                  End If
                  start = lelm.PointAtDistance(distance)
                  Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
                  ActiveModelReference.AddElement oCell
                Next z
              Case msdElementTypeArc
                Set aelm = elm.Current.AsArcElement
                Set oPH = CreatePropertyHandler(aelm)
                oPH.SelectByAccessString ("SweepAngle")
                vinkel = oPH.GetValue
                mtrxRotation = Matrix3dFromAxisAndRotationAngle(2, vinkel)
                start = aelm.StartPoint
                Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
    '            oCell.GraphicGroup = ggNum
                distance = 0
                oCell.Transform Transform3dFromMatrix3dAndFixedPoint3d(mtrxRotation, start)
               
                ActiveModelReference.AddElement oCell
                ant_cell = aelm.Length / 0.854
                ant_cell = ant_cell \ 1
                For z = 1 To ant_cell
                  distance = distance + 0.854
                  If distance > aelm.Length Then
                    Exit For
                  End If
                  start = aelm.PointAtDistance(distance)
                  Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
                oCell.Transform Transform3dFromMatrix3dAndFixedPoint3d(mtrxRotation, start)
                  ActiveModelReference.AddElement oCell
                Next z
            End Select
          Loop
        End If
      End If
    errExit:
    End Sub 'showLineElm
    

    The code is still "Work in Progress" and therefor not that pretty yet.

    Regards,

     

    Finn Mejding

    CAD Manager

    Railway and Metro

    COWI

Reply
  • Jan,

    Thought I was OK by tagging the post with MicroStation V8i Open mouth

    My version is: 08.11.09.459 (SelectSeries 3).

    This is what I mean by "Close, but no cigar", the blue ones are placed manually with the correct rotation, the black cells are drawn by my program.

    The code:

    Sub showLineElm(LinElm As ComplexStringElement)
      Dim elm As ElementEnumerator
      Dim aelm As ArcElement
      Dim lelm As LineElement
      Dim oPH As PropertyHandler
      Dim lastsegment As String
      Dim streng As String, streng1 As String
      Dim start As Point3d
      Dim skala As Point3d
      Dim oCell As CellElement
      Dim z As Integer
      Dim ant_cell As Double, distance As Double
      Dim vinkel As Double
      Dim mtrxRotation As Matrix3d
      
      skala.X = 1
      skala.Y = 1
      skala.z = 1
      If LinElm.Type = msdElementTypeComplexString Then
        If LinElm.IsTraversableElement Then
          Set elm = LinElm.GetSubElements
          Do While elm.MoveNext
            Select Case elm.Current.Type
              Case msdElementTypeLine
                Set lelm = elm.Current.AsLineElement
                lastsegment = "Segments[" & (lelm.VerticesCount - 2) & "]."
                Set oPH = CreatePropertyHandler(lelm)
                oPH.SelectByAccessString (lastsegment & "Start")
                start = oPH.GetValueAsPoint3d
                oPH.SelectByAccessString (lastsegment & "Direction")
                streng = oPH.GetValue
                vinkel = Degrees(CDbl(streng))
                mtrxRotation = Matrix3dFromAxisAndRotationAngle(2, CDbl(streng))
                Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
    '            oCell.GraphicGroup = ggNum
                ActiveModelReference.AddElement oCell
                ant_cell = lelm.Length / 0.854
                ant_cell = ant_cell \ 1
                distance = 0
                For z = 1 To ant_cell
                  distance = distance + 0.854
                  If distance > lelm.Length Then
                    Exit For
                  End If
                  start = lelm.PointAtDistance(distance)
                  Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
                  ActiveModelReference.AddElement oCell
                Next z
              Case msdElementTypeArc
                Set aelm = elm.Current.AsArcElement
                Set oPH = CreatePropertyHandler(aelm)
                oPH.SelectByAccessString ("SweepAngle")
                vinkel = oPH.GetValue
                mtrxRotation = Matrix3dFromAxisAndRotationAngle(2, vinkel)
                start = aelm.StartPoint
                Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
    '            oCell.GraphicGroup = ggNum
                distance = 0
                oCell.Transform Transform3dFromMatrix3dAndFixedPoint3d(mtrxRotation, start)
               
                ActiveModelReference.AddElement oCell
                ant_cell = aelm.Length / 0.854
                ant_cell = ant_cell \ 1
                For z = 1 To ant_cell
                  distance = distance + 0.854
                  If distance > aelm.Length Then
                    Exit For
                  End If
                  start = aelm.PointAtDistance(distance)
                  Set oCell = CreateCellElement2("cellname", start, skala, True, mtrxRotation)
                oCell.Transform Transform3dFromMatrix3dAndFixedPoint3d(mtrxRotation, start)
                  ActiveModelReference.AddElement oCell
                Next z
            End Select
          Loop
        End If
      End If
    errExit:
    End Sub 'showLineElm
    

    The code is still "Work in Progress" and therefor not that pretty yet.

    Regards,

     

    Finn Mejding

    CAD Manager

    Railway and Metro

    COWI

Children