三维空间下线与面的交点


CurveCurve::IntersectionsXY得到的交点都是从指定方向投影后的交点,而且只能是轮廓线上的交点。如果我们在三维空间下有一个任意方向的面和任意一条线,该如何获取这两者之间的真实交点呢?我们需要调用mdlSolid_XXX函数去求得交点,测试代码如下所示:

void IntersectsOfCurveAndSurface(bvector<DPoint3d>& intersectPts,ElementHandleCR eehCurve,ElementHandleCR eehSurface)
{
	mdlSolid_beginCurrTrans(ACTIVEMODEL);
	BODY_TAG bodySurface;
	Transform  tranSurface;
	if (SUCCESS != mdlSolid_elementToBody(&bodySurface, &tranSurface, (MSElementDescrP)eehSurface.GetElementDescrCP(), ACTIVEMODEL))
	{
		mdlSolid_endCurrTrans();
		return;
	}
	BODY_TAG bodyCurve;
	Transform  tranCurve;
	if (SUCCESS != mdlSolid_elementToBody(&bodyCurve, &tranCurve, (MSElementDescrP)eehCurve.GetElementDescrCP(), ACTIVEMODEL))
	{
		mdlSolid_endCurrTrans();
		return;
	}
	Transform tranInv, tranCurveToSurface;
	mdlTMatrix_getInverse(&tranInv, &tranSurface);
	mdlTMatrix_multiply(&tranCurveToSurface, &tranInv, &tranCurve);
	mdlSolid_applyTransform(bodyCurve, &tranCurveToSurface);
	TAG_ENTITY_LIST* edgeList = NULL;
	mdlSolid_listCreate(&edgeList);
	mdlSolid_getEdgeList(edgeList, bodyCurve);
	int count = 0;
	mdlSolid_listCount(&count, edgeList);
	if (count < 1)
	{
		mdlSolid_freeBody(bodySurface);
		mdlSolid_freeBody(bodyCurve);
		mdlSolid_listDelete(&edgeList);
		mdlSolid_endCurrTrans();
		return;
	}
	ENTITY_TAG edge;
	mdlSolid_listNthEl(&edge, edgeList, 0);
	CURVE_TAG curve_tag = 0L;
	double startParam = 0, endParam = 0;
	int result = mdlSolid_edgeData(NULL, NULL, NULL, NULL, &startParam, &endParam, NULL, &curve_tag, NULL, edge);
	TAG_ENTITY_LIST* faceList = NULL;
	mdlSolid_listCreate(&faceList);
	mdlSolid_getFaceList(faceList, bodySurface);
	ENTITY_TAG face;
	mdlSolid_listCount(&count, faceList);
	for (int i = 0; i < count; i++)
	{
		mdlSolid_listNthEl(&face, faceList, i);
		int ptNum = 0;
		DPoint3d* interPtP = NULL;
		if (SUCCESS != mdlSolid_faceIntersectCurve(&interPtP, NULL, NULL, &ptNum, face, curve_tag, startParam, endParam))
		{
			continue;
		}
		mdlTMatrix_transformPointArray(interPtP, &tranSurface, ptNum);
		mdlCurrTrans_transformPointArray(interPtP, interPtP, ptNum);
		intersectPts.insert(intersectPts.end(), interPtP, interPtP + ptNum);
		delete[] interPtP;
	}
	mdlSolid_endCurrTrans();
	mdlSolid_freeBody(bodySurface);
	mdlSolid_freeBody(bodyCurve);
	mdlSolid_listDelete(&faceList);
	mdlSolid_listDelete(&edgeList);
	return;
}

这个函数需要三个参数,第一个参数是输出参数,其中保存了计算得到的所有交点,如果函数返回后,容器中的点数为0的话就是没有相交。第二个参数是空间曲线,第三个参数是空间曲面。函数中将曲线和面都通过mdlSolid_elementToBody函数转换为BODY_TAG类型,mdlSolid_elementToBody还返回给了我们一个变换矩阵Transform的类型实例。在使用mdlSolid_XXX函数时,需要将Mstn元素转换为ParaSolid数据结构,再转换后元素的几何数据也从Mstn的设计坐标系转换到了ParaSolid的坐标系下了。通过mdlSolid_elementToBody返回的变换矩阵,我们可以将ParaSolid坐标系下的几何数据转换到Mstn的设计坐标系下。由于曲线和曲面都转换到了各自的ParaSolid坐标系下了,所有两者之间的相对位置关系也发生了改变,所以我们要将其中一个变换到另外一个的局部ParaSolid坐标系下。这一步是通过如下代码来实现的:

Transform tranInv, tranCurveToSurface;
	mdlTMatrix_getInverse(&tranInv, &tranSurface);
	mdlTMatrix_multiply(&tranCurveToSurface, &tranInv, &tranCurve);
	mdlSolid_applyTransform(bodyCurve, &tranCurveToSurface);

转换以后两者在Mstn设计坐标系下的相对位置关系,就在ParaSolid坐标系下又恢复了,后面我们就可以通过mdlSolid_faceIntersectCurve函数来求得两者之间的交点了。但是求得的交点同样也是在ParaSolid坐标系下的交点,所以我们还要将其再变换会Mstn设计坐标系下。由于我们是将曲线变换到了曲面的ParaSolid局部坐标系下,所以我们通过转换曲面时返回的变换矩阵将交点变换回Mstn的设计坐标系下的。