.NET

Reply
Contributor
kbrown
Posts: 19
Registered: ‎10-23-2012
Message 1 of 8 (288 Views)
Accepted Solution

How To Calculate Angular Displacement of a Block (3D)

288 Views, 7 Replies
05-19-2014 03:53 PM

I am having trouble calculating the angle between each of the axes of a blocks local coordinate system and the WCS. Since there is no method I am aware of to retrieve the WCS, I am just using Matrix3d.Identity to represent the WCS because the two should always be equivalent. Here is he code I am currently using to calculate the angle between each axis:

 

Dim transform As Matrix3d = DynamicBlockHelper.GetBlockTransform(BlockObjID)
Dim angleX As Double = transform.CoordinateSystem3d.Xaxis.GetAngleTo(Matrix3d.Identity.CoordinateSystem3d.Xaxis)
Dim angleY As Double = transform.CoordinateSystem3d.Yaxis.GetAngleTo(Matrix3d.Identity.CoordinateSystem3d.Yaxis)
Dim angleZ As Double = transform.CoordinateSystem3d.Zaxis.GetAngleTo(Matrix3d.Identity.CoordinateSystem3d.Zaxis)

 

Here is the source for the method used to retrieve a block's local coordinate system in the code above:

 

Public Shared Function GetBlockTransform(BlockObjectID As ObjectId) As Matrix3d
        Dim result As Matrix3d = Nothing
        Dim doc As Document = ApplicationServices.Application.DocumentManager.GetDocument(BlockObjectID.Database)
        Using lock As DocumentLock = doc.LockDocument()
            Using trans As Transaction = BlockObjectID.Database.TransactionManager.StartTransaction
                Try
                    Using blockRef As BlockReference = BlockObjectID.GetObject(OpenMode.ForRead)
                        result = blockRef.BlockTransform
                    End Using
                Catch ex As System.Exception
                    Try
                        EventLog.WriteEntry("DynamicBlockHelper.GetDynamicBlockTransform", ex.GetType().Name + ": " + ex.Message + Environment.NewLine + ex.StackTrace, EventLogEntryType.Error)
                    Catch eex As System.Exception

                    End Try
                End Try
            End Using
        End Using
        Return result
    End Function

 

 

The resulting angles are clearly incorrect, none of which even matches the value of the Rotation member of the BlockReference class for the given block. My aim is to store these angles, delete the block reference, and recreate the block reference and restore the position and rotation (x,y,z) of the new block. This is part of some code I have written to programatically redefine dynamic blocks, which requires that the block references be deleted, then the block definition be updated, then the block references be recreated and their state restored. The code works fine, except for the rotation angles.

 

Thank you,

Kevin

It's quite difficult to use rotations about multiple axis (a rotation of 30° about Z and then a rotation of 20° about X isn't the same as a rotation of 20° about X and then a rotation of 30° about Z).

This is the reason why AutoCAD (and most of the 3d softwares) prefer describe 3d transformations with a plane transformation in which only rotations about the Z axis of this plane are considered. This is how works the Object Coordinates System (oCS) of many autoCAD enities (bloc references,circles, polylines, texts, ...). I tried to explain this with my poor English to TheSwamp LISPers here (you'd have to register, if not done yet).

 

So a block reference geometry (excuding scale transformations) is completely dercribed with its position (WCS coordinates of the insertion point), its Normal (the z axis of the block OCS) and its Rotation (angle measured from the OCS X axis about the OCS Z axis). The BlockTransform Matrix3d is the combination of these transformations (more the scales one).

AutoCAD .NET provides many APIs to deal with these transformations with the Matrix3d methods.

 

If you explain what you want to do instead of how you try to do it, perhaps we can find a simpler route.

*Expert Elite*
_gile
Posts: 2,084
Registered: ‎04-29-2006
Message 2 of 8 (250 Views)

Re : How To Calculate Angular Displacement of a Block (3D)

05-19-2014 11:06 PM in reply to: kbrown

Hi,

 

I'm not sure to understand what you're looking for.

Anyway, instead of: Matrix3d.Identity.CoordinateSystem.Xaxis, you can simply use: Vector3d.Xaxis.

You should also have a look at the overloaded GetAngleTo(vector, referenceVector) method which returns the angle in the range of [0, 2*PI] (instead of [0, PI]).

 

Vector3d transformXaxis = transform.CoordinateSystem3d.Xaxis;
    double angleX = Vector3d.XAxis.GetAngleTo(
        transformXaxis, Vector3d.XAxis.CrossProduct(transformXaxis));

 

Gilles Chanteau
Contributor
kbrown
Posts: 19
Registered: ‎10-23-2012
Message 3 of 8 (240 Views)

Re : How To Calculate Angular Displacement of a Block (3D)

05-20-2014 01:00 PM in reply to: _gile

When I rotate about a point and the Z-Axis in AutoCAD, the result is that the vectors for both the X and Y axes are rotated by the angle given. This explains the strange results I have been experiencing where a rotation about Z results in my block being rotated double that amount when I run the code that follows, though it makes sense to represent the displacement in this way. It has been a long time since I have actively used 3D Geometry/Matrix Math/Linear Algebra. I'm sorry if my question is silly.

 

How would you suggest I use the 3 angles calculated to transform a block and return it to the original orientation. Currently I am doing the following, though I have eliminated some of my code in favor of showing only the API calls that seem relevant and used to create a transformation matrix, then use it to transform a block:

 

                Dim insertionPoint As New Point3d(state.Translate.X, state.Translate.Y, state.Translate.Z)
                Dim transformX As Matrix3d = Matrix3d.Rotation(state.Rotate.X, Vector3d.XAxis, insertionPoint)
                Dim transformY As Matrix3d = Matrix3d.Rotation(state.Rotate.Y, Vector3d.YAxis, insertionPoint)
                Dim transformZ As Matrix3d = Matrix3d.Rotation(state.Rotate.Z, Vector3d.ZAxis, insertionPoint)
                Dim transformXYZ As Matrix3d = transformX * transformY * transformZ
                Dim blockRef As BlockReferency(insertionPoint, objID)
                blockRef.TransformBy(transformXYZ)

 

Where State.Rotate contains the three angles calculated for X,Y, and Z. And state.Translate is just the X,Y, and Z position taken from the block's coordinate system.

 

Perhaps I should not calcuate the angles for each axis, but instead store the three vectors in the block's local coordinate system? If so, how would I correctly use the three vectors to initialize a block's coordinate system and restore it to the original orientation?

 

Thanks,

Kevin

*Expert Elite*
_gile
Posts: 2,084
Registered: ‎04-29-2006
Message 4 of 8 (232 Views)

Re : How To Calculate Angular Displacement of a Block (3D)

05-20-2014 02:11 PM in reply to: kbrown

It's quite difficult to use rotations about multiple axis (a rotation of 30° about Z and then a rotation of 20° about X isn't the same as a rotation of 20° about X and then a rotation of 30° about Z).

This is the reason why AutoCAD (and most of the 3d softwares) prefer describe 3d transformations with a plane transformation in which only rotations about the Z axis of this plane are considered. This is how works the Object Coordinates System (oCS) of many autoCAD enities (bloc references,circles, polylines, texts, ...). I tried to explain this with my poor English to TheSwamp LISPers here (you'd have to register, if not done yet).

 

So a block reference geometry (excuding scale transformations) is completely dercribed with its position (WCS coordinates of the insertion point), its Normal (the z axis of the block OCS) and its Rotation (angle measured from the OCS X axis about the OCS Z axis). The BlockTransform Matrix3d is the combination of these transformations (more the scales one).

AutoCAD .NET provides many APIs to deal with these transformations with the Matrix3d methods.

 

If you explain what you want to do instead of how you try to do it, perhaps we can find a simpler route.

Gilles Chanteau
Contributor
kbrown
Posts: 19
Registered: ‎10-23-2012
Message 5 of 8 (228 Views)

Re : How To Calculate Angular Displacement of a Block (3D)

05-20-2014 02:50 PM in reply to: _gile

Simply put, I want to store the position and orientation of a 3d block, and then later restore a block with an identical definition to the same position and orientation. Likely my own lack of proper vocabulary for this area of mathematics is more to blame than your English. I have had no trouble reading your responses, and I am very grateful for your time.

 

If you can provide me with code to store in floating point variables the position and orientation (by this I simply mean the end result of the any rotation applied to the block reference, as represented by its "OCS"). And code to use the values of the variables previously defined to apply the exact location and rotation in 3d space of another block reference of the same definition, I will have all that I need.

 

I completely understand your point about order of operations affecting resulting position and orientation when dealing with linear transformations. Although I have no AutoCAD specific knowledge in this area, I did tinker with 3D realtime rendering APIs like DirectX in college, but that was a decade ago. I do not need the transformation stack applied to the block reference to cause its final position and rotation. I just care about applying the final position and rotation to another block reference of the same type, so that the block reference's geometry is in the exact location of the original block.

 

Thank you again for your time and patience.

 

Best regards,

Kevin

Contributor
kbrown
Posts: 19
Registered: ‎10-23-2012
Message 6 of 8 (220 Views)

Re : How To Calculate Angular Displacement of a Block (3D)

05-20-2014 04:49 PM in reply to: _gile

I think I found a solution on my own. In hindsight I feel foolish for even asking this question. I should have looked more closely at the Matrix3d class.

 

I used the Matrix3d.ToArray() method to retrieve an array of doubles which I assume represent the elements of the matrix. I then just pass the array of doubles returned by ToArray to the constructor of the Matrix3d class. I then pass the initialized Matrix3d instance to Entity.TransformBy. This seems to work exactly as I need it to. It is worth noting that the block definition to which the transform is applied should be aligned with the WCS when using this approach.

 

Do you see any problem with this method?

 

Thanks again,

Kevin

*Expert Elite*
_gile
Posts: 2,084
Registered: ‎04-29-2006
Message 7 of 8 (202 Views)

Re : How To Calculate Angular Displacement of a Block (3D)

05-20-2014 10:34 PM in reply to: kbrown

kbrown a écrit :

Do you see any problem with this method?


No, but is there any reason to convert the matrix into an array and then convert back the array into a matrix? this seems to me absolutely unusefull.

Gilles Chanteau
Contributor
kbrown
Posts: 19
Registered: ‎10-23-2012
Message 8 of 8 (170 Views)

Re : How To Calculate Angular Displacement of a Block (3D)

05-23-2014 10:08 AM in reply to: _gile

Sorry for not responding; I've been off work for a few days.

 

I made solving this problem much more complicated than it needed to be. I'm still at a novice level of understanding about many areas of the ACAD .net APIs. Sorry if I gave you a headache with this question. I can see how poorly constructed my question was now. In the future I will think more carefully before posting questions. I try not to make a habit of asking for help, prefering instead to rely on documentation and existing forum threads and the like.

 

To answer your most recent question, the reason I wanted the matrix represented as a set of scalar values is that I have a need to serialize the data for later use. The matrix3d class does not appear to be serializable, though I have not looked into this. I just assumed it wasn't serializable because of the way the class is constructed.

 

Thanks again for your help,

 

Kevin

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.