.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

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

7 REPLIES 7
SOLVED
Reply
Message 1 of 8
kbrown
1038 Views, 7 Replies

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

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

7 REPLIES 7
Message 2 of 8
_gile
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
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 8
kbrown
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

Message 4 of 8
_gile
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
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 8
kbrown
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

Message 6 of 8
kbrown
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

Message 7 of 8
_gile
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
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 8 of 8
kbrown
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

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost