Как средствами ObjectARX получить точки пересечения кривой и плоскости
Вопрос: Имеется кривая (наследник AcDbCurve) и задана плоскость AcGePlane. Каким образом можно получить все точки пересечения кривой и плоскости?
Ответ: Для этой цели мы воспользуемся геометрической библиотекой. Во-первых, при помощи функции acdbConvertAcDbCurveToGelibCurve мы преобразуем AcDbCurve (и любого его наследника) в AcGeCurve3d. Во-вторых, воспользуемся классом AcGeCurveSurfInt для получения точек пересечения кривой и плоскости.
Ниже вы видите исходный код функции, которая запрашивает у пользователя кривую, начальный и конечный уровень для горизонтальных плоскостей и шаг между горизонтальными плоскостями. Результат её работы – желтые точки, отмечающие пересечение плоскостей и кривой.
- static void RivilisCheckInt () {
- Acad::ErrorStatus es;
- ads_name en; ads_point p;
- double level1 = -10.0;
- double level2 = +10.0;
- double step = 1.0;
- if (acedEntSel(_T("\nВыберите произвольную кривую: "), en, p) == RTNORM) {
- TCHAR buf1[32]; acdbRToS(level1,-1,-1, buf1, sizeof(buf1)-1);
- TCHAR buf2[32]; acdbRToS(level2,-1,-1, buf2, sizeof(buf2)-1);
- TCHAR buf3[32]; acdbRToS(step,-1,-1, buf3, sizeof(buf3)-1);
- AcString s1;
- s1.format(_T("\nУкажите начальную отметку уровня для проверки пересечения с плоскостью <%s>: "), buf1);
- AcString s2;
- s2.format(_T("\nУкажите конечную отметку уровня для проверки пересечения с плоскостью <%s>: "), buf2);
- if (acedGetReal(s1,&level1) != RTCAN && acedGetReal(s2,&level2) != RTCAN) {
- AcString s3; s3.format(_T("\nУкажите шаг уровней <%s>: "), buf3);
- acedInitGet(RSG_NOZERO | RSG_NONEG, NULL);
- if (acedGetReal(s3,&step) == RTCAN) return;
- AcDbObjectId eId; acdbGetObjectId(eId, en);
- AcDbObjectPointer<AcDbCurve> pCurve(eId, AcDb::kForRead);
- if (pCurve.openStatus() == Acad::eWrongObjectType) {
- acutPrintf(_T("\nВыбрана не кривая. Допустимы линии, полилинии, дуги, окружности, сплайны, и т.д."));
- return;
- }
- if (pCurve.openStatus() != Acad::eOk) {
- acutPrintf(_T("\nОшибка открытия: %s"), acadErrorStatusText(pCurve.openStatus()));
- return;
- }
- // GE-кривая, полученная из AcDb-кривой
- AcGeCurve3d *pGeCurve = NULL;
- if ((es = acdbConvertAcDbCurveToGelibCurve(pCurve, pGeCurve)) != Acad::eOk) {
- acutPrintf(_T("\nacdbConvertAcDbCurveToGelibCurve: %s"), acadErrorStatusText(es));
- return;
- }
- for (double z = min(level1, level2); z <= max(level1,level2); z += step)
- {
- // Плоскость сечения
- AcGePlane plan(AcGePoint3d(0,0,z), AcGeVector3d::kZAxis);
- AcGeIntersectError err;
- AcGeCurveSurfInt csint(*pGeCurve, plan);
- int n = csint.numIntPoints(err);
- if ((n = csint.numIntPoints(err)) != 0)
- {
- // Задаём форму точки
- acdbCurDwg()->setPdmode(34);
- acutPrintf(_T("\nВсего %d пересечений на уровне %g"), n, z);
- AcDbBlockTableRecordPointer pBTR(acdbCurDwg()->currentSpaceId(), AcDb::kForWrite);
- if (pBTR.openStatus() == Acad::eOk) {
- for (int i = 0; i < n; i++) {
- AcDbPoint *pPoint = new AcDbPoint(csint.intPoint(i,err));
- pPoint->setDatabaseDefaults();
- pPoint->setColorIndex(2);
- pBTR->appendAcDbEntity(pPoint);
- pPoint->close();
- }
- }
- }
- }
- delete pGeCurve;
- }
- }
- }
Полный проект: CurvSurfInter.zip
Результаты работы:
Обсуждение: http://adn-cis.org/forum/index.php?topic=7075
Опубликовано 07.05.2016