ngc 发表于 2016-10-13 22:11:35

双向偏移--while用法

本帖最后由 ngc 于 2016-10-13 22:18 编辑

看了好多关于while运用的帖子,也看了好多别人写的代码,我理解,就是有东西给while,他就会一直循环下去,没有就结束了。
下面是连续单选双向偏移的源码,带偏移后的改变线的颜色,或者改变线的图层,
(defun c:tt()
(vl-load-com)
(princ "\n单选双向偏移")
(setq os (getvar 'osmode))
(setq cmd (getvar 'cmdecho))
(mapcar 'setvar (list 'osmode 'cmdecho) '(0 0))
(setq w (getreal "\n【偏移宽度】:"))
(while (setq enpline (car(entsel)))
         (setvar 'osmode 0)
         (vla-Offset (vlax-ename->vla-object enpline) (/ w 2.0))
         (setq pline1 (entlast))
         (command "change" pline1"" "p" "c" "2" "" )
         (vla-Offset (vlax-ename->vla-object enpline) (/ w -2.0))
         (setq pline2 (entlast))
         (command "change" pline2"" "p" "la" "ngc6""" )
   )
(mapcar 'setvar (list 'osmode 'cmdecho) (list os cmd))
(princ)
)



下面请教高手,怎么能够在没有pline线的情况下,边画边偏移,连续生成双线,
下面是图片说明:



newer 发表于 2016-10-13 23:22:28

这样还能好点,不用就不执行。

(defun c:tt ()
(vl-load-com)
(princ "\n单选双向偏移")
(if (setq w (getreal "\n【偏移宽度】<退出>:"))
    (progn
      (setq os (getvar 'osmode))
      (setq cmd (getvar 'cmdecho))
      (mapcar
        'setvar
        (list 'osmode 'cmdecho)
        '(0 0)
      )
      (while (setq enpline (car (entsel)))
        (setvar 'osmode 0)
        (vla-Offset (vlax-ename->vla-object enpline) (/ w 2.0))
        (setq pline1 (entlast))
        (command "change" pline1 "" "p" "c" "2" "")
        (vla-Offset (vlax-ename->vla-object enpline) (/ w -2.0))
        (setq pline2 (entlast))
        (command "change" pline2 "" "p" "la" "ngc6" "")
      )
      (mapcar
        'setvar
        (list 'osmode 'cmdecho)
        (list os cmd)
      )
    )
)
(princ)
)

newer 发表于 2016-10-13 23:20:17

修改了下你的代码,这样能好点, 偏移距离那加个IF,输入回车就不执行循环了,否则代码就出错了。


(defun c:tt ()
(vl-load-com)
(princ "\n单选双向偏移")
(setq os (getvar 'osmode))
(setq cmd (getvar 'cmdecho))
(mapcar
    'setvar
    (list 'osmode 'cmdecho)
    '(0 0)
)
(if (setq w (getreal "\n【偏移宽度】<退出>:"))
    (while (setq enpline (car (entsel)))
      (setvar 'osmode 0)
      (vla-Offset (vlax-ename->vla-object enpline) (/ w 2.0))
      (setq pline1 (entlast))
      (command "change" pline1 "" "p" "c" "2" "")
      (vla-Offset (vlax-ename->vla-object enpline) (/ w -2.0))
      (setq pline2 (entlast))
      (command "change" pline2 "" "p" "la" "ngc6" "")
    )
)
(mapcar
    'setvar
    (list 'osmode 'cmdecho)
    (list os cmd)
)
(princ)
)

HLCAD 发表于 2016-10-13 22:47:20

...
(setq w (getreal "\n【偏移宽度】:"))
(setq L-en (entlast))
(while (or (setq enpline (car(entsel)))
            (progn (command "_.pline")
                        (while (>(getvar 'cmdactive)0)(command pause))
                        (setq enpline (entnext L-en))
                        )
            )
(setvar 'osmode 0)
...

newer 发表于 2016-10-13 23:13:10

理解的对,挺通俗的。 表求值不为NIL,就一直循环。

newer 发表于 2016-10-13 23:14:53

LISP没有

do
...
while (....)

语句,这个就是为真就结束循环了。

ngc 发表于 2016-10-13 23:20:37

HLCAD 发表于 2016-10-13 22:47


谢谢,我查了系统变量说明:
CMDACTIVE 系统变量


类型 整数
保存位置 尚未保存
初始值 无

指示激活的是普通命令、透明命令、脚本还是对话框。 系统将使用下列位码值之和将该设置存储为一个位码:
1激活普通命令
2激活普通命令和透明命令
4激活脚本
8激活对话框
16激活 DDE
32激活 AutoLISP(仅对 ObjectARX定义的命令可见)
64激活 ObjectARX 命令


这个运用方法,不知道是什么意思?

ngc 发表于 2016-10-13 23:30:29

根据HLCAD的方法,我改了改,还是不能实现,就是画一条多义线,就偏移,然后再画一条,再偏移,
最后右击鼠标退出程序,不用 (setq enpline (car(entsel))),直接画pline线就行
(defun c:tt ()
(setq os (getvar 'osmode))
(setq cmd (getvar 'cmdecho))
(mapcar 'setvar (list 'osmode 'cmdecho) '(0 0))
   (setq w 4)
   (setq L-en (entlast));先设置最后一次的图元为L-en
   (while (or (setq enpline (car(entsel)))
            (progn (command "_.pline")
                   (while (>(getvar 'cmdactive)0)(command pause))
                   (setq enpline (entnext L-en))
            );end progn
          );end or

   (setvar 'osmode 0)
   (setq enpline (entlast))
   (if (not (equal L-en enpline));比较 L-en enpline 是否相同,not nil为真 T
   (progn
       (vla-Offset (vlax-ename->vla-object enpline) (/ w 2.0))
       (setq pline1 (entlast))
       (vla-Offset (vlax-ename->vla-object enpline) (/ w -2.0))
       (setq pline2 (entlast))
       (setq ssbj (ssadd pline1))
       (ssadd pline2 ssbj)
      )
    );end if
);end while

(mapcar 'setvar (list 'osmode 'cmdecho) (list os cmd))
   (princ)
)

newer 发表于 2016-10-13 23:31:42

ngc 发表于 2016-10-13 23:20


就是在命令激活状态下,比如画PLINE,命令中间查询这个系统变量cmdactive就不等于0了。

用途挺广泛的,比如命令的参数需要你交互,不能在命令里面给出来,也不知道需要多少个参数的时候,

比如画PLINE

(defun c:tt ()
(command ".pline")
(while (/= (getvar "cmdactive") 0)
    (command ".pause")
)
(princ)
)



这个代码,如果不用这个系统变量,很不好利用PLINE命令的。

还比如,有些命令,比如STYLE等等,很多时候需要一直按“Y”,但不同的命令需要的"Y”不一样多,也可以利用这个性质

(while (/= (getvar "cmdactive") 0)
   (command "Y")
)


意思就是只要当前命令还要激活,我就一直输入“Y”。

还有:

(while (/= (getvar "cmdactive") 0)
   (command "")
)



表示当前命令我交互的完了,剩下的,只要命令还在执行,我就一直“回车”。直到命令结束。

ngc 发表于 2016-10-13 23:39:10

newer 发表于 2016-10-13 23:31


看来还是要多看看前辈们的代码,多理解,有些地方确实不知道怎么用
请问,能否实现画一条多义线,就偏移,然后再画一条,再偏移,最后右击鼠标退出程序

newer 发表于 2016-10-13 23:42:50

ngc 发表于 2016-10-13 23:30


你想要 画一段线 就偏移,然后接着PLINE,用命令不行的,命令执行内部,只能接受命令需要的参数,你给的每个值都对应命令要求的参数。

你可以写自己的PLINE啊,线都不用先画出来,你用GETPOINT不断的取点,然后画临时的向量到屏幕,中间把点都保存到表里面,最后结束的时候,根据点表再生成PLINE。

newer 发表于 2016-10-14 00:02:53

ngc 发表于 2016-10-13 23:39


下面代码是一个结构,绘制单线的,你可以在里面加进去偏移的代码。


(defun c:tt (/ p1 pt pts)
(setq i 0)
(setvar "plinewid" 0)
(while (if (= i 0)
           (setq pt (getpoint "\n第一点<退出>:"))
           (setq pt (getpoint p1 "\n下一点<结束>:"))
       )
    (if (> (length pts) 0)
      (grdraw p1 pt 1)
    )
    (setq i 1
          p1 pt
          pts (cons pt pts)
    )
)
(redraw)
(setq pts (reverse pts) i 0)
(command "pline")
(while (/= 0 (getvar "cmdactive"))
   (command (nth i pts))
   (setq i (1+ i))
)
(princ)
)


yoyoho 发表于 2016-10-14 00:07:24

啥也不说了,感谢楼主分享哇!

ngc 发表于 2016-10-14 00:42:16

newer 发表于 2016-10-14 00:02


非常感谢版主,你给的代码,我已经理解了,并加了标注,有很多值得学习的地方

ngc 发表于 2016-10-14 00:44:40

(defun c:tt (/ p1 pt pts)
(setq i 0)
(setvar "plinewid" 0);多段线宽度
;顺序说明:

;第一个假如等于零,执行:(setq pt (getpoint "\n第一点<退出>:"))
;;;                        (setq i 1
;;;                              p1 pt
;;;                              pts (cons pt pts)
;;;                           )

;第一个假如不等于零,执行:(setq pt (getpoint p1 "\n下一点<结束>:"))
;;;点数超零时触发第二个假如(if (> (length pts) 0)
;;;                                 (grdraw p1 pt 1)
;;;;;;                            )
;;;                        (setq i 1
;;;                              p1 pt
;;;                              pts (cons pt pts);向表的头部添加一个元素,或构造一个点对
(while
    ;第一个假如
       (if (= i 0)
         (setq pt (getpoint "\n第一点<退出>:"));等于零,执行
         (setq pt (getpoint p1 "\n下一点<结束>:"));不等于零,临时画红线
       );end 第一个if
    ;第二个假如
       (if (> (length pts) 0);以整数形式返回表中元素的数目
             (grdraw p1 pt 1);在当前视口中的两个点之间显示一条矢量线(grdraw from to color )
       );end 第二个if
   
    (setq i 1
          p1 pt
          pts (cons pt pts);向表的头部添加一个元素,后面的点往前添加,所以下面需要反转点表
    )
);end while
(redraw);重画当前视口
(setq pts (reverse pts);将表的元素顺序倒置后返回
i 0)
(command "pline")
(while (/= 0 (getvar "cmdactive"))
   (command (nth i pts));起点
   (setq i (1+ i));第二点,直到终点
);end while
(princ)
)版主的代码,我加了标注,
页: [1] 2
查看完整版本: 双向偏移--while用法