brbright 发表于 2015-4-2 09:05:32

[源码+教程]使用动态块函数简化AutoLisp参数设计编程

本帖最后由 brbright 于 2015-4-2 09:40 编辑

使用动态块函数简化AutoLisp编程(少用三角函数)作者:BrightRat时间:2015年04月02日

1 动态块在参数化设计编程中的重要性
您可知,《AutoCAD程序设计魔法书–AutoLisp&DCL基础篇》第五章有提到,参数设计的关键技巧是熟知三角函数关系。
没错,熟知三角函数可以精确地掌握点线面之间的关系,绘制出所需要的目标图形。
但是,如果图元稍稍增加一点,需要控制的对象之间的相对关系就会变得复杂起来,并使得需要编写的程序代码成倍的增长并且难以维护。尤其在需要紧急编写可用程序的时候,会使编程人员感到非常烦恼。
别急,自AutoCAD2006以后,我们可以使用非常强大的动态块,为小型绘图程序的编程带来便利。
请注意,本文中的动态块函数来自于Lee-Mac,在AutoCAD2008中文版中测试通过。程序代码在AutoCAD2014英文版中测试通过,AutoCAD2007版或以上应该能用(未测试)。更多有关动态块函数的信息,您可以到Lee-Mac的博客(英文)查询。
这是附件中的CAD文件预览:

寒潮大冬瓜 发表于 2024-8-25 22:39:19

很好→很棒!很好~很棒!!很好……很棒!!!
我觉得要是能针对箍筋与之配合使用的主筋直径→对应其转弯半径→那就完美了!
甚至还能根据抗震等级调整箍筋弯钩的长度!

brbright 发表于 2015-4-2 09:07:34

2 问题的提出 – 绘制大量角度不规则的建筑混凝土结构箍筋
2.1 已有的图纸

2.2 目标图纸:

brbright 发表于 2015-4-2 09:10:21

3 编程前的准备
3.1 动态块拉筋
制作一个动态块拉筋,参数是D1,动作是拉伸。

使之可以方便的通过拖动夹点,自动拉伸。旋转不影响拉伸功能。


3.2 动态块箍筋
制作一个动态块箍筋,参数是D1和D2,动作分别为两个方向的拉伸。

使之可以方便的通过拖动夹点,在两个方向上自动拉伸。旋转不影响拉伸功能。

doro 发表于 2015-4-2 09:10:31

论坛关于动态块的帖子不多 看这次楼主带来什么新东西

brbright 发表于 2015-4-2 09:11:58

4 理清编程思路
如果不使用LSP和其他插件,我们可以利用CAD自带的ALIGN对齐命令,使用4点捕捉的方式,可以一次性的完成块的平移和旋转动作。
然后对平移和旋转后的动态块,使用拖动动作夹点的拉伸方法,可以很方便的编辑,使之达到我们想要的效果。
最后通过复制拉伸后的动态块,完成作图目标。

然而,我们可以使用AutoLisp编程的方法,将上述过程简化。

具体思路:
4.1 使用 vla-copy函数复制一个动态块。
4.2 使用 command函数调用CAD的ALIGN命令平移和旋转复制后的动态块。
4.3 使用 lee-mac提供的动态块修改函数,修改目标参数D1、D2等。

brbright 发表于 2015-4-2 09:12:47

5 重要关键 - Lee-Mac动态函块数需要的形参数据类型

;;-----通用函数:设置动态块参数(源自LEE-MAC)
;;来源网站http://www.lee-mac.com/dynamicblockfunctions.html
;; 修改动态块的参数(如果存在)
;; blk - 数据类型为VLA的动态块
;; prp - 数据类型为字符串的动态块参数
;; val - 动态块参数的数值,数据类型根据系统定义,常见为字符串
;; 返回: 新的动态块参数(如果成功), 否则返回nil
(defun LM:setdynpropvalue ( blk prp val )
    (setq prp (strcase prp))
    (vl-some
       '(lambda ( x )
            (if (= prp (strcase (vla-get-propertyname x)))
                (progn
                  (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                  (cond (val) (t))
                )
            )
      )
      (vlax-invoke blk 'getdynamicblockproperties)
    )
)

brbright 发表于 2015-4-2 09:13:22

6 开始编程-动态块拉筋
下面的程序经过认真注释,朋友们不用当心难以阅读。

;;加载VlISP拓展
(vl-load-com)
;;-----通用函数:设置动态块参数(源自LEE-MAC)
;;来源网站http://www.lee-mac.com/dynamicblockfunctions.html
;; 修改动态块的参数(如果存在)
;; blk - 数据类型为VLA的动态块
;; prp - 数据类型为字符串的动态块参数
;; val - 动态块参数的数值,数据类型根据系统定义,常见为字符串
;; 返回: 新的动态块参数(如果成功), 否则返回nil
(defun LM:setdynpropvalue (blk prp val)
(setq prp (strcase prp))
(vl-some
    '(lambda (x)
       (if (= prp (strcase (vla-get-propertyname x)))
       (progn
           (vla-put-value
             x
             (vlax-make-variant
             val
             (vlax-variant-type (vla-get-value x))
             )
           )
           (cond (val)
               (t)
           )
       )
       )
   )
    (vlax-invoke blk 'getdynamicblockproperties)
)
)
;;-----程序集1:一个参数动态块的复制、旋转、参数调整-------------------------------
;;-----程序1.1:设置动态块标注源
;;本程序用于取得参考用的动态块和用于ALIGN平移旋转定位的两个点
(defun c:rds ()
(setq d_dynbx1_1 (car (entsel "\n请选择源动态块")))
(setq        d_dynbx1_point_1
       (getpoint "\n请选择源动态块的平移基点(align的第一点)"
       )
)
(setq        d_dynbx1_point_2
       (getpoint
           "\n请选择源动态块的角度对齐点(align的第三点)"
       )
)
;;lisp对象转换为vl对象,用于vla-copy函数
(setq dx_dynbx1_1 (vlax-ename->vla-object d_dynbx1_1))
)
;;-----程序1.2:复制动态块到指定位置并设置参数
;;本程序先在原地复制一个动态块,
;;然后根据选择的两个点将复制后的动态块ALIGN平移、旋转
;;最后计算选择的两个点之间的距离,修改移动后的动态块
(defun c:rd ()
(setq
    t_point_3 (getpoint "\n请选择复制动态块的平移基点(align的第二点)")
)
(setq
    t_point_4
   (getpoint "\n请选择复制动态块的角度对齐点(align的第四点)")
)
;;复制一个动态块
(setq tx_dynbx1_2 (vla-copy dx_dynbx1_1))
;;vl对象转换为lisp对象,用于align命令
(setq t_dynbx1_2 (vlax-vla-object->ename tx_dynbx1_2))
;;调用CAD的内置命令align实现动态块的平移和转角对齐
(command "align"          t_dynbx1_2       ""                d_dynbx1_point_1
           t_point_3          d_dynbx1_point_2                t_point_4
           ""                  "n"
          )
;;计算复制后的动态块基点到对齐点的距离
(setq t_dynbx1_dist_1 (rtos (distance t_point_3 t_point_4)))
;;调用动态块设置函数,设置复制后的动态块的参数
;;设置参数distance1
(LM:setdynpropvalue
    tx_dynbx1_2
    "D1"
    t_dynbx1_dist_1
)
(princ)
)

brbright 发表于 2015-4-2 09:15:59

7 使用动态块的好处-以箍筋为例

7.1 使用动态块的好处一:已于拓展
通过上例,我们了解到,利用动态块编程的方式,可以避免各个定位点之间繁琐的三角函数关系运算。
按正常的编程思路,我们至少需要知道拉筋中间直线两端的两个点,拉筋两端的两个弯钩圆心,以及弯钩后钢筋伸长锚固直线的端点,共6个参数点之间的关系。之后还要反复调用直线和圆弧的绘图命令才能完成作图。
然而,如果我们使用动态块,读者可以注意到,我们实质上仅仅只需调用distance函数一次,计算两个点间的距离,即可完成编程任务,并节省大量不必要的代码。

如果您的数学功底比较好,可能不在意以上6个参数点。
现在,我们继续下一个任务:使用程序绘制箍筋。
首先,对需要计算参数点进行初步估计:

从上图可以看到,按常规的编程思路,不需找某种“技巧性”的编程方法,我们需要考虑12个点之间的坐标三角函数关系,然后使用直线和圆弧将之连起来。可以想象,这种编程的思路,需要比较扎实的数学基础,参数量和代码函数都比较可观。
但是,如果使用动态块,可以节省不少代码,降低思考强度。

;;-----程序2:两个参数动态块的复制、旋转、参数调整-------------------------------
;;-----程序2.1:设置动态块标注源
;;本程序用于取得参考用的动态块和用于ALIGN平移旋转定位的两个点
;;将本程序rd2s和上面的rds程序比对,可以发现,除了改变几个参数的名称,完全是一模一样的。

;;加载VlISP拓展
(vl-load-com)
;;-----通用函数:设置动态块参数(源自LEE-MAC)
;;来源网站http://www.lee-mac.com/dynamicblockfunctions.html
;; 修改动态块的参数(如果存在)
;; blk - 数据类型为VLA的动态块
;; prp - 数据类型为字符串的动态块参数
;; val - 动态块参数的数值,数据类型根据系统定义,常见为字符串
;; 返回: 新的动态块参数(如果成功), 否则返回nil
(defun LM:setdynpropvalue (blk prp val)
(setq prp (strcase prp))
(vl-some
    '(lambda (x)
       (if (= prp (strcase (vla-get-propertyname x)))
       (progn
           (vla-put-value
             x
             (vlax-make-variant
             val
             (vlax-variant-type (vla-get-value x))
             )
           )
           (cond (val)
               (t)
           )
       )
       )
   )
    (vlax-invoke blk 'getdynamicblockproperties)
)
)
(defun c:rd2s ()
(setq d_dynbx2_1 (car (entsel "\n请选择源动态块")))
(setq        d_dynbx2_point_1
       (getpoint "\n请选择源动态块的平移基点(align的第一点)"
       )
)
(setq        d_dynbx2_point_2
       (getpoint
           "\n请选择源动态块的角度对齐点(align的第三点)"
       )
)
;;lisp对象转换为vl对象,用于vla-copy函数
(setq dx_dynbx2_1 (vlax-ename->vla-object d_dynbx2_1))
)
;;-----程序2.2:复制动态块到指定位置并设置参数
;;本程序先在原地复制一个动态块,
;;然后根据选择的两个点将复制后的动态块ALIGN平移、旋转
;;最后计算选择的三个点之间的距离,修改移动后的动态块
;;将本程序rd2和上面的rd比对,只增加了3行代码,新增的代码会在下面提示。
;;可以看到,新增的代码是很简单的,功能和邻近的代码完全一样,不需要创新的思路。
(defun c:rd2 ()
(setq
    t_point_3 (getpoint "\n请选择复制动态块的平移基点(align的第二点)")
)
(setq
    t_point_4
   (getpoint "\n请选择复制动态块的角度对齐点(align的第四点)")
)
;;------此处是新增的代码1-------
(setq        t_point_5 (getpoint
                  "\n请选择复制动态块参数点(用于计算到基点的距离)"
                  )
)
;;------上面是新增的代码1-------
;;复制一个动态块
(setq tx_dynbx2_2 (vla-copy dx_dynbx2_1))
;;vl对象转换为lisp对象,用于align命令
(setq t_dynbx2_2 (vlax-vla-object->ename tx_dynbx2_2))
;;调用CAD的内置命令align实现动态块的平移和转角对齐
(command "align"          t_dynbx2_2       ""                d_dynbx2_point_1
           t_point_3          d_dynbx2_point_2                t_point_4
           ""                  "n"
          )
;;分别计算复制后的动态块基点道对齐点和参数点的距离
(setq t_dynbx2_dist_1 (rtos (distance t_point_3 t_point_4)))

;;------此处是新增的代码2-------
(setq t_dynbx2dist_2 (rtos (distance t_point_3 t_point_5)))
;;------上面是新增的代码2-------

;;调用动态块设置函数,设置复制后的动态块的参数
;;设置参数distance1
(LM:setdynpropvalue
    tx_dynbx2_2
    "D1"
    t_dynbx2_dist_1
)

;;------此处是新增的代码3-------
;;设置参数distance2
(LM:setdynpropvalue
    tx_dynbx2_2
    "D2"
    t_dynbx2dist_2
)
;;------上面是新增的代码3-------

(princ)
)

brbright 发表于 2015-4-2 09:19:03

7.2 使用动态块的好处二:易于维护
细心的建筑结构同行会发现,上文中的箍筋明显漏画了弯钩。

如果是常规的编程方法,我们会直接增加相关的带以满足新的功能。这将直接让编程人员继续研究各种三角函数以及运算,相当枯燥。
但是,在动态块中做点小改变却丝毫不费力气。


对于本例,加弯钩的动态块拉伸、移动动作和逻辑与未加拉钩前一模一样,动态块参数(D1、D2)保持不变。原来的代码无需任何修改可以直接使用。

brbright 发表于 2015-4-2 09:19:38

8 结束语
本文通过常规编程与利用动态块编程的方法之间的对比,得出使用动态块可以减少编程时间和思考强度的结论。
页: [1] 2 3
查看完整版本: [源码+教程]使用动态块函数简化AutoLisp参数设计编程