和尚777 发表于 2024-6-12 16:37:46

以面向对象的概念设计lisp函数

本帖最后由 和尚777 于 2024-6-12 16:56 编辑

以面向对象的基本概念设计你的lisp函数
; 以最常用的实体包围盒为例(defun c:t2 (/ e p1 p5 p7)
(if(and(setq e(car(entsel)))
       (setq p1 (hs-Ent9pt e 1)) ; 传统方式,每次都要重新获取包围盒
       (setq p5 (hs-Ent9pt e 5))
       (setq p7 (hs-Ent9pt e 7)) ; 获取了3次
   )
    (progn   
      (mk-circle p1 10)
      (mk-circle p5 10)
      (mk-circle p7 10)
      
    )
)(princ)
); 进阶做法(defun c:t3 (/ e lst p1 p5 p7)
(if(and(setq e(car(entsel)))
      (setq lst(hs-AssocCdr "list"(hs-BoundingBoxInfo e))) ; 进阶做法,获取包围盒9点列表
      
   )
    (progn
      (setq p1 (nth 0 lst)) ; 不会重复获取包围盒
      (setq p5 (nth 4 lst)) ; 按索引取值,忘了其意义就要去看表是怎么获取的,表结构是什么
      (setq p7 (nth 6 lst))
      (mk-circle p1 10)
      (mk-circle p5 10)
      (mk-circle p7 10)
      
    )
)(princ)
) ; 面向对象的方式(defun c:t1 (/ e lst p1 p5 p7)
(if(and(setq e(car(entsel)))
      (setq lst (hs-BoundingBoxInfo e)) ; 获取包围盒信息
      
   )
    (progn
      (setq p1 (hs-AssocCdr "p1" lst)) ; 从信息中以key获取值,意义明确,把key当做对象的属性
      (setq p5 (hs-AssocCdr "p5" lst)) ; 不会重复获取包围盒
      (setq p7 (hs-AssocCdr "p7" lst)) ; 更好的操作和利用数据
      (mk-circle p1 10)
      (mk-circle p5 10)
      (mk-circle p7 10)
      (princ (hs-AssocCdr "area" lst))
    )
)(princ)
); 和一般的以9位码获取坐标函数相同,获取包围盒只返回一个坐标
; 包围盒9位码坐标
; P7---------------P8----------------P9
; |                |               |
; |                |               |
; |                |               |
; P4---------------P5----------------P6
; |                |               |
; |                |               |
; |                |               |
; P1---------------P2----------------P3

(defun hs-Ent9pt(ent i / lst)
(setq lst(hs-AssocCdr "list"(hs-BoundingBoxInfo ent))) ; 不想再写个函数,所以从info里取
(nth (- i 1) lst)
) ; (hs-Subst "1" 22 '(("0" . 0)("1" . 1)("2" . 2)))
; 修改关联表的值,返回表
(defun hs-Subst(key value lst)
(if(and key value lst
       (setq key(strcase key))
       (setq lst(hs-Uppercase lst))
      
   )
    (progn
      (subst (cons key value) (assoc key lst) lst)
    )
)
)
; key大写
(defun hs-Uppercase(lst)
(if (and lst(listp lst))
    (mapcar
      (function
      (lambda(x)
          (cons(strcase (car x) )(cdr x))
      )
      )
      lst
    )   
)
); 获取关联点对表的值,忽略大小写
(defun hs-AssocCdr(a lst)
(if(and a lst (listp lst))
    (progn      
      (cdr
      (assoc
          (strcase a)
          (hs-Uppercase lst)
      )      
      )
    )
)
)
; 获取实体包围盒信息
; 返回信息关联点对表
(defun hs-BoundingBoxInfo(ent / p1 p9)
(if(and (setq pts (hs-GetBox ent))
       (listp pts)
       (setq p1 (car pts))
       (setq p9 (cadr pts))
       (listp p1)(listp p9)      
   )
    (progn
      (hs-BoundingBox p1 p9)
    )
) ; 把返回的结果设计成点对表结构,就像dxf码那样 ; 获取包围盒信息关联点对表
; 返回的列表就像一个对象,width是属性
(defun hs-BoundingBox(p1 p9 / height p2 p3 p4 p5 p6 p7 p8 width)
(if(and p1 p9(listp p1)(listp p9))
    (progn
      (setq p5 (hs-PointMid p1 p9)
      p3 (if (< (car p9) (car p1))
             (list (car p1) (cadr p9) (caddr p1))
             (list (car p9) (cadr p1) (caddr p1))
         )
      p7 (if (< (car p9) (car p1))
             (list (car p9) (cadr p1) (caddr p9))
             (list (car p1) (cadr p9) (caddr p9))
         )
      p2 (hs-PointMid p1 p3)
      p4 (hs-PointMid p1 p7)
      p6 (hs-PointMid p3 p9)
      p8 (hs-PointMid p7 p9)
      width(distance p1 p3)
      height(distance p1 p7)
      area(* width height)
      )
      (list   
      (cons "p6" p6) ; 不按顺序构建表,assoc能获取到
      (cons "p7" p7) ; 和尚777
      (cons "p8" p8)
      (cons "p9" p9)
      
      (cons "p1" p1)
      (cons "p2" p2)
      (cons "p3" p3)
      (cons "p4" p4)
      (cons "p5" p5)      
      (cons "width" width)
      (cons "height" height)
      (cons "area" area)
      (cons "list" (list p1 p2 p3 p4 p5 p6 p7 p8 p9 width height area)) ; 表顺序不能错
      )      
    )
)
)
; 两点之中点
(defun hs-PointMid (p1 p2)
(if (and p1 p2(listp p1)(listp p2))
    (mapcar
      '(lambda (x)
         (* x 0.5)
       )
      (mapcar '+ p1 p2)   
    )
)
)

; 包围盒2点列表
(defun hs-GetBox(ent / MinPt MaxPt)
(if ent
    (progn
      (vla-getboundingbox (vlax-ename->vla-object ent) 'MinPt 'MaxPt)
      (list (vlax-safearray->list MinPt)
      (vlax-safearray->list MaxPt)
      )
    )
)
)

; 创建圆
(defun mk-Circle (cen r)
(entmakeX (list '(0 . "CIRCLE") (cons 10 cen) (cons 40 r))))



pxt2001 发表于 2024-6-13 13:06:27

kozmosovia 发表于 2024-6-12 19:14
其实没啥用,首先,不见得有需要重复算N的操作,真需要了,最合理的选择是定义一个变量保存第一次的计算结 ...

赞同,张元英扭屁股、跳舞很流行,很多人喜欢,非常有美感。但你让张元英来唱宋祖英的歌曲,把扭屁股强加进来,其实真没啥用。估计老江都受不了

gzcsun 发表于 2024-6-19 20:12:17

list就可以,就12个数,car类函数可以到第四个和最后一个,就算list中12个数值,也就是最多3个函数串,可做函数car5~car11。
其实极少极少情况用到12个数值。最多是四角+中间的5点。刚好lisp有对应的位置函数。

kozmosovia 发表于 2024-6-12 19:14:41

其实没啥用,首先,不见得有需要重复算N的操作,真需要了,最合理的选择是定义一个变量保存第一次的计算结果,以后从里面提取数据。所以,没必要面向对象,面向变量就行。

d1742647821 发表于 2024-6-12 17:20:35

不明觉厉~~~~~~~

liuhe 发表于 2024-6-12 17:28:16

函数不能重载,太限制了

czb203 发表于 2024-6-12 19:01:57

感谢大佬的热心分享

tranque 发表于 2024-6-12 19:02:45

不明觉厉+1~~~~~~~

dcl1214 发表于 2024-6-12 20:29:23

索引法用好了,速度飞快

guosheyang 发表于 2024-6-12 20:49:41

感谢和尚777大佬的分享!

紫苏炒黄瓜 发表于 2024-6-12 21:07:01

授人以渔,鼓掌鼓掌

marcoyuwen 发表于 2024-6-13 09:05:36

厉害了,有思路有码。
页: [1] 2
查看完整版本: 以面向对象的概念设计lisp函数