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坐标系下恢复了在设计坐标系下两者之间的相对位置关系。