How can I compute the intersection point, if any, between an AcDbFace entity and an AcDbLine?
Solution
There are mainly two ways you can do that using arx, the following DevNote exposes both:
1 – First technique create an infinite plane and infinite line, then uses a ray to check if the intersection point of these two infinite entities is inside the face.
2 – Second technique uses 3D solids. It creates a thin extruded solid from the face and another to represent the line, then uses checkInterferences method to find out the intersection point.
Below are the samples for these functions, along with a test function:
/////////////////////////////////////////////////////////////////////
//Use: Intersection between Face and Line using Ray
//
/////////////////////////////////////////////////////////////////////
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());
//Create temp plane
AcGePlane plane(vertex1, vecU, vecV);
//Create temp line
AcGeLineSeg3d line (pLine->startPoint(), pLine->endPoint());
//Check intersection
AcGePoint3d resultPoint;
if (plane.intersectWith(line, resultPoint) == Adesk::kTrue)
{
AcGeRay3d ray(resultPoint, vertex1.asVector() – vertex2.asVector());
int intNum = 0;
//check if intersection point is inside the face
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;
//if intNum is ‘odd’ then point is inside
if((intNum%2) != 0)
{
acutPrintf (L"\nIntersection point: [%f, %f, %f]",
resultPoint.x, resultPoint.y, resultPoint.z);
}
}
}
/////////////////////////////////////////////////////////////////////
//Use: Intersection between Face and Line using 3D Solids
//
/////////////////////////////////////////////////////////////////////
void FindIntersection2(AcDbFace* pFace, AcDbLine* pLine)
{
//Line direction
AcGeVector3d direction (pLine->endPoint()-pLine->startPoint());
//Create temp circle
AcDbCircle* pcircle =
new AcDbCircle(pLine->startPoint(), direction, 0.01);
//Create temp solid line
AcDb3dSolid* pSolidLine = new AcDb3dSolid ();
AcDbSweepOptions sweepOptions;
pSolidLine->createExtrudedSolid(pcircle, direction, sweepOptions);
//Create temp solid Face
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());
//Compute face’s normal
AcGeVector3d faceNormal = vec2.crossProduct(vec1);
faceNormal *= 0.01 / faceNormal.length();
//Create a very thin extruded solid
p
SolidFace->createExtrudedSolid(pFace, faceNormal, sweepOptions);
//Check interference between the two solids
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"\nIntersection point: [%f, %f, %f]",
centroid.x, centroid.y, centroid.z);
delete commonVolumeSolid;
}
delete pcircle;
delete pSolidLine;
delete pSolidFace;
}
//The test method
void FindIntersectionTest(void)
{
ads_name ename;
ads_point pickpt;
AcDbObjectId objId;
AcDbObject *pObj;
int rc;
rc= acedEntSel(L"\nSelect Face: ", ename, pickpt);
if(rc != RTNORM)
{
if (rc != RTCAN) acutPrintf(L"\nError selecting entity ");
return;
}
acdbGetObjectId(objId, ename);
acdbOpenObject(pObj, objId, AcDb::kForRead);
AcDbFace* pEntity1 = AcDbFace::cast(pObj);
if(!pEntity1)
{
acutPrintf(L"\nSelection Invalid…");
pObj->close();
return;
}
rc= acedEntSel(L"\nSelect line: ", ename, pickpt);
if(rc != RTNORM)
{
if (rc != RTCAN) acutPrintf(L"\nError selecting entity ");
return;
}
acdbGetObjectId(objId, ename);
acdbOpenObject(pObj, objId, AcDb::kForRead);
AcDbLine* pEntity2 = AcDbLine::cast(pObj);
if(!pEntity2)
{
acutPrintf(L"\nSelection Invalid…");
pObj->close();
return;
}
FindIntersection (pEntity1, pEntity2);
FindIntersection2(pEntity1, pEntity2);
pEntity1->close();
pEntity2->close();
}
<
p style=”line-height: normal;margin: 0in 0in 0pt” class=”MsoNormal”>

Leave a Reply