Реализация мультикопирования объектов с изюминкой
В недавнем запросе, разработчик упомянул о поведении команды _COPY в AutoCAD , которое, как я думаю, немного отличается от того, как ведут себя остальные команды. В команде _COPY, когда выбран режим мультикопирования, выбраны примитивы для копирования и после указания базовой точки AutoCAD размещает копии выбранных объектов. Но если нажать Enter, то мы как правило ожидаем прекращения команды, как и в большинстве других команд AutoCAD. Но в случае с командой _COPY , нажатие на клавишу Enter трактуется как "использовать первую точку в качестве смещения" и появляется новая копия до завершения команды.
Если вас не устраивает такое поведение, то возможно вам потребуется создать свою команду для копирования нескольких примитивов. Вот пример кода, который реализует это с помощью ObjectARX API и предоставляется в качестве Lisp-функции. Кроме того, при перетаскивании объектов позиция ограничена по оси X так же, как и координатный фильтр .YZ для родной команды _COPY.
Вот код:
- // Глобальная переменная, так что мы сможем использовать её
- // в функции обратного вызова DragGen...
- AcGePoint3d basePt;
- // Здесь фунция обратного вызова
- static int dragGenCallback(ads_point pt,ads_matrix mt)
- {
- //AcGeVector3d vec(pt[0]-basePt[0],
- // pt[1]-basePt[1], pt[2]-basePt[2]);
- // Ограничиваем движение только осью X
- AcGeVector3d vec(pt[0]-basePt[0], 0, 0);
- AcGeMatrix3d mat;
- // Устанавливаем матрицу для преобразования координат
- mat.setToTranslation(vec);
- // Помещаем результаты в mt
- for (int c=0;c<4;c++)
- {
- for (int cd=0;cd<4;cd++)
- mt[c][cd]=mat(c,cd);
- }
- return RTNORM;
- }
- int CopyMultipleEntitiesFunc()
- {
- ads_name ss;
- // Выбираем примитивы
- acedSSGet(NULL, NULL, NULL, NULL, ss);
- // Указываем базовую точку длякопирования...
- acedGetPoint(NULL,
- L"Укажите базовую точку: " ,
- asDblArray(basePt));
- long len;
- acedSSLength(ss,&len);
- int ret = 0;
- do
- {
- // Значение последней точки
- // после того как пользователь закончил
- // перетаскивание набора
- AcGePoint3d final_pt;
- // Вызываем DragGen с функцией обратного вызова
- ret = acedDragGen(ss,
- L"\nУкажите вторую точку" ,
- 0,
- dragGenCallback,
- asDblArray(final_pt));
- if (ret == RTNONE || ret == RTCAN)
- {// Нажато ENTER или ESC
- break ;
- }
- // Получаем итоговую мтрицу и выполняем копирование
- // используя значение final_pt
- AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
- AcDbObjectIdArray idArr;
- {
- long l=0, lNumber=0;
- ads_sslength(ss, &lNumber);
- idArr.setPhysicalLength(lNumber);
- for (; l<lNumber; ++l)
- {
- ads_name ent;
- ads_ssname(ss, l, ent);
- AcDbObjectId idEnt;
- if (Acad::eOk == acdbGetObjectId(idEnt,ent))
- {
- idArr.append(idEnt);
- }
- }
- AcDbIdMapping idMapping;
- AcDbObjectId idOwner = acdbSymUtil()->blockModelSpaceId (pDb);
- Acad::ErrorStatus es =
- curDoc()->database()->deepCloneObjects(idArr, idOwner, idMapping);
- if (es == Acad::eOk)
- {
- AcDbIdMappingIter iter2 (idMapping) ;
- AcDbIdPair idPair2 ;
- for ( iter2.start ();
- !iter2.done ();
- iter2.next () )
- {
- if ( !iter2.getMap (idPair2) )
- continue ;
- if ( !idPair2.isCloned () )
- continue ;
- AcDbObjectId keyId = idPair2.key();
- AcDbObjectId valueId = idPair2.value();
- // Трансформируем клоны согласно матрицы
- // Открываем для записи
- AcDbEntity *pEnt;
- acdbOpenAcDbEntity(pEnt, valueId, AcDb::kForWrite);
- AcGeMatrix3d dispmat = AcGeMatrix3d::kIdentity;
- dispmat.setToTranslation(
- AcGeVector3d(final_pt[0]-basePt[0], 0, 0));
- pEnt->transformBy(dispmat);
- pEnt->close();
- }
- }
- }
- }while (TRUE);
- ads_ssfree(ss);
- return 0;
- }
- class CMyTest1App : public AcRxArxApp
- {
- public :
- CMyTest1App () : AcRxArxApp ()
- {
- }
- virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt)
- {
- AcRx::AppRetCode retCode
- =AcRxArxApp::On_kInitAppMsg (pkt) ;
- acedDefun(_T("CopyMultiple" ), 1000);
- acedRegFunc(CopyMultipleEntitiesFunc, 1000);
- return (retCode) ;
- }
- virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt)
- {
- AcRx::AppRetCode retCode = AcRxArxApp::On_kUnloadAppMsg (pkt) ;
- acedUndef(_T("CopyMultiple" ),1000);
- return (retCode) ;
- }
- virtual void RegisterServerComponents()
- {
- }
- };
Так это выгдядит:
Источник: http://adndevblog.typepad.com/autocad/2015/04/implementing-copy-multiple-entities-with-a-twist-.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=2697
Опубликовано 12.05.2015