ADN Club > ObjectARX

Конвертация 3DSOLID в AcDbPolyFaceMesh

(1/4) > >>

Виталий:
Нужна универсальная конвертация 3DSOLID в AcDbPolyFaceMesh. Есть пример на C#, но я в нем ничего не понимаю, Понятно лишь, что такое возможно.
вот ссылка: http://adn-cis.org/sozdanie-polyfacemesh-iz-3d-solid.html
Хотелось бы увидеть пример того же самого, но в коде С++ ObjectARX, поскольку функцию нужно внедрить в существующий ARX проект. Есть решение конвертации в 3DSOLID через brep, теперь фактически стоит обратная задача.

Александр Ривилис:
Попробуй. Я тестировал в AutoCAD 2016. Результаты для обычных твердых тел (желтые - AcDbPolyFaceMesh, белые - AcDb3Dsolid):




--- Код - C++ [Выбрать] ---//-----------------------------------------------------------------------------//----- acrxEntryPoint.cpp//-----------------------------------------------------------------------------#include "StdAfx.h"#include "resource.h" //-----------------------------------------------------------------------------#define szRDS _RXST("") //-----------------------------------------------------------------------------//----- ObjectARX EntryPointclass CMy3DSolidToPolyMeshApp : public AcRxArxApp { public:  CMy3DSolidToPolyMeshApp () : AcRxArxApp () {}   virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {    AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;    return (retCode) ;  }   virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {    AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;    return (retCode) ;  }   virtual void RegisterServerComponents () {    }   static void Rivilis3DSolidToPolyMesh () {     ads_name en; ads_point p;     if (acedEntSel(_T("\nВыберите твердое тело: "), en, p) != RTNORM)      return;     AcDbObjectId eid;     if (acdbGetObjectId(eid, en) != Acad::eOk)       return;     AcDbObjectPointer<AcDb3dSolid> p3DSolid(eid, AcDb::kForRead);    if (p3DSolid.openStatus() == Acad::eWrongObjectType) {      acutPrintf(_T("\nЭто не твердое тело!"));      return;    }     AcDbExtents ext; p3DSolid->getGeomExtents(ext);    double length = ext.minPoint().distanceTo(ext.maxPoint());     AcBrBrep brp;      AcBr::ErrorStatus ebr;    ebr = brp.set(*p3DSolid);    if (ebr != AcBr::eOk) {      acutPrintf(_T("\nОшибка br.set(*p3DSolid) = %d"), ebr);      return;    }      AcBrMesh2dControl mc;    // Задаём максимальное расстояние между узлами    // mc.setMaxNodeSpacing( length / 100.0);    // Задаём максимальное количество элементов в сети.    // mc.setMaxSubdivisions(100000);    // Задаём максимальное отклонение точки    mc.setDistTol(length / 100.0);    // Задаём тип элементов - только треугольники    mc.setElementShape(AcBr::kAllTriangles);     AcBrMesh2dFilter mf;    const AcBrEntity* meshEnt = (AcBrEntity*)&brp;    mf.insert(make_pair(meshEnt, mc));    AcBrMesh2d brepMesh;    if ((ebr = brepMesh.generate(mf)) != AcBr::eOk) {      acutPrintf(_T("\n Ошибка в AcBrMesh2d::generate %d"), ebr);      return;    }     AcDbObjectPointer<AcDbPolyFaceMesh> pMesh; pMesh.create();    pMesh->setDatabaseDefaults();    pMesh->setColorIndex(2); // Пусть сеть будет желтая    AcDbBlockTableRecordPointer pBtr(acdbCurDwg()->currentSpaceId(), AcDb::kForWrite);    if (pBtr.openStatus() != Acad::eOk)       return;    pBtr->appendAcDbEntity(pMesh);     int v0 = 0, v1 = 0, v2 = 0, v3 = 0;     int iter = 0;    AcGePoint3dArray vertexLookup;    vertexLookup.setPhysicalLength(10000);    // Чтобы пропустить нулевой элемент    vertexLookup.append(AcGePoint3d::kOrigin);     AcBrMesh2dElement2dTraverser meshElemTrav;     for (ebr = meshElemTrav.setMesh(brepMesh); !meshElemTrav.done(); ebr = meshElemTrav.next()) {      if (ebr != AcBr::eOk) return;      AcBrElement2d e;   ebr = meshElemTrav.getElement(e);      AcBrElement2dNodeTraverser elemNodeTrav;      for (ebr = elemNodeTrav.setElement(e) ; !elemNodeTrav.done(); elemNodeTrav.next())  {        AcBrNode n;        ebr = elemNodeTrav.getNode(n);        AcGePoint3d p; n.getPoint(p);        if (!vertexLookup.contains(p)) {          AcDbObjectPointer<AcDbPolyFaceMeshVertex> pMeshVert;  pMeshVert.create();          pMeshVert->setPosition(p);          pMesh->appendVertex(pMeshVert);          vertexLookup.append(p);        }      }    }     for (ebr = meshElemTrav.setMesh(brepMesh); !meshElemTrav.done(); ebr = meshElemTrav.next()) {      if (ebr != AcBr::eOk) return;      AcBrElement2d e;   ebr = meshElemTrav.getElement(e);      AcBrElement2dNodeTraverser elemNodeTrav;       AcGePoint3dArray pts;       for (ebr = elemNodeTrav.setElement(e) ; !elemNodeTrav.done(); ebr = elemNodeTrav.next())  {        if (ebr != AcBr::eOk) return;        AcBrNode n;        ebr = elemNodeTrav.getNode(n);        AcGePoint3d p; n.getPoint(p);        pts.append(p);      }       v0 = v1 = v2 = v3 = 0;      vertexLookup.find(pts[0],v0);      vertexLookup.find(pts[1],v1);      vertexLookup.find(pts[2],v2);      if (pts.length() == 4)   {        vertexLookup.find(pts[3],v3);      }       AcDbFaceRecord *pFaceRecord = new AcDbFaceRecord(v0, v1, v2, v3);      pMesh->appendFaceRecord(pFaceRecord);      pFaceRecord->close();    }  }} ; //-----------------------------------------------------------------------------IMPLEMENT_ARX_ENTRYPOINT(CMy3DSolidToPolyMeshApp) ACED_ARXCOMMAND_ENTRY_AUTO(CMy3DSolidToPolyMeshApp, Rivilis, 3DSolidToPolyMesh, 3DSolidToPolyMesh, ACRX_CMD_MODAL, NULL)
P.S.: Можно играться параметрами AcBrMesh2dControl для лучшего преобразования 3DSolid в Mesh

Виталий:
Спасибо! Оперативно. Но с первого раза не получается чисто. Скомпилировал у себя, проверил на тех же телах и на своих. Везде одни и те же нюансы. 1. Polyface не красится в желтый цвет, становится всегда черной. 2. Моя команда конвертации таких сетей в другой объект на данных сетях виснет, приходится ее расчленять и пересобирать, тогда становится желтой и конвертируемой. 3. Появляются лишние грани триангуляции на плоских, ровных поверхностях, от которых не отделаться. В Polyface есть такая возможность делать грани невидимыми но это возможно когда знаешь какие грани. Может быть есть функция как в 3Dsolid cleanBody() убирающая такие грани автоматически?  Первые 2 пункта вообще странные, может я что то не так сделал. 3 пункт требует анализа и доработки.

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

--- Цитата: Виталий от 31-03-2016, 14:38:13 ---Может быть есть функция как в 3Dsolid cleanBody() убирающая такие грани автоматически?
--- Конец цитаты ---
Нет.

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

--- Цитата: Виталий от 31-03-2016, 14:38:13 ---Скомпилировал у себя, проверил на тех же телах и на своих.
--- Конец цитаты ---
Скомпилировал мой исходник или свой, в который впихивал мой код?
Цвет не устанавливается, если какие-то ошибки в сети. Например, когда у меня небыло строк:

--- Код - C++ [Выбрать] ---    // Чтобы пропустить нулевой элемент    vertexLookup.append(AcGePoint3d::kOrigin);то возникала такая проблема и были дырки в сети.

Навигация

[0] Главная страница сообщений

[#] Следующая страница

Перейти к полной версии