|
关于AcDbEntity::intersectWith()实体求交及将
曲线实体AcDbCurve沿交点打断
Autocad实体求交均使用AcDbEntity::intersectWith()求交函数,该函数有两个版本,分别对应不同的情况。
一、 同一平面实体求交及曲线沿交点打断
位于同一平面的两实体求交,使用:
virtual Acad::ErrorStatus
intersectWith(
const AcDbEntity* pEnt,
AcDb::Intersect intType,
AcGePoint3dArray& points,
int thisGsMarker = 0,
int otherGsMarker = 0) const;
其中:
pEnt 为与使用该方法的“this”实体求交的实体
intType 输入要求求交类型
points 输出求得的交点数组
thisGsMarker Input GS marker of subentity of"this" entity that's involved in the intersection operation. Use the0 default if not applicable.
otherGsMarker Input GS marker of subentity of the entitypointed to by pEnt that's involved in the intersection operation. Use the 0default if not applicable.
用途:
找出pEnt实体和“this”实体边界框所有边的交点。
(It finds the intersections of the entitypointed to by pEnt and all the edges of the bounding box of this entity.)
1、当两实体均为曲线AcDbCurve实体派生类实体时,是曲线间的交点
2、当两实体中有块(AcDbBlockReference)、文字(AcDbText、AcDbMText)时,是曲线与他们边界框的交点,或边界框之间的交点
3、当曲线实体与填充图案(AcDbHatch)求交时,是曲线与组织图案的线段的交点,这点与曲线与块的交点不同
4、当填充图案与文字、块求交时,是组成图案的线段与文字、块的边界框的交点。
两个实体只要位于同一平面,均可以用该版本求交函数求得交点,这样求得曲线上的交点后,曲线均可以采用曲线AcDbCurve的方法:
virtual Acad::ErrorStatus
getSplitCurves(
const AcGePoint3dArray& points,
AcDbVoidPtrArray& curveSegments) const;进行打断。
但最好使用其另一版本:
virtual Acad::ErrorStatus
getSplitCurves(
const AcGeDoubleArray& params,
AcDbVoidPtrArray& curveSegments) const;
二、 不同平面二维实体求交
当二维多线段有高程、样条曲线有z坐标时,求他们与它不在同一平面其它实体的交点。由于他们不在同一平面上,需用求交的另一版本函数:
virtualAcad::ErrorStatus
intersectWith(
constAcDbEntity* pEnt,
AcDb::IntersectintType,
constAcGePlane& projPlane,
AcGePoint3dArray&points,
intthisGsMarker = 0,
intotherGsMarker = 0) const;
其中:
projPlane 两个实体外观交点的投影平面
这个函数与上一个函数的区别:
这个函数把“this”实体和pEnt实体投影到projPlane平面上、找出交点,然后把交点投影回“this”实体上。这是与上一个函数的不同点,其它的相同。所有增加到points数组的点是在“this”实体上。投影按平行projPlane平面的法线矢量方向进行。
对于三维多线段,也能使用该函数求得交点,但交点不是在三维多线段上,因此不能按此求得的交点将三维多线段沿交点打断。
经测试下面两种使用方法均能得出交点,但要正确沿交点打断曲线,确定好“this”实体是很重要的。要打断的那条曲线就是“this”实体,也即需要使用被打断的曲线实体的求交函数来求交点。
1、将两实体投影到XY平面
AcGePlaneplane; //XY平面
AcGePoint3dArray intersectionPoints;
pEnt1->intersectWith (pEnt2,AcDb::kOnBothOperands,plane,intersectionPoints);
此时,交点的z坐标就是曲线pEnt1的z坐标或标高。
2、将两实体投影到“this”实体所在平面或者投影到pEnt实体所在平面
AcDb::Planarity flag;
AcGePlane plane;
AcGePoint3dArray intersectionPoints;
Acad::ErrorStatus es;
es=pEnt1->getPlane(plane,flag); //获得实体pEnt1所在平面plane
// es=pEnt2->getPlane(plane,flag); //获得实体pEnt2所在平面plane
pEnt1->intersectWith (pEnt2,AcDb::kOnBothOperands,plane,intersectionPoints);
交点的z坐标就是使用求交方法实体的z坐标或标高,也就是交点是在使用求交方法的曲线实体上的。
三、 三维多段线与其它实体的求交
为了正确求得三维多线段上的交点及沿其交点打断三维多线段,应采用下列方法:
1、获取pCur2曲线(“this”实体,需打断的三维多线段)在pCur1曲线所在平面的正射投影曲线projCrv
2、取得projCrv曲线上与pCur1曲线的交点
3、取得projCrv曲线上交点对应的参数化曲线的参数
4、依据投影曲线projCrv与原曲线pCur2参数相同,将投影面上的交点投影返回到原曲线pCur2上,取得pCur2曲线与pCur1曲线在pCur2曲线上的交点。
程序代码段:
AcDb::Planarity flag;
AcGePlane plane;
AcDbCurve * projCrv,*pCur1,*pCur2;
AcGePoint3dArray pnts, intersectionPoints;
Acad::ErrorStatus es;
es=pEnt1->getPlane(plane,flag); //获得曲线pCur1所在平面plane
if(es!=Acad::eOk)
{
acutPrintf (_T("\ngetPlanefailed : es = %s"),acadErrorStatusText(es));
return(RTERROR);
}
es=pCur2->getOrthoProjectedCurve(plane,projCrv);
if (es!=Acad::eOk)
{
acutPrintf (_T("\ngetOrthoProjectedCurve : es =%s"),acadErrorStatusText(es));
return (RTERROR);
}
es=projCrv->intersectWith(pCur1,AcDb::kOnBothOperands,pnts);
if(es!=Acad::eOk)
{
acutPrintf (_T("\nintersectWith : es =%s"),acadErrorStatusText(es));
return (RTERROR);
}
int len=pnts.length();
double * param=new double[len];
AcGePoint3d pt;
for (int i=0;i<len;i++)
{
projCrv->getClosestPointTo(pnts,pt);
projCrv->getParamAtPoint(pt,param);
}
for (int i=0;i<len;i++)
{
pCur2->getPointAtParam(param,pt);
intersectionPoints.append(pt);
}
四、两条z坐标均为非定值的样条曲线相交打断
以下三种情况采用上述方法均不能求得交点,也就不能沿交点打断曲线。
1、两条z坐标均为非定值的三维多线段相交打断
2、z坐标非定值的样条曲线与z坐标非定值的三维多线段相交打断
3、两条z坐标均为非定值的样条曲线相交打断
解决问题设想:
1、先求两条曲线在同一平面正射投影曲线projCrv
2、求两条正射投影曲线projCrv的交点
3、再将交点投影回到原曲线上得交点。
经测试,在autocad2006下,能达到目的,但在cad2012下有时不能达到目的
该部分代码可从上面的代码演变可得。
五、存在问题
目前根据求交、打断编制的任意多边形裁图程序的裁图效果还比较满意。但存在以下问题:
1、有时会出现极个别曲线不能裁断的情况,有的进行二次操作后可以剪断。这个别曲线有的用cad命名也无法剪断。不知何故?
2、当自相交曲线的交点正好位于剪切边界上时,只能打断曲线其中一边
3、该程序在打断前求交选择实体对象及打断后平移、旋转实体变换均是采用获取选择集的方式,因此要裁剪部分图形选择后必须位于屏幕可见区域内,否则就会出现**没有裁剪的情况,不知用何方法解决??
4、对于打断样条拟合的二维多线段在2006会出错,打断前需进行预处理,而在2012下没有问题,打断前不需预处理。
附上程序:cad2006版
任意多边形裁剪命令:brkcur
实体求交测试命令:curjd
两条曲线交点打断测试命令:ddcur |
|