- UID
- 756
- 积分
- 197
- 精华
- 贡献
-
- 威望
-
- 活跃度
-
- D豆
-
- 在线时间
- 小时
- 注册时间
- 2002-1-16
- 最后登录
- 1970-1-1
|
楼主 |
发表于 2013-8-24 20:49:49
|
显示全部楼层
[ 本帖最后由 LoveArx 于 2016-11-27 12:52 编辑 ]\n\nFree-Lancer 发表于 2013-8-24 12:21
选了 18000 个Line arc CAD 没反应了!
我优化了下打断的代码,效率极大地提高!测试300*350的直线方格网,也就是650条相交直线,速度居然是秒杀,竟然XDRX_CURVE_INTERSECTBREAK 函数快了几十倍!
500X500的直线方格网比较结果:
比较的结果令人震惊!我改进后的代码主要在于优化了计算曲线交点的过程,看来优化算法对于大量计算来说至关重要!
cad2008 编译的ARX程序:
在CAD2008上同时加载ssbreak2008_x32.arx和晓东API,用如下代码测试:
 - (defun c:tt ()
- (princ "\n第一组曲线:")
- (setq ss (ssget '((0 . "*line,arc,circle,ellipse"))))
- (princ "\n第二组曲线:")
- (setq ss1 (ssget '((0 . "*line,arc,circle,ellipse"))))
- (if (and ss ss1)
- (progn
- (setq *StartTime* (car (_VL-TIMES)))
- (setq l1 (XDRX_CURVE_INTERSECTBREAK ss))
- (princ
- (strcat "\n XDRX_CURVE_INTERSECTBREAK 用时\n "
- (rtos (* 0.001 (- (car (_VL-TIMES)) *StartTime*)) 2 4)
- " 秒 "
- )
- )
- (setq *StartTime* (car (_VL-TIMES)))
- (setq l2 (XLRX-SSBreak ss1 0.01))
- (princ
- (strcat "\n XLRX-SSBreak 用时\n "
- (rtos (* 0.001 (- (car (_VL-TIMES)) *StartTime*)) 2 4)
- " 秒 "
- )
- )
- (princ)
- )
- )
- )
改进后arx的IntersectBreakSS函数源码:
 - //改进后的曲线选择集交点打断
- void IntersectBreakSS (ads_name ss,AcDbVoidPtrArray& curveSegments,ads_real rTol)
- {
- Acad::ErrorStatus es;
- ads_name e1;
- AcGePoint3dArray nPoints;
- AcGeTol tol;
- tol.setEqualPoint(rTol);
- tol.setEqualVector(rTol);
- if (!(nPoints.isEmpty()))
- {
- nPoints.setPhysicalLength(0);
- nPoints.setLogicalLength(0);
- }
- long len;
- acedSSLength(ss,&len);
- //实体个数小于两个,直接返回值
- if (len < 2)
- {
- if (len = 1)
- {
- AcDbEntity *pEnt;
- AcDbObjectId Id;
- acedSSName(ss,0,e1);
- acdbGetObjectId(Id,e1);
- es = acdbOpenObject(pEnt,Id,AcDb::kForRead);
- if (es != Acad::eOk)
- {
- pEnt->close();
- }
- curveSegments.append(pEnt);
- pEnt->close();
- }
- return;
- }
- //将选择集实体转换到对象数组IdArray
- AcDbObjectIdArray IdArray;
- AcDbEntity *pEnt,*pEnt1;
- AcDbObjectId Id,Id1;
- AcDbCurve *pCurve,*pCurve1;
- for (long i =0;i < len;i++)
- {
- acedSSName(ss,i,e1);
- acdbGetObjectId(Id,e1);
- es = acdbOpenObject(pEnt,Id,AcDb::kForRead);
- if (es != Acad::eOk)
- {
- pEnt->close();
- }
- pCurve = AcDbCurve::cast(pEnt);
- if (pCurve == NULL)
- {
- pEnt->close();
- continue;
- }
- IdArray.append(Id);
- pEnt->close();
- }
- //曲线总个数
- len = IdArray.length();
- //创建每条曲线的交点数组
- AcGePoint3dArray *Pt3DArrays = new AcGePoint3dArray[len];
- for (int i = 0;i < len;i++)
- {
- Pt3DArrays.setPhysicalLength(0);
- Pt3DArrays.setLogicalLength(0);
- }
- //计算所有交点,存储在Pt3DArrays数组中
- for (long i = 0;i < len-1;i++)
- {
- Id = IdArray.at(i);
- acdbOpenObject(pEnt,Id,AcDb::kForRead);
- pCurve = AcDbCurve::cast(pEnt);
- AcGePoint3d pstart0,pend0;
- pCurve->getStartPoint(pstart0);
- pCurve->getEndPoint(pend0);
- for (long j = i+1;j < len;j++)
- {
- Id1 = IdArray.at(j);
- acdbOpenObject(pEnt1,Id1,AcDb::kForRead);
- pCurve1 = AcDbCurve::cast(pEnt1);
- AcGePoint3dArray nPts;
- //计算交点
- pEnt->intersectWith(pEnt1,AcDb::kOnBothOperands,nPts);
- AcGePoint3d pstart1,pend1,pt;
- pCurve1->getStartPoint(pstart1);
- pCurve1->getEndPoint(pend1);
- //遍历nPts,除落在曲线端点外的点添加到Pt3DArrays
- for (int m = 0;m < nPts.length();m++)
- {
- pt = nPts[m];
- if (!(pstart0.isEqualTo(pt,tol) || pend0.isEqualTo(pt,tol)))
- {
- //交点添加到第i条曲线上
- Pt3DArrays.append(pt);
- }
- if (!(pstart1.isEqualTo(pt,tol) || pend1.isEqualTo(pt,tol)))
- {
- //交点添加到第j条曲线上
- Pt3DArrays[j].append(pt);
- }
- }
- //判断pCurve1的端点是否在pCurve容差范围之内,添加到交点表第i条曲线上
- pCurve->getClosestPointTo(pstart1,pt);
- if (pstart1.isEqualTo(pt,tol) && !(pstart0.isEqualTo(pt,tol) || pend0.isEqualTo(pt,tol)))
- {
- Pt3DArrays.append(pt);
- }
- pCurve->getClosestPointTo(pend1,pt);
- if (pend1.isEqualTo(pt,tol) && !(pstart0.isEqualTo(pt,tol) || pend0.isEqualTo(pt,tol)))
- {
- Pt3DArrays.append(pt);
- }
- //判断pCurve的端点是否在pCurve1容差范围之内,添加到交点表第j条曲线上
- pCurve1->getClosestPointTo(pstart0,pt);
- if (pstart0.isEqualTo(pt,tol) && !(pstart1.isEqualTo(pt,tol) || pend1.isEqualTo(pt,tol)))
- {
- Pt3DArrays[j].append(pt);
- }
- pCurve1->getClosestPointTo(pend0,pt);
- if (pend0.isEqualTo(pt,tol) && !(pstart1.isEqualTo(pt,tol) || pend1.isEqualTo(pt,tol)))
- {
- Pt3DArrays[j].append(pt);
- }
- pEnt1->close();
- }
- pEnt->close();
- }
- for (long i = 0;i < len;i++)
- {
- AcGePoint3dArray nPts;
- nPts.setPhysicalLength(0);
- nPts.setLogicalLength(0);
- nPts = Pt3DArrays;
- //取出第i条曲线pCurve
- Id = IdArray.at(i);
- acdbOpenObject(pEnt,Id,AcDb::kForRead);
- pCurve = AcDbCurve::cast(pEnt);
- //根据点nPts打断第i条曲线
- if (nPts.length() > 0)
- {
- //nPts按曲线pCurve排序
- CCalculation::QSortPointsOnCurve(pCurve,nPts);
- //len1打断曲线前curveSegments的长度
- long len1 = curveSegments.length();
- pCurve->upgradeOpen();
- //按参数表params打断曲线pCurve
- es = pCurve->getSplitCurves(nPts,curveSegments);
- //len2打断曲线后curveSegments的长度
- long len2 = curveSegments.length();
- if ((len2 - len1) > 1)/*生成了新的曲线*/
- {
- //acutPrintf(_T("\n共生成直线 %d 条!"),(len2 - len1));
- pCurve->erase();
- pEnt->close();
- for (int ii = len1; ii <len2; ii++)
- {
- AcDbEntity *pEntity = NULL;
- pEntity = (AcDbEntity *)curveSegments[ii];
- //将生成的曲线添加到数据库
- CCreateEnt::PostToSpace(pEntity);
- }
- }
- else /*没有生成新曲线*/
- {
- pEnt->close();
- AcDbEntity *pEnt1;
- pEnt1 = (AcDbEntity *)curveSegments[(len2 - 1)];
- delete(pEnt1);
- curveSegments.setAt(len2 - 1,pCurve);
- }
- }
- else /*曲线没有交点,无需打断*/
- {
- pEnt->close();
- curveSegments.append(pCurve);
- }
- }
- delete []Pt3DArrays;
- }
|
-
-
|