找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1020|回复: 5

[讨论]:返回选择集内各类型图元名称及数量-函数优化

[复制链接]

已领礼包: 1个

财富等级: 恭喜发财

发表于 2007-3-12 13:46:02 | 显示全部楼层 |阅读模式

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

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

×
返回选择集内各类型图元名称及数量 
;;当参数为nil时为全图,为T时为当前选择。

  1. (defun NBTF_GetObjTypenum (ss / i j ee objslst ObjName objlst)
  2. ;;  (VL-LOAD-COM)
  3.   ;;若不为选择集且不为nil
  4.   (if (and (/= (type ss) 'PICKSET)
  5.            ss
  6.       ) ;_ 结束and
  7.     (setq ss (ssget "_i"))
  8.   ) ;_ 结束if
  9.   ;;若选择集仍为空
  10.   (if(null ss)(setq ss (ssget "_X")))
  11.   ;;若选择集存在
  12.   (if ss
  13.     (progn
  14.       ;;初始化计数器及总数
  15.       (setq i -1
  16.             j (1-(sslength ss))
  17.       ) ;_ 结束setq
  18.       (while (< i j)
  19.         (setq ee      (ssname ss (setq i(1+ i)));_读图元
  20.               objname (vla-get-ObjectName  (vlax-ename->vla-object ee))
  21.         ) ;_ 结束setq
  22.         ;;写计数表
  23.         (if (setq objlst (assoc objname objSlst))
  24.           (setq        objslst
  25.                  (subst (cons objname (1+ (cdr objlst))) objlst objslst)
  26.           ) ;_ 结束setq
  27.           (setq objslst (append (LIST (cons objname 1)) objslst))
  28.         ) ;_ 结束if
  29.       ) ;_ 结束while
  30.     ) ;_ 结束progn
  31.   ) ;_ 结束if
  32.   objslst
  33. ) ;_ 结束defun

在图元数目过多时,用while遍历很慢,不知能不能优化呢?
能用Active方法来搞就好了。
关键是参数只能是LISP的选择集变量。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 593个

财富等级: 财运亨通

发表于 2007-3-12 16:45:32 | 显示全部楼层

  1. (defun ss_typeandNum (ss / )
  2.   (if (and (/= (type ss) 'PICKSET)
  3.            ss
  4.       ) ;_ 结束and
  5.     (setq ss (ssget "_i"))
  6.   ) ;_ 结束if
  7.   ;;若选择集仍为空
  8.   (if (null ss)
  9.     (setq ss (ssget "_X"))
  10.   )
  11.   (if ss
  12.     (progn
  13.       (vla-delete);_清除一个Bug
  14.       (command ".select" ss "")
  15.       (vlax-for        obj (vla-get-activeselectionset
  16.                       (vla-get-activedocument (vlax-get-acad-object))
  17.                     )
  18.         .
  19.         .
  20.         .
  21.       )
  22.     )
  23.   )
  24. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 24个

财富等级: 恭喜发财

发表于 2007-3-12 17:10:05 | 显示全部楼层
慢的原因不是while,而是你用assoc扫描一个无序表
应该先排序再统计
方法1:
[php]
(DEFUN test1 (ss / tmplst i item)
  ;;选择集->表(也可直接用ssname添加)
  (SETQ ss (VL-REMOVE-IF 'LISTP (MAPCAR 'CADR (SSNAMEX ss))))
  ;;获取图元类型(DXF0)
  (SETQ        ss (MAPCAR (FUNCTION (LAMBDA (x) (CDR (ASSOC 0 (ENTGET x)))))
                   ss
           )
  )
  ;;排序
  (SETQ ss (VL-SORT ss '<))
  ;;统计(也可用vl-remove-if方法)
  (SETQ tmplst nil)
  (SETQ i 1)
  (WHILE ss
    (SETQ item (CAR ss)
          ss  (CDR ss)
    )
    (IF        (= item (CAR ss))
      (SETQ i (1+ i))
      (SETQ tmplst (CONS (LIST item i) tmplst)
            i           1
      )
    )
  )
  tmplst
)
[/php]

不排序的方法
方法2:
[php]
(DEFUN test2 (ss / A LEN LST N RETURN)
  (SETQ lst nil)
  (REPEAT (SETQ n (SSLENGTH ss))
    (SETQ lst (CONS (CDR (ASSOC 0 (ENTGET (SSNAME ss (SETQ n (1- n))))))
                    lst
              )
    )
  )
  (SETQ len (LENGTH lst))
  (WHILE lst
    (SETQ a (CAR lst))
    (SETQ lst (VL-REMOVE-IF (FUNCTION (LAMBDA (x) (= a x))) lst))
    (SETQ return (CONS (LIST a (- len (SETQ len (LENGTH lst)))) return))
  )
  return
)
[/php]

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

使用道具 举报

发表于 2007-3-12 21:26:35 | 显示全部楼层
我觉得用了 append 是主要的原因之一


试试我的
10万个实体统计用5秒; 5万个实体2.4秒,  平均每秒统计2万个实体

  1. 命令: CNTSS
  2. 回车全选!
  3. 选择对象:
  4. 共选中100672个实体
  5. 用时
  6. 00时00分04.97秒
  7. ((SOLID . 45) (HATCH . 2149) (INSERT . 4759) (DIMENSION . 234) (TEXT . 4715)
  8. (LWPOLYLINE . 10338) (LINE . 78432))

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

使用道具 举报

已领礼包: 24个

财富等级: 恭喜发财

发表于 2007-3-12 22:33:13 | 显示全部楼层
好象不是assoc的问题,
刚才把楼主的(vla-get-ObjectName  (vlax-ename->vla-object ...
改成(cdr (assoc 0 (entget ...
速度提高了6倍,呵呵

所以如果不需要得到"AcDb...",那就直接用DXF0
如果需要得到"AcDb...",那还是可以用dxf0,然后设一个一一对应的表,将dxf0 转换为AcDb...
或者使用dxf100获取"AcDb..."
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1个

财富等级: 恭喜发财

 楼主| 发表于 2007-3-13 11:23:51 | 显示全部楼层
测试了一下,我的图形文件有对象29907个,

采用

  1. (vlax-for obj (vla-get-activeselectionset
  2.                      (vla-get-activedocument (vlax-get-acad-object))
  3.                    ) ;_ 结束vla-get-activeselectionset
  4.        (setq
  5.          objname (vla-get-ObjectName obj)
  6.        ) ;_ 结束setq
  7.        ;;写计数表
  8.        (setq objlst (cons objname objlst))
  9.      ) ;_ 结束vlax-for

读对象名称列表就需要7秒多。

而采用

  1. (SETQ lst nil)
  2.   (REPEAT (SETQ n (SSLENGTH ss))
  3.     (SETQ lst (CONS (CDR (ASSOC 100 (reverse(ENTGET (SSNAME ss (SETQ n (1- n)))))))
  4.             lst
  5.           )
  6.     )
  7.   )
复制代码

只需要2秒多

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-17 17:42 , Processed in 0.235526 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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