Пересечение Поверхности и Отрезка с использованием ARX
В другой статье, мой коллега Philippe рассказал о получении точки пересечения между плоскостью и отрезком. В этой статье мы увидим, как получить пересечение любой поверхности и отрезка.
ARX даёт нам класс AcGeCurveSurfInt который позволяет получить точки пересечения между 3D-кривой и поверхностью. Конструктор AcGeCurveSurfInt или метод AcGeCurveSurfInt::Set получает в качестве параметров кривую и поверхность. В качестве поверхности требуется экземпляр класса AcGeSurface. Так что нам потребуется получить объект AcGeSurface на основе объекта AcDbSurface. А для этого в качестве промежуточного объекта нам потребуется объект AcBrBrep.
Ниже приведен небольшой пример. Он просит пользователя выбрать поверхность и получает пересечение отрезка (из (0,0,0) в (0,0,1)) и поверхности.
Примечание: для использования BREP объектов нужны отдельные .h- и .lib-файлы. Их можно найти в каталоге ObjectARX SDK\utils\brep
- static AcGePoint3dArray Intersect(AcDbSurface* pSurface,AcGeLine3d line)
- {
- AcGePoint3dArray returnPtArray;
- AcDbBody* pBody = new AcDbBody();
- // 2013
- // Acad::ErrorStatus es = pBody->setASMBody(pSurface->ASMBodyCopy());
- // До 2013
- Acad::ErrorStatus es = pBody->setBody(pSurface->body());
- // build AcBrBrep
- AcBrBrep* pBrep = new AcBrBrep();
- //
- if(AcBr::eOk == pBrep->set(*pBody))
- {
- AcBrBrepFaceTraverser* pFaceTrav = new AcBrBrepFaceTraverser;
- if(AcBr::eOk == pFaceTrav->setBrep(*pBrep))
- {
- for(pFaceTrav->restart(); !pFaceTrav->done(); pFaceTrav->next())
- {
- AcBrFace face;
- if(AcBr::eOk == pFaceTrav->getFace(face))
- {
- double area = 0.0f;
- face.getSurfaceArea(area);
- acutPrintf(L"\nПлощадь поверхности: %f", area);
- //***** полная поверхность Brep-грани******
- //AcGeNurbSurface nurbSurface;
- //face.getSurfaceAsNurb(nurbSurface);
- //AcGeCurveSurfInt curveSI;
- ////исходные отрезок и поверхность
- //curveSI.set(line,nurbSurface);
- ////подсчитываем число точек пересечения
- //int count = curveSI.numIntPoints(err_1);
- // if(err_1 == AcGe::kXXOk && count >0 )
- // {
- // AcGeIntersectError err_2;
- // for(int index = 0 ;index < count; index ++)
- // {
- // AcGePoint3d pt =
- // curveSI.intPoint(index,err_2);
- // returnPtArray.append(pt);
- // }
- //
- // }
- //**********
- //****настоящая поверхность AcDbSurface
- AcGeExternalBoundedSurface** nurbs = NULL;
- Adesk::UInt32 numNurbs = 0;
- face.getSurfaceAsTrimmedNurbs(numNurbs,nurbs);
- //*****
- for (Adesk::UInt32 i = 0; i < numNurbs; i++)
- {
- AcGeCurveSurfInt curveSI;
- AcGeIntersectError err_1 = AcGe::kXXOk;
- // исходные поверхность и отрезок
- curveSI.set(line,*nurbs[i]);
- // подсчитываем количество точек пересечения
- int count = curveSI.numIntPoints(err_1);
- if(err_1 == AcGe::kXXOk && count >0 )
- {
- AcGeIntersectError err_2;
- for(int index = 0 ;index < count; index ++)
- {
- AcGePoint3d pt =
- curveSI.intPoint(index,err_2);
- returnPtArray.append(pt);
- }
- }
- delete nurbs[i];
- }
- // вы обязаны удалить массив поверхностей
- delete[] nurbs;
- }
- }
- }
- delete pFaceTrav;
- }
- delete pBrep;
- return returnPtArray;
- }
- static void getIntersectPts(void)
- {
- ads_name ename;
- ads_point pickpt;
- AcDbObjectId objId;
- AcDbObject *pObj;
- int rc;
- // Выберем поверхность
- rc= acedEntSel(L"\nВыберите Поверхность: ", ename, pickpt);
- if(rc != RTNORM)
- {
- if (rc != RTCAN)
- acutPrintf(L"\nОшибка выбора примитива ");
- return;
- }
- acdbGetObjectId(objId, ename);
- acdbOpenObject(pObj, objId, AcDb::kForRead);
- AcDbSurface* pEntity1 = AcDbSurface::cast(pObj);
- if(!pEntity1)
- {
- acutPrintf(L"\nВыбор неправильный...");
- pObj->close();
- return;
- }
- // Вызываем функцию Intersect
- AcGePoint3dArray points =
- Intersect(pEntity1,AcGeLine3d(AcGePoint3d(0,0,0),
- AcGePoint3d(0,0,1)));
- if(points.length() >0)
- {
- // Проходим по всем точкам
- }
- pObj->close();
- }
Обсуждение: http://adn-cis.org/forum/index.php?topic=59.0
Отредактировано 06.06.2013 в 13:21:58