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

31/03/2016

Конвертация AcDb3DSolid в AcDbPolyFaceMesh средствами ObjectARX

Вопрос: Стоит задача получить на основе AcDb3DSolid сеть AcDbPolyFaceMesh. Как это можно сделать?

Ответ: Ниже код, который позволяет это сделать. Возможны вариации в настройке AcBrMesh2dControl, определяющей насколько сеть будет повторять контуры твердого тела и какие элементы будут в основе этой сети.

Код - C++: [Выделить]
  1. //-----------------------------------------------------------------------------
  2. //----- acrxEntryPoint.cpp
  3. //-----------------------------------------------------------------------------
  4. #include "StdAfx.h"
  5. #include "resource.h"
  6.  
  7. //-----------------------------------------------------------------------------
  8. #define szRDS _RXST("")
  9.  
  10. //-----------------------------------------------------------------------------
  11. //----- ObjectARX EntryPoint
  12. class CMy3DSolidToPolyMeshApp : public AcRxArxApp {
  13.  
  14. public:
  15.   CMy3DSolidToPolyMeshApp () : 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.   static void Rivilis3DSolidToPolyMesh () {
  30.  
  31.     ads_name en; ads_point p;
  32.  
  33.     if (acedEntSel(_T("\nВыберите твердое тело: "), en, p) != RTNORM)
  34.       return;
  35.  
  36.     AcDbObjectId eid;
  37.     if (acdbGetObjectId(eid, en) != Acad::eOk)
  38.       return;
  39.  
  40.     AcDbObjectPointer<AcDb3dSolid> p3DSolid(eid, AcDb::kForRead);
  41.     if (p3DSolid.openStatus() == Acad::eWrongObjectType) {
  42.       acutPrintf(_T("\nЭто не твердое тело!"));
  43.       return;
  44.     }
  45.  
  46.     AcDbExtents ext; p3DSolid->getGeomExtents(ext);
  47.     double length = ext.minPoint().distanceTo(ext.maxPoint());
  48.  
  49.     AcBrBrep brp;
  50.  
  51.     AcBr::ErrorStatus ebr;
  52.     ebr = brp.set(*p3DSolid);
  53.     if (ebr != AcBr::eOk) {
  54.       acutPrintf(_T("\nОшибка br.set(*p3DSolid) = %d"), ebr);
  55.       return;
  56.     }
  57.  
  58.     AcBrMesh2dControl mc;
  59.     // Задаём максимальное расстояние между узлами
  60.     // mc.setMaxNodeSpacing( length / 100.0);
  61.     // Задаём максимальное количество элементов в сети.
  62.     // mc.setMaxSubdivisions(100000);
  63.     // Задаём максимальное отклонение точки
  64.     mc.setDistTol(length / 100.0);
  65.     // Задаём тип элементов - только треугольники
  66.     mc.setElementShape(AcBr::kAllTriangles);
  67.  
  68.     AcBrMesh2dFilter mf;
  69.     const AcBrEntity* meshEnt = (AcBrEntity*)&brp;
  70.     mf.insert(make_pair(meshEnt, mc));
  71.     AcBrMesh2d brepMesh;
  72.     if ((ebr = brepMesh.generate(mf)) != AcBr::eOk) {
  73.       acutPrintf(_T("\n Ошибка в AcBrMesh2d::generate %d"), ebr);
  74.       return;
  75.     }
  76.  
  77.     AcDbObjectPointer<AcDbPolyFaceMesh> pMesh; pMesh.create();
  78.     pMesh->setDatabaseDefaults();
  79.     pMesh->setColorIndex(2); // Пусть сеть будет желтая
  80.     AcDbBlockTableRecordPointer pBtr(acdbCurDwg()->currentSpaceId(), AcDb::kForWrite);
  81.     if (pBtr.openStatus() != Acad::eOk)
  82.       return;
  83.     pBtr->appendAcDbEntity(pMesh);
  84.  
  85.     int v0 = 0, v1 = 0, v2 = 0, v3 = 0;
  86.  
  87.     int iter = 0;
  88.     AcGePoint3dArray vertexLookup;
  89.     vertexLookup.setPhysicalLength(10000);
  90.     // Чтобы пропустить нулевой элемент
  91.     vertexLookup.append(AcGePoint3d::kOrigin);
  92.  
  93.     AcBrMesh2dElement2dTraverser meshElemTrav;
  94.  
  95.     for (ebr = meshElemTrav.setMesh(brepMesh); !meshElemTrav.done(); ebr = meshElemTrav.next()) {
  96.       if (ebr != AcBr::eOk) return;
  97.       AcBrElement2d e;   ebr = meshElemTrav.getElement(e);
  98.       AcBrElement2dNodeTraverser elemNodeTrav;
  99.       for (ebr = elemNodeTrav.setElement(e) ; !elemNodeTrav.done(); elemNodeTrav.next())  {
  100.         AcBrNode n;
  101.         ebr = elemNodeTrav.getNode(n);
  102.         AcGePoint3d p; n.getPoint(p);
  103.         if (!vertexLookup.contains(p)) {
  104.           AcDbObjectPointer<AcDbPolyFaceMeshVertex> pMeshVert;  pMeshVert.create();
  105.           pMeshVert->setPosition(p);
  106.           pMesh->appendVertex(pMeshVert);
  107.           vertexLookup.append(p);
  108.         }
  109.       }
  110.     }
  111.  
  112.     for (ebr = meshElemTrav.setMesh(brepMesh); !meshElemTrav.done(); ebr = meshElemTrav.next()) {
  113.       if (ebr != AcBr::eOk) return;
  114.       AcBrElement2d e;   ebr = meshElemTrav.getElement(e);
  115.       AcBrElement2dNodeTraverser elemNodeTrav;
  116.  
  117.       AcGePoint3dArray pts;
  118.  
  119.       for (ebr = elemNodeTrav.setElement(e) ; !elemNodeTrav.done(); ebr = elemNodeTrav.next())  {
  120.         if (ebr != AcBr::eOk) return;
  121.         AcBrNode n;
  122.         ebr = elemNodeTrav.getNode(n);
  123.         AcGePoint3d p; n.getPoint(p);
  124.         pts.append(p);
  125.       }
  126.  
  127.       v0 = v1 = v2 = v3 = 0;
  128.       vertexLookup.find(pts[0],v0);
  129.       vertexLookup.find(pts[1],v1);
  130.       vertexLookup.find(pts[2],v2);
  131.       if (pts.length() == 4)   {
  132.         vertexLookup.find(pts[3],v3);
  133.       }
  134.  
  135.       AcDbFaceRecord *pFaceRecord = new AcDbFaceRecord(v0, v1, v2, v3);
  136.       pMesh->appendFaceRecord(pFaceRecord);
  137.       pFaceRecord->close();
  138.     }
  139.   }
  140. } ;
  141.  
  142. //-----------------------------------------------------------------------------
  143. IMPLEMENT_ARX_ENTRYPOINT(CMy3DSolidToPolyMeshApp)
  144.  
  145. ACED_ARXCOMMAND_ENTRY_AUTO(CMy3DSolidToPolyMeshApp, Rivilis, 3DSolidToPolyMesh, 3DSolidToPolyMesh, ACRX_CMD_MODAL, NULL)

 

Серый металлик – твердые тела, золотистые – сети.

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

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

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