ADN Open CIS
Сообщество программистов Autodesk в СНГ

24/11/2014

Сохранение порядка отрисовки примитивов при операции клонирования блоков

WblockClone API не гарантирует сохранение порядка отрисовки примитивов (DrawOrder) при клонировании блоков, т.к. операция WblockClone – это очень низкоуровневая операция, которая только копирует примитивы. Так что программисту придется самому позаботится о сохранении порядка отрисовки примитивов в блоке при его клонировании.

 

Эти картинки показывают правильный и неправильный порядок отрисовки примитивов в блоке в случае клонирования блока. Чтобы сохранить порядок отрисовки нам нужно воспользоваться DrawOrderTable API для сортировки примитивов в блоке.

C++ код :

Код - C++: [Выделить]
  1. static void ADSKMyGroupWTEST()
  2. {
  3.   Acad::ErrorStatus es;
  4.   TCHAR fullpath[_MAX_PATH];
  5.   int ret = acedFindFile(_T("C:\\VESSELBLOCKS.dwg"), fullpath );
  6.   if ( ret != RTNORM )
  7.     return;
  8.   AcDbDatabase *pSrcDb = new AcDbDatabase( false, false );
  9.   es = pSrcDb->readDwgFile( fullpath, _SH_DENYNO );
  10.   if ( es != Acad::eOk )
  11.   {
  12.     acutPrintf( _T("\nНе могу открыть файл.") );
  13.     delete pSrcDb;
  14.     return;
  15.   }
  16.  
  17.   AcApDocument *pActiveDoc = acDocManager->mdiActiveDocument();
  18.   AcDbDatabase *pDestDb = pActiveDoc->database();
  19.   AcDbObjectIdArray objIds2Copy;
  20.   AcDbBlockTable *pBlockTable,*pBlockTable2;
  21.   es = pSrcDb->getSymbolTable(pBlockTable, AcDb::kForRead);
  22.   AcDbObjectId recordId = AcDbObjectId::kNull;
  23.   es = pBlockTable->getAt(ACRX_T("CP_STERN_SY"), recordId, AcDb::kForRead);
  24.   objIds2Copy.append(recordId);
  25.   es = pBlockTable->close();
  26.  
  27.   AcDbIdMapping idMap;
  28.  
  29.   es = pSrcDb->wblockCloneObjects(objIds2Copy,
  30.     acdbSymUtil()->blockModelSpaceId(pDestDb),
  31.     idMap, AcDb::kDrcReplace);
  32.  
  33.   if (es == Acad::eOk)
  34.   {
  35.     acutPrintf( _T("\nКлонируем блок в текущий чертеж.") );
  36.     AcDbObjectId targetBlockId = AcDbObjectId::kNull;
  37.     es = pDestDb->getSymbolTable(pBlockTable2, AcDb::kForRead);
  38.     es = pBlockTable2->getAt(ACRX_T("CP_STERN_SY"), targetBlockId, AcDb::kForRead);
  39.     SetBlockDrawOrder(recordId,targetBlockId,idMap);
  40.     es = pBlockTable2->close();
  41.   }
  42.   else
  43.   {
  44.     acutPrintf(_T("\nОшибка при клонировании блока текущий чертеж."));
  45.   }
  46.   delete pSrcDb;
  47. }
  48.  
  49. static void SetBlockDrawOrder(AcDbObjectId srcBlockId,
  50.                               AcDbObjectId targetBlockId,
  51.                               AcDbIdMapping& idMap)
  52. {
  53.   AcDbBlockTableRecord *pSrcBlock = NULL;
  54.   acdbOpenObject(pSrcBlock, srcBlockId, AcDb::kForRead);
  55.   AcDbSortentsTable *pSortTab1 = NULL;
  56.   pSrcBlock->getSortentsTable(pSortTab1, AcDb::kForRead, true);
  57.   AcDbObjectIdArray oids;
  58.   pSortTab1->getFullDrawOrder(oids);
  59.   pSortTab1->close();
  60.   pSrcBlock->close();
  61.   AcDbBlockTableRecord *pTargetBlock = NULL;
  62.   acdbOpenObject(pTargetBlock, targetBlockId,  AcDb::kForRead);
  63.   AcDbSortentsTable *pSortTab2 = NULL;
  64.   pTargetBlock->getSortentsTable(pSortTab2, AcDb::kForWrite, true);
  65.   AcDbObjectIdArray targetIds;
  66.   int len = oids.length();
  67.   for(int cnt = 0; cnt < len; cnt++)
  68.   {
  69.     AcDbIdPair idPair(oids.at(cnt), AcDbObjectId::kNull, true);
  70.     if (idMap.compute (idPair)) targetIds.append(idPair.value());
  71.   }
  72.   pSortTab2->setRelativeDrawOrder(targetIds);
  73.   pSortTab2->close();
  74.   pTargetBlock->close();
  75. }

.NET код :

Код - C#: [Выделить]
  1. [CommandMethod("WTEST")]
  2. public void MyWTEST()
  3. {
  4.   string blockName = "CP_STERN_SY";
  5.   string pathDWG = "C:\\VESSELBLOCKS.dwg";
  6.   var doc = Application.DocumentManager.MdiActiveDocument;
  7.   using (Database OpenDb = new Database(false, false))
  8.   {
  9.     OpenDb.ReadDwgFile(pathDWG, System.IO.FileShare.ReadWrite, true, "");
  10.     ObjectIdCollection ids = new ObjectIdCollection();
  11.     BlockTable bt;
  12.     ObjectId sourceBlockId = ObjectId.Null;
  13.     using (Transaction tr = OpenDb.TransactionManager.StartTransaction())
  14.     {
  15.       bt = (BlockTable)tr.GetObject(OpenDb.BlockTableId, OpenMode.ForRead);
  16.       if (bt.Has(blockName))
  17.       {
  18.         ids.Add(bt[blockName]);
  19.         sourceBlockId = bt[blockName];
  20.       }
  21.       if (ids.Count != 0)
  22.       {
  23.         Database destdb = doc.Database;
  24.         IdMapping iMap = new IdMapping();
  25.         OpenDb.WblockCloneObjects(ids, destdb.BlockTableId,
  26.           iMap, DuplicateRecordCloning.Replace, false);
  27.         using (Transaction t = destdb.TransactionManager.StartTransaction())
  28.         {
  29.           ObjectId targetBlockId = ObjectId.Null;
  30.           BlockTable b = (BlockTable)t.GetObject(destdb.BlockTableId, OpenMode.ForRead);
  31.           if (b.Has(blockName))
  32.           {
  33.             targetBlockId = b[blockName];
  34.           }
  35.           SetBlockDrawOrder(sourceBlockId, targetBlockId, iMap);
  36.           t.Commit();
  37.         }
  38.       }
  39.       tr.Commit();
  40.     }
  41.   }
  42. }
  43.  
  44. public void SetBlockDrawOrder(ObjectId sourceBlockId,
  45.                               ObjectId targetBlockId,
  46.                               IdMapping iMap)
  47. {
  48.   Database db = HostApplicationServices.WorkingDatabase;
  49.   using (Transaction t = db.TransactionManager.StartTransaction())
  50.   {
  51.     var sourceBTR = (BlockTableRecord)t.GetObject(sourceBlockId, OpenMode.ForRead);
  52.     var dotSource = (DrawOrderTable)t.GetObject(sourceBTR.DrawOrderTableId,  OpenMode.ForRead, true);
  53.     ObjectIdCollection srcDotIds = new ObjectIdCollection();
  54.     srcDotIds = dotSource.GetFullDrawOrder(0);
  55.  
  56.     var targetBTR =  (BlockTableRecord)t.GetObject(targetBlockId, OpenMode.ForRead);
  57.  
  58.     var dotTarget =  (DrawOrderTable)t.GetObject(targetBTR.DrawOrderTableId, OpenMode.ForWrite, true);
  59.  
  60.     ObjectIdCollection trgDotIds = new ObjectIdCollection();
  61.  
  62.     foreach (ObjectId oId in srcDotIds)
  63.     {
  64.       if (iMap.Contains(oId))
  65.       {
  66.         IdPair idPair = iMap.Lookup(oId);
  67.         trgDotIds.Add(idPair.Value);
  68.       }
  69.     }
  70.     dotTarget.SetRelativeDrawOrder(trgDotIds);
  71.     t.Commit();
  72.   }
  73. }

Источник: http://adndevblog.typepad.com/autocad/2014/11/preserving-draworder-of-entities-while-wblockcloning-the-blocks.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=1103

Опубликовано 24.11.2014