|
AcdbFace和AcdbLine
答复:
有两种主要的方法可以通过ARX实现,这两种方法都进一步表明:
1–第一种方法-建立无限平面和无限直线,然后使用它们的相交点的射束,以了解是否在3-面这一点。
2-第二种方法-使用三维物体。从3面和另一个线段。在这种情况下,我们将为他们提供一种检查Interferences方法,以获得过境点。[code]//////////////////////////////////////////////////
// Использование: Пересечение между 3-гранью
// и Отрезком с использованием луча
//////////////////////////////////////////////////
void FindIntersection(AcDbFace* pFace, AcDbLine* pLine)
{
AcGePoint3d vertex1, vertex2, vertex3, vertex4;
pFace->getVertexAt(0, vertex1);
pFace->getVertexAt(1, vertex2);
pFace->getVertexAt(2, vertex3);
pFace->getVertexAt(3, vertex4);
AcGeVector3d vecU(vertex2.asVector()-vertex1.asVector());
AcGeVector3d vecV(vertex3.asVector()-vertex1.asVector());
// Создаём временную плоскость
AcGePlane plane(vertex1, vecU, vecV);
// Создаём временный отрезок
AcGeLineSeg3d line (pLine->startPoint(), pLine->endPoint());
// Находим пересечение
AcGePoint3d resultPoint;
if (plane.intersectWith(line, resultPoint) == Adesk::kTrue)
{
AcGeRay3d ray(resultPoint, vertex1.asVector() - vertex2.asVector());
int intNum = 0;
// Проверяем точку пересечения на попадание внутрь 3-грани
AcGePoint3d intPoint;
if (ray.intersectWith(AcGeLineSeg3d(vertex1, vertex2), intPoint)
== Adesk::kTrue) ++intNum;
if (ray.intersectWith(AcGeLineSeg3d(vertex2, vertex3), intPoint)
== Adesk::kTrue) ++intNum;
if (ray.intersectWith(AcGeLineSeg3d(vertex3, vertex4), intPoint)
== Adesk::kTrue) ++intNum;
if (ray.intersectWith(AcGeLineSeg3d(vertex4, vertex1), intPoint)
== Adesk::kTrue) ++intNum;
// если intNum нечетное – точка внутри
if((intNum%2) != 0)
{
acutPrintf (L"\nТочка пересечения: [%f, %f, %f]",
resultPoint.x, resultPoint.y, resultPoint.z);
}
}
}
/////////////////////////////////////////////////////////////////////
// Использование: Пересечение между 3-гранью
// и Отрезком с помощью 3D-тел
/////////////////////////////////////////////////////////////////////
void FindIntersection2(AcDbFace* pFace, AcDbLine* pLine)
{
// Направление отрезка
AcGeVector3d direction (pLine->endPoint()-pLine->startPoint());
// Создаём временный круг
AcDbCircle* pcircle =
new AcDbCircle(pLine->startPoint(), direction, 0.01);
// Создаем временное 3D-тело
AcDb3dSolid* pSolidLine = new AcDb3dSolid ();
AcDbSweepOptions sweepOptions;
pSolidLine->createExtrudedSolid(pcircle, direction, sweepOptions);
// Создаём временное 3D-тело для 3-грани
AcDb3dSolid *pSolidFace = new AcDb3dSolid ();
AcGePoint3d vertex1, vertex2, vertex3;
pFace->getVertexAt(0, vertex1);
pFace->getVertexAt(1, vertex2);
pFace->getVertexAt(2, vertex3);
AcGeVector3d vec1(vertex2.asVector()-vertex1.asVector());
AcGeVector3d vec2(vertex3.asVector()-vertex1.asVector());
// Вычисляем перпендикуляр к 3-грани
AcGeVector3d faceNormal = vec2.crossProduct(vec1);
faceNormal *= 0.01 / faceNormal.length();
// Создаём очень тонкое выдавленное 3D-тело
pSolidFace->createExtrudedSolid(pFace, faceNormal, sweepOptions);
// Проверяем пересечение между двумя 3D-телами
Adesk::Boolean IsIntersec;
AcDb3dSolid* commonVolumeSolid;
Acad::ErrorStatus es =
pSolidFace->checkInterference(
pSolidLine,
Adesk::kTrue,
IsIntersec,
commonVolumeSolid);
if (IsIntersec == Adesk::kTrue)
{
double volume;
AcGePoint3d centroid;
double momInertia[3], prodInertia[3], prinMoments[3],
radiiGyration[3];
AcGeVector3d prinAxes[3];
AcDbExtents extents;
commonVolumeSolid->getMassProp(
volume,
centroid,
momInertia,
prodInertia,
prinMoments,
prinAxes,
radiiGyration,
extents);
acutPrintf (L"\nТочка пересечения: [%f, %f, %f]",
centroid.x, centroid.y, centroid.z);
delete commonVolumeSolid;
}
delete pcircle;
delete pSolidLine;
delete pSolidFace;
}
// Тестовая функция
void FindIntersectionTest(void)
{
ads_name ename;
ads_point pickpt;
AcDbObjectId objId;
AcDbObject *pObj;
int rc;
rc= acedEntSel(L"\nВыберите 3-грань: ", ename, pickpt);
if(rc != RTNORM)
{
if (rc != RTCAN) acutPrintf(L"\nОшибка выбора примитива ");
return;
}
acdbGetObjectId(objId, ename);
acdbOpenObject(pObj, objId, AcDb::kForRead);
AcDbFace* pEntity1 = AcDbFace::cast(pObj);
if(!pEntity1)
{
acutPrintf(L"\nОшибочный выбор ...");
pObj->close();
return;
}
rc= acedEntSel(L"\nВыберите отрезок: ", ename, pickpt);
if(rc != RTNORM)
{
if (rc != RTCAN) acutPrintf(L"\nОшибка выбора примитива ");
return;
}
acdbGetObjectId(objId, ename);
acdbOpenObject(pObj, objId, AcDb::kForRead);
AcDbLine* pEntity2 = AcDbLine::cast(pObj);
if(!pEntity2)
{
acutPrintf(L"\nОшибочный выбор...");
pObj->close();
return;
}
FindIntersection (pEntity1, pEntity2);
FindIntersection2(pEntity1, pEntity2);
pEntity1->close();
pEntity2->close();
}[/code] |
|