ADN Club > ObjectARX
Конвертация 3DSOLID в AcDbPolyFaceMesh
Виталий:
Аккуратно перенес твои строки к себе. Прилагаю тестовое тело. Если у тебя пройдет, будет сразу желтым, то я что-то напортачил. Работаю в 2015.
Александр Ривилис:
Немного изменил код:
1) Изменил тип предпочитаемых элементов сети с треугольников на 4-хугольники (если не устраивает - можешь поменять)
2) Устанавливаю цвет не только всей сети, но и каждой из её граней.
--- Код - 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); // Задаём тип элементов - пытаемся заменить на 4-угольники mc.setElementShape(AcBr::kAllQuadrilaterals); 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(65536); // Чтобы пропустить нулевой элемент 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(4); 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); pFaceRecord->setColorIndex(2); // Задаём цвет грани - желтый pMesh->appendFaceRecord(pFaceRecord); pFaceRecord->close(); } }} ; //-----------------------------------------------------------------------------IMPLEMENT_ARX_ENTRYPOINT(CMy3DSolidToPolyMeshApp) ACED_ARXCOMMAND_ENTRY_AUTO(CMy3DSolidToPolyMeshApp, Rivilis, 3DSolidToPolyMesh, 3DSolidToPolyMesh, ACRX_CMD_MODAL, NULL)
Результат в приложенном файле и на видео:
Как видишь никаких дырок нет. Специально проверял именно в AutoCAD 2015 SP2 x64
P.S.: Приложил полный проект.
Виталий:
Не проходит для разных тел, например в которых есть грани из 3х и 4х вершин. Там в Polymesh есть грани как треугольники так 4-х угольники, но все имеют по 4 точки. В треугольниках 2 точки совпадают. У тебя вроде все правильно если расчленить и проверить, но что то не так.
См. на рисунке слева тела, посередине твои сети, справа синии мои после ремонта твоих. Мои все правильные.
проверял чисто твой проект.
Виталий:
Александр, большое спасибо тебе. Я думаю отложить эту тему вообще. Твой пример в принципе делает, то что положено. Чисто для моей идеи дальше их чисто конвертировать не подходит. Но тема очень полезная своими частями, которые нужно еще осознать.
Интересно, что вообще такое brep, как его вообще добавить, увидеть в рисунке, на какие примитивы он расчленяется?
Александр Ривилис:
--- Цитата: Виталий от 01-04-2016, 08:37:12 ---См. на рисунке слева тела, посередине твои сети, справа синии мои после ремонта твоих. Мои все правильные.
--- Конец цитаты ---
Я не знаю, почему ты считаешь свои правильными. В теории они как раз и неправильные.
Вот это мои:
А вот это твои:
Во всех твоих PolyFaceMesh 4-ая точка в грани не пустая, а совпадающая с третьей и она видимая. В чем глубокий смысл этого я не знаю. Во всяком случае и в моём коде если код
--- Код - C++ [Выбрать] --- if (pts.length() == 4) { vertexLookup.find(pts[3],v3); }заменить на
--- Код - C++ [Выбрать] --- if (pts.length() == 4) { vertexLookup.find(pts[3],v3); } else { v3 = v2; }то результат должен быть аналогично твоему.
Навигация
Перейти к полной версии