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)
public void Initialize() {
App.Document doc = cad.DocumentManager.MdiActiveDocument;
Db.Database db = doc.Database;
Ed.Editor ed = doc.Editor;
using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
Db.BlockTable bt = tr.GetObject(db.BlockTableId, Db.OpenMode.ForRead) as Db.BlockTable;
List
<String> processed
= new List
<String>(); Db.BlockTableRecord btr = tr.GetObject(bt[Db.BlockTableRecord.ModelSpace],
Db.OpenMode.ForRead) as Db.BlockTableRecord;
Int32 count = GetReferencesCount(btr, ref processed);
ed.WriteMessage("\nCommon count of block references: {0}", count);
tr.Commit();
}
}
Int32 GetReferencesCount(Db.BlockTableRecord btr, ref List<String> processed) {
App.Document doc = cad.DocumentManager.MdiActiveDocument;
Db.Database db = doc.Database;
Ed.Editor ed = doc.Editor;
Int32 result = 0;
using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
foreach (Db.ObjectId id in btr.Cast<Db.ObjectId>()
.Where(n => !n.IsErased && n.IsValid && n.ObjectClass.Name
.Equals("AcDbBlockReference", StringComparison.CurrentCulture))) {
++result;
Db.BlockReference br = tr.GetObject(id, Db.OpenMode.ForRead) as Db.BlockReference;
if (!processed.Contains(br.Name)) {
Db.BlockTableRecord btr2 = tr.GetObject(br.BlockTableRecord, Db.OpenMode.ForRead)
as Db.BlockTableRecord;
processed.Add(br.Name);
result += GetReferencesCount(btr2, ref processed);
}
}
tr.Commit();
}
return result;
}
count of block references: 13
I've got expected value.
The second variant: full database iteration.
App.Document doc = cad.DocumentManager.MdiActiveDocument;
Db.Database db = doc.Database;
Ed.Editor ed = doc.Editor;
Int32 count = 0;
using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
Db.Handle handle = default(Db.Handle);
Db.ObjectId id = Db.ObjectId.Null;
for (Int64 i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++) {
handle
= new Db
.Handle(i
); Boolean result = db.TryGetObjectId(handle, out id);
if (result && id.IsValid && !id.IsErased && id.ObjectClass.Name
.Equals("AcDbBlockReference", StringComparison.CurrentCulture)) {
Db.BlockReference btr = tr.GetObject(id, Db.OpenMode.ForRead) as Db.BlockReference;
ed.WriteMessage("\nThe '{0}' block reference", btr.Name);
++count;
}
}
tr.Commit();
}
ed.WriteMessage("\nCommon block references count: {0}\n", count);
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.
App.Document doc = cad.DocumentManager.MdiActiveDocument;
Db.Database db = doc.Database;
Ed.Editor ed = doc.Editor;
Int32 count = 0;
using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
Db.BlockTable bt = tr.GetObject(db.BlockTableId, Db.OpenMode.ForRead) as Db.BlockTable;
foreach (Db.ObjectId id in bt) {
Db.BlockTableRecord btr = tr.GetObject(id, Db.OpenMode.ForRead) as Db.BlockTableRecord;
Db.ObjectIdCollection refs = btr.GetBlockReferenceIds(false, true);
ed.WriteMessage("\nCount of '{0}' references: {1}", btr.Name, refs.Count);
count += refs.Cast<Db.ObjectId>().Where(n=>n.IsValid && !n.IsErased).Count();
}
ed.WriteMessage("\nCommon count of block references: {0}", count);
tr.Commit();
}
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.