[MSCE C++]曲线压印至实体


SolidUtil::Modify下有一个ImprintCurveVectorOnBody函数,可以将一条曲线按照指定的方向投影压印到指定的实体上。此函数的原型如下所示:

static PSOLIDCORE_EXPORT BentleyStatus ImprintCurveVectorOnBody ( ISolidKernelEntityPtr & target,

 CurveVectorCR curveVector,

 DVec3dCR direction,

 bool extendOpenCurvesToEdge = true

)

第一个参数“target”是被压印的实体,第二个参数“curveVector”是用来压印的曲线,第三个参数“direction”用来指定投影压印的方向,如果第二个参数指定的曲线是一个“Open”(非闭合)的曲线时,第四个参数“extendOpenCurvesToEdge”用来控制是否延长曲线两端,使曲线能将面分割成两部分。这个函数虽然实现了压印功能,但是有一个缺陷是无法获取压印到实体后的曲线,或者说我们需要通过其他手段去获取。如果在压印的同时想方便地获取压印到实体后的曲线,我们可以使用老式的“mdlSolid_imprintCurveVector”函数去实现,此函数的原型如下所示:

MSPSOLID_EXPORT StatusInt mdlSolid_imprintCurveVector ( TAG_ENTITY_LIST * pImprintList,

 BODY_TAG body,

 TAG_ENTITY_LIST * pEdgeList,

 DPoint3d * pVector,

 double tolerance

)

第一个 参数“pImprintList”就是压印到实体以后的线,第二个参数“body”是被压印的实体,第三个参数“pEdgeList”是用来压印的线,第四个参数“pVector”用来指定压印投影的方向,最后一个参数“tolerance”用来指定容差。如下代码演示了此函数的用法,执行此段代码时,需要通过选择集工具,选中两个元素,第一个选中的元素用来作为被压印的实体,第二个用作压印的曲线,压印的结果将被添加到dgn文件中。

void TestmdlSolid_imprintCurveVector()
{
	ElementAgenda selectset;
	SelectionSetManager::GetManager().BuildAgenda(selectset);
	if (selectset.GetCount() < 2)
	{
		return;
	}
	EditElementHandle& eeh1 = selectset[0];
	EditElementHandle& eeh2 = selectset[1];

	BODY_TAG body = 0L;
	Transform  transform1;
	mdlSolid_beginCurrTrans(ACTIVEMODEL);
	StatusInt status = mdlSolid_elementToBody(&body, &transform1, (MSElementDescrP)eeh1.GetElementDescrCP(), ACTIVEMODEL);
	if (status != SUCCESS)
	{
		return;
	}
	BODY_TAG body2 = 0L;
	Transform  transform2;
	status = mdlSolid_elementToBody(&body2, &transform2, (MSElementDescrP)eeh2.GetElementDescrCP(), ACTIVEMODEL);
	if (status != SUCCESS)
	{
		return;
	}
	Transform invTransform, toolTransform;
	mdlTMatrix_getInverse(&invTransform, &transform1);
	mdlTMatrix_multiply(&toolTransform, &invTransform, &transform2);
	mdlSolid_applyTransform(body2, &toolTransform);
	TAG_ENTITY_LIST * edgeList = NULL;
	mdlSolid_listCreate(&edgeList);
	mdlSolid_getEdgeList(edgeList, body2);
	int count = 0;
	mdlSolid_listCount(&count, edgeList);
	if (count)
	{
		DVec3d vec = DVec3d::From(0, 0, -1);
		invTransform.MultiplyMatrixOnly(vec);
		TAG_ENTITY_LIST * edgeListResult = NULL; 
		mdlSolid_listCreate(&edgeListResult);
		if (SUCCESS == mdlSolid_imprintCurveVector(edgeListResult, body, edgeList, &vec, 1E-05))
		{
			mdlSolid_listCount(&count, edgeListResult);
			for (int i = 0; i < count; i++)
			{
				MSElementDescrP edp;
				ENTITY_TAG pEdge = 0L;
				mdlSolid_listNthEl(&pEdge, edgeListResult, i);
				mdlSolid_elementFromEdge(&edp, NULL, pEdge, NULL, NULL, ACTIVEMODEL);
				mdlElmdscr_transform(&edp, &transform1);
				mdlElmdscr_add(edp);
				mdlElmdscr_freeAll(&edp);
			}
		}
		mdlSolid_listDelete(&edgeListResult);
	}
	mdlSolid_freeBody(body);
	mdlSolid_freeBody(body2);
	mdlSolid_listDelete(&edgeList);
	mdlSolid_endCurrTrans();
}

在使用mdlSolid_XXX系列函数对Mstn元素操作时,我们需要将Mstn的元素转换成ParaSolid的数据结构,即BODY_TAG类型。在这个转换过程中,Mstn的元素会从设计坐标系下变换到ParaSolid坐标系下,如下图所示:

由于两个用来操作的元素都被分别转换到了ParaSolid坐标系下,所以两元素之间的相对位置也发生了变化,在真正调用mdlSolid_imprintCurveVector函数之前,我们需要恢复转换成BODY_TAG后两者之前的相对位置。在调用mdlSolid_elementToBody函数将Mstn元素转换成BODY_TAG时,此函数会返回一个Transform实例,此实例是ParaSolid坐标系到设计坐标系的变换矩阵。我们通过两次调用mdlSolid_elementToBody函数返回的变换矩阵,构造了一个“toolTransform”,将”body2”变换至“body1”的局部坐标系下,这样就在ParaSolid坐标系下恢复了在设计坐标系下两者之间的相对位置关系。