Identifying specific block references

Identifying specific block references

mdoddKFBCF
Participant Participant
461 Views
4 Replies
Message 1 of 5

Identifying specific block references

mdoddKFBCF
Participant
Participant

We are creating an application where the drafters have created templates with blocks and we read data from a few sources and populate the block attributes with the correct data. To do this I have a separate windows exe app that gets all of the data and writes it to a JSON file then the AutoCAD command reads the JSON file and builds the drawing as required. To date, we have had single references to unique block definitions in each drawing. So, I've been able to search for the block def, get all references (only one), and then select the first item from the collection (of length 1).

But, what happens when I have more than one block reference to the same definition? How do I know it's the one I want? For instance, let's say I know that x, y, z should be in the block in the upper left and that a, b, and c data should be in the block in the lower right. I used relative coordinates in the example, but just as an example, I'd like something that can robustly determine the "correct" block for the data I have grabbed.

I've dug into this a bit and the best I can come up with is to have the drafters run the LIST command on a block and get me the HANDLE, which I could use to identify that block, but I'm unfamiliar with handles in AutoCAD and if they change as the drafters make changes to the drawings, or if they change each time I open a drawing.

Looking for advice here.

Below is some of the code that I am using, which I have received some help with already. These functions are inside of a class that has the database and transaction as instance variables. As you can see, I go and get all block references, but I also assume that I only get 1 back. If I get more than one I have no idea how to deal with it.

public void ProcessBlock(AcadBlockData block)
{
    BlockReference br = GetAcadBlockReference(block.Name);
    if (br != null)
    {
        if(block.Name == "VALVE_BODY")
        {
            SetDynamicPropertyValue(br, "Visibility1", block.Attributes["VALVE_TYPE"]);
        }
        ProcessBlockRefAttributes(br, block.Attributes);
    }
}

private BlockReference GetAcadBlockReference(string blockName)
{
    ObjectIdCollection ids = GetAllBlockReferences(blockName);
    return ids.Count > 0 ? (BlockReference)tr.GetObject(ids[0], OpenMode.ForWrite) : null;
}

private ObjectIdCollection GetAllBlockReferences(string blockName)
{
    var blockReferenceIds = new ObjectIdCollection();
    var bt = GetBlocktable();
    if (bt.Has(blockName))
    {
        var btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
        foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
        {
            blockReferenceIds.Add(id);
        }
        foreach (ObjectId anonymousBlockId in btr.GetAnonymousBlockIds())
        {
            var anonymousBtr = (BlockTableRecord)tr.GetObject(anonymousBlockId, OpenMode.ForRead);
            foreach (ObjectId id in anonymousBtr.GetBlockReferenceIds(true, false))
            {
                blockReferenceIds.Add(id);
            }
        }
    }
    return blockReferenceIds;
}

 

0 Likes
Accepted solutions (2)
462 Views
4 Replies
Replies (4)
Message 2 of 5

_gile
Consultant
Consultant
Accepted solution

Hi,

 

Using Handle is the reliable way to keep object identifiers outside of a DWG file.

A Handle is persitent and unique per drawing.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 5

mdoddKFBCF
Participant
Participant

Ok, that's unfortunate, but at least it gives us a path forward.

 

It begs another question though. If I know the handle is there a way for me to query the database directly for that block reference?

0 Likes
Message 4 of 5

norman.yuan
Mentor
Mentor
Accepted solution

The whole purpose of Handle is to be the ID of an object in drawing database, and ObjectId  is the same thing when drawing is loaded into AutoCAD. That is, when drawing is save as file, object's Handle persists and when drawing is loaded into AutoCAD, AutoCAD runtime will create an ObjectId, based on each Handle.

 

So, if you know the Handle, you can get the object's ObjectId, and then the object itself (BlockRefernece in your case):

 

var blkHandle=new Handle(long.Parse(handleString, NumberStyle.HexNumber));

if (db.TryGetObjectId(blkHandle, out ObjectId blkId))

{

  var blockReference=(BlockReference)tran.GetObject(blkId, OpenMode.ForRead);

  // Do work with the BlockReference

}

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 5 of 5

kerry_w_brown
Advisor
Advisor

Perhaps have a look at :

https://www.keanw.com/2007/02/getting_access_.html


// Called Kerry or kdub in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub
Sometimes the question is more important than the answer. ~ kdub

NZST UTC+12 : class keyThumper<T> : Lazy<T>;      another  Swamper
0 Likes