20/03/2018
Как получить пересечение прямой и твердого тела?
Это можно сделать при помощи B-Rep API. Следующий код иллюстрирует как получить пересечение линейного примитива (ОТРЕЗОК, ЛУЧ, ПРЯМАЯ) с примитивом, который представляется в виде ACIS (т.е. твердое тело - SOLID, область - REGION, или тело - BODY).
Код - C++: [Выделить]
- //-----------------------------------------------------------------------------
- //----- acrxEntryPoint.cpp
- //-----------------------------------------------------------------------------
- #include "StdAfx.h"
- #include "resource.h"
- //-----------------------------------------------------------------------------
- #define szRDS _RXST("")
- //-----------------------------------------------------------------------------
- //----- ObjectARX EntryPoint
- class CIntSolid3DApp : public AcRxArxApp {
- public:
- CIntSolid3DApp () : 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 () {}
- // Команда INTSOLID
- static void Asdkintsolid()
- {
- AcDbObjectId lineId;
- AcDbObjectId solidId;
- AcDbEntity * pEnt;
- AcDbEntity * pLinearEnt;
- AcGePoint3dArray hitPoints;
- int nHitsWanted;
- ads_name en;
- ads_point pt;
- // Просим пользоваля выбрать линию
- if (acedEntSel(_T("\nВыберите линию: "), en, pt) != RTNORM)
- return;
- // Получаем указатель на неё
- if (acdbGetObjectId(lineId, en) != Acad::eOk)
- {
- return;
- }
- acdbOpenAcDbEntity(pLinearEnt, lineId, AcDb::kForRead);
- if (pLinearEnt == NULL)
- {
- acutPrintf(_T("\nНе смогли открыть линию"));
- return;
- }
- // Просим пользователя выбрать твердое тело
- if (acedEntSel(_T("\nВыберите твердое тело: "), en, pt) != RTNORM)
- return;
- // Получаем указатель на него
- if (acdbGetObjectId(solidId, en) != Acad::eOk)
- {
- return;
- }
- acdbOpenAcDbEntity(pEnt, solidId, AcDb::kForRead);
- if (pEnt == NULL)
- {
- acutPrintf(_T("\nНе смогли открыть твердое тело"));
- pLinearEnt->close();
- return;
- }
- // Спрашиваем количество пересечений, которые должны быть возвращены.
- // Если введено значение 0, то возвращаются все пересечения.
- if (RTNORM != acedGetInt(_T("\nУкажите количество требуемых пересечений : "),
- &nHitsWanted))
- {
- acutPrintf(_T("\nЭто должно быть целое число"));
- pEnt->close();
- pLinearEnt->close();
- return;
- }
- // Находим количество пересечений
- if (Acad::eOk != getHits(pLinearEnt, pEnt,
- nHitsWanted, hitPoints))
- {
- pEnt->close();
- pLinearEnt->close();
- return;
- }
- // Примитивы нам больше не нужны - закрываем
- pEnt->close();
- pLinearEnt->close();
- // Печатаем пересечения
- int len = hitPoints.length();
- if (len == 0)
- {
- acutPrintf(_T("\nПересечения не найдены."));
- }
- else
- {
- acutPrintf(_T("\nНайдено %d пересечений."), len);
- for (int i = 0; i < len; i++)
- {
- AcGePoint3d pt = hitPoints[i];
- acutPrintf(_T("\nПересечение %d: (%f, %f, %f)"),
- i + 1, pt[X], pt[Y], pt[Z]);
- }
- }
- return;
- }
- static Acad::ErrorStatus getHits(
- AcDbEntity * pLinearEnt,
- AcDbEntity * pEnt,
- int nHitsWanted,
- AcGePoint3dArray &hitPoints)
- // Parameters:
- // AcDbEntity * pLinearEnt - указатель на линию (отрезок, луч, прямая)
- // AcDbEntity * pEnt - указатель на твердое тело
- // int nHitsWanted - количество запрашиваемых пересечений
- // (0 означает все)
- // AcGePoint3dArray hitPoints - массив точек пересечений
- // Returns:
- // Acad::eOk - если всё хорошо
- // Acad::eInvalidInput - если возникли проблемы
- {
- // Проверяем, что примитив правильного типа
- if (!(pEnt->isKindOf(AcDb3dSolid::desc()) ||
- pEnt->isKindOf(AcDbRegion::desc()) ||
- pEnt->isKindOf(AcDbBody::desc())))
- {
- acutPrintf(_T("\nВторой аргумент должен быть твердым телом, а не %s"),
- pEnt->isA()->name());
- return Acad::eInvalidInput;
- }
- // Проверяем, что указатель на линию соответствующего типа и
- // создаём соотвествующий AcGe-объект.
- AcGeLinearEnt3d * pGeLine;
- if (pLinearEnt->isKindOf(AcDbLine::desc()))
- {
- AcDbLine * pLine = (AcDbLine*)pLinearEnt;
- pGeLine = new AcGeLineSeg3d(pLine->startPoint(), pLine->endPoint());
- }
- else if (pLinearEnt->isKindOf(AcDbRay::desc()))
- {
- AcDbRay * pRay = (AcDbRay*)pLinearEnt;
- pGeLine = new AcGeRay3d(pRay->basePoint(), pRay->unitDir());
- }
- else if (pLinearEnt->isKindOf(AcDbXline::desc()))
- {
- AcDbXline * pXline = (AcDbXline *)pLinearEnt;
- pGeLine = new AcGeLine3d(pXline->basePoint(), pXline->unitDir());
- }
- else
- {
- acutPrintf(_T("\nПервый агрумент должен быть линией, а не %s"),
- pLinearEnt->isA()->name());
- return Acad::eInvalidInput;
- }
- // Находим количество пересечений при помощи B-Rep API
- AcBrBrep*pBrep = new AcBrBrep;
- AcDbObjectId solidId = pEnt->objectId();
- pBrep->setSubentPath(AcDbFullSubentPath(solidId,
- AcDbSubentId()));
- AcBrHit*pHits = NULL;
- Adesk::UInt32 nHitsFound;
- pBrep->getLineContainment(*pGeLine, nHitsWanted, nHitsFound, pHits);
- // Добавляем допустимые точки пересечения в hitPoints
- for (Adesk::UInt32 i = 0; i < nHitsFound; i++)
- {
- AcBrEntity*pHitEntity = NULL;
- pHits[i].getEntityHit(pHitEntity);
- if (pHitEntity == NULL)
- continue;
- AcGePoint3d hitPt;
- pHits[i].getPoint(hitPt);
- if (!pHitEntity->isKindOf(AcBrBrep::desc()))
- {
- hitPoints.append(hitPt);
- }
- else
- {
- acutPrintf(
- _T("\nИгнорируемая точка (%f, %f, %f) в %s"),
- hitPt.x, hitPt.y, hitPt.z, pHitEntity->isA()->name());
- }
- delete pHitEntity;
- }
- // Конвертируем точки из МСК в ПСК
- int nPts = hitPoints.length();
- for (int i = 0; i<nPts;i++)
- {
- ads_point pt;
- asPnt3d(pt) = hitPoints[i];
- acdbWcs2Ucs(pt, pt, 0);
- hitPoints[i] = asPnt3d(pt);
- }
- // Чистим всё ненужное
- delete[] pHits;
- delete pBrep;
- delete pGeLine;
- return Acad::eOk;
- }
- } ;
- //-----------------------------------------------------------------------------
- IMPLEMENT_ARX_ENTRYPOINT(CIntSolid3DApp)
- ACED_ARXCOMMAND_ENTRY_AUTO(CIntSolid3DApp, Asdk, intsolid, intSolid, ACRX_CMD_MODAL, NULL)
Источник: http://adndevblog.typepad.com/autocad/2013/02/how-to-intersect-a-line-with-a-solid.html
Автор перевода: Александр Ривилис
Обсуждение: http://adn-cis.org/forum/index.php?topic=
Опубликовано 20.03.2018