ADN Club > ObjectARX
Конвертация 3DSOLID в AcDbPolyFaceMesh
Виталий:
Нужна универсальная конвертация 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);то возникала такая проблема и были дырки в сети.
Навигация
Перейти к полной версии