3dpolyline to 2dpolyline

Автор Тема: 3dpolyline to 2dpolyline  (Прочитано 8454 раз)

0 Пользователей и 2 Гостей просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Грасмик АлексейАвтор темы

  • ADN OPEN
  • Сообщений: 29
  • Карма: 0
3dpolyline to 2dpolyline
« : 21-05-2015, 06:26:56 »
коллеги, доброе утро, подскажите - если ли функция по конверсии трехмерной полилинии в двухмерную? или хотя бы что-то чтобы сделать трехмерную линию планарной.
есть такой момент, что порой трехмерная линия нарисована обсолютно в одной плоскости, но свойство isPlanar показывает, что она не планарна, а это плохо, так как регион с такой линии не сделать.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: 3dpolyline to 2dpolyline
« Ответ #1 : 21-05-2015, 10:47:48 »
Нашёл у себя старинный код. Надеюсь он тебе поможет. Предполагается, что 3dpoly лежит в плане МСК. Результирующая 2dpoly получается в любом случае в плане МСК. Исходная 3dpoly стирается.
Код - C++ [Выбрать]
  1. //-----------------------------------------------------------------------------
  2. //----- acrxEntryPoint.h
  3. //-----------------------------------------------------------------------------
  4. #include "StdAfx.h"
  5. #include "resource.h"
  6.  
  7. //-----------------------------------------------------------------------------
  8. #define szRDS _RXST("")
  9.  
  10. //-----------------------------------------------------------------------------
  11. //----- ObjectARX EntryPoint
  12. class CPolyApp : public AcRxArxApp {
  13.  
  14. public:
  15.         CPolyApp () : AcRxArxApp () {}
  16.  
  17.         virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
  18.                 AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
  19.                 return (retCode) ;
  20.         }
  21.  
  22.         virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
  23.                 AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
  24.                 return (retCode) ;
  25.         }
  26.  
  27.         virtual void RegisterServerComponents () {
  28.         }
  29.  
  30. public:
  31.   static Acad::ErrorStatus ObjectIdArrayFromSelSet(ads_name sset, AcDbObjectIdArray &ids)
  32.   {
  33.     Acad::ErrorStatus es = Acad::eOk;
  34.     long nset = -1;
  35.     if (acedSSLength(sset,&nset) != RTNORM) return Acad::eAmbiguousInput;
  36.     ids.setLogicalLength(nset);
  37.     ads_name en;
  38.     AcDbObjectId id;
  39.     for (long i=0; i < nset; i++) {
  40.       if (acedSSName(sset,i,en) == RTNORM) {
  41.         if ((es = acdbGetObjectId(id,en)) != Acad::eOk) return es;
  42.         ids[i] = id;
  43.       }
  44.     }
  45.     return Acad::eOk;
  46.   }
  47.  
  48.   static Acad::ErrorStatus postToDwgAndClose (AcDbEntity *pEnt, AcDbDatabase *pDb = NULL, ACHAR *requiredSpace = NULL)
  49.   {
  50.     // if the default database is to be used
  51.     if (pDb == NULL) {
  52.       pDb = acdbHostApplicationServices ()->workingDatabase ();
  53.     }
  54.  
  55.     AcDbBlockTable *blockTable = NULL;
  56.     // get a pointer to the block table
  57.     Acad::ErrorStatus es = pDb->getBlockTable (blockTable, AcDb::kForRead);
  58.     // if it failed then abort
  59.     if (es != Acad::eOk)
  60.       return (es);
  61.  
  62.     AcDbBlockTableRecord *blockTableRecord = NULL;
  63.     // now get a pointer to the model space entity records
  64.     if (requiredSpace)  {
  65.       es = blockTable->getAt (requiredSpace, blockTableRecord, AcDb::kForWrite);
  66.     } else {
  67.       es = acdbOpenObject(blockTableRecord, pDb->currentSpaceId(), AcDb::kForWrite);
  68.     }
  69.     // can close the block table itself as we don't need it anymore
  70.     blockTable->close ();
  71.     // if it failed then abort
  72.     if (es != Acad::eOk)
  73.       return (es);
  74.     // otherwise put the entity into the model space
  75.     es = blockTableRecord->appendAcDbEntity (pEnt);
  76.     // now close it up
  77.     blockTableRecord->close();
  78.     // close entity
  79.     pEnt->close();
  80.     return (es);
  81.   }
  82.  
  83.  
  84.   // - Poly.Poly3dto2d command (do not rename)
  85.   static void PolyPoly3dto2d(void)
  86.   {
  87.     resbuf *prbGrip = NULL, *prbPick = NULL;
  88.     ads_name sset_templ = { 0, 0};
  89.     long len_templ = 0;
  90.     AcDbObjectIdArray ids_set,ids_templ;
  91.     AcDbVoidPtrArray  ents_templ;
  92.     resbuf *filter = acutBuildList(-4,_T("<and"),RTDXF0,_T("POLYLINE"),-4,_T("&"),70,8,-4,_T("and>"),RTNONE);
  93.  
  94.     if (acedSSGetFirst(&prbGrip, &prbPick) == RTNORM && acedSSLength(prbPick->resval.rlname, &len_templ) == RTNORM && len_templ > 0) {
  95.       ObjectIdArrayFromSelSet(prbPick->resval.rlname,ids_templ);  acedSSFree(prbPick->resval.rlname);
  96.     }  else  {
  97.       TCHAR* promptPtrs[] = { _T("\nВыберите 3D-полилинии: "), _T("\nУдалите из выбранного: ") };
  98.       if (acedSSGet(_T(":$"),promptPtrs,NULL,filter,sset_templ) == RTNORM) {
  99.         ObjectIdArrayFromSelSet(sset_templ,ids_templ); acedSSFree(sset_templ);
  100.       }
  101.     }
  102.     acutRelRb(filter);
  103.     for (int i=0; i < ids_templ.length(); i++) {
  104.       AcDbObjectPointer<AcDb3dPolyline> poly3d(ids_templ[i],AcDb::kForWrite);
  105.       if (poly3d.openStatus() == Acad::eOk) {
  106.         AcGePoint3dArray pts; AcDbObjectIterator *pVtxIt = poly3d->vertexIterator();
  107.         if (pVtxIt) {
  108.           AcDbObjectId firstId = pVtxIt->objectId();
  109.           if(pVtxIt->objectId().isErased()) { // Пропускаем удалённые вершины
  110.             pVtxIt->step(); firstId = pVtxIt->objectId();
  111.           }
  112.           for (pVtxIt->setPosition(firstId); !pVtxIt->done(); pVtxIt->step()){
  113.             if(pVtxIt->objectId().isErased()) continue;
  114.             AcDbObjectPointer<AcDb3dPolylineVertex> pVt(pVtxIt->objectId(), AcDb::kForRead);
  115.             if (pVt.openStatus() != Acad::eOk) continue;
  116.             pts.append(pVt->position());
  117.           }
  118.           if (pts.length() > 1) {
  119.             AcDbPolyline *poly2d = new AcDbPolyline();
  120.             poly2d->setLayer(poly3d->layerId());
  121.             poly2d->setLinetype(poly3d->linetypeId());
  122.             poly2d->setLinetypeScale(poly3d->linetypeScale());
  123.             poly2d->setLineWeight(poly3d->lineWeight());
  124.             for (int iv=0; iv < pts.length(); iv++)
  125.               poly2d->addVertexAt(iv,asPnt2d(asDblArray(pts[iv])));
  126.             poly2d->setClosed(poly3d->isClosed());
  127.             postToDwgAndClose(poly2d);
  128.             poly3d->erase();
  129.           }
  130.           delete pVtxIt;
  131.         }
  132.       }
  133.     }
  134.   }
  135. } ;
  136.  
  137. //-----------------------------------------------------------------------------
  138. IMPLEMENT_ARX_ENTRYPOINT(CPolyApp)
  139.  
  140. ACED_ARXCOMMAND_ENTRY_AUTO(CPolyApp, Poly, Poly3dto2d, Poly3dto2d, ACRX_CMD_TRANSPARENT | ACRX_CMD_USEPICKSET, NULL)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Грасмик АлексейАвтор темы

  • ADN OPEN
  • Сообщений: 29
  • Карма: 0
Re: 3dpolyline to 2dpolyline
« Ответ #2 : 21-05-2015, 13:03:09 »
Ваш пример посмотрел - спасибо. это не совсем то, мне нужно иметь планарную полилинию в ее плоскости.
да тут обнаружилось еще подозрительнее место - даже полилиния из трех точек показывает, что она не планарна! как это возможно?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: 3dpolyline to 2dpolyline
« Ответ #3 : 21-05-2015, 13:09:42 »
как это возможно?
Возможно баг. Тебе же важно получить 2dpoly в плоскости 3dpoly. Ну алгоритм расписать не сложно. Находишь в 3dpoly три точки не лежашие на одной прямой и строишь по ним AcGePlane. Проецируешь на неё все точки 3dpoly. Ну и дальше по ним строишь 2dpoly. Сложностей не вижу.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Александр Ривилис 28-11-2016, 12:00:26

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: 3dpolyline to 2dpolyline
« Ответ #4 : 21-05-2015, 14:51:57 »
Я переписал функцию для работы с 3DPoly лежащей в любой плоскости. Считается что в ней не меньше трёх вершин и первые три вершины не лежат на одной прямой (т.е. однозначно определяют плоскость). Результирующая 2DPoly лежит в этой же плоскости и её вершины совпадают с вершинами 3DPoly в той степени, в которой вершины 3DPoly сами лежат в этой плоскости.
Код - C++ [Выбрать]
  1. // - Poly.Poly3dto2d command (do not rename)
  2. static void PolyPoly3dto2d(void)
  3. {
  4.   resbuf *prbGrip = NULL, *prbPick = NULL;
  5.   ads_name sset_templ = { 0, 0};
  6.   long len_templ = 0;
  7.   AcDbObjectIdArray ids_set,ids_templ;
  8.   AcDbVoidPtrArray  ents_templ;
  9.   resbuf *filter = acutBuildList(-4,_T("<and"),RTDXF0,_T("POLYLINE"),-4,_T("&"),70,8,-4,_T("and>"),RTNONE);
  10.  
  11.   if (acedSSGetFirst(&prbGrip, &prbPick) == RTNORM && acedSSLength(prbPick->resval.rlname, &len_templ) == RTNORM && len_templ > 0) {
  12.     ObjectIdArrayFromSelSet(prbPick->resval.rlname,ids_templ);  acedSSFree(prbPick->resval.rlname);
  13.   }  else  {
  14.     TCHAR* promptPtrs[] = { _T("\nВыберите 3D-полилинии: "), _T("\nУдалите из выбранного: ") };
  15.     if (acedSSGet(_T(":$"),promptPtrs,NULL,filter,sset_templ) == RTNORM) {
  16.       ObjectIdArrayFromSelSet(sset_templ,ids_templ); acedSSFree(sset_templ);
  17.     }
  18.   }
  19.   acutRelRb(filter);
  20.   for (int i=0; i < ids_templ.length(); i++) {
  21.     AcDbObjectPointer<AcDb3dPolyline> poly3d(ids_templ[i],AcDb::kForWrite);
  22.     if (poly3d.openStatus() == Acad::eOk) {
  23.       AcGePoint3dArray pts; AcDbObjectIterator *pVtxIt = poly3d->vertexIterator();
  24.       if (pVtxIt) {
  25.         AcDbObjectId firstId = pVtxIt->objectId();
  26.         if(pVtxIt->objectId().isErased()) { // Пропускаем удалённые вершины
  27.           pVtxIt->step(); firstId = pVtxIt->objectId();
  28.         }
  29.         for (pVtxIt->setPosition(firstId); !pVtxIt->done(); pVtxIt->step()){
  30.           if(pVtxIt->objectId().isErased()) continue;
  31.           AcDbObjectPointer<AcDb3dPolylineVertex> pVt(pVtxIt->objectId(), AcDb::kForRead);
  32.           if (pVt.openStatus() != Acad::eOk) continue;
  33.           pts.append(pVt->position());
  34.         }
  35.         delete pVtxIt;
  36.         if (pts.length() > 2) {
  37.           AcGePlane plan(pts[0],pts[1],pts[2]);
  38.           AcGeMatrix3d mat = AcGeMatrix3d::worldToPlane(plan);
  39.           AcDbPolyline *poly2d = new AcDbPolyline();
  40.           poly2d->setNormal(plan.normal());
  41.           poly2d->setLayer(poly3d->layerId());
  42.           poly2d->setLinetype(poly3d->linetypeId());
  43.           poly2d->setLinetypeScale(poly3d->linetypeScale());
  44.           poly2d->setLineWeight(poly3d->lineWeight());
  45.           for (int iv=0; iv < pts.length(); iv++) {
  46.             AcGePoint3d p = pts[iv]; p = p.transformBy(mat);
  47.             poly2d->addVertexAt(iv,asPnt2d(asDblArray(p)));
  48.           }
  49.           poly2d->setClosed(poly3d->isClosed());
  50.           AcGePoint3d pStart;  poly2d->getStartPoint(pStart);
  51.           mat.setToTranslation(pts[0] - pStart);
  52.           poly2d->transformBy(mat);
  53.           postToDwgAndClose(poly2d);
  54.           // poly3d->erase(); // для тестирования оставим пока
  55.         }
  56.       }
  57.     }
  58.   }
  59. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение