找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3851|回复: 18

[求助] 求改进:计算曲线选择集交点

[复制链接]
发表于 2013-8-20 14:23:46 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
初学arx,很多方面知识欠缺!自己尝试写了个曲线选择集计算交点的函数,代码如下:
  1. void CurveInters(ads_name ss,AcGePoint3dArray & pPoints)
  2. {
  3.   long len,total;
  4.   acedSSLength(ss,&len);
  5.   if (len < 2)
  6.   {
  7.     return ;
  8.   }
  9.    AcDbVoidPtrArray entArray;
  10.   ads_name ent;
  11.   AcDbObjectId entId;
  12.   for (int i = 0;i < len; i++)
  13.   {
  14.     acedSSName(ss, i, ent);
  15.     acdbGetObjectId(entId,ent);
  16.     AcDbEntity *pEnt;
  17.     acdbOpenObject(pEnt,entId, AcDb::kForRead);
  18.     entArray.append(pEnt);
  19.   }
  20.   AcDbEntity *pEnt1,*pEnt2;
  21.   for (int i = 0;i < (len - 1);i++)
  22.   {
  23.     pEnt1 = AcDbEntity::cast((AcRxObject*)entArray);
  24.     for (int j = i + 1;j < len;j++)
  25.     {

  26.       pEnt2 = AcDbEntity::cast((AcRxObject*)entArray[j]);
  27.       AcGePoint3dArray pPtArray;
  28.       pEnt1->intersectWith(pEnt2,AcDb::kOnBothOperands,pPtArray);
  29.       pPoints.append(pPtArray);

  30.     }

  31.   }
  32.   for (int i = 0;i < len;i++)
  33.   {
  34.     pEnt1 = AcDbEntity::cast((AcRxObject*)entArray);
  35.     pEnt1->close();
  36.   }

  37.   return ;
  38. }


问题:该函数计算4000个实体交点的用时是晓东API函数 XDRX_GETSSINTERS 用时的3倍!
我相信,肯定是我的代码有问题,望高手们指点指点!不胜感激!

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
发表于 2013-8-20 14:38:28 | 显示全部楼层
不会ARX,只是听说过有AcDb和AcGe区别,用AcDb和ActivX的 IntersectWith 类似吧,效率高不上去

点评

还没开始学习几何类的用法!  详情 回复 发表于 2013-8-20 14:43
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-20 14:43:00 | 显示全部楼层
Free-Lancer 发表于 2013-8-20 14:38
不会ARX,只是听说过有AcDb和AcGe区别,用AcDb和ActivX的 IntersectWith 类似吧,效率高不上去

还没开始学习几何类的用法!

点评

呵呵,借用LoveARX一句话“不会AcGe库就是不会ARX”,努力啊  详情 回复 发表于 2013-8-20 14:49
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2013-8-20 14:49:57 | 显示全部楼层
Love-Lisp 发表于 2013-8-20 14:43
还没开始学习几何类的用法!

呵呵,借用LoveARX一句话“不会AcGe库就是不会ARX”,努力啊
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 145个

财富等级: 日进斗金

发表于 2013-8-20 15:17:20 | 显示全部楼层
楼主,确信用的是 xdrx_getSSInters 还是 xdrx_curve_getinters ?

如果是xdrx_getSSInters ,你用的什么时候版本的API? 现在新的API已经没这函数了。

点评

之前测试的是8月5号未更新的版本! 更新8月20号的API,用xdrx_curve_getinters计算交点,好像效率低了很多啊!不过4000个实体求交点还是比我定义的arx快近1倍! 老大给解释解释原因啊!  详情 回复 发表于 2013-8-20 15:37
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-20 15:37:05 | 显示全部楼层
XDSoft 发表于 2013-8-20 15:17
楼主,确信用的是 xdrx_getSSInters 还是 xdrx_curve_getinters ?

如果是xdrx_getSSInters ,你用的什么 ...

之前测试的xdrx_getSSInters 函数是8月5号未更新的版本!
更新8月20号的API,用xdrx_curve_getinters计算交点,好像效率低了很多啊!不过4000个实体求交点还是比我定义的arx快近1倍!
老大给解释解释原因啊!

点评

上面的代码是 xdrx_getSSInters实现的核心部分,你放你的代码里面看看,速度提高不?  详情 回复 发表于 2013-8-20 15:42
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 145个

财富等级: 日进斗金

发表于 2013-8-20 15:40:10 | 显示全部楼层
10多年前写的代码了,和你的比较,

没把选择集先放到AcDbVoidPtrArray里面,直接选择集提出实体,你可能这个地方慢了,这个地方先放到数组里面多余了。

  1. Adesk::Boolean RetIntersSec(ads_name ss ,AcGePoint3dArray& nPts,int IntExtMode)
  2. {
  3.         long len;
  4.         ads_name nEname1,nEname2;
  5.         AcDbObjectId id1,id2;
  6.         AcDbCurve *pCurve1,*pCurve2;;
  7.         AcDbEntity *pEnt1,*pEnt2;
  8.         Acad::ErrorStatus es;
  9.         if ((ads_sslength(ss,&len)!=RTNORM)&&(len<2))
  10.                 return Adesk::kFalse;
  11.         if (!(nPts.isEmpty())){
  12.                 nPts.setPhysicalLength(0);
  13.                 nPts.setLogicalLength(0);
  14.         }
  15.         for (int i=0;i<len;i++){
  16.                 ads_ssname(ss,i,nEname1);
  17.                 acdbGetObjectId(id1,nEname1);
  18.                 es=acdbOpenAcDbEntity(pEnt1,id1,AcDb::kForRead);
  19.                 if (es!=Acad::eOk)
  20.                         continue;
  21.                 if ((pCurve1=AcDbCurve::cast(pEnt1))==NULL){
  22.                         pEnt1->close();
  23.                         continue;
  24.                 }
  25.                 for (int j=i+1;j<len;j++){
  26.                         ads_ssname(ss,j,nEname2);
  27.                         acdbGetObjectId(id2,nEname2);
  28.                         es=acdbOpenAcDbEntity(pEnt2,id2,AcDb::kForRead);
  29.                         if (es!=Acad::eOk)
  30.                                 continue;
  31.                         if ((pCurve2=AcDbCurve::cast(pEnt2))==NULL){
  32.                                 pEnt2->close();
  33.                                 continue;
  34.                         }
  35.                         if (IntExtMode==1){
  36.                                 pEnt1->intersectWith(pEnt2,AcDb::kExtendBoth,nPts);
  37.                         }
  38.                         else if (IntExtMode==0){
  39.                                 pEnt1->intersectWith(pEnt2,AcDb::kOnBothOperands,nPts);
  40.                         }
  41.                         pEnt2->close();
  42.                 }
  43.                 pEnt1->close();
  44.         }
  45.         return ((nPts.isEmpty())?Adesk::kFalse:Adesk::kTrue);
  46. }



论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 145个

财富等级: 日进斗金

发表于 2013-8-20 15:42:28 | 显示全部楼层
Love-Lisp 发表于 2013-8-20 15:37
之前测试的xdrx_getSSInters 函数是8月5号未更新的版本!
更新8月20号的API,用xdrx_curve_getinters计算 ...

上面的代码是 xdrx_getSSInters实现的核心部分,你放你的代码里面看看,速度提高不?

点评

通过看你的代码,我找到慢的原因了!问题在这里: / AcGePoint3dArray pPtArray; pEnt1->intersectWith(pEnt2,AcDb::kOnBothOperands,pPtArray); pPoints.append(pPtArray); 改成这样  详情 回复 发表于 2013-8-20 16:39
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-20 16:39:40 | 显示全部楼层
本帖最后由 Love-Lisp 于 2013-8-20 16:40 编辑
XDSoft 发表于 2013-8-20 15:42
上面的代码是 xdrx_getSSInters实现的核心部分,你放你的代码里面看看,速度提高不?

通过看你的代码,我找到慢的原因了!问题在这里:             AcGePoint3dArray pPtArray;
         pEnt1->intersectWith(pEnt2,AcDb::kOnBothOperands,pPtArray);
         pPoints.append(pPtArray);
        改成这样即可:
          pEnt1->intersectWith(pEnt2,AcDb::kOnBothOperands,pPoints);

       还是对指针理解不透彻!
      现在修改后的4000个物体的计算速度已经比xdrx_curve_getinters函数要快30%!



点评

你的函数传递进来的是引用,所以直接往里面赋值就传回去了,你慢的原因是在循环里面,创建数组对象,没循环次都要创建,析构。 另外,修改后,你比较了和 xdrx_getSSInters 的快慢了吗?  详情 回复 发表于 2013-8-20 18:10
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

发表于 2013-8-20 16:49:48 来自手机 | 显示全部楼层

就是说xdrx_curve_getinters还有优化空间?来自: Android客户端
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 145个

财富等级: 日进斗金

发表于 2013-8-20 18:10:59 | 显示全部楼层
Love-Lisp 发表于 2013-8-20 16:39
通过看你的代码,我找到慢的原因了!问题在这里:             AcGePoint3dArray pPtArray;
         pE ...

你的函数传递进来的是引用,所以直接往里面赋值就传回去了,你慢的原因是在循环里面,创建数组对象,没循环次都要创建,析构。

另外,修改后,你比较了和 xdrx_getSSInters 的快慢了吗? 原先你说慢3倍,现在比curve_getinters快30%,好像还是比xdrx_getSSInters慢啊。

点评

经测试,4000个实体,我修改后的函数运行效率要比xdrx_getSSInters高! xdrx_getSSInters : 用时 94.646 秒 CURVEINTERS : 用时 87.158 秒 xdrx_curve_getinters函数效率比xdrx_getSSInters低,  详情 回复 发表于 2013-8-20 19:11
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-20 19:11:53 | 显示全部楼层
本帖最后由 Love-Lisp 于 2013-8-20 19:18 编辑
XDSoft 发表于 2013-8-20 18:10
你的函数传递进来的是引用,所以直接往里面赋值就传回去了,你慢的原因是在循环里面,创建数组对象,没循 ...

经测试,4000个实体,我修改后的函数运行效率要比xdrx_getSSInters高!计算出的交点个数同为64419个!
xdrx_getSSInters :
  用时  94.646  秒

CURVEINTERS :
  用时  87.158  秒
我想7楼给出的代码里,每次计算交点,实体都要先打开,再关闭,这样打开关闭的次数是 n+ (n-1) + ... 1次,我的代码是先将所有的对象一次先打开,全部交点计算完成后再一次性关闭,是不是这儿也会有不少时间差呢?

xdrx_curve_getinters函数效率比xdrx_getSSInters低,是不是考虑了容差导致的?


点评

看代码你的就应该快,我的程序里面加了曲线的判断,也加了两种扩展方式的判断,在大量循环的时候肯定要浪费不少时间,一次性都打开提高不了太多的性能,以前测试过,打开对象写表格不关闭,和打开关闭时间差不多多少  详情 回复 发表于 2013-8-20 19:41
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-20 19:32:35 | 显示全部楼层
同样测试4000条直线,交点个数为12800,
xdrx_getSSInters :
  用时  1.67  秒
CURVEINTERS :
  用时  1.248  秒
要是实体包含其他各种曲线,正如12楼的用时,和纯直线比起来,计算速度差距也太大了!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 145个

财富等级: 日进斗金

发表于 2013-8-20 19:41:26 | 显示全部楼层
Love-Lisp 发表于 2013-8-20 19:11
经测试,4000个实体,我修改后的函数运行效率要比xdrx_getSSInters高!计算出的交点个数同为64419个!
x ...

看代码你的就应该快,我的程序里面加了曲线的判断,也加了两种扩展方式的判断,在大量循环的时候肯定要浪费不少时间,一次性都打开提高不了太多的性能,以前测试过,打开对象写表格不关闭,和打开关闭时间差不多多少。

不推荐你一次性都打开对象,然后等着操作,万一有故障什么的程序不正常退出了呢,那些对象都打开,CAD就要出错了。

点评

明白了!一次性打开万万使不得!程序中途意外中断就麻烦了!修改后的代码用时基本和xdrx_getssinters一样了!  详情 回复 发表于 2013-8-20 20:24
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-20 20:24:22 | 显示全部楼层
XDSoft 发表于 2013-8-20 19:41
看代码你的就应该快,我的程序里面加了曲线的判断,也加了两种扩展方式的判断,在大量循环的时候肯定要浪 ...

明白了!一次性打开万万使不得!程序中途意外中断就麻烦了!修改后的代码用时基本和xdrx_getssinters一样了!
  1. void SSInters(ads_name ss,AcGePoint3dArray & pPoints)
  2. {
  3.   Acad::ErrorStatus es;
  4.   long len;
  5.   acedSSLength(ss,&len);
  6.   if (len < 2)
  7.   {
  8.     return ;
  9.   }

  10.   ads_name e1,e2;
  11.   AcDbEntity *pEnt1,*pEnt2;
  12.   AcDbObjectId Id1,Id2;
  13.   for (int i = 0;i < (len - 1);i++)
  14.   {
  15.     acedSSName(ss, i, e1);
  16.     acdbGetObjectId(Id1,e1);
  17.         es = acdbOpenObject(pEnt1,Id1, AcDb::kForRead);
  18.     if (es != Acad::eOk)
  19.     {
  20.       pEnt1->close();
  21.       continue;
  22.     }/*如果只计算曲线交点,请使用如下语句
  23.     if (AcDbCurve::cast(pEnt1) == NULL)
  24.     {
  25.       pEnt1->close();
  26.       continue;
  27.     }*/
  28.     for (int j = i + 1;j < len;j++)
  29.     {
  30.       acedSSName(ss, j, e2);
  31.       acdbGetObjectId(Id2,e2);
  32.       es = acdbOpenObject(pEnt2,Id2, AcDb::kForRead);
  33.       if (es != Acad::eOk)
  34.       {
  35.         pEnt2->close();
  36.         continue;
  37.       }/*如果只计算曲线交点,请使用如下语句
  38.       if (AcDbCurve::cast(pEnt2) == NULL)
  39.       {
  40.         pEnt2->close();
  41.         continue;
  42.       }*/

  43.       pEnt1->intersectWith(pEnt2,AcDb::kOnBothOperands,pPoints);
  44.       pEnt2->close();

  45.     }
  46.     pEnt1->close();

  47.   }

  48.   return ;
  49. }

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-11-14 22:06 , Processed in 0.203130 second(s), 56 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表