明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 14827|回复: 37

写给新手,也谈已知选择集中根据实体类型筛选实体及代码优化

    [复制链接]
发表于 2012-4-26 11:08:16 | 显示全部楼层 |阅读模式
本帖最后由 firstinti 于 2012-4-26 11:11 编辑

看到斑竹在讨论这个问题,http://bbs.mjtd.com/thread-84990-1-1.html
刚好最近写程序也遇上,以前虽然也有做过但是没有系统考虑过,而且斑竹也提到代码简化的问题,所以现在整理一下把成果发上来,大家讨论讨论,一起感受下lisp的语言之美
我们目的就是要从一个已知选择集中剥离出需要的类型实体,一种办法可以采用网友lazybug 的办法:
(defun c:test ()
  (setq ss1 nil ss2 nil)
  (if (setq ss1 (ssget '((0 . "LINE,circle"))))
    (progn
      (setq ss2 (ssget "p" '((0 . "circle"))))
      (command "select" ss1 "")
      (setq ss1 (ssget "p" '((0 . "LINE"))))
    )
  )
)
这个代码关键其实就是上面的红字部分,采用命令select来解决重复选择的问题,但是一般对我来说是尽量避免直接采用命令来嵌入程序,因为有时候会有副作用
我的做法是采用  (sssetfirst nil ss),也可以达到目的
下面是筛选天正实体的一段代码:
(setq ss(ssget))  
  ;墙
  (setq ss-wall(ssget "p" (list(cons 0 "TCH_WALL"))))
  (sssetfirst nil ss)
  ;窗
  (setq ss-window(ssget "p" (list(cons 0 "TCH_OPENING")(cons  71 1))))
  (sssetfirst nil ss)
  ;柱
  (setq ss-column(ssget "p" (list(cons 0 "TCH_COLUMN"))))
这两种办法既有区别也有相通之处,区别下面再说,相同之处就是如果要筛选出不同的实体集就需要不停的重复选择,筛选实体写多了的话就会有大段大段的重复代码。这其实不符合lisp精简高效的结构,所以代码需要优化。经验告诉我们,只要重复的,就是多余的。
比如下面这段代码:
(setq ss(ssget))  
;圆
  (setq ss-circle(ssget "p" (list(cons 0 "circle"))))
(sssetfirst nil ss)
;线
(setq ss-line(ssget "p" (list(cons 0 "*line"))))
  (sssetfirst nil ss)
;文字
(setq ss-text(ssget "p" (list(cons 0 "*text"))))
  sssetfirst nil ss)
仅仅筛选三个实体集,就写了这么长的一段,太冗长,这种情况可以用子函数解决:
(defun wmg-ssgetp (ss filter)
(sssetfirst nil ss)
  (ssget "p" (list (cons 0 filter)))
)
(这里我顺便说一下,我习惯采用 (list (cons 0 filter)))这种结构,因为参数是可以变化的,这样的做法对于lisp来说好处非常多,而'((0 . "circle"))的局限比较多,尽量少用为好)
后面的代码就简单了:
(setq ss-circle(wmg-ssgetp  ss "circle") )
(setq ss-lline(wmg-ssgetp  ss "*line") )
(setq  ss-text(wmg-ssgetp  ss "*text") )
筛选选择集个数越多,子函数的优势越明显。但是,是不是觉得还是有很多代码结构是一样的?所以代码还可以进一步优化。
现在面临的问题就是:如何把筛选出的多个选择集赋给多个变量?这里我采用的是字符串转为变量的办法,看看下面这段代码:
(defun c:tt ()
  (setq ss (ssget))
  (setq vartxtlst (list "ss1" "ss2" "ss3")
filterlst (list "circle" "*line" "*text")
  )
  (mapcar (function (lambda (x y) (set x (wmg-ssgetp ss y))))
   (mapcar 'read vartxtlst)
   filterlst
  )
)
上面这段代码有两个小技巧,一个是read函数,一个是set函数,这两个函数其实用处是相当大的,但是很容易被忽略,我个人是把这样的函数归类为代码函数,就是专门用来优化程序语言本身的函数,程序优化后,完整的代码如下:
(defun c:tt ()
(defun wmg-ssgetp (ss filter)
  (sssetfirst nil ss)
  (ssget "p" (list (cons 0 filter)))
)

  (setq ss (ssget))
  (setq vartxtlst (list "ss1" "ss2" "ss3")
filterlst (list "circle" "*line" "*text")
  )
  (mapcar (function (lambda (x y) (set x (wmg-ssgetp ss y))))
   (mapcar 'read vartxtlst)
   filterlst
  )
)

到此好像大功告成了,但是真的就结束了么?不是的,其实上面的代码是有问题的,上面代码运行是不会得到想要的结果的。
问题在哪?其实是出在 (sssetfirst nil ss)这个语句上,正确的做法是把 (sssetfirst nil ss)改为(vl-cmdf "select" ss ""),这也就是前面我说有区别的原因。
最后的代码:
(defun c:tt ()

(defun wmg-ssgetp (ss filter)   
    (vl-cmdf "select" ss "")
    (ssget "p" (list (cons 0 filter)))
)

  (setq ss (ssget))
  (setq vartxtlst (list "ss1" "ss2" "ss3")
filterlst (list "circle" "*line" "*text")
  )
  (mapcar (function (lambda (x y) (set x (wmg-ssgetp ss y))))
   (mapcar 'read vartxtlst)
   filterlst
  )
)
但是,这样就完了?只要你愿意,你完全可以把上述代码写成一个函数,以后直接调用就好了,lisp的优化之路永远没有尽头。
=======================================================
其实好几年我一直在明经潜水,在这里学习了很多,收获了很多,今天刚好看到斑竹的问题,突然想特别写一个给新手的帖子,因为我也是从新手菜鸟过来的,但是个人水平很差,其实不应该写这些的,希望高手包含。

点评

直觉告诉我,此贴很有价值  发表于 2017-4-4 22:01
今天后天看此贴还是不明白, (sssetfirst nil ss)改为(vl-cmdf "select" ss ""),, 我用前者也挺好呀。不明白区别  发表于 2013-5-23 09:30

评分

参与人数 6明经币 +9 金钱 +15 收起 理由
wowan1314 + 1 受益良多,感谢
gbhsu + 2
langjs + 2 很给力!写的真好
500w008 + 1 赞一个!
xiaxiang + 2 赞一个!
Gu_xl + 1 + 15 赞一个!

查看全部评分

本帖被以下淘专辑推荐:

  • · 学习|主题: 95, 订阅: 8
发表于 2012-7-11 08:29:27 | 显示全部楼层
说得非常好!之前没有关注到这个帖子
回复 支持 0 反对 1

使用道具 举报

发表于 2020-5-29 11:11:13 | 显示全部楼层
  1. (defun C:swed(/ ss ssgetpy)
  2.         (defun ssgetpy(ssall entpy)
  3.                 (sssetfirst nil ssall)
  4.                 ;(vl-cmdf "SELECT" ssall "")
  5.                 (ssget "P" (list (cons 1 entpy)))
  6.         )
  7.         (if (setq ss (ssget '((0 . "*TEXT") (1 . "A*,B*,C*,D*") (7 . "宋 宽0.7 高3,宋 宽0.75 高3"))))
  8.                 (progn
  9.                         (setq
  10.                                 alst (ssgetpy ss "A*")
  11.                                 blst (ssgetpy ss "B*")
  12.                                 clst (ssgetpy ss "C*")
  13.                                 dlst (ssgetpy ss "D*")
  14.                         )
  15.                 )
  16.         )
  17. )

这个程序中ssgetpy函数只有效一次,不知道是啥原因!
发表于 2021-2-17 03:08:51 来自手机 | 显示全部楼层
直接保存选择集是不行的,可以变通一下,选择集转图元表,再转handent表,后表存为全局LDATA。不要再问记录以后怎么调用,能实现记录,自然就知道了该如何读取。
发表于 2012-4-26 13:22:04 | 显示全部楼层
学习了,现在还是新手,要学的还很多啊
发表于 2012-4-26 14:45:42 来自手机 | 显示全部楼层
我的明细表程序中也有大量的read和set、eval等函数
发表于 2012-4-26 15:58:22 | 显示全部楼层
写得太好了!!!
发表于 2012-4-26 16:53:34 | 显示全部楼层
楼主写的很好,很值得我们新手去研究。我这儿有一处选择集的问题想请教,比如程序中用entmake创建了text的list 表,可否将这个表定义为一个新的ssget,供程序下一步提取应用?
发表于 2012-4-26 18:39:59 | 显示全部楼层
偶也来学习学习
发表于 2012-4-26 18:50:37 来自手机 | 显示全部楼层
做个记号,回头来学习。
发表于 2012-6-27 22:05:09 | 显示全部楼层
代码优化:质和量。。。无止境啊
发表于 2012-6-27 22:37:29 | 显示全部楼层
谢谢楼主,学习学习。
发表于 2012-6-28 08:39:48 | 显示全部楼层
讲的很详细,学习无止境
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-11-23 15:20 , Processed in 0.237343 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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