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

07/07/2015

Выбор точки на 3DSolid при выборе примитива

Функция acedEntSel даёт возможность пользователю выбрать примитив и также позволяет получить точку, которая была указана при выборе примитива. Когда эту функцию используют с 2D-примитивом, тока возвращаемая acedEntSel очень удобна в случае если нужна информация для таких задач как РАЗОРВАТЬ (Break), ОБРЕЗАТЬ (Trim) и т.д. 

Однако если acedEntSel используется с 3DSolid, точка возвращается в плоскости XY текущей ПСК вне зависимости от того где указали точку на 3DSolid. Если включена объектная привязка (OSNAP) при выборе примитива, тогда точка будет на поверхности 3DSolid. Если важно получить точку на 3DSolid, которая использовалась при выборе объекта именно при помощи кода, то можно использовать следующий алгоритм:

В следующем коде создаётся луч (Ray) вдоль направления взгляда и находятся все точки пересечения луча с 3DSolid. Код показывает все точки пересечения. Но первая точка пересечения будет именно той точкой, которую выбрал пользователь.

Необходимо отметить, что в AutoCAD 2015 и AutoCAD 2016, метод "AcBrBrep::getLineContainment" возвращает меньшее количество точек пересечения при тесте. Это поведение передано для изучения и исправления команде инженер. AutoCAD 2014 и предыдущие возвращают правильное количество точек.

Ниже записанное видео и пример кода:

 

 

Код - C++: [Выделить]
  1. static void SelectOn3dSolid()
  2. {
  3.   Acad::ErrorStatus es;
  4.  
  5.   // pt - это точка в ПСК, а точнее в плоскости XY ПСК 
  6.   // если не включены привязки при выборе объекта
  7.   // В этом случае у точки есть все три координаты в ПСК 
  8.   ads_name  ename;
  9.   ads_point pt;
  10.   int  ret = acedEntSel(_T("\nУкажите 3DSOLID : " ), ename, pt);
  11.   if  (ret != RTNORM)
  12.     return ;
  13.  
  14.   AcDbObjectId entId = AcDbObjectId::kNull;
  15.   es = acdbGetObjectId(entId, ename);
  16.  
  17.   AcDbEntity *pEnt = NULL;
  18.   AcDb3dSolid *pSolid = NULL;
  19.   es = acdbOpenAcDbEntity(pEnt, entId, AcDb::kForRead);
  20.   pSolid = AcDb3dSolid::cast(pEnt);
  21.   if (pSolid == NULL)
  22.   {
  23.     acutPrintf(L"\nВыбранный объект не 3DSOLID.\\n" );
  24.     return ;
  25.   }
  26.  
  27.   // Получаем координату в МСК для выбранной точки
  28.   AcGePoint3d wcsPt = AcGePoint3d::kOrigin;
  29.   acdbUcs2Wcs(pt, pt, 0);
  30.   wcsPt = asPnt3d(pt);
  31.  
  32.   resbuf viewRb;
  33.  
  34.   AcGePoint3d  target = AcGePoint3d::kOrigin;
  35.   // Получаем Цель (TARGET) в ПСК
  36.   acedGetVar(_T("TARGET" ), &viewRb);
  37.   target = asPnt3d(viewRb.resval.rpoint);
  38.   acdbUcs2Wcs(asDblArray(target), asDblArray(target), 0);
  39.  
  40.   AcGeVector3d dir = AcGeVector3d::kIdentity;
  41.   // Направление взгляда (VIEWDIR) в ПСК
  42.   acedGetVar( ACRX_T("VIEWDIR" ), &viewRb );
  43.   dir = asVec3d(viewRb.resval.rpoint);
  44.   acdbUcs2Wcs(asDblArray(dir), asDblArray(dir), 1);
  45.   AcGePoint3d  position = target + dir;
  46.   dir = dir.normalize().negate();
  47.  
  48.   AcGeLine3d testRay(
  49.     wcsPt.project(AcGePlane(position, dir), dir.negate()),
  50.     dir);
  51.  
  52.   AcBrBrep* pBrep = new  AcBrBrep();
  53.   pBrep->setSubentPath(AcDbFullSubentPath( pEnt->objectId(), AcDbSubentId()));
  54.  
  55.   AcBr::ErrorStatus bres;
  56.   AcBrHit *pHits = NULL;
  57.   Adesk::UInt32 nHitsFound = 0;
  58.   // Находим все пересечения
  59.   bres = pBrep->getLineContainment(testRay, 0, nHitsFound, pHits );
  60.   if (bres == AcBr::eOk)
  61.   {
  62.     for ( Adesk::UInt32 i = 0; i < nHitsFound; i++)
  63.     {
  64.       AcBrEntity *pHitEntity = NULL;
  65.       pHits[i].getEntityHit( pHitEntity );
  66.       if ( pHitEntity == NULL )
  67.         continue ;
  68.  
  69.       if ( ! pHitEntity->isKindOf(AcBrBrep::desc()))
  70.       {
  71.         AcGePoint3d hitPt;  pHits[i].getPoint(hitPt);
  72.  
  73.         AcDbPoint *pDbPt = new  AcDbPoint(hitPt);
  74.         PostToDb(pDbPt);
  75.         es = pDbPt->close();
  76.       }
  77.       delete  pHitEntity;
  78.     }
  79.     delete [] pHits;
  80.   }
  81.   delete  pBrep;
  82.  
  83.   pEnt->close();
  84.  
  85. }

 

Источник: http://adndevblog.typepad.com/autocad/2015/06/selected-point-on-solid-during-entity-selection.html

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

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

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