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

21/05/2015

Преобразование AcDbObjectIdArray в IAcadSelectionSet

Недавно я получил запрос от партнера ADN как передать массив ObjectID в Export COM API. Проблема заключается в том, что необходимо преобразование из C++ в COM

Прототип функции Export в COM описывается так :

Export ( /*[in]*/ BSTR FileName, /*[in]*/ BSTR Extension, /*[in]*/ struct IAcadSelectionSet * SelectionSet ) = 0;

Ей передаётся имя файла, расширение файла и IAcadSelectionSet – набор примитивов, тогда как у нас есть массив ObjectId.

Поставим перед собой цель выполнить экспорт набора примитивов в BMP-файл.

Для этого мы:

- Получим массив ObjectId, получим для каждого из элементов IAcadEntity исползуя глобальную функцию AcAxGetIUnknownOfObject.
- Добавляем IAcadEntity к AcadSelectionSet при помощи метода AddItems
- Используем AcadSelectionSet в Export API

Пример кода:

Код - C++: [Выделить]
  1. void TestExport()
  2. {
  3.   ads_name ss;
  4.   AcDbObjectIdArray* pIdArray = new AcDbObjectIdArray();
  5.   // Получаем набор примитивов
  6.   int res = acedSSGet (NULL, NULL, NULL, NULL, ss);
  7.   if (res == RTNORM)
  8.   {
  9.     // Получаем количество элементов в наборе
  10.     long length = 0l;
  11.     acedSSLength (ss, &length);
  12.     // Цикл по всем элементам
  13.     for (long i= 0l; i < length; ++i)
  14.     {
  15.       ads_name ename;
  16.       // Получаем имя примитива (ename)
  17.       if (acedSSName (ss, i, ename) != RTNORM)
  18.         continue;
  19.  
  20.       AcDbObjectId objId;
  21.       // Преобразуем ename в ObjectId
  22.       acdbGetObjectId (objId, ename);
  23.       pIdArray->append(objId);
  24.     }
  25.   }
  26.  
  27.   /* Экспортируем выбранные примитивы в BMP-файл */
  28.  
  29.   ExportToFile(pIdArray);
  30.  
  31.   // освобождаем набор после его использования
  32.   acedSSFree (ss);
  33.   delete pIdArray;
  34. }
  35.  
  36. //////////////////////////////////////////////////////////////////////////
  37. //                        Вспомогательные функции
  38. //////////////////////////////////////////////////////////////////////////
  39.  
  40. /* Помещаем AcadEntity в заданный IAcadSelectionSet */
  41. HRESULT addToSelSet(AutoCAD::IAcadSelectionSet* pSelSet, AutoCAD::IAcadEntity* pEntity)
  42. {
  43.   HRESULT hr;
  44.   SAFEARRAYBOUND rgsabound[1];
  45.   rgsabound[0].lLbound = 0;
  46.   rgsabound[0].cElements = 1;
  47.   SAFEARRAY* psa = SafeArrayCreateVector(VT_DISPATCH, rgsabound->lLbound, rgsabound->cElements);
  48.   if(!psa) return E_OUTOFMEMORY;
  49.  
  50.   long i = 0;
  51.   LPDISPATCH pDisp = pEntity;
  52.   pEntity->Release();
  53.  
  54.   /*
  55.   Эта функция назначает единичный элемент массива.
  56.   */
  57.  
  58.   /*
  59.   Типы вариантов VT_DISPATCH, VT_UNKNOWN, и VT_BSTR являются
  60.   указателями и не требуют разименования.
  61.   */
  62.  
  63.   hr = SafeArrayPutElement(psa, &i,pDisp);
  64.   if( FAILED(hr) )
  65.   {
  66.     SafeArrayDestroy(psa);
  67.     return hr;
  68.   }
  69.  
  70.   VARIANT v;
  71.   VariantInit(&v);
  72.   v.vt = VT_DISPATCH|VT_ARRAY;
  73.   v.parray = psa;
  74.   return pSelSet->AddItems(v);
  75. }
  76.  
  77. /* Получаем набор или создаём его, если его еще нет */
  78.  
  79. AutoCAD::IAcadSelectionSet *GiveMeSelectionSet(AutoCAD::IAcadSelectionSets *pSelSets, BSTR Name)
  80. {
  81.   try {
  82.     AutoCAD::IAcadSelectionSet *pSet = NULL;
  83.     if (pSelSets->Add(Name,&pSet) == S_OK) {
  84.       return pSet;
  85.     } else if (pSelSets->Item(_variant_t(Name),&pSet) == S_OK) {
  86.       return pSet;
  87.     } else return NULL;
  88.   } catch(...) {
  89.     return NULL;
  90.   }
  91.   return NULL;
  92. }
  93.  
  94. void ExportToFile(AcDbObjectIdArray*&  pIdArray)
  95. {
  96.   HRESULT hr;
  97.   try
  98.   {
  99.     AutoCAD::IAcadApplication *pAcad =NULL;
  100.     AutoCAD::IAcadDocument *pDoc =NULL;
  101.     AutoCAD::IAcadModelSpace *pMSpace = NULL;
  102.     AutoCAD::IAcadSelectionSets *pSelSets = NULL;
  103.     AutoCAD::IAcadSelectionSet *pSet= NULL;
  104.     hr = NOERROR;
  105.     LPUNKNOWN pUnk = NULL;
  106.     LPDISPATCH pAcadDisp = acedGetIDispatch(TRUE);
  107.  
  108.     if(pAcadDisp == NULL)
  109.       return ;
  110.  
  111.     hr = pAcadDisp->QueryInterface(AutoCAD::IID_IAcadApplication,(void**)&pAcad);
  112.     pAcadDisp->Release();
  113.  
  114.     if (FAILED(hr))
  115.       return;
  116.  
  117.     if (pAcad)
  118.     {
  119.       if (pAcad->get_ActiveDocument(&pDoc) == S_OK)
  120.       {
  121.         if (pDoc->get_SelectionSets(&pSelSets) == S_OK) {
  122.           /* Получаем или создаём набор */
  123.           if ((pSet = GiveMeSelectionSet(pSelSets,_bstr_t("TestSet"))) != NULL)
  124.           {
  125.             pSet->Clear();
  126.             for (int i = 0; i < pIdArray->length(); i++)
  127.             {
  128.               AcDbObjectId id = pIdArray->at(i);
  129.               // Получаем COM-обертку для примитива
  130.               if(FAILED(hr = AcAxGetIUnknownOfObject(&pUnk, id, pAcadDisp)))
  131.                 throw (_com_error(hr));
  132.               // Получаем AutoCAD::IAcadEntity
  133.               AutoCAD::IAcadEntity *pEnt = NULL;
  134.               if(FAILED(hr= pUnk->QueryInterface(AutoCAD::IID_IAcadEntity, (void **)&pEnt)))
  135.                 throw (_com_error(hr));
  136.               /* Добавляем примитив к набору */
  137.               if (FAILED(hr = addToSelSet(pSet,pEnt)))
  138.                 throw(_com_error(hr)) ;
  139.             }
  140.  
  141.             if (FAILED(hr = pDoc->Export(_bstr_t("c:\\temp\\test"),_bstr_t("BMP"),pSet)))
  142.               throw(_com_error(hr)) ;
  143.             pSet->Release();
  144.           }
  145.  
  146.           else
  147.             return ;
  148.  
  149.           pSelSets->Release();
  150.         }
  151.         pDoc->Release();
  152.       }
  153.       pAcad->Release();
  154.     }
  155.     pUnk->Release();
  156.   }
  157.   catch (...)
  158.   {
  159.     return ;
  160.   }
  161.   return ;
  162. }

Источник: http://adndevblog.typepad.com/autocad/2015/05/converting-acdbobjectidarray-to-iacadselectionset.html

Автор перевода: Александр Ривилис

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

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