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,timbelow is the code snippet that I am using...
dim v3d1 As Vector3ddim StrVertices() As Point3ddim StrVindex As Longdim myAngle as doubledim TV_matrix As Matrix3dim TV_trans As Transform3dDim myCell As CellElementDim X_angle As DoubleDIM Y_angle As DoubleDIM Z_angle As Doubledim 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
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
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
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
TV_matrix = Matrix3dFromVectorAndRotationAngle(cellscale, Y_angle)
'rotate about z
cellscale.z = 1
TV_matrix = Matrix3dFromVectorAndRotationAngle(cellscale, Z_angle)
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
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.