乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 9|回复: 6

[编程交流] Lisp-向se提示用户输入

[复制链接]

1

主题

4

帖子

3

银币

初来乍到

Rank: 1

铜币
5
发表于 2022-7-5 19:46:25 | 显示全部楼层 |阅读模式
我想编写一些类似于autocad提示选项的lisp例程,例如“offset”命令,当命令提示输入偏移距离时,它还可以接收其他类型的输入“through/erase/layer”。或者当提示选择实体时,仍然可以接收“退出/撤消”关键字。
 
如何编写类似的lisp程序?
 
提前感谢。
回复

使用道具 举报

114

主题

1万

帖子

1万

银币

中流砥柱

Rank: 25

铜币
543
发表于 2022-7-5 19:58:22 | 显示全部楼层
研究initget函数。
 
举个简单的例子:
  1. (initget "Through Erase Layer")
  2. (setq ans (getdist "\nSpecify offset distance [Through/Erase/Layer]: "))
回复

使用道具 举报

1

主题

4

帖子

3

银币

初来乍到

Rank: 1

铜币
5
发表于 2022-7-5 20:06:44 | 显示全部楼层
谢谢你,李先生。你真是太棒了。
我从你的教程中学到了很多。我会继续向你学习。
回复

使用道具 举报

1

主题

4

帖子

3

银币

初来乍到

Rank: 1

铜币
5
发表于 2022-7-5 20:24:19 | 显示全部楼层
  1. (setq ent_lst nil ent0 nil)
  2. (while (= ent0 nil)
  3. (initget "Distance")
  4. (setq ans (entsel "\nSelect rectangle to chamfer [Distance]: "))
  5. (if (= ans "Distance")
  6.         (progn
  7.         (setq cdis (getreal "Chamfer Distance: <1.0>"))
  8.         )
  9.         (progn
  10.         (setq ent0 ans)
  11.         (setq ent_lst (entget(car ent0)))
  12.         )
  13. )
  14. )
  15. (if (= cdis nil) (setq cdis 1.0))

这是我所做的代码的一部分,用于提示选择图元(矩形)并选择更改倒角距离的选项。
倒角距离的默认值为1.0,如果我希望该值在默认情况下显示为1.0,但如果用户之前已经输入了一个新值,则会显示该值。
这可能吗?
回复

使用道具 举报

114

主题

1万

帖子

1万

银币

中流砥柱

Rank: 25

铜币
543
发表于 2022-7-5 20:26:48 | 显示全部楼层
 
你太善良了kokjoo89-我很高兴你能从我的教程中学习
 
 
您的代码是一个良好的开端-做得好
 
就我个人而言,我更喜欢使用以下结构:
  1. (defun c:test ( / ans dis ent enx ) ;; Define function & declare local variables ('dis-global' remains a global variable)
  2.    ;; Initialise global variable if null
  3.    (if (null dis-global)
  4.        (setq dis-global 1.0)
  5.    )
  6.    (while ;; While the following expression returns a non-nil value
  7.        (progn ;; Evaluate the following expressions and return the result of the last evaluated expression
  8.            (setvar 'errno 0) ;; Reset the ERRNO system variable (this sys var does not automatically reset)
  9.            (initget "Distance") ;; Initialise the keyword for the next user prompt
  10.            (setq ans (entsel "\nSelect rectangle to chamfer [Distance]: ")) ;; Prompt the user for a selection or keyword
  11.            (cond
  12.                (   (= 7 (getvar 'errno)) ;; Missed pick
  13.                    (princ "\nMissed, try again.") ;; Notify user & stay in loop
  14.                )
  15.                (   (null ans) ;; User pressed Enter
  16.                    nil ;; Exit loop
  17.                )
  18.                (   (= "Distance" ans) ;; User entered keyword
  19.                    (if (setq dis (getdist (strcat "\nChamfer distance <" (rtos dis-global) ">: "))) ;; Prompt user for chamfer distance
  20.                        (setq dis-global dis) ;; Update global variable if user enters a new value
  21.                        (setq dis dis-global) ;; Else use global variable value
  22.                    ) ;; end if
  23.                ) ;; end condition
  24.            ) ;; end cond
  25.        ) ;; end progn
  26.    ) ;; end while
  27.    (if ans ;; If an object was selected
  28.        (progn ;; Evaluate the following expressions and return the result of the last evaluated expression
  29.            (setq ent (car ans) ;; Obtain the selected entity name
  30.                  enx (entget ent) ;; Obtain the DXF data for the selected entity
  31.            ) ;; end setq
  32.            (princ ;; Print the entity type & chamfer distance for the selected object (just as an example)
  33.                (strcat ;; Concatenate the following strings
  34.                    "\nUser selected a " (cdr (assoc 0 enx))
  35.                    " with a chamfer distance of " (rtos dis)
  36.                ) ;; end strcat
  37.            ) ;; end princ
  38.        ) ;; end progn
  39.        (princ "\nUser did not select an object.") ;; Else the user did not select anything
  40.    ) ;; end if
  41.    (princ) ;; Suppress the return of the last evaluated expression
  42. ) ;; end defun

(请注意,以上内容未经测试!)
 
在我看来,通过使用(while(progn))结构,可以更容易地控制循环,并避免需要“标志”变量。
 
这还允许错过选择,并允许用户在提示下按ENTER键退出。
回复

使用道具 举报

1

主题

4

帖子

3

银币

初来乍到

Rank: 1

铜币
5
发表于 2022-7-5 20:42:36 | 显示全部楼层
:notworthy:再次感谢您的精彩代码,比我一整天所做的要好100倍。我会研究你的代码来改进我的lisp。
下面是我花了一整天的时间错误地尝试得到的冗长、杂乱、低效的lisp程序。这并不漂亮,但能完成任务。
 
该程序主要提示用户选择一个矩形,然后将矩形偏移到内部,对选定矩形的所有角进行倒角。然后创建4条线,将拐角连接到倒角。偏移和倒角距离相同,可以更改“距离”。
  1. (defun C:PLA ()
  2. (setq osmd (getvar "osmode"))
  3. (setq ocmd (getvar "cmdecho"))
  4. (graphscr)
  5. (setvar "osmode" 0)
  6. (setvar "cmdecho" 0)
  7. (setvar "plinetype" 2)
  8. (command "UCS" "world");reset UCS to "World"
  9. (setq ent_lst nil ent0 nil)
  10. (while (= ent0 nil)
  11.         (initget "Distance")
  12.         (setq ans (entsel "\nSelect rectangle to chamfer [Distance]: "))
  13.         (if (= ans "Distance")
  14.                 (progn
  15.                 (setq cdis (getreal "Chamfer Distance: <1.0>"))
  16.                 )
  17.                 (progn
  18.                 (setq ent0 ans)
  19.                 (setq ent_lst (entget(car ent0)))
  20.                 )
  21.         )
  22. )
  23. (if (= cdis nil) (setq cdis 1.0))
  24. (setq olyr (getvar "clayer"))
  25. (setvar "clayer" (cdr(assoc '8 ent_lst)))
  26. (if (= (cdr(assoc 0 ent_lst)) "LWPOLYLINE")
  27. (progn
  28. (setq len (length ent_lst))
  29. (setq n 0)
  30. (setq vernum 1 verlst nil)
  31. (repeat len
  32.         (setq ent_tmp (car(nth n ent_lst)))
  33.         (if (= ent_tmp 10)
  34.                 (progn
  35.                 (terpri)
  36.                 ;(princ (cdr(nth n ent_lst)))
  37.                 (setq verlst (cons (cons vernum (cdr(nth n ent_lst))) verlst))
  38.                 (setq vernum (1+ vernum))
  39.                 )
  40.         )
  41.         (setq n (1+ n))
  42. )
  43. (if (= (length verlst) 4)
  44.         (progn
  45.         (setvar "chamfera" cdis)
  46.         (setvar "chamferb" cdis)
  47.         (setq midp_x (/(+ (cadr(assoc '1 verlst)) (cadr(assoc '3 verlst))) 2))
  48.         (setq midp_y (/(+ (caddr(assoc '1 verlst)) (caddr(assoc '3 verlst))) 2))
  49.         (setq midp (list midp_x midp_y))
  50.         (command "offset" cdis ent0 midp "")
  51.         (command "chamfer" "p" ent0)
  52.        
  53.         (if (< (cadr(assoc '1 verlst)) (cadr(assoc '3 verlst)))
  54.                 (setq pt_x (cadr(assoc '1 verlst)))
  55.                 (setq pt_x (cadr(assoc '3 verlst)))
  56.         );get ori point_x to start line
  57.         (if (< (caddr(assoc '1 verlst)) (caddr(assoc '3 verlst)))
  58.                 (setq pt_y (caddr(assoc '1 verlst)))
  59.                 (setq pt_y (caddr(assoc '3 verlst)))
  60.         );get ori point_y to start line
  61.         (setq pt0 (list (+ pt_x cdis) (+ pt_y cdis)))
  62.         (setq ldis (/(sqrt (* (* cdis cdis) 2)) 2))
  63.         (setq pt1 (polar pt0 (* 1.25 PI ) ldis))
  64.         (command "line" pt1 pt0 "")
  65.        
  66.         (setq mid_ymp (list midp_x (1+ midp_y)))
  67.         (setq mid_xmp (list (1+ midp_x) midp_y))
  68.         (setq ent_l (entlast))
  69.         (command "mirror" ent_l "" midp mid_ymp "N")
  70.         (setq ent_2 (entlast))
  71.         (command "mirror" ent_l ent_2 "" midp mid_xmp "N")
  72.         (princ "\nDone")
  73.        
  74.         (command "UCS" "P");restore previous UCS
  75.        
  76.         )
  77.         (progn
  78.         (terpri)
  79.         (princ "Invalid Rectangle, ")
  80.         (princ "It has ")
  81.         (princ (length verlst))
  82.         (princ " corners")
  83.         )
  84. )
  85. )
  86. (princ "Invalid lwpolyline")
  87. )
  88. (setvar "osmode" osmd)
  89. (setvar "cmdecho" ocmd)
  90. (setvar "clayer" olyr)
  91. (princ)
  92. )

 
此程序的目标示例:

                               
登录/注册后可看大图

 
我在声明局部变量时仍然有问题。当我声明一些为局部变量时,程序不工作。非常混乱。关于lisp有很多需要学习的地方。
 
一些问题:
1) 我不熟悉(while(progn))结构,我只知道(while)。(while(progn))结构如何工作?它可以在没有旗帜的情况下工作?
2) (null xxx),(=xxx nil),(=xxx“”)之间有什么区别?
3) 为什么(如果是…)如果“ans”不是“T”/零,可以评估“ans”?它是否需要一些求值表达式,如(if(=ans xxx))?
 
再次感谢李:不值得:
回复

使用道具 举报

114

主题

1万

帖子

1万

银币

中流砥柱

Rank: 25

铜币
543
发表于 2022-7-5 20:56:13 | 显示全部楼层
 
就局部变量声明而言,以下内容可能有助于您更好地理解该概念:
 
局部变量范围
本地化变量
 
现在,回答您的问题:
progn表达式是本例中的测试表达式(或您所指的“标志”);然而,在我的示例中,在验证测试表达式时,没有要计算的表达式。
 
progn函数将仅计算提供的表达式,并返回最后计算的表达式返回的值。因此,使用此结构,我们可以计算许多表达式,并通过简单地控制最后一个计算表达式返回的值来控制循环-这在本质上类似于其他语言中的do-while表达式。
 
 
[列表]
  • null验证符号或表达式的计算结果是否为零
    [/列表]
     
    [列表]
  • =通常用于比较数字、符号或字符串的绝对相等性;因此,在本例中,您正在测试由符号xxx持有的值是否与返回true的符号nil相同。虽然在本例中,null和(=nil)的作用相同,但在语义上,我在本例中使用null。
    [/列表]
     
    [列表]
  • (=xxx“”)与(=xxx nil)完全不同:一个表达式正在测试符号xxx持有的值是否等于符号nil;另一个是测试该值是否等于空字符串。请注意,空字符串和nil非常不同:
    [/列表]
    1. _$ (= "" nil)
    2. nil
    3. _$ (< nil "")
    4. T

    在AutoLISP中,任何非nil表达式都可以验证条件函数的测试表达式(if/cond/while)。也就是说,如果符号或表达式不等于零,则将验证测试表达式-符号或表达式不需要包含布尔值。
     
    观察:
    1. _$ (if 1 "yes" "no")
    2. "yes"
    3. _$ (if "a" "yes" "no")
    4. "yes"
    5. _$ (if "" "yes" "no")
    6. "yes"
    7. _$ x
    8. nil
    9. _$ (if x "yes" "no")
    10. "no"
    11. _$ (if 'x "yes" "no")
    12. "yes"

     
    不客气!
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    • 微信公众平台

    • 扫描访问手机版

    • 点击图片下载手机App

    QQ|关于我们|小黑屋|乐筑天下 繁体中文

    GMT+8, 2025-3-12 01:16 , Processed in 0.475242 second(s), 69 queries .

    © 2020-2025 乐筑天下

    联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表