The WblockClone API doesn’t guarantee draw order when Blocks are cloned ,wblockclone is very low level function ,it does only copying of entities ,the high-level functionality likes preserving draw order should be explicitly implement by application developer.
The above screenshots display correct and incorrect draw orders when wblock clone is perform ,to preserve order same a source block ,we need to use drawordertable API to sort entities as per source block.
C++ Code :
static void ADSKMyGroupWTEST()
{
Acad::ErrorStatus es;
TCHAR fullpath[_MAX_PATH];
int ret = acedFindFile(_T("C:\VESSELBLOCKS.dwg"),
fullpath );
if ( ret != RTNORM )
return;
AcDbDatabase *pSrcDb = new AcDbDatabase( false, false );
es = pSrcDb->readDwgFile( fullpath, _SH_DENYNO );
if ( es != Acad::eOk )
{
acutPrintf( _T("nCan not open file.") );
delete pSrcDb;
return;
}
AcApDocument *pActiveDoc
= acDocManager->mdiActiveDocument();
AcDbDatabase *pDestDb
= pActiveDoc->database();
AcDbObjectIdArray objIds2Copy;
AcDbBlockTable *pBlockTable,*pBlockTable2;
es = pSrcDb->getSymbolTable(pBlockTable, AcDb::kForRead);
AcDbObjectId recordId = AcDbObjectId::kNull;
es = pBlockTable->getAt(ACRX_T("CP_STERN_SY"), recordId, AcDb::kForRead);
objIds2Copy.append(recordId);
es = pBlockTable->close();
AcDbIdMapping idMap;
es = pSrcDb->wblockCloneObjects(objIds2Copy,
acdbSymUtil()->blockModelSpaceId(pDestDb),
idMap, AcDb::kDrcReplace);
if(es == Acad::eOk)
{
acutPrintf( _T("nCloned the block to the current drawing.") );
AcDbObjectId targetBlockId = AcDbObjectId::kNull;
es = pDestDb->getSymbolTable(pBlockTable2, AcDb::kForRead);
es = pBlockTable2->getAt(ACRX_T("CP_STERN_SY"),
targetBlockId,
AcDb::kForRead);
SetBlockDrawOrder(recordId,targetBlockId,idMap);
es = pBlockTable2->close();
}
else
acutPrintf( _T("nFailed to clone the block to the current drawing.") );
delete pSrcDb;
}
static void SetBlockDrawOrder(AcDbObjectId srcBlockId,
AcDbObjectId targetBlockId,
AcDbIdMapping& idMap)
{
AcDbBlockTableRecord *pSrcBlock = NULL;
acdbOpenObject(pSrcBlock,
srcBlockId,
AcDb::kForRead);
AcDbSortentsTable *pSortTab1 = NULL;
pSrcBlock->getSortentsTable(pSortTab1,
AcDb::kForRead,
true);
AcDbObjectIdArray oids;
pSortTab1->getFullDrawOrder(oids);
pSortTab1->close();
pSrcBlock->close();
AcDbBlockTableRecord *pTargetBlock = NULL;
acdbOpenObject(pTargetBlock,
targetBlockId,
AcDb::kForRead);
AcDbSortentsTable *pSortTab2 = NULL;
pTargetBlock->getSortentsTable(pSortTab2,
AcDb::kForWrite,
true);
AcDbObjectIdArray targetIds;
int len = oids.length();
for(int cnt = 0; cnt < len; cnt++)
{
AcDbIdPair idPair(oids.at(cnt),
AcDbObjectId::kNull,
true);
if (idMap.compute (idPair))
targetIds.append(idPair.value());
}
pSortTab2->setRelativeDrawOrder(targetIds);
pSortTab2->close();
pTargetBlock->close();
}
.NET Code :
[CommandMethod("WTEST")]
public void MyWTEST()
{
string blockName = "CP_STERN_SY";
string pathDWG = "C:\VESSELBLOCKS.dwg";
var doc = Application.DocumentManager.MdiActiveDocument;
using (Database OpenDb = new Database(false, false))
{
OpenDb.ReadDwgFile(pathDWG,
System.IO.FileShare.ReadWrite,
true, "");
ObjectIdCollection ids = new ObjectIdCollection();
BlockTable bt;
ObjectId sourceBlockId = ObjectId.Null;
using (Transaction tr =
OpenDb.TransactionManager.StartTransaction())
{
bt = (BlockTable)tr.GetObject(OpenDb.BlockTableId,
OpenMode.ForRead);
if (bt.Has(blockName))
{
ids.Add(bt[blockName]);
sourceBlockId = bt[blockName];
}
if (ids.Count != 0)
{
Database destdb = doc.Database;
IdMapping iMap = new IdMapping();
OpenDb.WblockCloneObjects(ids,
destdb.BlockTableId,
iMap,
DuplicateRecordCloning.Replace,
false);
using (Transaction t =
destdb.TransactionManager.StartTransaction())
{
ObjectId targetBlockId = ObjectId.Null;
BlockTable b = (BlockTable)t.GetObject(destdb.BlockTableId,
OpenMode.ForRead);
if (b.Has(blockName))
{
targetBlockId = b[blockName];
}
SetBlockDrawOrder(sourceBlockId, targetBlockId, iMap);
t.Commit();
}
}
tr.Commit();
}
}
}
public void SetBlockDrawOrder(ObjectId sourceBlockId,
ObjectId targetBlockId,
IdMapping iMap)
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction t = db.TransactionManager.StartTransaction())
{
var sourceBTR =
(BlockTableRecord)t.GetObject(sourceBlockId,
OpenMode.ForRead);
var dotSource =
(DrawOrderTable)t.GetObject(sourceBTR.DrawOrderTableId,
OpenMode.ForRead, true);
ObjectIdCollection srcDotIds = new ObjectIdCollection();
srcDotIds = dotSource.GetFullDrawOrder(0);
var targetBTR =
(BlockTableRecord)t.GetObject(targetBlockId,
OpenMode.ForRead);
var dotTarget =
(DrawOrderTable)t.GetObject(targetBTR.DrawOrderTableId,
OpenMode.ForWrite, true);
ObjectIdCollection trgDotIds = new ObjectIdCollection();
foreach (ObjectId oId in srcDotIds)
{
if (iMap.Contains(oId))
{
IdPair idPair = iMap.Lookup(oId);
trgDotIds.Add(idPair.Value);
}
}
dotTarget.SetRelativeDrawOrder(trgDotIds);
t.Commit();
}
}

Leave a Reply to Nick GorlovCancel reply