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

C#, Get Block at Point

9 REPLIES 9
SOLVED
Reply
Message 1 of 10
DirtyDanLand
3210 Views, 9 Replies

C#, Get Block at Point

In C#, what would be the best way to get a block inserted at a specified point?

I am trying to get attributes from a block inserted at the endpoint of a polyline.  The endpoints of the polyline and the blockname are known.

 

I just can not figure out how to get the block.  Once I get the block I know how to get the attributes.

 

Thanks

Dan

9 REPLIES 9
Message 2 of 10
DirtyDanLand
in reply to: DirtyDanLand

I should mention that I need to be able to do this without having the user select the block.
Message 3 of 10
DirtyDanLand
in reply to: DirtyDanLand

With some help from this site, this is what I came up with...  Wondering, if there is a better way?

 

            using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
            {

                BlockTable acBlkTble = tr.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;

                foreach (ObjectId btrObjId in acBlkTble)
                {
                    BlockTableRecord btr = tr.GetObject(btrObjId, OpenMode.ForRead) as BlockTableRecord;

                    ObjectIdCollection objIdColl = btr.GetBlockReferenceIds(true, true);

                    foreach (ObjectId objId_loopVariable in objIdColl)
                    {
                        BlockReference blk = (BlockReference)tr.GetObject(objId_loopVariable, OpenMode.ForRead);
                        blockName = blk.Name.ToUpper();

                        if (blockName.IndexOf("WIRE-END") != -1)
                        {
                            pntBlockOrigin = blk.Position;
                            if (pntBlockOrigin == pntPolyBeg)
                            {
                                //get the attributes
                                AttributeCollection attCol = blk.AttributeCollection;
                                foreach (ObjectId attId in attCol)
                                {
                                    AttributeReference attRef = (AttributeReference)tr.GetObject(attId, OpenMode.ForRead);

                                    switch (attRef.Tag.ToUpper())
                                    {
                                        case "END-ID":
                                            attBegValue[0] = attRef.TextString;
                                            break;
                                        case "END-TERM":
                                            attBegValue[1] = attRef.TextString;
                                            break;
                                    }
                                }
                            }
                            else if (pntBlockOrigin == pntPolyEnd)
                            {
                                //get the attributes
                                AttributeCollection attCol = blk.AttributeCollection;
                                foreach (ObjectId attId in attCol)
                                {
                                    AttributeReference attRef = (AttributeReference)tr.GetObject(attId, OpenMode.ForRead);

                                    switch (attRef.Tag.ToUpper())
                                    {
                                        case "END-ID":
                                            attEndValue[0] = attRef.TextString;
                                            break;
                                        case "END-TERM":
                                            attEndValue[1] = attRef.TextString;
                                            break;
                                    }
                                }
                            }

                        }
                    }
                }
                tr.Commit();
            }
Message 4 of 10
fieldguy
in reply to: DirtyDanLand

Create a pair of Point3D objects that define a window.  P3D1 will be bottom right, and P3D2 will be top left.  I use the term "aperture" - the last value I used was 20 metres.  This creates a window that is 40 metres square, with your endpoint in the centre.

 

double aperture = 20.0;

Point3d P3D1 = new Point3d(yourpolylineendpoint.X - aperture, yourpolylineendpoint.Y - aperture, 0);
Point3d P3D2 = new Point3d(yourpolylineendpoint.X + aperture, yourpolylineendpoint.Y + aperture, 0);

 

Define a typedvalue and selection filter for "INSERT".

acdb.TypedValue[] values = { new acdb.TypedValue((int)acdb.DxfCode.Start, "INSERT") };
SelectionFilter sf = new SelectionFilter(values);

 

Create a prompt for select crossing window using your new points.
PromptSelectionResult psr = doc.Editor.SelectCrossingWindow(P3D1, P3D2, sf);

 

Check the status and see if there are any inserts within the window.

if (psr.Status == PromptStatus.OK && psr.Value.Count > 0)
{

  acdb.ObjectIdCollection psrobjids = new acdb.ObjectIdCollection(psr.Value.GetObjectIds());
foreach (acdb.ObjectId oid in psrobjids)
{
acdb.BlockReference myblk = (acdb.BlockReference)tx.GetObject(oid, acdb.OpenMode.ForRead);
if (myblk.Name == "the block you are looking for")
{
  // do what you need to do
  // break;
}
}

}

 

 <edit>

I am not sure if this way is any better than your last post.  It looks like that works as well.  Your way will work even if the block is not visible in the editor.  I believe that object selection using window crossing implies that the object is visible in the editor window. If that's correct, your way is better.

</edit> 

Message 5 of 10
DirtyDanLand
in reply to: fieldguy

thanks for the reply... the only problem is I can not have anything else getting selected since my palette and the information it receives is based on a single selected polyline. It would create more of a headache iterating through the selected objects since the polyline needs to stay selected.

Message 6 of 10
fieldguy
in reply to: DirtyDanLand

The user selection and your program selection are not the same.  The user is not involved with (and does not see) the crossing window selection. 

Message 7 of 10
DirtyDanLand
in reply to: fieldguy

I did not know that, thanks...

Message 8 of 10
_gile
in reply to: DirtyDanLand

Hi,

 

The GetBlockReferenceIds() route is fine, but your code can be optimized:

- get directly the block table record in the block table using its name instead of scaning the whole block table ;

- exit the foreach loop as soon as a matching position block is found.

 

            using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
            {
                BlockTable acBlkTble = tr.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;

                // directly get the record in the table using its name
                BlockTableRecord btr = tr.GetObject(acBlkTble["WIRE-END"], OpenMode.ForRead) as BlockTableRecord;

                foreach (ObjectId objId_loopVariable in btr.GetBlockReferenceIds(true, true))
                {
                    BlockReference blk = (BlockReference)tr.GetObject(objId_loopVariable, OpenMode.ForRead);

                    if (blk.Position == pntPolyBeg)
                    {
                        //get the attributes
                        AttributeCollection attCol = blk.AttributeCollection;
                        foreach (ObjectId attId in attCol)
                        {
                            AttributeReference attRef = (AttributeReference)tr.GetObject(attId, OpenMode.ForRead);

                            switch (attRef.Tag.ToUpper())
                            {
                                case "END-ID":
                                    attBegValue[0] = attRef.TextString;
                                    break;
                                case "END-TERM":
                                    attBegValue[1] = attRef.TextString;
                                    break;
                            }
                        }
                        break; // exit the foreach loop as soon as the block is found
                    }
                    else if (blk.Position == pntPolyEnd)
                    {
                        //get the attributes
                        AttributeCollection attCol = blk.AttributeCollection;
                        foreach (ObjectId attId in attCol)
                        {
                            AttributeReference attRef = (AttributeReference)tr.GetObject(attId, OpenMode.ForRead);

                            switch (attRef.Tag.ToUpper())
                            {
                                case "END-ID":
                                    attEndValue[0] = attRef.TextString;
                                    break;
                                case "END-TERM":
                                    attEndValue[1] = attRef.TextString;
                                    break;
                            }
                        }
                        break;  // exit the foreach loop as soon as the block is found
                    }
                }
                tr.Commit();
            }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 10
DirtyDanLand
in reply to: _gile

thanks for the tip...

Message 10 of 10
Anonymous
in reply to: _gile

Just keep in mind that

btr.GetBlockReferenceIds(true, true)

will return a 0 on a dynamic block.

_gile himself talks about how to fetch dynamic blocks on a more recent post:

https://forums.autodesk.com/t5/net/blockreferenceids-is-sometimes-empty/m-p/7044001#M53047

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

Post to forums  

Forma Design Contest


Autodesk Design & Make Report