30/03/2016
Конвертация AcDb3DSolid в AcDbPolyFaceMesh средствами ObjectARX
Вопрос: Стоит задача получить на основе AcDb3DSolid сеть AcDbPolyFaceMesh. Как это можно сделать?
Ответ: Ниже код, который позволяет это сделать. Возможны вариации в настройке AcBrMesh2dControl, определяющей насколько сеть будет повторять контуры твердого тела и какие элементы будут в основе этой сети.
Код - C++: [Выделить]
- //-----------------------------------------------------------------------------
- //----- acrxEntryPoint.cpp
- //-----------------------------------------------------------------------------
- #include "StdAfx.h"
- #include "resource.h"
- //-----------------------------------------------------------------------------
- #define szRDS _RXST("")
- //-----------------------------------------------------------------------------
- //----- ObjectARX EntryPoint
- class 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)
Серый металлик – твердые тела, золотистые – сети.
Автор: Александр Ривилис
Обсуждение: http://adn-cis.org/forum/index.php?topic=6999
Опубликовано 30.03.2016