一、本节课程
C++ ARX二次开发点和闭合多段线的位置关系
二、本节要讲解的知识点
结合自己的业务场景,想想自己开发中可能碰到的点和闭合多段线相对关系的需求:统计多段线内部的所有图块;还可以拓展判断任意曲线跟多段线的相对关系。
三、具体内容
工具函数的添加:
static bool IsEqual(double a,double b,double tol=1.0*10E-7); static int GetRand(int minValue,int maxValue); static double Round(double a,int precision); static int Round(double a); |
bool CMathUtil::IsEqual(double a,double b,double tol/*=1.0*10E-7*/) { return (fabs(a-b)<tol); } //对一个数按照指定的小数位数进行四舍五入 double CMathUtil::Round(double a,int precision) { return (floor(a*pow(10.0,precision)+0.5))/pow(10.0,precision); } int CMathUtil::Round(double a) { return (int)(a+0.5); } int CMathUtil::GetRand(int minValue,int maxValue) { assert(maxValue-minValue>0); int value=rand(); int rc=minValue+(int)CMathUtil::Round(((double)value)/RAND_MAX*(maxValue-minValue));//将生成的随机数映射到区间上。 return rc; } |
static bool IsEqual(const AcGePoint3d &firstPoint,const AcGePoint3d &secondPoint,double tol=1.0E-7); static bool IsEqual(const AcGePoint2d &firstPoint,const AcGePoint2d &secondPoint,double tol=1.0E-7); static int FindPoint(const AcGePoint3dArray &points,const AcGePoint3d &point,double tol=1.0E-7); static int FindPoint(const AcGePoint2dArray &points,const AcGePoint2d &point,double tol=1.0E-7); static void FilterEqualPoints(AcGePoint3dArray &points,double tol=1.0E-7); static void FilterEqualPoints(AcGePoint3dArray &points,const AcGePoint2d &pt,double tol=1.0E-7); |
bool CGePointUtil::IsEqual(const AcGePoint3d &firstPoint,const AcGePoint3d &secondPoint,double tol/*=1.0E-7*/) { return (fabs(firstPoint.x-secondPoint.x)<tol && fabs(firstPoint.y-secondPoint.y)<tol && fabs(firstPoint.z-secondPoint.z)<tol); }
bool CGePointUtil::IsEqual(const AcGePoint2d &firstPoint,const AcGePoint2d &secondPoint,double tol/*=1.0E-7*/) { return (fabs(firstPoint.x-secondPoint.x)<tol && fabs(firstPoint.y-secondPoint.y)<tol ); } //在数组中查找点,返回点在数组中的索引,如果没有找到点就返回-1 int CGePointUtil::FindPoint(const AcGePoint3dArray &points,const AcGePoint3d &point,double tol/*=1.0E-7*/) { for (int i=0;i<points.length();i++) { if (IsEqual(points[i],point,tol)) { return i; } } return -1; }
//在数组中查找点,返回点在数组中的索引,如果没有找到点就返回-1 int CGePointUtil::FindPoint(const AcGePoint2dArray &points,const AcGePoint2d &point,double tol/*=1.0E-7*/) { for (int i=0;i<points.length();i++) { if (IsEqual(points[i],point,tol)) { return i; } } return -1; }
//点数组本身去重复点 void CGePointUtil::FilterEqualPoints( AcGePoint3dArray &points,double tol/*=1.0E-7*/) { for (int i=points.length()-1;i>0;i--) { for (int j=0;j<i;j++) { if (CMathUtil::IsEqual(points[i].x,points[j].x,tol)&& CMathUtil::IsEqual(points[i].y,points[j].y,tol)&& CMathUtil::IsEqual(points[i].z,points[j].z,tol)) { points.removeAt(i); break; } } } } void CGePointUtil::FilterEqualPoints( AcGePoint3dArray &points,const AcGePoint2d &pt,double tol/*=1.0E-7*/) { AcGePoint3dArray tempPoints; for (int i=0;i<points.length();i++) { if (CConvertUtil::ToPoint2d(points[i]).distanceTo(pt)>tol) { tempPoints.append(points[i]); } } points=tempPoints; } |
static bool PointIsPolyVert(AcDbPolyline* pPoly,const AcGePoint2d &pt,double tol=1.0E-7); static void IntersectWithGeRay(AcDbPolyline *pPoly,const AcGeRay2d &geRay,AcGePoint3dArray &intPoints,double tol=1.0E-7); static int PtRelationToPoly(AcDbPolyline *pPoly,const AcGePoint2d &pt,double tol=1.0E-7); |
void CPolylineUtil::IntersectWithGeRay(AcDbPolyline *pPoly,const AcGeRay2d &geRay,AcGePoint3dArray &intPoints,double tol/*=1.0E-7*/) { intPoints.setLogicalLength(0); AcGePoint2dArray intPoints2d;
AcGeTol geTol; geTol.setEqualPoint(tol); for (int i=0;i<(int)(pPoly->numVerts());i++) { if (i<(int)(pPoly->numVerts())-1||pPoly->isClosed()==Adesk::kTrue) { double bugle=0; pPoly->getBulgeAt(i,bugle); if (fabs(bugle)<1.0E-7) { AcGeLineSeg2d geLine; Acad::ErrorStatus es=pPoly->getLineSegAt(i,geLine); AcGePoint2d intPoint; if (geLine.intersectWith(geRay,intPoint,geTol)==Adesk::kTrue) { if (CGePointUtil::FindPoint(intPoints2d,intPoint,tol)<0) { intPoints2d.append(intPoint); } } } else { AcGeCircArc2d geArc; pPoly->getArcSegAt(i,geArc); AcGePoint2d pt1,pt2; int count=0; if (geArc.intersectWith(geRay,count,pt1,pt2,geTol)==Adesk::kTrue) { if (CGePointUtil::FindPoint(intPoints2d,pt1,tol)<0) { intPoints2d.append(pt1); } if (count>1 && CGePointUtil::FindPoint(intPoints2d,pt2,tol)<0) { intPoints2d.append(pt2); } } } } } double z=pPoly->elevation(); for (int i=0;i<intPoints2d.length();i++) { intPoints.append(AcGePoint3d(intPoints2d[i].x,intPoints2d[i].y,z)); } }
int CPolylineUtil::PtRelationToPoly(AcDbPolyline *pPoly,const AcGePoint2d &pt,double tol/*=1.0E-7*/) { assert (pPoly); //1.如果点在多段线的最近点和给定的点重合,表示点在多段线上 AcGePoint3d closestPoint; pPoly->getClosestPointTo(CConvertUtil::ToPoint3d(pt,pPoly->elevation()),closestPoint);
if (fabs(closestPoint.x-pt.x)<tol && fabs(closestPoint.y-pt.y)<tol) { return 0; } //2 第一个射线的方向是从最近点到当前点,起点是当前点 //射线的起点是pt,方向从最近点到pt,如果反向做判断,则最近点距离pt太近的时候,最近点也会被作为一个交点(这个交点不太容易被排除掉) //此外,这样的射线方向很容易判断出点不在内部的情况 AcGeVector3d vec(-(closestPoint[X]-pt[X]),-(closestPoint[Y]-pt[Y]),0); AcGeRay2d geRay(AcGePoint2d(pt.x,pt.y),AcGePoint2d(pt.x+vec.x,pt.y+vec.y));
//3、射线与多段线计算交点 AcGePoint3dArray intPoints; IntersectWithGeRay(pPoly,geRay,intPoints,1.0E-4);
// CGePointUtil::FilterEqualPoints(intPoints,1.0E-4);
RETRY: if(intPoints.length()==0) { return -1; } else { CGePointUtil::FilterEqualPoints(intPoints,CConvertUtil::ToPoint2d(closestPoint));
for (int i=intPoints.length()-1;i>=0;i--) { if ( (intPoints[i][X]-pt[X])*(closestPoint[X]-pt[X])>=0 && (intPoints[i][Y]-pt[Y])*(closestPoint[Y]-pt[Y])>=0 ) { intPoints.removeAt(i); } }
int count=intPoints.length(); for (int i=0;i<intPoints.length();i++) { if (PointIsPolyVert(pPoly,CConvertUtil::ToPoint2d(intPoints[i]),1.0E-4)) { if (PointIsPolyVert(pPoly,AcGePoint2d(pt.x,pt.y),1.0E-4)) { return 0; }
vec=vec.rotateBy(0.035,AcGeVector3d::kZAxis); geRay.set(AcGePoint2d(pt.x,pt.y),AcGePoint2d(pt.x+vec.x,pt.y+vec.y)); intPoints.setLogicalLength(0); IntersectWithGeRay(pPoly,geRay,intPoints,1.0E-4); goto RETRY; } } if (count%2==0) { return -1; } else { return 1; } } } |
详细笔记细节请关注 yunyou.ke.qq.com 报名免费课后加老师微信后获取。