[MS CE C++]获取指定线串上距离指定点最近位置的方法的疑问

本人想在自定义tool中,根据指定线串和点,获取线串上距离指定点最近位置的坐标,以下是调用代码:

double d;
DPoint3d p1, p2;
mdlElmdscr_distanceAtPoint(&d, &p1, &p2, eehRefLine.GetElementDescrP(), &pt, 1e-6 * UOR_PER_METER);

其中pt是_OnDynamicFrame(DgnButtonEventCR ev)中的ev.GetPoint()得来;

在计算得到参数3后,将结果向上下各延伸一定长度用于测试计算结果,最终测试得到了以下结果,

其中1是光标悬停的位置(未开启捕捉),2是根据计算结果动态绘制的线串,明显可以看出计算结果不正确,个人分析有两个可能的原因:

1._OnDynamicFrame(DgnButtonEventCR ev)中的ev.GetPoint()得到的坐标与我们主观感觉的坐标有偏差;

2.mdlElmdscr_distanceAtPoint方法有漏洞或者我调用方式错误;

请教,为什么会出现这种情况呢?

Parents Reply Children
  • DPoint3d GetClosestPointInSpecifyView(EditElementHandleR eehTarget, int viewNum, DPoint3dR spacePt)
    {
    	double uorperMer = mdlModelRef_getUorPerMeter(ACTIVEMODEL);
    	DPoint3d rtnPt = DPoint3d::FromZero();
    	MSElementDescrP elmdscr2dTarget;
    	if (SUCCESS != mdlElmdscr_convertTo2D(&elmdscr2dTarget, eehTarget.GetElementDescrP(), viewNum, NULL, ACTIVEMODEL, ACTIVEMODEL, false))
    	{
    		return rtnPt;
    	}
    	EditElementHandle eeh2dTarget(elmdscr2dTarget, true, false, ACTIVEMODEL);
    	MSElementDescrP elmdscr3dTarget;
    	RotMatrix rMatrix;
    	mdlRMatrix_fromView(&rMatrix, viewNum, false);
    	DPoint3d viewVecZ, viewVecX;
    	mdlVec_fromRotMatrixRow(&viewVecX, &rMatrix, 0);
    	mdlVec_fromRotMatrixRow(&viewVecZ, &rMatrix, 2);
    	mdlVec_normalize(&viewVecZ);
    	mdlVec_normalize(&viewVecX);
    	rMatrix.Invert();
    	Transform transform = Transform::FromIdentity();
    	transform.SetMatrix(rMatrix);
    	if (SUCCESS != mdlElmdscr_convertTo3D(&elmdscr3dTarget, eeh2dTarget.GetElementDescrP(), FIXEDDEPTH, 0, &transform, ACTIVEMODEL, ACTIVEMODEL))
    	{
    		return rtnPt;
    	}
    	EditElementHandle eeh3dTarget(elmdscr3dTarget, true, false, ACTIVEMODEL);
    	mdlMeasure_closestPointOnElement(&rtnPt, &eeh3dTarget, NULL, &spacePt);
    	DRange3d range1, range2;
    	mdlElmdscr_computeRange(&range1.low, &range1.high, eehTarget.GetElementDescrP(), NULL);
    	mdlElmdscr_computeRange(&range2.low, &range2.high, eeh3dTarget.GetElementDescrP(), NULL);
    	range1.UnionOf(range1, range2);
    	double maxLength = mdlVec_distance(&range1.low, &range1.high);
    	DPoint3d linePtArr[2] = { rtnPt ,rtnPt };
    	if (viewVecZ.x == 0 && viewVecZ.y == 0)
    	{
    		linePtArr->x += uorperMer / 2;
    		(linePtArr + 1)->x -= uorperMer / 2;
    		MSElement lineEle;
    		mdlLine_create(&lineEle, NULL, linePtArr);
    		MSElementDescrP lineElmdscr;
    		mdlElmdscr_new(&lineElmdscr, NULL, &lineEle);
    		EditElementHandle eehLine(lineElmdscr, true, false, ACTIVEMODEL);
    		const int intPtArrCnt = 10;
    		Dpoint3d interPtArr1[intPtArrCnt];
    		Dpoint3d interPtArr2[intPtArrCnt];
    		RotMatrix rMatrixId = RotMatrix::FromIdentity();
    		int interCnt;
    		if (SUCCESS == mdlIntersect_closestBetweenElms
    		(interPtArr1, interPtArr2, &interCnt, eehLine.GetElementDescrP(), eehTarget.GetElementDescrP(), &rMatrixId, &rtnPt, 0.00001))
    		{
    			rtnPt = interPtArr2[0];
    		}
    	}
    	else
    	{
    		mdlVec_addScaled(linePtArr, linePtArr, &viewVecZ, maxLength * 2);
    		mdlVec_addScaled(linePtArr + 1, linePtArr + 1, &viewVecZ, -maxLength * 2);
    		MSElement lineEle;
    		mdlLine_create(&lineEle, NULL, linePtArr);
    		MSElementDescrP lineElmdscr;
    		mdlElmdscr_new(&lineElmdscr, NULL, &lineEle);
    		EditElementHandle eehLine(lineElmdscr, true, false, ACTIVEMODEL);
    		const int intPtArrCnt = 10;
    		Dpoint3d interPtArr1[intPtArrCnt];
    		Dpoint3d interPtArr2[intPtArrCnt];
    		RotMatrix rMatrixId = RotMatrix::FromIdentity();
    		int interCnt = mdlIntersect_allBetweenElms(interPtArr1, interPtArr2, intPtArrCnt, eehLine.GetElementDescrP(), eehTarget.GetElementDescrP(), &rMatrixId, 0.00001);
    		if (interCnt == 0)
    		{
    			return rtnPt;
    		}
    		for (int i = 0; i < (interCnt < intPtArrCnt ? interCnt : intPtArrCnt); i++)
    		{
    			if (abs(interPtArr1[i].z - interPtArr2[i].z) < 0.1)
    			{
    				rtnPt = interPtArr2[i];
    				break;
    			}
    		}
    	}
    	return rtnPt;
    }

    试试我这个函数

    Answer Verified By: Redrum Tan 

  • 如果您就想在工具执行过程中让用户点的点落在三维线的最近点处,其实完全可以不用编程,只需要如下图所示设置MS的捕捉方式为最近(Nearest)即可。



  • 符老师您好,MS自身的Nearest捕捉机制存在两个不足,这是我们与用户确认之后他们所不能接受的:

    1.Nearsest存在距离限制,当距离过大就无法捕捉了,而我们的实际用例中就会出现这种情况;

    2.Nearest无法指定仅捕捉特定的某条线或者某个元素;