明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 408|回复: 10

[经验] 非递归模式获取块中深度嵌套的图元

[复制链接]
发表于 前天 20:36 | 显示全部楼层 |阅读模式
本帖最后由 dcl1214 于 2024-12-22 21:42 编辑

块中块深度嵌套的时候,要想获取块中所有图元,很多同仁一开始就想到递归,其实我是比较抵触递归的,所以,随手写了一个非递归模式获取块中块图元的代码,哪位还有速度更快的(块中块深度嵌套很多),可以一起切磋一下
请下载vlx测试,速度极快
  1. (defun $kuai-nei-tu-yuan$ (ENT-B lst / $kn-objs$ a blks e ents-all obj)
  2.           ;非递归模式获取块内图元
  3.   (defun $kn-objs$ (ENT-B / a blk ents km obj)
  4.     (if
  5.       (= (TYPE ENT-B) 'ENAME)
  6.        (SETQ OBJ (vlax-ename->vla-object ENT-B))
  7.     )
  8.     (IF  (and OBJ (= (type obj) 'VLA-object))
  9.       (if (vlax-property-available-p obj 'effectivename)
  10.   (setq km (vla-get-effectivename obj))
  11.   (if (vlax-property-available-p obj 'name)
  12.     (setq km (vla-get-name obj))
  13.   )
  14.       )
  15.     )
  16.     (setq blk (vl-catch-all-apply
  17.     'vla-item
  18.     (list (vla-get-blocks
  19.       (vla-get-activedocument
  20.         (vlax-get-acad-object)
  21.       )
  22.           )
  23.           km
  24.     )
  25.         )
  26.     )
  27.     (if  blk
  28.       (vlax-for  a blk
  29.   (setq ents (cons a ents))
  30.       );遍历blk对象
  31.     )
  32.     ents
  33.   )
  34.   (setq ents-all nil)
  35.   (setq obj nil)
  36.   (setq blks ($kn-objs$ ENT-B));块中obj对象
  37.   (while (setq obj (car blks));循环第一个obj
  38.     (setq e nil)
  39.     (setq e (vlax-vla-object->ename obj));转换为图元
  40.     (if  (= (vla-get-objectname obj) "AcDbBlockReference");如果是块对象
  41.       (setq blks (append blks ($kn-objs$ e)));获取块中obj对象,拼接到blks尾巴上
  42.       (setq ents-all (cons e ents-all));如果不是块对象就收集到ents-all里面,下面要返回给上一级
  43.     )
  44.     (setq blks (cdr blks));下一个obj对象
  45.   )
  46.   (setq ents-all (reverse ents-all));倒置
  47.   ents-all
  48. )



  1. ;;; 示例
  2. (setq ent-b (car (entsel)))
  3. (setq ents ($kuai-nei-tu-yuan$ ent-b nil))
  4. (mapcar  (function
  5.     (lambda (a)
  6.       (vl-catch-all-apply
  7.         'vla-put-color
  8.         (list
  9.     (vl-catch-all-apply 'vlax-ename->vla-object (list a))
  10.     1
  11.         )
  12.       )
  13.     )
  14.   )
  15.   ents
  16. )



本帖子中包含更多资源

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

x

评分

参与人数 1明经币 +1 收起 理由
飞雪神光 + 1 很给力!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
回复

使用道具 举报

发表于 前天 23:05 | 显示全部楼层
本帖最后由 你有种再说一遍 于 2024-12-22 17:16 编辑

我也有一段时间跟你一样觉得,
既然递归会爆栈,那么全改循环不就好了,后来发现其实不然.
如果不喜欢递归,这通常对于编译器的信心不足引起的,
因为尾递归优化是可以消除新栈帧的,
而且存入堆容器再拿出来,比起开辟栈帧再拿出来效率更低,
所以其实建议是多写递归,尤其是尾递归,
毕竟有成千上万的人来实现编译器优化,就连Lisp内部也会做的.

点评

大师;尾递归和递归的区别就是,把结果重新赋值给变量;其他不变;是这样吗  发表于 1 小时前
回复 支持 反对

使用道具 举报

发表于 昨天 11:30 | 显示全部楼层
这样获取出来的图元列表没有任何用途,块内定义的图形,其parent都是各自上层块定义,一堆父亲不一样的图元弄到一个列表里,你咋做下一步处理?有啥实际需求要做这种处理?同时,同名的图块如果嵌套在不同的层次,或者同一个层级有若干同名图块,会返回一堆图形重复,都混合在一个表里,这种垃圾数据表有存在的意义吗?
回复 支持 反对

使用道具 举报

发表于 昨天 12:16 | 显示全部楼层
本帖最后由 wudechao 于 2024-12-22 13:10 编辑

有bug.但是速度很快,我用在关闭图块所有图层(建筑提资的图,很多块中块,比如想关闭某些块,这些块是块中块),先获取图块所有图元,取块中每个图元的图层,消重复图层,最后逐个关闭图层,速度非常快,比我原来用递归快一倍。反复执行这个函数,就出现错误,不知道是什么原因。
回复 支持 反对

使用道具 举报

发表于 昨天 13:31 | 显示全部楼层
本帖最后由 ssyfeng 于 2024-12-22 13:56 编辑
你有种再说一遍 发表于 2024-12-21 23:05
我也有一段时间跟你一样觉得,
然后递归会爆栈,那么全改循环不就好了,
后来发现其实不然.

确实尾递归比其它递归要快一倍,比楼主的也稍微快一点
回复 支持 反对

使用道具 举报

发表于 昨天 15:24 | 显示全部楼层
wudechao 发表于 2024-12-22 12:16
有bug.但是速度很快,我用在关闭图块所有图层(建筑提资的图,很多块中块,比如想关闭某些块,这些块是块中 ...

这种需求,直接用DBX比这种递归快n倍,尤其是大图。
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 21:39 | 显示全部楼层
kozmosovia 发表于 2024-12-22 11:30
这样获取出来的图元列表没有任何用途,块内定义的图形,其parent都是各自上层块定义,一堆父亲不一样的图元 ...

我编译成【独立空间】了,提速9000倍
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 21:40 | 显示全部楼层
ssyfeng 发表于 2024-12-22 13:31
确实尾递归比其它递归要快一倍,比楼主的也稍微快一点

下载我的vlx试试,我编译成【独立空间】了,提速9000倍
回复 支持 反对

使用道具 举报

发表于 10 小时前 | 显示全部楼层
同一个图元重复处理无数次,有什么意义?
回复 支持 反对

使用道具 举报

发表于 10 小时前 | 显示全部楼层
根本不存在快不快的概念,同一图元重复处理无数次,本身就是慢的方案,CAD数据库块里只有参照,不存在多层的概念,块参照就是一个图元,n个参照的图元数量就只有块内图元数量+n,而并不是块内图元数量*n
回复 支持 反对

使用道具 举报

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

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-12-23 11:17 , Processed in 0.207777 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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