How to get the position of an nested block that changes size due to constraint parameter

How to get the position of an nested block that changes size due to constraint parameter

YYCad·Lover
Explorer Explorer
571 Views
2 Replies
Message 1 of 3

How to get the position of an nested block that changes size due to constraint parameter

YYCad·Lover
Explorer
Explorer

Hi. Thank you so much guys, for your help! this problem is bothering me.

Problem Description:
    1. I have a block "door" like a rectangle that has been shaped with automatic constraints;
    2. Then a vertical constraint parameter is built in the "Door" block: "Height", so the height is 500;
    3. In addition, an nested block like a cross is inserted: "coordinateBlock";
    4. Create a coincidence constraint on the top of the "Height" edge of "coordinateBlock" and "Door", such that the position is (0, 500);
    5. Insert the "Door" block reference in the new file through the C# API code, and modify the "Door" constraint parameter "Height" to change the block reference height, such as from 500 to 800;
    6. At this time, the position of the "coordinateBlock" has changed, and it has actually followed (0, 800);

 

Phenomenon:
    1. The display position of the nested block "coordinateBlock" in the "Door" block in model space has indeed become (0, 800);
    2. I have tried many methods, but I can't get the coordinate position (0, 800) after the "coordinateBlock" changes, but can only get the insert position (0, 500);

 

Question:
    1. Is there any way to get the position data of the inline block changed by constraints without explode the "Door" block;

 

Code I use:

Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
Editor ed = acDoc.Editor;
using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
    BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
    BlockTableRecord acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
    
    foreach (ObjectId acObjId in acBlkTblRec)
    {
        if (acObjId.ObjectClass.Name == "AcDbBlockReference")
        {
            BlockReference bf = acObjId.GetObject(OpenMode.ForRead) as BlockReference;
            string bname = (bf.IsDynamicBlock) ? (bf.DynamicBlockTableRecord.GetObject(OpenMode.ForRead) as BlockTableRecord).Name : bf.Name;
            
            if (bname.StartsWith("Door"))
            {
                if (bf.IsDynamicBlock)
                {
                    BlockTableRecord btr = bf.DynamicBlockTableRecord.GetObject(OpenMode.ForRead) as BlockTableRecord;
                    foreach (ObjectId item in btr)
                    {
                        if (item.ObjectClass.Name == "AcDbBlockReference")
                        {
                            BlockReference btf = item.GetObject(OpenMode.ForWrite) as BlockReference;
                            string tname = (btf.IsDynamicBlock) ? (btf.DynamicBlockTableRecord.GetObject(OpenMode.ForRead) as BlockTableRecord).Name : btf.Name;

                            if (tname.StartsWith("coordinateBlock"))
                            {
                                btf.Position; // here is not change (0, 200);
                            }
                        }
                    }
                }
            }
        }
    }
    acTrans.Commit();
}

 

0 Likes
Accepted solutions (1)
572 Views
2 Replies
Replies (2)
Message 2 of 3

tbrammer
Advisor
Advisor
Accepted solution

When you create a dynamic BREF with a defined parameter set, the BREF doesn't point to the original block but to an unnamed block.

I used the tool ArxDbg.arx from  <ARX>\\samples\database\ARXDBG to analyse TestBlock.dwg. 
Call SNOOPENTS and select the 800mm BREF shows this:

UnnamedDynBlock_SNOOPENTS.png

So you see the "real" block name is "*U7".

With SNOOPDB you can examine the block *U7:
UnnamedDynBlock_SNOOPDB.png

 

Expand the Block Table, select *U7 from the list and hit [Entities in Block].

There you find the BREF to "coordinateBlock" at position (0,800,0).

 

Unfortunately I can't tell you how to code this in C# - I'm more into C++.

But I think you can figure out how to do it.  

In C++ I would query the objectid of the BREF's blocktablerecord, open it and search for the nested BREF to "coordinateBlock" using an iterator.


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes
Message 3 of 3

YYCad·Lover
Explorer
Explorer

Thank you very much!

 

You gave me very important clues;


Since I am not very familiar with the mechanism of CAD internal block generation, it creates a new anonymous block for static blocks to show, I used the wrong way to get dynamic blocks to get static blocks;

 

And thank you for teaching me to use ArxDbg to view the internal relationship of graphics, this is very useful;

 

Finally, to share the API I found in C# to help others:


In C#, use `GetBlockReferenceIds` API to get all reference IDs of a static block, which I think are the created anonymous block IDs;

 

Code like:

BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[blockName], OpenMode.ForRead);
ObjectIdCollection blockIds = btr.GetBlockReferenceIds(true, true);
foreach (ObjectId id in blockIds)
{
    BlockReference block = (BlockReference)trans.GetObject(id, OpenMode.ForRead);
    // here can get block's position
}