|
使用 ObjectARX 将 acDb3DSolid 转换为 AcDbPolyFaceMesh
问:任务是获取基于 AcDb3DSolid 的 AcDbPolyFaceMesh 网络。如何做到这一点?
答:下面是允许您执行此操作的代码。AcBrMesh2dControl 设置可能存在变化,该设置决定了网络在多大程度上遵循实体的轮廓以及哪些元素将成为该网络的核心。
//-----------------------------------------------------------------------------
//----- 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) |
|