Applying a 3D rotation to a cell

After many failed attempts I have to ask the question.... what is the correct sequence of events that needs to occur to place a cell (or any object) at a specific 3D rotation.  I have computed all of the rotations (shown below).  When I apply the rotation to the cell I can get it to rotate based on either the X,Y, or Z rotation, but once I combine the rotations the cell is not correctly rotated.  Needless to say I have done a lot of reading on the 3dmatrix, 3dtransforms, vectors, etc.  trying to figure this out, I get close, but close does not count! 

My rotations are based on using existing geometry in the file, specifically a 3D linestring.  I have included below how I go about computing the rotation angles, as well as how I am apply the rotation to the cell.  I think my logic with respect to computing the angles is correct, but not 100% sure.  This works if I am rotating in ONE of the X, Y, or Z rotations, but not when any combination of rotations are applied. 

Thanks in advance for any advice,
tim

below is the code snippet that I am using...

dim v3d1 As Vector3d
dim StrVertices() As Point3d
dim StrVindex As Long
dim myAngle as double
dim TV_matrix As Matrix3
dim TV_trans As Transform3d
Dim myCell As CellElement
Dim X_angle As Double
DIM Y_angle As Double
DIM Z_angle As Double
dim myPoints as point3d

    With Telement.AsVertexList
        StrVertices = .GetVertices
        'get the start vertex Id of segment
        StrVindex = .GetClosestSegment(TempPoint)
        'get the vector of the segment
        v3d1 = Vector3dFromXY(StrVertices(StrVindex + 1).x - StrVertices(StrVindex).x, StrVertices(StrVindex + 1).y - StrVertices(StrVindex).y)
     end with

      'now get the "TOP view angle"
      Z_angle= Vector3dPolarAngle(v3d1) 

     'this computes the "profile" angle using delta Z difference of the points, and the XY distance of the points
     'the profile angle is the "normal" angle that uses Z values and the distance between the points to compute the "profile" angle
     Y_angle = Atn((StrVertices(StrVindex).z - StrVertices(StrVindex + 1).z) / Point3dDistanceXY(StrVertices(StrVindex), StrVertices(StrVindex + 1)))

     'this computes the "cross section rotation", using a user key-in to define the angle
     X_angle = radians(myAngle)

        Set myCell = CreateCellElement2(myCellname,myPoints, cellscale, True, Matrix3dIdentity)

        'rotate about X
        cellscale.x = 1
        cellscale.y = 0
        cellscale.z = 0
        TV_matrix = Matrix3dFromVectorAndRotationAngle(cellscale, X_angle)
        TV_trans = Transform3dFromMatrix3dAndFixedPoint3d(TV_matrix, myPoints)
        myCell.Transform TV_trans

          'rotate about y
        cellscale.x = 0
        cellscale.y = 1
        cellscale.z = 0
        TV_matrix = Matrix3dFromVectorAndRotationAngle(cellscale, Y_angle)
        TV_trans = Transform3dFromMatrix3dAndFixedPoint3d(TV_matrix, myPoints)
        myCell.Transform TV_trans

        'rotate about z
        cellscale.x = 0
        cellscale.y = 0
        cellscale.z = 1
        TV_matrix = Matrix3dFromVectorAndRotationAngle(cellscale, Z_angle)
        TV_trans = Transform3dFromMatrix3dAndFixedPoint3d(TV_matrix, myPoints)
        myCell.Transform TV_trans

        ActiveModelReference.AddElement myCell
        myCell.Redraw msdDrawingModeNormal

 

 

Parents
  • Both the order of rotation and the centre of rotation are important in 3D. In 2D it's much simpler. In 4D it's beyond human comprehension 8-)

    I'd start with 2D, just to keep things as simple as possible. When you construct a rotation matrix, you're telling MicroStation "I want to rotate an object by this angle about this point".

    Unless you tell it otherwise, MicroStation assumes the rotation centre point to be 0,0,0. If your object happens to be at 100,0,0 and you rotate it by PI/2 (90°) it will be translated to location 0,100,0 as well as rotated by 90°. If you can figure out how to set the centre of rotation of the matrix that's fine; otherwise subtract the origin of the object (so it's located at 0,0,0), rotate it, then add back the origin.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Jon,

    I have all of the information (including rotation point), its the order of rotation (and maybe the procedure in code that I am using) that seems to be the place where I am stumbling.  If I know all three rotations, as well as the point of rotation, is there a specific VBA MS matrix3D or transform3D method that should be used?  Needless to say I have scoured the MS VBA help (and examples) and its been a humbling experience (although I am learning alot more about 3D rotation matrices than I ever thought I needed to know)!

    Tim Kohn

  • Something like …

    Dim origin As Point3d
    origin = oElement.Origin
    Dim offset As Point3d
    offset = Point3dSubtract (Point3dZero, origin)
    oElement.Move offset
    ... do rotation
    oElement.Move origin
    oElement.Rewrite

    You haven't told us how you're obtain the proposed rotation. We don't know if you have X,Y,Z angles or a rotation matrix. If you have angles, you could use Matrix3dFromAxisAndRotationAngle …

    Dim rotation As Matrix3d
    rotation = Matrix3dFromAxisAndRotationAngle (...)
    Dim transform As Transform3d
    transform = Transform3dFromMatrix3d (rotation)
    oElement.Transform transform

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Jon,

    In my original post I did include the code of how i was capturing the rotation angles, and how I was processing the info... each of the angles is computed from a user selected element, in my instance its a linestring element.  I calculate the X, Y, and Z angles based on the element info (see my post below for how I do this).  I then process the angles as shown below...

           'rotate about X

           cellscale.x = 1

           cellscale.y = 0

           cellscale.z = 0

           TV_matrix = Matrix3dFromVectorAndRotationAngle(cellscale, X_angle)

           TV_trans = Transform3dFromMatrix3dAndFixedPoint3d(TV_matrix, myPoints)

           myCell.Transform TV_trans

             'rotate about y

           cellscale.x = 0

           cellscale.y = 1

           cellscale.z = 0

           TV_matrix = Matrix3dFromVectorAndRotationAngle(cellscale, Y_angle)

           TV_trans = Transform3dFromMatrix3dAndFixedPoint3d(TV_matrix, myPoints)

           myCell.Transform TV_trans

           'rotate about z

           cellscale.x = 0

           cellscale.y = 0

           cellscale.z = 1

           TV_matrix = Matrix3dFromVectorAndRotationAngle(cellscale, Z_angle)

           TV_trans = Transform3dFromMatrix3dAndFixedPoint3d(TV_matrix, myPoints)

           myCell.Transform TV_trans

    This works for one rotation, but not when I combine the rotations, for example, when I rotate only in the Y direction the cell is correctly positioned.  But if I try to then rotate in the X direction, the cell is not correctly rotated.  I think I understand why this will not work as I am making the assumption that the X direction rotation is based on the Y angle BEFORE rotation.  After the Y rotation, the X angle that was computed is no longer valid with respect to the position of the object in the model, but valid with respect to the rotation angle that somehow needs to get applied to the object  (the above method of rotation was one of several different (and failed attempts) at getting the correct results).   Your thoughts/comments as always are appreciated!

    The cout

    Tim Kohn

  • Unknown said:
    In my original post I did include the code of how i was capturing the rotation angles …

    Oops! So you did — mea culpa!

    Unknown said:
    This works for one rotation, but not when I combine the rotations, for example, when I rotate only in the Y direction the cell is correctly positioned. But if I try to then rotate in the X direction, the cell is not correctly rotated. I think I understand why this will not work as I am making the assumption that the X direction rotation is based on the Y angle BEFORE rotation. After the Y rotation, the X angle that was computed is no longer valid with respect to the position of the object in the model, but valid with respect to the rotation angle that somehow needs to get applied to the object (the above method of rotation was one of several different (and failed attempts) at getting the correct results). Your thoughts/comments as always are appreciated!

    How to compute multiple rotations is often tricky, because successive rotations are not commutative. Meaning that X.Y.Z is not the same as Y.X.Z or X.Z.Y.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Good afternoon Tim

    I trod this path many moons ago and got a lot of help from the VBA forum.  I then wrote an article in MSM Online titled "What's my Vector Victor" that explained it all - rotation, translation and scaling.

    Go to

    discussion.bentley.com/.../dnewsweb.exe

    where you will find my code, documentation and prototype drawing at the bottom.

    Or search "What's my Vector victor bentley"

    Let us know if it helps

    regards

    Patrick

  • Thanks!  I will download the examples and hopefully get this completed!

    Tim Kohn

Reply Children
No Data