I am making a call to acadDoc.ModelSpace.InsertBlock()
Then I want to get the newly inserted block and rotate it on a specific axis.
I see that InsertBlock returns an AcadBlockReference object, but if I try a Rotate3D() or TransformBy() on it, then I get this error:
************* Exception Text **************
System.ArgumentException: Value does not fall within the expected range.
at Autodesk.AutoCAD.Interop.Common.AcadBlockReferenceClass.Rotate3D(Object Point1, Object Point2, Double RotationAngle)
As a different test, I am able to create a new box from a Solid3d object and use Transform By() on it, so as an alternative, is there a way to get my AcadBlockReference to behave like a Solid3d?
Does it have anything to with UCS coordinates?
thanks.
TransformBy is a member of the Entity Class, and so is Inherited by All things derived from Entity.
I don't understand what you are getting at. AcadBlockReference is derived from Entity correct?
But calling TransformBy() off of the AcadBlockReference object that comes back from InsertBlock() causes the error about the value not in the expected range.
Sorry, I glazed over the first part of your post too quickly and didn't notice the COM objects. using the AcadBlockReference is completely different than the managed BlockReference object. The Solid3D object is a managed object, so the TransformBy that you call on a Solid3D object is different from the TransformBy on a COM object.
The Rotate3D method says it wants Object for the first two arguments, but my (very old) COM code used to pass a 3 element array of Double for each point parameter. That code was ported to .NET from VBA in ACAD 2007, and was completely migrated to the managed API by 2009.
the COM TransformBy method says it wants object as well, but if you have successfully used the Managed Solid3D.TransformBy Method then you must have managed to create the Matrix3D object required by that function. If so, you could try creating a Matrix3d object and passing Matrix3d.ToArray to the COM TransformBy function.
I know that Rotate3D works, so the problem must be in the way you are passing the args. If none of this helps solve the problem, you should post the pertinent lines of code.
No problem.. thanks for the help so far. I tried the ToArray with TansformBy() and creating Object Arrays for Rotated3D.. bothe had erros as shown below. Note: My AddBlock() function calls InsertBlock() and returns what it returns.
Here is the relative part of the code:
AcadBlockReference BlockRef;
BlockRef = AddBlock("beam1", "crossbars", new Point3d(0, Tip_Radius, HeightAboveGL), new Scale3d(Length, Width, Height));
AcadEntity ent = BlockRef as AcadEntity;
Matrix3d mtrx = Matrix3d.Rotation(45, Vector3d.YAxis, new Point3d(0, 0, 0));
BlockRef.TransformBy(mtrx.ToArray()); // ERROR: System.Runtime.InteropServices.COMException (0x8021000F): Incorrect SafeArray dimension
Object[] array1 = new Object[3];
Object[] array2 = new Object[3];
array1[0]=0;
array1[1]=0;
array1[2]=0;
array2[0]=0;
array2[1]=0;
array2[2]=0;
BlockRef.Rotate3D(array1, array2, 45); // ERROR: Value does not fall within the expected range.
I'm not sure about the Incorrect SafeArray dimension.
As far as the Rotate3D, if you are actually passing (0,0,0) to both points, then you are creating a Zero Length Axis of rotation, which shouldn't work. To duplicate the Matrix3D you have shown with a axis of rotation = Y-Axis, pass (0,1,0) as the second point.
Just in case the (0,0,0)'s are a by-product of you editing down your code for posting, I'll take a step back and return to your original question:
is there a way to get my AcadBlockReference to behave like a Solid3d?
You can use the .FromAcadObject method to get an ObjectID for the managed object, then open it with a transaction (which returns DBObject, you'll have to cast it up to Entity in C#) Then you can use the TransformBy method with a Matrix3D argument just like with Solid3D.
Dim ObjID As ObjectId = Entity.FromAcadObject(BlockRef)
Using trans As Transaction = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction
Dim dbObj As DBObject = trans.GetObject(ObjID, OpenMode.ForWrite, False, True)
Dim ent As Entity = CType(dbObj, Entity)
ent.TransformBy(mtrx)
....
the forum garbled my Paste
Thank you so much! I got it working (after some confusion becuase I needed to use radians and not degrees). I had actually something similar a few days ago but it was with an AcadEntity not just Entity, (so close). Anyway here is the function I ended up with:
public static void RotateObject(AcadBlockReference BlockRef, Double Angle, Vector3d Axis, Point3d RotationPoint)
{
if (Angle < 0)
Angle += 360;
Angle = Angle * PI / 180; // Convert from Degrees to Radians
Matrix3d mtrx = Matrix3d.Rotation(Angle, Axis, RotationPoint);
ObjectId ObjID = Entity.FromAcadObject(BlockRef);
using (Transaction trans = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
{
DBObject dbObj = trans.GetObject(ObjID, OpenMode.ForWrite, false, true);
Entity ent = (Entity)dbObj;
ent.TransformBy(mtrx);
trans.Commit();
}
}