Base Point Location of Block Reference

Base Point Location of Block Reference

Anonymous
Not applicable
8,022 Views
23 Replies
Message 1 of 24

Base Point Location of Block Reference

Anonymous
Not applicable


I am having trouble getting the "Base Point" of a Block Reference in autocad. I am not sure if base point is the correct terminology or not.





If I perform a LIST command on a Block Reference in autocad the values for the location are the same as if I use the BlockReference.Position in .NET



i.e.



External reference

at point, X=128170.18580000 Y=44629.83387360 Z=26037.43318039

X scale factor: 1.00000000

Y scale factor: 1.00000000

Z scale factor: 1.00000000

Extrusion direction relative to UCS:

X=0.00000000 Y=-0.25881731 Z=0.96592629





However if i use a LISP command (entget (car (entsel))) I get different values in the dxf code 10 position. The values that I get here, are the ones that I want to get in .NET.



i.e.

Select object: ((-1 . <Entity name: -51963e98>) (0 . "INSERT") (5 . "29F5")

(102 . "{ACAD_XDICTIONARY") (360 . <Entity name: -51963e90>) (102 . "}") (330 .

<Entity name: -4011f2f8>) (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 .

"ADE_TEMP") (100 . "AcDbBlockReference") (2 . "T61-5-2-0103") (10 128170.0

49848.1 13599.3) (41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 1.5708) (70 . 0) (71 .

0) (44 . 0.0) (45 . 0.0) (210 0.0 -0.258817 0.965926))





Does anyone know the equivalent .NET command to get the Block References original insertion point (base point) which is the same as a the DXF 10 code?





In VBA I have noticed there is a object.BasePoint property however I do not know how to convert this to .NET.





Cheers,





Kate



0 Likes
8,023 Views
23 Replies
Replies (23)
Message 2 of 24

chiefbraincloud
Collaborator
Collaborator
The position property is the correct property. Your issue of seeing different data from the entity data is likely to be related to the UCS not being world, in which case you just use the coordinate system translation matrix to convert the point from one UCS to the other. There are several posts on this forum which describe how to do that.
Dave O.                                                                  Sig-Logos32.png
0 Likes
Message 3 of 24

Anonymous
Not applicable
I have had a look around today and I think my question is now -

How do I translate the position of the block reference to what it was before the blockRef.Normal was applied.

So I place the block Reference at the correct position
I change the block reference's extrusion using Blockref.Normal which in turn gives it a new position.

I need the original position of the block for my comparision. So i need to somehow "undo" the extrusion I have applied without manipulating the block.

Im nearly certain I am doing all my calcualtion in WCS and position is in WCS, but I also dont really know what I'm doing 🙂

I can post code if it will help in anyway.

Cheers,

Kate
0 Likes
Message 4 of 24

Anonymous
Not applicable
Perhaps you can tell us what it is you ultimately are trying to do,
since there may be easier ways.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message news:[email protected]...

I am having trouble getting the "Base Point" of a Block Reference in
autocad. I am not sure if base point is the correct terminology or not.







If I perform a LIST command on a Block Reference in autocad the values for
the location are the same as if I use the BlockReference.Position in .NET



i.e.





External reference

at point, X=128170.18580000 Y=44629.83387360 Z=26037.43318039

X scale factor: 1.00000000

Y scale factor: 1.00000000

Z scale factor: 1.00000000

Extrusion direction relative to UCS:

X=0.00000000 Y=-0.25881731 Z=0.96592629







However if i use a LISP command (entget (car (entsel))) I get different
values in the dxf code 10 position. The values that I get here, are the ones
that I want to get in .NET.



i.e.

Select object: ((-1 . ) (0 . "INSERT") (5 . "29F5")

(102 . "{ACAD_XDICTIONARY") (360 . ) (102 . "}")
(330 .

) (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 .

"ADE_TEMP") (100 . "AcDbBlockReference") (2 . "T61-5-2-0103") (10 128170.0

49848.1 13599.3) (41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 1.5708) (70 . 0) (71
..

0) (44 . 0.0) (45 . 0.0) (210 0.0 -0.258817 0.965926))







Does anyone know the equivalent .NET command to get the Block References
original insertion point (base point) which is the same as a the DXF 10
code?







In VBA I have noticed there is a object.BasePoint property however I do not
know how to convert this to .NET.







Cheers,







Kate
0 Likes
Message 5 of 24

Anonymous
Not applicable
Basically what is happening is we have a database store of Block Reference information, my application places the Xreferences according to the values we have stored and then monitors if the position/rotation/scale/extrusion of the Block Ref changes if the user accidently moves the item. If the item changes the Application alerts the user.

The values we have stored are the initial Position of the object and any manipulation values of the object i.e. scale, rotation. Once the extrusion (3d rotate) of the item has been applied (using BlockRef.Normal), the position of the Block Ref (BlockRef.Position) changes which then appears as an alert in my application which is incorrect. The value that we store, and the value I need to do my comparison against is the original position the item was placed in, or the original insertion point of the object before 3d rotate occurred.

When a user then commits the changes of the block reference back to our database, I need to store the values to recreate the current location of the object. So I need to store the position before the 3d rotate has occured so I can then recreate the position again by apply the series of values we store.
0 Likes
Message 6 of 24

Anonymous
Not applicable
The insertion point returned by LISP's (entget) is in OCS (Object Coordinate
System) coords.

The Position property of the BlockReference is in WCS coords.

To translate from one to the other, you can use the transformation matrix
returned by the BlockReference's 'Ecs' property.

You use the Point3d's TransformBy() method to do the transformation:

{code}

BlockReference blkref = // set to a valid BlockReference

// Transform from WCS to OCS
Point3d OcsPosition =
blkRef.Position.TransformBy(blkref.Ecs.Inverse() );

// Transform from OCS to WCS:
Point3d WcsPosition = OcsPosition.TransformBy(blkref.Ecs);

{code}

Using something like the above, OcsPosition should have the same value
returned by the LISP (entget) function.

If you're storing coordinates in an external datasource, it would probably
be better to store WCS coordinates rather than OCS coordinates, as that
would eliminate the need to do any transformations.



--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message news:[email protected]...
Basically what is happening is we have a database store of Block Reference
information, my application places the Xreferences according to the values
we have stored and then monitors if the position/rotation/scale/extrusion of
the Block Ref changes if the user accidently moves the item. If the item
changes the Application alerts the user. The values we have stored are the
initial Position of the object and any manipulation values of the object
i.e. scale, rotation. Once the extrusion (3d rotate) of the item has been
applied (using BlockRef.Normal), the position of the Block Ref
(BlockRef.Position) changes which then appears as an alert in my application
which is incorrect. The value that we store, and the value I need to do my
comparison against is the original position the item was placed in, or the
original insertion point of the object before 3d rotate occurred. When a
user then commits the changes of the block reference back to our database, I
need to store the values to recreate the current location of the object. So
I need to store the position before the 3d rotate has occured so I can then
recreate the position again by apply the series of values we store.
0 Likes
Message 7 of 24

Anonymous
Not applicable
Thanks for your help Tony.

I tried what you suggested however I still seem to be getting the same values. I used your example above and got the same values for both OcsPosition and WcsPosition.

If i inspect the blockRef.BlockTransform.Inverse().Translation property, the values I want are there however they are in the wrong positions with the wrong +/-.
i.e.
- Translation {(-49848.06833,128170.1858,-13599.2677)} Autodesk.AutoCAD.Geometry.Vector3d
LargestElement 1 int
Length 138193.22170864654 double
LengthSqrd 19097366526.215137 double
X -49848.06833 double
Y 128170.1858 double
Z -13599.267700000006 double


Instead of transforming by the Ecs, should I be using the BlockTransform somehow?
0 Likes
Message 8 of 24

Anonymous
Not applicable
The OCS and WCS coordinates are the same if the block lies in the XY plane
and its normal is 0,0,1.

You'll need to post a drawing and some sample code.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message news:[email protected]...
Thanks for your help Tony. I tried what you suggested however I still seem
to be getting the same values. I used your example above and got the same
values for both OcsPosition and WcsPosition. If i inspect the
blockRef.BlockTransform.Inverse().Translation property, the values I want
are there however they are in the wrong positions with the wrong +/-. i.e. -
Translation {(-49848.06833,128170.1858,-13599.2677)}
Autodesk.AutoCAD.Geometry.Vector3d LargestElement 1 int Length
138193.22170864654 double LengthSqrd 19097366526.215137 double
X -49848.06833 double Y 128170.1858 double Z -13599.267700000006 double
Instead of transforming by the Ecs, should I be using the BlockTransform
somehow?
0 Likes
Message 9 of 24

SEANT61
Advisor
Advisor
I think I see the issue you’re describing. The attached sample code continues with the BlockTransform method to retrieve coordinates as would be shown by group code 10.

It does seem like a more elegant solution should be available, however.

************************************************************
May your cursor always snap to the location intended.
0 Likes
Message 10 of 24

Anonymous
Not applicable
I have attached the original drawing and will attach the drawing that I have Xref'd the drawing into in the next post ( I seem to be only able to attach one drawing).

My code for placing the object is as follows.
The values that are in item are -
Extrusion
CoordinateX 0.0 double
CoordinateY -0.25881731 double
CoordinateZ 0.96592629 double
refPoint {(128170.1858,49848.06833,13599.2677)} Autodesk.AutoCAD.Geometry.Point3d
X 128170.1858 double
Y 49848.06833 double
Z 13599.2677 double
Rotation 90.0 double
ScaleX 1.0 double
ScaleY 1.0 double
ScaleZ 1.0 double


{code}
// Get and store the current layer string
string savedCurLayer = (string)CADApplicationServices.Application.GetSystemVariable("CLAYER");
// Get and store the current ucs
Matrix3d savedUCS = currentDoc.Editor.CurrentUserCoordinateSystem;
currentDoc.Editor.CurrentUserCoordinateSystem = Matrix3d.Identity;

reference = new CADDatabaseServices.BlockReference(refPoint, xrefId);

reference.Rotation = Math.PI * item.Rotation / 180.00;
reference.ScaleFactors = new Scale3d(item.ScaleX, item.ScaleY, item.ScaleZ);

var v = new Vector3d(item.Extrusion.CoordinateX, item.Extrusion.CoordinateY, item.Extrusion.CoordinateZ);
reference.Normal = v;

// Make the original layer active again:
CADApplicationServices.Application.SetSystemVariable("CLAYER", savedCurLayer);

// Restore the UCS:
currentDoc.Editor.CurrentUserCoordinateSystem = savedUCS;

record.AppendEntity(reference);
trans.AddNewlyCreatedDBObject(reference, true);
SetLayerForBlock(layerName, reference);

ExtensionData.WriteBlockXRecord(reference, item);

trans.Commit();
{code}

I then try and read the values back from the block once the item has been placed. BlockRef is a valid block Reference.
The values I am getting are -
+ OcsPosition {(128170.1858,44629.8338736,26037.4331803939)} Autodesk.AutoCAD.Geometry.Point3d
+ WcsPosition {(128170.1858,44629.8338736,26037.4331803939)} Autodesk.AutoCAD.Geometry.Point3d
+ zero {(0,0,0)} Autodesk.AutoCAD.Geometry.Point3d
+ GCTp3d {(49848.06833,-128170.1858,13599.2677)} Autodesk.AutoCAD.Geometry.Point3d

The values for the GCTp3d are the correct values, just in the wrong order and +/-.

{code}
CADApplicationServices.Document currentDoc = CADApplicationServices.Application.DocumentManager.MdiActiveDocument;
Matrix3d savedUCS = currentDoc.Editor.CurrentUserCoordinateSystem;
currentDoc.Editor.CurrentUserCoordinateSystem = Matrix3d.Identity;

blockInDrawing.XReference = blockRef.Name;

// Transform from WCS to OCS -- this gives me the same values as blockRef.Position
Point3d OcsPosition = blockRef.Position.TransformBy(blockRef.Ecs.Inverse());

// Transform from OCS to WCS -- this gives me the same values as blockRef.Position
Point3d WcsPosition = OcsPosition.TransformBy(blockRef.Ecs);

//this gives me the correct values, but in the wrong positions with the wrong +/-
Point3d zero = new Point3d();
Point3d GCTp3d = zero - zero.TransformBy(blockRef.BlockTransform.Inverse()).GetAsVector();

blockInDrawing.InsertionPoint.CoordinateX = Math.Round(GCTp3d.X, 8);
blockInDrawing.InsertionPoint.CoordinateY = Math.Round(GCTp3d.Y, 8);
blockInDrawing.InsertionPoint.CoordinateZ = Math.Round(GCTp3d.Z, 8);
//blockInDrawing.InsertionPoint.CoordinateX = Math.Round(blockRef.Position.X, 8);
//blockInDrawing.InsertionPoint.CoordinateY = Math.Round(blockRef.Position.Y, 8);
//blockInDrawing.InsertionPoint.CoordinateZ = Math.Round(blockRef.Position.Z, 8);

blockInDrawing.ScaleX = blockRef.ScaleFactors.X;
blockInDrawing.ScaleY = blockRef.ScaleFactors.Y;
blockInDrawing.ScaleZ = blockRef.ScaleFactors.Z;
blockInDrawing.Rotation = Math.Round(180.00 * blockRef.Rotation / Math.PI, 8);

blockInDrawing.Extrusion.CoordinateX = Math.Round(blockRef.Normal.X, 8);
blockInDrawing.Extrusion.CoordinateY = Math.Round(blockRef.Normal.Y, 8);
blockInDrawing.Extrusion.CoordinateZ = Math.Round(blockRef.Normal.Z, 8);

// Restore the UCS:
currentDoc.Editor.CurrentUserCoordinateSystem = savedUCS;
{code}

I dont actually use AutoCad at all, so I am not very familar with the way blocks get rotated etc. Hopefully this is something really basic that I am just missing.

Thanks for all your help 🙂

Kate Edited by: kwarmington on Apr 30, 2009 11:16 PM
0 Likes
Message 11 of 24

Anonymous
Not applicable
I have attached the file that I have Xref'd the block into using the code above.

Cheers,

Kate
0 Likes
Message 12 of 24

chiefbraincloud
Collaborator
Collaborator
From your earlier post: So I place the block Reference at the correct position I change the block reference's extrusion using Blockref.Normal {color:#0000ff}which in turn gives it a new position.{color}

I also have a lot of blocks that I insert with normals that are not (0,0,1), and I thought it worth mentioning that in my code I simply set the position property after setting the normal. Technically I'm Re-setting the position, since it is set first in the New constructor of BlockReference.
Dave O.                                                                  Sig-Logos32.png
0 Likes
Message 13 of 24

Anonymous
Not applicable
I have tried that, however the AutoCad guy here at work had a look at where the block had been placed, and said it was now in the wrong position.

The values we store are the WCS coordinates for the item. If I place the item and then apply the values for the Normal and then apply the position again, the block wont be in the correct position. It will have been placed, moved, and then moved again. The position that I'm placing the item in is correct (as far as I can tell), I just want to somehow read the values back where it was originally placed.
0 Likes
Message 14 of 24

SEANT61
Advisor
Advisor
Even more lacking in elegancy, but:

Point3d zero = new Point3d();

Point3d GCTp3d = zero - zero.TransformBy(br.BlockTransform.Inverse()).GetAsVector();//Crux

GCTp3d = GCTp3d.RotateBy(br.Rotation, new Vector3d(0.0,0.0,1.0),zero);

************************************************************
May your cursor always snap to the location intended.
0 Likes
Message 15 of 24

Anonymous
Not applicable
Thank you so much.

This has done the trick 🙂
0 Likes
Message 16 of 24

Anonymous
Not applicable
Oh for cry'n out loud.....

That has got to be the most long-winded, roundabout attempt to ask little
more than "how do I rotate a block reference about its insertion point, so
that its new normal is parallel to a given vector" ?

Sheesh !

http://www.caddzone.com/Rotate3d.cs

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message news:[email protected]...
Thank you so much. This has done the trick 🙂
0 Likes
Message 17 of 24

Anonymous
Not applicable
Thanks for putting up with my long winded question.

If only I knew that's what I wanted to ask, I could have saved everyone a heap of trouble.

Hopefully next time ill know what I'm trying to do 🙂
0 Likes
Message 18 of 24

Anonymous
Not applicable
Kate - No problem.

It's not uncommon for folks to first try to solve a problem themselves, and
then come here and make the mistake of describing the problem by presenting
their attempt to solve it.

In other words, you don't rotate an object by changing its Normal property,
you you just use its TransformBy() method with the required matrix, which
the sample I published shows how to get.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message news:[email protected]...
Thanks for putting up with my long winded question. If only I knew that's
what I wanted to ask, I could have saved everyone a heap of trouble.
Hopefully next time ill know what I'm trying to do 🙂
0 Likes
Message 19 of 24

SEANT61
Advisor
Advisor
Now the question is still in question, to me at least. Was the ultimate objective to change the orientation of the reference from how it is in “Drawing_with_xref.dwg”?

Or, to return a Point3d to use as comparison with a DXF Group code 10 reading, perhaps stored as some database entry?

************************************************************
May your cursor always snap to the location intended.
0 Likes
Message 20 of 24

Anonymous
Not applicable
i think it was to do :

> {quote:title=seant61 wrote:}{quote}
> Or, to return a Point3d to use as comparison with a DXF Group code 10 reading, perhaps stored as some database entry?

Which I achieved by the code you posted ( I am no longer at work and have not tried what Tony posted).

I didn't want to manipulate the block at all, only get the information to compare with the original placement values.
0 Likes