Author Topic: Different block references count. Why?  (Read 2933 times)

0 Members and 1 Guest are viewing this topic.

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Different block references count. Why?
« on: March 01, 2013, 04:01:41 AM »
The attached Blocks.dwg file contains some block definitions, and their instances (block references). Some block definitions contains block references as a content. It is necessary to count the common count of block references. I thought the task is very simple, but I was mistaken, as I see... Through different ways I've got the different results.

Common count of block references is 13, as I see:

- Block_2 definition contains two Block_1 instances.
- Block_3 definition contains one Block_2 instance, and one Block_1 instance.
 - Model namespace contains 9 block instances.

Common block references count is: 9 + 2 + 2 = 13.

 I have tried three ways of decision.

The first variant: the recursive processing (Model Space only, for this case)
Code - C#: [Select]
  1. public void Initialize() {            
  2.     App.Document doc = cad.DocumentManager.MdiActiveDocument;
  3.     Db.Database db = doc.Database;
  4.     Ed.Editor ed = doc.Editor;            
  5.     using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  6.         Db.BlockTable bt = tr.GetObject(db.BlockTableId, Db.OpenMode.ForRead) as Db.BlockTable;  
  7.         List<String> processed = new List<String>();
  8.         Db.BlockTableRecord btr = tr.GetObject(bt[Db.BlockTableRecord.ModelSpace],
  9.             Db.OpenMode.ForRead) as Db.BlockTableRecord;
  10.         Int32 count = GetReferencesCount(btr, ref processed);
  11.         ed.WriteMessage("\nCommon count of block references: {0}", count);
  12.         tr.Commit();
  13.     }
  14. }
  15.  
  16. Int32 GetReferencesCount(Db.BlockTableRecord btr, ref List<String> processed) {
  17.     App.Document doc = cad.DocumentManager.MdiActiveDocument;
  18.     Db.Database db = doc.Database;
  19.     Ed.Editor ed = doc.Editor;
  20.     Int32 result = 0;
  21.     using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {              
  22.         foreach (Db.ObjectId id in btr.Cast<Db.ObjectId>()
  23.             .Where(n => !n.IsErased && n.IsValid && n.ObjectClass.Name
  24.         .Equals("AcDbBlockReference", StringComparison.CurrentCulture))) {
  25.             ++result;                    
  26.             Db.BlockReference br = tr.GetObject(id, Db.OpenMode.ForRead) as Db.BlockReference;
  27.             if (!processed.Contains(br.Name)) {
  28.                 Db.BlockTableRecord btr2 = tr.GetObject(br.BlockTableRecord, Db.OpenMode.ForRead)
  29.                     as Db.BlockTableRecord;
  30.                 processed.Add(br.Name);
  31.                 result += GetReferencesCount(btr2, ref processed);
  32.             }
  33.         }
  34.         tr.Commit();
  35.     }
  36.     return result;
  37. }
  38.  
Quote from: Output result
count of block references: 13
I've got expected value.

The second variant: full database iteration.
Code - C#: [Select]
  1. App.Document doc = cad.DocumentManager.MdiActiveDocument;
  2. Db.Database db = doc.Database;
  3. Ed.Editor ed = doc.Editor;
  4. Int32 count = 0;
  5. using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  6.     Db.Handle handle = default(Db.Handle);
  7.     Db.ObjectId id = Db.ObjectId.Null;
  8.     for (Int64 i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++) {
  9.         handle = new Db.Handle(i);
  10.         Boolean result = db.TryGetObjectId(handle, out id);
  11.         if (result && id.IsValid && !id.IsErased && id.ObjectClass.Name
  12.             .Equals("AcDbBlockReference", StringComparison.CurrentCulture)) {
  13.             Db.BlockReference btr = tr.GetObject(id, Db.OpenMode.ForRead) as Db.BlockReference;
  14.             ed.WriteMessage("\nThe '{0}' block reference", btr.Name);
  15.             ++count;
  16.         }
  17.     }
  18.     tr.Commit();
  19. }
  20. ed.WriteMessage("\nCommon block references count: {0}\n", count);
  21.  
Quote from: Output result
The 'Block_1' block reference
The 'Block_2' block reference
The 'Block_3' block reference
The 'Block_1' block reference
The 'Block_2' block reference
The 'Block_2' block reference
The 'Block_3' block reference
The 'Block_3' block reference
The 'Block_1' block reference
The 'Block_1' block reference
The 'Block_2' block reference
The 'Block_1' block reference
The 'Block_1' block reference
Common block references count: 13

I've got expected value again.

The third variant: through the BlockTableRecord.GetBlockReferenceIds method.
Code - C#: [Select]
  1. App.Document doc = cad.DocumentManager.MdiActiveDocument;
  2. Db.Database db = doc.Database;
  3. Ed.Editor ed = doc.Editor;
  4. Int32 count = 0;
  5. using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  6.     Db.BlockTable bt = tr.GetObject(db.BlockTableId, Db.OpenMode.ForRead) as Db.BlockTable;
  7.     foreach (Db.ObjectId id in bt) {
  8.         Db.BlockTableRecord btr = tr.GetObject(id, Db.OpenMode.ForRead) as Db.BlockTableRecord;
  9.         Db.ObjectIdCollection refs = btr.GetBlockReferenceIds(false, true);
  10.         ed.WriteMessage("\nCount of '{0}' references: {1}", btr.Name, refs.Count);
  11.         count += refs.Cast<Db.ObjectId>().Where(n=>n.IsValid && !n.IsErased).Count();
  12.     }
  13.     ed.WriteMessage("\nCommon count of block references: {0}", count);
  14.     tr.Commit();
  15. }
  16.  
Quote from: Output result
Count of '*Model_Space' references: 0
Count of '*Paper_Space' references: 0
Count of '*Paper_Space0' references: 0
Count of 'Block_1' references: 13
Count of 'Block_2' references: 7
Count of 'Block_3' references: 3
Common count of block references: 23

I've expected to get the 13, but I got other value, as I see...

I think the third variant counts the count of displayed items. But at this case I expect 27 items:
- 18 items of Block_1
- 6 items of Block_2
- 3 items of Block_3

Common count is 18 + 6 + 3 = 27. But I got the 23 items through my code (the third variant).

Why I've got the 23 items at my third variant?

Regards, Andrey.
« Last Edit: March 01, 2013, 07:18:28 AM by Andrey »

TheMaster

  • Guest
Re: Different block references count. Why?
« Reply #1 on: March 03, 2013, 04:25:31 PM »

Why I've got the 23 items at my third variant?

Regards, Andrey.

If the first argument to GetBlockReferenceIds() is true, it returns the ids of insertions of any BlockTableRecord whose definition contains an insertion of the BlockTableRecord the method is invoked on.

In other words, if 'A' contains an insertion of 'B', and you call GetBlockReferenceIds(true, false) on the BlockTableRecord of 'B', it returns the ids of all insertions of 'A' and 'B' because 'A' contains an insertion of 'B'.

Perhaps what you're trying to do is count how many insertions you can see, as opposed to the number of physical BlockReferences.

In that case, see the attached file.

« Last Edit: March 04, 2013, 03:08:11 AM by TT »