Lisp-向se提示用户输入
我想编写一些类似于autocad提示选项的lisp例程,例如“offset”命令,当命令提示输入偏移距离时,它还可以接收其他类型的输入“through/erase/layer”。或者当提示选择实体时,仍然可以接收“退出/撤消”关键字。如何编写类似的lisp程序?
提前感谢。 研究initget函数。
举个简单的例子:
(initget "Through Erase Layer")
(setq ans (getdist "\nSpecify offset distance : ")) 谢谢你,李先生。你真是太棒了。
我从你的教程中学到了很多。我会继续向你学习。 (setq ent_lst nil ent0 nil)
(while (= ent0 nil)
(initget "Distance")
(setq ans (entsel "\nSelect rectangle to chamfer : "))
(if (= ans "Distance")
(progn
(setq cdis (getreal "Chamfer Distance: <1.0>"))
)
(progn
(setq ent0 ans)
(setq ent_lst (entget(car ent0)))
)
)
)
(if (= cdis nil) (setq cdis 1.0))
这是我所做的代码的一部分,用于提示选择图元(矩形)并选择更改倒角距离的选项。
倒角距离的默认值为1.0,如果我希望该值在默认情况下显示为1.0,但如果用户之前已经输入了一个新值,则会显示该值。
这可能吗?
你太善良了kokjoo89-我很高兴你能从我的教程中学习
您的代码是一个良好的开端-做得好
就我个人而言,我更喜欢使用以下结构:
(defun c:test ( / ans dis ent enx ) ;; Define function & declare local variables ('dis-global' remains a global variable)
;; Initialise global variable if null
(if (null dis-global)
(setq dis-global 1.0)
)
(while ;; While the following expression returns a non-nil value
(progn ;; Evaluate the following expressions and return the result of the last evaluated expression
(setvar 'errno 0) ;; Reset the ERRNO system variable (this sys var does not automatically reset)
(initget "Distance") ;; Initialise the keyword for the next user prompt
(setq ans (entsel "\nSelect rectangle to chamfer : ")) ;; Prompt the user for a selection or keyword
(cond
( (= 7 (getvar 'errno)) ;; Missed pick
(princ "\nMissed, try again.") ;; Notify user & stay in loop
)
( (null ans) ;; User pressed Enter
nil ;; Exit loop
)
( (= "Distance" ans) ;; User entered keyword
(if (setq dis (getdist (strcat "\nChamfer distance <" (rtos dis-global) ">: "))) ;; Prompt user for chamfer distance
(setq dis-global dis) ;; Update global variable if user enters a new value
(setq dis dis-global) ;; Else use global variable value
) ;; end if
) ;; end condition
) ;; end cond
) ;; end progn
) ;; end while
(if ans ;; If an object was selected
(progn ;; Evaluate the following expressions and return the result of the last evaluated expression
(setq ent (car ans) ;; Obtain the selected entity name
enx (entget ent) ;; Obtain the DXF data for the selected entity
) ;; end setq
(princ ;; Print the entity type & chamfer distance for the selected object (just as an example)
(strcat ;; Concatenate the following strings
"\nUser selected a " (cdr (assoc 0 enx))
" with a chamfer distance of " (rtos dis)
) ;; end strcat
) ;; end princ
) ;; end progn
(princ "\nUser did not select an object.") ;; Else the user did not select anything
) ;; end if
(princ) ;; Suppress the return of the last evaluated expression
) ;; end defun
(请注意,以上内容未经测试!)
在我看来,通过使用(while(progn))结构,可以更容易地控制循环,并避免需要“标志”变量。
这还允许错过选择,并允许用户在提示下按ENTER键退出。 :notworthy:再次感谢您的精彩代码,比我一整天所做的要好100倍。我会研究你的代码来改进我的lisp。
下面是我花了一整天的时间错误地尝试得到的冗长、杂乱、低效的lisp程序。这并不漂亮,但能完成任务。
该程序主要提示用户选择一个矩形,然后将矩形偏移到内部,对选定矩形的所有角进行倒角。然后创建4条线,将拐角连接到倒角。偏移和倒角距离相同,可以更改“距离”。
(defun C:PLA ()
(setq osmd (getvar "osmode"))
(setq ocmd (getvar "cmdecho"))
(graphscr)
(setvar "osmode" 0)
(setvar "cmdecho" 0)
(setvar "plinetype" 2)
(command "UCS" "world");reset UCS to "World"
(setq ent_lst nil ent0 nil)
(while (= ent0 nil)
(initget "Distance")
(setq ans (entsel "\nSelect rectangle to chamfer : "))
(if (= ans "Distance")
(progn
(setq cdis (getreal "Chamfer Distance: <1.0>"))
)
(progn
(setq ent0 ans)
(setq ent_lst (entget(car ent0)))
)
)
)
(if (= cdis nil) (setq cdis 1.0))
(setq olyr (getvar "clayer"))
(setvar "clayer" (cdr(assoc '8 ent_lst)))
(if (= (cdr(assoc 0 ent_lst)) "LWPOLYLINE")
(progn
(setq len (length ent_lst))
(setq n 0)
(setq vernum 1 verlst nil)
(repeat len
(setq ent_tmp (car(nth n ent_lst)))
(if (= ent_tmp 10)
(progn
(terpri)
;(princ (cdr(nth n ent_lst)))
(setq verlst (cons (cons vernum (cdr(nth n ent_lst))) verlst))
(setq vernum (1+ vernum))
)
)
(setq n (1+ n))
)
(if (= (length verlst) 4)
(progn
(setvar "chamfera" cdis)
(setvar "chamferb" cdis)
(setq midp_x (/(+ (cadr(assoc '1 verlst)) (cadr(assoc '3 verlst))) 2))
(setq midp_y (/(+ (caddr(assoc '1 verlst)) (caddr(assoc '3 verlst))) 2))
(setq midp (list midp_x midp_y))
(command "offset" cdis ent0 midp "")
(command "chamfer" "p" ent0)
(if (< (cadr(assoc '1 verlst)) (cadr(assoc '3 verlst)))
(setq pt_x (cadr(assoc '1 verlst)))
(setq pt_x (cadr(assoc '3 verlst)))
);get ori point_x to start line
(if (< (caddr(assoc '1 verlst)) (caddr(assoc '3 verlst)))
(setq pt_y (caddr(assoc '1 verlst)))
(setq pt_y (caddr(assoc '3 verlst)))
);get ori point_y to start line
(setq pt0 (list (+ pt_x cdis) (+ pt_y cdis)))
(setq ldis (/(sqrt (* (* cdis cdis) 2)) 2))
(setq pt1 (polar pt0 (* 1.25 PI ) ldis))
(command "line" pt1 pt0 "")
(setq mid_ymp (list midp_x (1+ midp_y)))
(setq mid_xmp (list (1+ midp_x) midp_y))
(setq ent_l (entlast))
(command "mirror" ent_l "" midp mid_ymp "N")
(setq ent_2 (entlast))
(command "mirror" ent_l ent_2 "" midp mid_xmp "N")
(princ "\nDone")
(command "UCS" "P");restore previous UCS
)
(progn
(terpri)
(princ "Invalid Rectangle, ")
(princ "It has ")
(princ (length verlst))
(princ " corners")
)
)
)
(princ "Invalid lwpolyline")
)
(setvar "osmode" osmd)
(setvar "cmdecho" ocmd)
(setvar "clayer" olyr)
(princ)
)
此程序的目标示例:
http://i.imgur.com/tsHEf1A.png
我在声明局部变量时仍然有问题。当我声明一些为局部变量时,程序不工作。非常混乱。关于lisp有很多需要学习的地方。
一些问题:
1) 我不熟悉(while(progn))结构,我只知道(while)。(while(progn))结构如何工作?它可以在没有旗帜的情况下工作?
2) (null xxx),(=xxx nil),(=xxx“”)之间有什么区别?
3) 为什么(如果是…)如果“ans”不是“T”/零,可以评估“ans”?它是否需要一些求值表达式,如(if(=ans xxx))?
再次感谢李:不值得:
就局部变量声明而言,以下内容可能有助于您更好地理解该概念:
局部变量范围
本地化变量
现在,回答您的问题:
progn表达式是本例中的测试表达式(或您所指的“标志”);然而,在我的示例中,在验证测试表达式时,没有要计算的表达式。
progn函数将仅计算提供的表达式,并返回最后计算的表达式返回的值。因此,使用此结构,我们可以计算许多表达式,并通过简单地控制最后一个计算表达式返回的值来控制循环-这在本质上类似于其他语言中的do-while表达式。
[列表]
[*]null验证符号或表达式的计算结果是否为零
[/列表]
[列表]
[*]=通常用于比较数字、符号或字符串的绝对相等性;因此,在本例中,您正在测试由符号xxx持有的值是否与返回true的符号nil相同。虽然在本例中,null和(=nil)的作用相同,但在语义上,我在本例中使用null。
[/列表]
[列表]
[*](=xxx“”)与(=xxx nil)完全不同:一个表达式正在测试符号xxx持有的值是否等于符号nil;另一个是测试该值是否等于空字符串。请注意,空字符串和nil非常不同:
[/列表]
_$ (= "" nil)
nil
_$ (< nil "")
T
在AutoLISP中,任何非nil表达式都可以验证条件函数的测试表达式(if/cond/while)。也就是说,如果符号或表达式不等于零,则将验证测试表达式-符号或表达式不需要包含布尔值。
观察:
_$ (if 1 "yes" "no")
"yes"
_$ (if "a" "yes" "no")
"yes"
_$ (if "" "yes" "no")
"yes"
_$ x
nil
_$ (if x "yes" "no")
"no"
_$ (if 'x "yes" "no")
"yes"
不客气!
页:
[1]