明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 696|回复: 14

[经验] 多参数动态移动图元

[复制链接]
发表于 2024-5-27 14:00 | 显示全部楼层 |阅读模式
  1. (defun $dyn-move$ (lst /     $ents-dui-qi-pt$     $grvecs$
  2.            $move$     blck-not-sc block-r     code
  3.            color     data         do_rotate   do_scale
  4.            ents     grread-pt-old     mode
  5.            move     offset      phjg     pt0
  6.            pt-old     pts         scale     scalefactor
  7.            tishiyu     xunhuan     zt     zimu
  8.            *error*     fhgs         ents->block ESC-DEL? fd-ents
  9.           )
  10.           ;动态移动,动态插入块,动态插入图元,动态移动图元,移动图元
  11.       ;|
  12. ;调用方法:
  13. (and (setq ss (ssget))
  14.      (setq ents  (vl-remove-if
  15.       (function listp)
  16.       (mapcar (function cadr) (ssnamex SS))
  17.     )
  18.      )
  19.      ($dyn-move$
  20.        (list (cons "图元列表" ents)
  21.        (cons "矢量图" nil)
  22.        (cons "颜色" 1)
  23.           ;(cons "追踪点" (list 0 0 0))
  24.        (cons "矢量图偏移距离" (list 1 100))
  25.        (cons "系数" 3)
  26.        (cons "块保持正方向" 0)
  27.        (cons "对齐方式" 0)
  28.        (cons "返回格式" "坐标")
  29.        (cons "ESC" "是")
  30.        (cons "附带删除" fd-ents)
  31.        (CONS "键盘字母"
  32.        (LIST "A" "a" "F" "f" "E" "e" "C" "c" "D" "d")
  33.        )
  34.           ;(cons "保持原比例的块图元"(ssToentlst (ssget)))
  35.        )
  36.      )
  37. )
  38. |;
  39.   (defun *error* (msg)
  40.     (if  (and ENTS (or (= msg "函数已取消") (= msg "函数被取消")))
  41.       (progn
  42.   (if msg
  43.     (PROGN (PRINT)
  44.      (princ (strcat "$dyn-move$  遇到错误: " msg))
  45.     )
  46.   )
  47.   (IF (or  (not ESC-DEL?)    ;没有传参的模式,默认行为,兼容历史程序
  48.     (= ESC-DEL? "是")
  49.       )        ;传入参数中是否需要支持esc键删除图元的要求
  50.     (PROGN(MAPCAR (function (lambda (xx)
  51.             (if (AND (= (type xx) 'ENAME) (ENTGET XX))
  52.         (entdel xx)
  53.             )
  54.             (if (AND xx (= (type xx) 'VLA-OBJECT))
  55.         (vla-delete xx)
  56.             )
  57.           )
  58.       )
  59.       ENTS
  60.     )
  61.       (IF  (AND ents->block (ENTGET ents->block))
  62.         (ENTDEL ents->block)
  63.       )
  64.       )
  65.   )
  66.   (redraw)
  67.       )
  68.     )
  69. ;;;    (vl-catch-all-apply (function (lambda () (c:var nil nil))));强制将变量还原
  70.     (vl-catch-all-apply (function (lambda () (c:var2 nil nil (list (CONS  "DEL" fd-ents))))));强制将变量还原
  71.     (princ)
  72.   )
  73.   (defun $ents-dui-qi-pt$ (entlst  mod     /     maxpo0  minpo0
  74.          pt-f     pts     x-max   x-min   y-max
  75.          y-min
  76.         )
  77.           ;求图元的对齐点坐标
  78.     (mapcar
  79.       (function(lambda (x / minpo maxpo box)
  80.    (IF (= (TYPE X) 'ENAME)
  81.      (SETQ X (vlax-ename->vla-object X))
  82.    )
  83.    (if (and
  84.          (not (vl-catch-all-error-p
  85.           (vl-catch-all-apply
  86.       'vla-GetBoundingBox
  87.       (list x 'minpo 'maxpo)
  88.           )
  89.         )
  90.          )
  91.          (setq minpo (vlax-safearray->list minpo))
  92.          (setq maxpo (vlax-safearray->list maxpo))
  93.        )
  94.      (progn
  95.        (if (and minpo0 (car minpo) (car minpo0))
  96.          (setq
  97.      minpo0  (list (min (car minpo) (car minpo0))
  98.             (min (cadr minpo) (cadr minpo0))
  99.             0
  100.       )
  101.          )
  102.          (setq minpo0 (list (car minpo) (cadr minpo)))
  103.        )
  104.        (if maxpo0
  105.          (setq
  106.      maxpo0  (list (max (car maxpo) (car maxpo0))
  107.             (max (cadr maxpo) (cadr maxpo0))
  108.             0
  109.       )
  110.          )
  111.          (setq maxpo0 (list (car maxpo) (cadr maxpo)))
  112.        )
  113.      )
  114.      (progn
  115.        (if (not err-print)
  116.          (progn
  117.      (setq err-print 't)
  118.      (print "vla-GetBoundingBox error,可能字体有问题")
  119.          )
  120.        )
  121.      )
  122.    )
  123.        ))
  124.       entlst
  125.     )
  126.     (and (SETQ PTS (VL-REMOVE NIL (LIST minpo0 maxpo0)))
  127.    (SETQ X-MIN (APPLY 'MIN (MAPCAR 'CAR PTS)))
  128.    (SETQ X-MAX (APPLY 'MAX (MAPCAR 'CAR PTS)))
  129.    (SETQ Y-MIN (APPLY 'MIN (MAPCAR 'CADR PTS)))
  130.    (SETQ Y-MAX (APPLY 'MAX (MAPCAR 'CADR PTS)))
  131.     )
  132.     (COND ((= MOD 1)
  133.      (SETQ PT-F (LIST X-MIN Y-MIN)) ;左下
  134.     )
  135.     ((= MOD 2)
  136.      (SETQ PT-F (LIST X-MAX Y-MIN)) ;右下
  137.     )
  138.     ((= MOD 3)
  139.      (SETQ PT-F (LIST X-MAX Y-MAX)) ;右上
  140.     )
  141.     ((= MOD 4)
  142.      (SETQ PT-F (LIST X-MIN Y-MAX)) ;左上
  143.     )
  144.     ((= MOD 5)
  145.      (SETQ PT-F (LIST (* (+ X-MIN X-MAX) 0.5) Y-MIN)) ;下中
  146.     )
  147.     ((= MOD 6)
  148.      (SETQ PT-F
  149.       (LIST (* (+ X-MIN X-MAX) 0.5) (* (+ Y-MIN Y-MAX) 0.5))
  150.      )        ;右中
  151.     )
  152.     ((= MOD 7)
  153.      (SETQ PT-F (LIST (* (+ X-MIN X-MAX) 0.5) Y-MAX)) ;上中
  154.     )
  155.     ((= MOD 8)
  156.      (SETQ PT-F (LIST X-MIN (* (+ Y-MIN Y-MAX) 0.5))) ;左中
  157.     )
  158.     ((= MOD 0)
  159.      (SETQ PT-F (mapcar '(lambda (x y)
  160.          (* (+ x y) 0.5)
  161.              )
  162.             minpo0
  163.             maxpo0
  164.           )
  165.      )
  166.     )
  167.     )
  168.     PT-F
  169.   )
  170.   (defun $Move$  (entlst PT-F PT-T MOD /)
  171.     (if  PT-F
  172.       ()
  173.       (setq PT-F ($ents-dui-qi-pt$ ENTS MODE))
  174.     )
  175.     (mapcar
  176.       (function(lambda (x)
  177.    (vl-catch-all-apply
  178.      'vla-move
  179.      (LIST (vl-catch-all-apply 'vlax-ename->vla-object (LIST X))
  180.      (vl-catch-all-apply 'vlax-3D-point (LIST PT-F))
  181.      (vl-catch-all-apply 'vlax-3D-point (LIST PT-T))
  182.      )
  183.    )
  184.        ))
  185.       entlst
  186.     )
  187.     PT-T
  188.   )
  189.   (defun do_Rotate (entlst PT +-? block-r)
  190.     (mapcar
  191.       (function
  192.   (lambda  (x / obj dxf)
  193.     (SETQ obj (vlax-ename->vla-object X))
  194.     (and x (setq dxf (entget x)))
  195.     (if (= +-? "-")
  196.       (VL-CATCH-ALL-APPLY
  197.         'vla-Rotate
  198.         (LIST obj
  199.         (VL-CATCH-ALL-APPLY 'vlax-3D-point (LIST PT))
  200.         (* pi 0.05)
  201.         )
  202.       )
  203.       (VL-CATCH-ALL-APPLY
  204.         'vla-Rotate
  205.         (LIST obj
  206.         (VL-CATCH-ALL-APPLY 'vlax-3D-point (LIST PT))
  207.         (- 0 (* pi 0.05))
  208.         )
  209.       )
  210.     )
  211.     (if (AND dxf (= (cdr (assoc 0 dxf)) "INSERT"))
  212.       (if  (= block-r 0)    ;1代表支持旋转,0代表保持正方向,不旋转的意思(无值自然是支持旋转,记住这个)
  213.         (if (VL-CATCH-ALL-APPLY
  214.         'vlax-property-available-p
  215.         (list obj 'InsertionPoint)
  216.       )
  217.     (VL-CATCH-ALL-APPLY
  218.       'vla-Rotate
  219.       (list
  220.         x
  221.         (VL-CATCH-ALL-APPLY
  222.           'vla-get-InsertionPoint
  223.           (list obj)
  224.         )
  225.         (if  (= +-? "-")
  226.           (- 0 (* pi 0.05))
  227.           (* pi 0.05)
  228.         )
  229.       )
  230.     )
  231.         )
  232.       )
  233.     )
  234.   )
  235.       )
  236.       entlst
  237.     )
  238.   )
  239.   (defun do_Scale (entlst PT +-? ScaleFactor blck-not-sc)
  240.     (mapcar (function(lambda (x)
  241.          (IF (= (TYPE X) 'ENAME)
  242.      (SETQ X (vlax-ename->vla-object X))
  243.          )
  244.          (if (= +-? "+")
  245.      (vla-ScaleEntity
  246.        x
  247.        (vlax-3D-point pt)
  248.        ScaleFactor
  249.      )
  250.      (vla-ScaleEntity
  251.        x
  252.        (vlax-3D-point pt)
  253.        (/ 1.0 ScaleFactor)
  254.      )
  255.          )
  256.        ))
  257.       entlst
  258.     )
  259.     (if  blck-not-sc
  260.       (mapcar
  261.   (function(lambda (x / dxf)
  262.      (setq dxf (entget x))
  263.      (IF (= (TYPE X) 'ENAME)
  264.        (SETQ X (vlax-ename->vla-object X))
  265.      )
  266.      (vla-ScaleEntity
  267.        x
  268.        (vlax-3D-point (cdr (assoc 10 dxf)))
  269.        (if (= +-? "+")
  270.          (/ 1.0 ScaleFactor)
  271.          ScaleFactor
  272.        )
  273.      )
  274.    ))
  275.   blck-not-sc
  276.       )
  277.     )
  278.   )
  279.   (defun $grvecs$ (data pt pt0 scale color offset / pt1 r1 scalelist)
  280.           ;矢量图行显示
  281.     (setq pt1 pt)
  282.     (SETQ scalelist (list scale 1000.0))
  283.     (setq r1 (getvar "viewsize"))
  284.     (setq r1 (* (car scalelist) (/ r1 (cadr scalelist))))
  285.     (redraw)
  286.     (if  (AND pt0 color)
  287.       (grdraw pt0 pt1 color)
  288.     )
  289.     (IF  DATA
  290.       (grvecs
  291.   (apply
  292.     'append
  293.     (mapcar
  294.       (function(lambda (x)
  295.          (list color
  296.          (mapcar '+
  297.            (mapcar '*
  298.              (mapcar '+ (car x) offset)
  299.              (list r1 r1)
  300.            )
  301.            pt1
  302.          )
  303.          (mapcar '+
  304.            (mapcar '*
  305.              (mapcar '+ (cadr x) offset)
  306.              (list r1 r1)
  307.            )
  308.            pt1
  309.          )
  310.          )
  311.        ))
  312.       data
  313.     )
  314.   )
  315.       )
  316.     )
  317.   )
  318.   (and lst (setq ents (cdr (assoc "图元列表" lst))))
  319.   (and (= (type (cdr (assoc "矢量图" lst))) 'list)
  320.        (setq data (cdr (assoc "矢量图" lst)))
  321.   )
  322.   (and (= (type (cdr (assoc "颜色" lst))) 'int)
  323.        (setq color (cdr (assoc "颜色" lst)))
  324.   )
  325.   (and (= (type (cdr (assoc "追踪点" lst))) 'list)
  326.        (setq pt0 (cdr (assoc "追踪点" lst)))
  327.   )
  328.   (and (= (type (cdr (assoc "矢量图偏移距离" lst))) 'list)
  329.        (setq offset (cdr (assoc "矢量图偏移距离" lst)))
  330.   )
  331.   (or(and (= (type (cdr (assoc "系数" lst))) 'int)
  332.        (setq scale (cdr (assoc "系数" lst)))
  333.   )(setq scale 1.0))
  334.   (and (= (type (cdr (assoc "块保持正方向" lst))) 'int)
  335.           ;0保持正方向(不允许旋转),1不保持正方向(允许旋转)(无值自然是支持旋转,记住这个)
  336.        (setq block-r (cdr (assoc "块保持正方向" lst)))
  337.   )
  338.   (setq ESC-DEL?(cdr(assoc "ESC" lst)))
  339.   (if (not (setq fd-ents(cdr(assoc "附带删除" lst))))
  340.     (setq fd-ents nil)
  341.     )
  342.   (setq fhgs(cdr(assoc "返回格式" lst)))
  343.   (or (and (setq mode (cdr (assoc "对齐方式" lst)))
  344.      (member mode (list '0 '1 '2 '3 '4 '5 '6 '7 '8))
  345.       )
  346.       (setq mode 0)
  347.   )
  348.   (if (cdr (assoc "键盘字母" lst))
  349.     (setq zimu (cdr (assoc "键盘字母" lst)))
  350.     (setq zimu (LIST "A" "D" "F" "E" "C" "a" "d" "f" "e" "c"));这里是为了兼容历史其他程序的,因为好多历史其他程序默认没有传入这个参数,但是,程序是支持了旋转和缩放的,如果不加上这个默认,好多历史的代码会导致无法旋转了
  351.   )
  352.   (setq blck-not-sc (cdr (assoc "保持原比例的块图元" lst)))
  353.   (setq ScaleFactor 1.25)
  354.   (and ents (= (type ents) 'ename) (setq ents (list ents)))
  355.   (if (and ents (= (type ents) 'list))
  356.     (progn
  357.       (setq ents->block nil)
  358.       (if (> (length ents) 1000)
  359.   (progn (setq ents->block ($制作块$ ents "*U" 0 1));转换为块(如果影响到上级调用了,请告知客户,不要将图形画那么多线条,上级调用方也是可以再次过滤分析的,“返回格式”的参数传入“表”值程序就会返回炸开后的图元)
  360.          (setq ents (list ents->block))
  361.   );图元数量太多了,直接转换为块
  362.       )
  363.       (PRINT)
  364.       (setq tishiyu "")
  365.       (if (or (member "A" zimu)
  366.         (member "a" zimu)
  367.         (member "F" zimu)
  368.         (member "f" zimu)
  369.     )
  370.   (setq tishiyu (strcat tishiyu "[A/F]旋转 "))
  371.       )
  372.       (if (or (member "E" zimu)
  373.         (member "e" zimu)
  374.         (member "C" zimu)
  375.         (member "c" zimu)
  376.     )
  377.   (setq tishiyu (strcat tishiyu "[E/C]缩放 "))
  378.       )
  379.       (if (or (member "D" zimu) (member "d" zimu))
  380.   (setq tishiyu (strcat tishiyu "[D]对齐 "))
  381.       )
  382.       (prinC tishiyu)
  383.       (SETQ ENTS (VL-REMOVE NIL ENTS))
  384.       (COND
  385.   ((> (LENGTH ENTS) 900) (SETQ PHJG 5))
  386.   ((> (LENGTH ENTS) 800) (SETQ PHJG 4))
  387.   ((> (LENGTH ENTS) 600) (SETQ PHJG 3))
  388.   ((> (LENGTH ENTS) 400) (SETQ PHJG 2))
  389.   ((> (LENGTH ENTS) 200) (SETQ PHJG 1))
  390.   ((> (LENGTH ENTS) 100) (SETQ PHJG 0.5))
  391.   (T (SETQ PHJG 0.25))
  392.       )          ;平滑度间隔
  393.       (setq grread-pt-old (cadr (GRREAD (GRREAD 15 2))))
  394.       (SETQ PT-OLD NIL)
  395.       (setq zt NIL)
  396.       (setq move nil)
  397.       (setq xunhuan t)
  398.       (while xunhuan
  399.   (setq code nil)
  400.   (setq code (grread T 15))
  401.   (cond
  402.     ((= (car code) 5)    ;移动
  403.      (IF PT-OLD
  404.        (if (> (DISTANCE (cadr code) PT-OLD) PHJG)
  405.          (setq PT-OLD ($move$ ents PT-OLD (cadr code) mode))
  406.        )
  407.        (setq PT-OLD ($move$ ents PT-OLD (cadr code) mode))
  408.      )
  409.      (if (> (DISTANCE (cadr code) grread-pt-old) 10)
  410.        (setq move t)
  411.      )        ;做个标记,防止误操作,有的电脑还没有来得及移动鼠标就开始按下按键了
  412.      ($grvecs$ data PT-OLD pt0 scale color offset)
  413.      (SETQ PTS (CONS (CADR code) PTS))
  414.     )
  415.     ((= (car code) 3)    ;左键
  416.      (setq PT-OLD ($move$ ents PT-OLD (cadr code) mode))
  417.      (setq xunhuan nil)
  418.      (if ents->block(setq ents(sn:Explode ents->block)));如果有转换为块的动作,就再次将块炸开为图元列表
  419.      (setq zt T)
  420.     )
  421.     ((and  (or (equal code '(2 68)) (equal code '(2 100)))
  422.     (or (member "D" zimu) (member "d" zimu))
  423.      )
  424.           ;用户按下了键盘D键
  425.      (SETQ MODE (1+ MODE))
  426.      (IF (> MODE 8)
  427.        (SETQ MODE 1)
  428.      )
  429.      (setq PT-OLD ($ents-dui-qi-pt$ ENTS MODE))
  430.     )
  431.     ((OR (MEMBER (car code) (LIST '11 '25))
  432.          (equal code '(2 13))
  433.          (equal code '(2 32))
  434.      )        ;右键,右键,回车,空格
  435.      (setq PT-OLD ($move$ ents PT-OLD (cadr code) mode))
  436.      (setq xunhuan nil)    ;让while结束循环
  437.     )
  438.     ((and
  439.        move
  440.        (or (equal code '(2 65)) (equal code '(2 97)))
  441.        (OR (NOT tishiyu) (or (member "A" zimu) (member "a" zimu)))
  442.      )
  443.           ; A or a
  444.      (do_Rotate ents PT-OLD "-" (cdr (assoc "块保持正方向" lst)))
  445.      (setq move nil)
  446.     )
  447.     ((and
  448.        move
  449.        (or (equal code '(2 70)) (equal code '(2 102)))
  450.        (OR (NOT tishiyu) (or (member "F" zimu) (member "f" zimu)))
  451.      )
  452.           ; F or f
  453.      (do_Rotate ents PT-OLD "+" (cdr (assoc "块保持正方向" lst)))
  454.      (setq move nil)
  455.     )
  456.     ((and
  457.        move
  458.        (or (equal code '(2 69)) (equal code '(2 101)))
  459.        (OR (NOT tishiyu) (or (member "E" zimu) (member "e" zimu)))
  460.      )
  461.           ; E or e
  462.      (do_Scale ents PT-OLD "+" ScaleFactor blck-not-sc)
  463.      (setq PT-OLD ($ents-dui-qi-pt$ ENTS MODE))
  464.      (setq move nil)
  465.     )
  466.     ((and
  467.        move
  468.        (or (equal code '(2 67)) (equal code '(2 99)))
  469.        (OR (NOT tishiyu) (or (member "C" zimu) (member "c" zimu)))
  470.      )
  471.           ; C or c
  472.      (do_Scale ents PT-OLD "-" ScaleFactor blck-not-sc)
  473.      (setq PT-OLD ($ents-dui-qi-pt$ ENTS MODE))
  474.      (setq move nil)
  475.     )
  476.   )
  477.   (setq code nil)
  478.       )
  479.       (list (cons "状态" zt)
  480.       (cons "坐标" PT-T)
  481.       (cons "图元列表" ents)
  482.       )
  483.     )
  484.   )
  485.   (IF (or(not fhgs);如果没有传入这个参数【默认行为,兼容历史程序】
  486.    (= fhgs "坐标");如果有传参进来,同时其值等于“坐标”
  487.    )
  488.     PT-OLD
  489.     (list (cons "坐标" PT-OLD) (cons "图元" ENTS))
  490.             ;坐标返回去给上一级
  491.   )
  492. )

"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2024-5-29 11:12 | 显示全部楼层
高飞鸟的动态arx函数库
是目前最好的
可惜只支持到2014

CAD自带的arx函数库也挺好
没有版本问题
就是功能略简单

除此之外我试过的其它方法
包括各种dll和arx
都存在各种无法接受的硬伤
比如不支持按住鼠标中键平移视窗等
发表于 2024-5-29 10:45 | 显示全部楼层
grread模拟动态
对大量图元的预览显示较慢
这是函数的硬伤
除此之外
最大的难点是实现捕捉
除了预置捕捉
还有右键捕捉菜单
和手输的临时指定捕捉
杜总的这个代码显然没有考虑这些
对需要精确定位的情况
就不是很合适了
 楼主| 发表于 2024-5-28 10:47 | 显示全部楼层

如果缺少函数,列出来,我补充,当然我很多帖子,可能函数在其他帖子里面有
发表于 2024-5-27 16:27 | 显示全部楼层
感谢分享,感谢杜总~~~~
发表于 2024-5-27 16:31 | 显示全部楼层
啊,大牛写的程序,菜鸡表示看不懂。
发表于 2024-5-27 16:52 | 显示全部楼层
按键没反应
发表于 2024-5-27 18:11 | 显示全部楼层
感谢杜总的分享!
发表于 2024-5-27 22:24 | 显示全部楼层
运行不起来呢
发表于 2024-5-28 09:58 | 显示全部楼层
不明觉厉,膜拜大神,先收藏了
发表于 2024-5-28 11:52 | 显示全部楼层
测试能运行的
发表于 2024-5-28 12:46 | 显示全部楼层
除了D键可以换基点,A、F、E、C键按了都没反应
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-6-26 19:52 , Processed in 0.171630 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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