### Author Topic: Reading 3D rotation properties  (Read 1929 times)

0 Members and 1 Guest are viewing this topic.

#### silveroak

• Guest « on: October 27, 2008, 09:38:54 AM »
Greetings, all

I have a piece of code that reads back Rotation property of blockreferences in drawings. Now I need to be able to look at rotation of a blockreference in all three planes.  I always understood the Rotation property as around the insertion point in XY plane in WCS. How would one go about reading back XZ and YZ rotation relatively the insertion point?

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Reading 3D rotation properties
« Reply #1 on: October 27, 2008, 10:22:35 AM »
If you can follow matricies I could post the rest of the code
Code: [Select]
`Function BlockRefMatrix(oBref As AcadBlockReference) As Variant    Dim V, m(3, 3) As Double, M1, M2    Dim j As Integer    Dim x, y, Z, ins    Dim Rot As Double        Rot = oBref.Rotation    Z = oBref.Normal    V = GetOcsFromNormal(Z)    x = V(0): y = V(1)    ins = oBref.InsertionPoint        M1 = RotZ(-Rot)    For j = 0 To 2        m(0, j) = x(j)        m(1, j) = y(j)        m(2, j) = Z(j)        m(3, j) = ins(j)    Next j    m(3, 3) = 1    If Rot = 0 Then        BlockRefMatrix = m    Else        M2 = M4xM4(m, M1)        BlockRefMatrix = M2    End If        End FunctionFunction GetOcsFromNormal(N As Variant) As Variant    'Arbitrary Axis Algorithm in dxf help    'N is the normal vector.    'Wy is the world Y axis, which is always (0,1,0).    'Wz is the world Z axis, which is always (0,0,1).    Dim Wy(2) As Double    Dim Wz(2) As Double    Dim Nx As Double, Ny As Double    Dim Ax, Ay, Ocs(1) As Variant        N = NormaliseVector(N)    Wy(0) = 0: Wy(1) = 1: Wy(2) = 0    Wz(0) = 0: Wz(1) = 0: Wz(2) = 1    Nx = N(0): Ny = N(1)    If (Abs(Nx) < 1 / 64) And (Abs(Ny) < 1 / 64) Then         'Ax = Wy X N (where X is the cross-product operator).         Ax = Crossproduct(Wy, N)    Else         Ax = Crossproduct(Wz, N)    End If    Ocs(0) = Ax      Ay = Crossproduct(N, Ax)    Ocs(1) = Ay    GetOcsFromNormal = OcsEnd Function`

#### silveroak

• Guest ##### Re: Reading 3D rotation properties
« Reply #2 on: October 27, 2008, 12:19:57 PM »
Bryco, the 4x4 that we get back from BlocRefMatrix, is it rotation and translation from 0,0,0? It would be great if you posted the rest of the functions.
What I will have to do from there is to orient a number of block references the same way, could you point me to or post a source on applying the rotation component to a block reference?

Or something that can apply the 4x4 transformation will work as well, I can get my blockreferences to origin and they will not be rotated.

I am very new to all this and not sure where to start in AutoCAD. In the tool I am working on our blocks and locations were always 3d but only xy rotation has ever been used which is conveniently in a property. My knowledge of 3d transformation in CAD is 0 and the theory is almost forgotten.  If I can get the transformation from the rest of your code and then a way to apply it to something else I will be well on my way to recovery!

Thanks!
« Last Edit: October 27, 2008, 12:37:32 PM by silveroak »

#### silveroak

• Guest ##### Re: Reading 3D rotation properties
« Reply #3 on: October 27, 2008, 05:06:19 PM »
I was reading the documention and realized that we've got TransformBy,

as stated above I need to orient unrotated block references the same way.  Their insertion point should stay where it is.

if I take the 4x4 from BlockRefMatrix, set translation xyz information in the last row to 0 and TransformBy desired blocks with it, will it result in desired same orientation? Please let me know if I am on the right track.

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Reading 3D rotation properties
« Reply #4 on: October 27, 2008, 10:27:08 PM »
I'm still not quite sure what you are doing, but here is the rest.
Yes this gives both a transformation and a rotation in x,y & z

If you have your immediatewindow up (ctrl+G) you will see the matrix print out (the way I like it printed out)
I think you will find what you need, I'm not sure how to translate them directly into angles as the order is important

Code: [Select]
`Option ExplicitSub TEST()    Dim b As AcadBlockReference, ent As AcadEntity, V, m    ThisDrawing.Utility.GetEntity ent, V, "Pick"    If ent Is Nothing Then Exit Sub    If Not TypeOf ent Is AcadBlockReference Then Exit Sub    Set b = ent    m = BlockRefMatrix(b)    PrintM m    End SubFunction RotZ(ang As Double) As Variant   'Rotate by an angle around the z axis    Dim m    Dim CosAng As Double, sinAng As Double        CosAng = Cos(ang): sinAng = Sin(ang)    m = IDMatrix    m(0, 0) = CosAng    m(0, 1) = -sinAng    m(1, 0) = sinAng    m(1, 1) = CosAng          RotZ = mEnd FunctionFunction M4xM4(M1, M2) As Variant    'Matrix x matrix    Dim m(3, 3) As Double    Dim I As Integer, j As Integer    Dim k As Integer    Dim Sum As Double        For I = 0 To 3        For j = 0 To 3            For k = 0 To 3                Sum = Sum + M1(k, j) * M2(I, k)            Next k            m(I, j) = Sum            Sum = 0        Next j    Next I    M4xM4 = m    End FunctionFunction NormaliseVector(V As Variant) As Variant    Dim Unit As Double    Dim Vn(2) As Double    Unit = Sqr(V(0) * V(0) + V(1) * V(1) + V(2) * V(2))    Vn(0) = V(0) / Unit: Vn(1) = V(1) / Unit: Vn(2) = V(2) / Unit    NormaliseVector = VnEnd FunctionFunction Crossproduct(a, b) As Variant    Dim Ax As Double, Ay As Double, Az As Double    Dim Bx As Double, By As Double, Bz As Double    Dim Unit As Double    Dim c(2) As Double    'get CrossProduct    Ax = a(0): Ay = a(1): Az = a(2)    Bx = b(0): By = b(1): Bz = b(2)        c(0) = Ay * Bz - Az * By    c(1) = Az * Bx - Ax * Bz    c(2) = Ax * By - Ay * Bx        'Convert to unit normal    Unit = Sqr(c(0) * c(0) + c(1) * c(1) + c(2) * c(2))    c(0) = c(0) / Unit: c(1) = c(1) / Unit: c(2) = c(2) / Unit    Crossproduct = cEnd FunctionFunction IDMatrix()    Dim m(3, 3) As Double    Dim I As Integer, j As Integer    m(0, 0) = 1    m(1, 1) = 1    m(2, 2) = 1    m(3, 3) = 1    IDMatrix = m    End FunctionSub PrintM(m)    Dim I As Integer    Dim j As Integer    Debug.Print    If UBound(m, 2) > 3 Then        For I = 0 To 3             Debug.Print m(I, 0), m(I, 1), m(I, 2), m(I, 3), m(I, 4), m(I, 5), m(I, 6), m(I, 7)        Next    Else        For I = 0 To 3             Debug.Print m(I, 0), m(I, 1), m(I, 2), m(I, 3)        Next    End If    End Sub`

#### silveroak

• Guest ##### Re: Reading 3D rotation properties
« Reply #5 on: October 28, 2008, 08:50:56 AM »
Thanks again, Bryco,
your code is a great place to start for me. I am going to have to convert it to C# as that's what I use to drive AutoCAD, but from there I will see what can be done with the matrix.

The most important part for me is copying orientation of one block to another. I was thinking about extracting angles and applying Rotate3D but like you said I don't know the order.  I might be able to achieve the same by using the rotational component of your matrix and applying it through TransformBy to another block reference.

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Reading 3D rotation properties
« Reply #6 on: October 28, 2008, 09:33:39 AM »
Matricies are very easy in C#, if you post the rotation part of your code in the net part of code red you should get some help

#### silveroak

• Guest ##### Re: Reading 3D rotation properties
« Reply #7 on: October 29, 2008, 09:33:35 PM »
I finally got it to work after conversion to C# and trying to apply it with TransformBy,
it turns out the resulting block matrix must be transposed or rebuilt column-first to work with TransformBy.  It will fully recreate a block's position and orientation if applied to unrotated block at 0,0,0.
If it is not transposed, it will do strangest things including wild scaling and making blocks disappear (maybe become tiny, not sure)  :ugly:

I noticed the difference when it dawned on me that the transform matrix examples in AutoCAD help have the unused 0,0,0 in the bottom row as opposed to rightmost as in the test output.

I am wondering why is this so and what would this code build it like that (just curiosity)?

#### Bryco

• Water Moccasin
• Posts: 1850 ##### Re: Reading 3D rotation properties
« Reply #8 on: October 29, 2008, 11:06:42 PM »
I personally hate the way matricies are built in cad and the code I supplied is the way it makes sense to me.
I found out by back tracking the cad matrix supplied with getsubentity, which gives you the matrix to put the subentity from the blockref back to the 0,0 blockdef. This was 180 degrees from what  I wanted so you may need an inverse and a transposing.