如何在AutoLisp中访问带引号的变量数据?

时间:2018-12-26 15:21:17

标签: lisp autocad autolisp

我无法访问存储在STPT1ENDPT1x(0)坐标的列表y(1)z(2)中的信息。

例如,得到一个要点后:(45.4529 21.6384 0.0)使用Visual LISP (-(NTH 1 STPT1) 0.5)进行检查时,我得到了实数21.1384,但以下内容:

(SETQ STPTP2 '((NTH 0 STPT1) (- (NTH 1 STPT1) 0.5) 0))

创建列表:

((NTH 0 STPT1) (- (NTH 1 STPT1) 0.5) 0)

代替:

(45.4529 21.1384 0.0)

我的目标是同时创建两条相距0.5个单位的平行线。

如何访问列表STPT1ENDPT1不同位置的信息,然后在列表STPT2ENDPT2中分配它们?

(VL-LOAD-COM)
(DEFUN C:CURBYOURENTHUSIASM ( / STPT1 ENDPT1 STPT2 ENDPT2)
(SETQ STPT1  (GETPOINT "\nSpecify start point: "))
(SETQ ENDPT1 (GETPOINT STPT1 "\nSpecify end point: "))
(SETQ STPT2  '((NTH 0 STPT1)  (-(NTH 1 STPT1) 0.5) 0))
(SETQ ENDPT2 '((NTH 0 ENDPT1) (-(NTH 1 ENDPT1) 0.5) 0))
(SETQ TOP    (ENTMAKE (LIST (CONS 0 "LINE")(CONS 10 STPT1)(CONS 11 ENDPT1)(CONS 8 "CONCRETE"))))
(SETQ BOTTOM (ENTMAKE (LIST (CONS 0 "LINE")(CONS 10 STPT2)(CONS 11 ENDPT2)(CONS 8 "CONCRETE"))))
(PRINC)
)

1 个答案:

答案 0 :(得分:6)

当前问题

您当前的代码存在很多问题:

1。括号不对称

您的代码第5行上的右括号太多:

(SETQ STPT2  '((NTH 0 STPT1)  (-(NTH 1 STPT1) 0.5) 0)))

上述表达式末尾的最后一个闭合括号是闭合defun表达式,导致其余表达式在加载时进行求值,而不是在函数求值时进行求值。

2。引用变量数据

您错误地将以下表达式引用为文字表达式:

(SETQ STPT2  '((NTH 0 STPT1)  (-(NTH 1 STPT1)  0.5) 0))
(SETQ ENDPT2 '((NTH 0 ENDPT1) (-(NTH 1 ENDPT1) 0.5) 0))

单引号后的表达式不会由AutoLISP解释器评估,而是以“面值”获取。

这意味着nth-函数将不被评估,而是将其简单地解释为嵌套列表结构中的符号。有关字面量表达式的更多信息,您可能希望参考我的描述Apostrophe & Quote Function的教程。

要构建变量(即非文字)数据的列表,应使用list函数,例如:

    (setq stpt2 (list (nth 0 stpt1) (- (nth 1 stpt1) 0.5) 0))

3。不必要的ActiveX

您不必要地加载Visual LISP ActiveX扩展(使用(vl-load-com)),但是未在代码中使用此库中的任何功能。这是一个相对较小的问题,但仍然值得一提。


更正上述问题并使用适当的缩进格式设置代码格式,

(defun c:curbyourenthusiasm ( / stpt1 endpt1 stpt2 endpt2 )
    (setq stpt1  (getpoint "\nSpecify start point: "))
    (setq endpt1 (getpoint stpt1 "\nSpecify end point: "))
    (setq stpt2  (list (nth 0 stpt1)  (- (nth 1 stpt1)  0.5) 0))
    (setq endpt2 (list (nth 0 endpt1) (- (nth 1 endpt1) 0.5) 0))
    (setq top    (entmake (list (cons 0 "line") (cons 10 stpt1) (cons 11 endpt1) (cons 8 "concrete"))))
    (setq bottom (entmake (list (cons 0 "line") (cons 10 stpt2) (cons 11 endpt2) (cons 8 "concrete"))))
    (princ)
)

此代码现在可以成功运行,但是有许多可能的改进:


可能的改进

1。用户输入验证

在继续对从用户那里获得的数据进行操作之前,应测试用户输入是否有效:如果用户在不提供提示的情况下取消了提示,则列表值的任何算术运算都会出错,因为这些值将为{{1 }}。

您只需使用nil语句即可避免此类错误:

if

2。线角变化

当前,您的代码将始终在y负方向上偏移第二行,这将导致行间距随行角的变化而变化-当行角垂直时,两条行将重叠。 / p>

为避免这种情况,您可以使用(defun c:curbyourenthusiasm ( / ep1 sp1 ) (if (and (setq sp1 (getpoint "\nSpecify start point: ")) (setq ep1 (getpoint "\nSpecify end point: " sp1)) ) (progn ;; Continue with program operations ) ) (princ) ) 函数在与线角垂直的方向上计算与指定起点和终点相距预定距离的点,您可以使用{{ 1}}函数:

polar

3。 UCS记帐

angle函数将返回其点相对于评估程序时处于活动状态的当前UCS(用户坐标系)表示的点。

但是,与图形数据库中(defun c:curbyourenthusiasm ( / ang ep1 ep2 sp1 sp2 ) (if (and (setq sp1 (getpoint "\nSpecify start point: ")) (setq ep1 (getpoint "\nSpecify end point: " sp1)) ) (progn (setq ang (- (angle sp1 ep1) (/ pi 2)) sp2 (polar sp1 ang 0.5) ep2 (polar ep1 ang 0.5) ) ;; Continue with program operations ) ) (princ) ) 实体的DXF组10和11相关联的点应该相对于WCS(世界坐标系)表示。

我们可以使用AutoLISP getpoint函数在两个坐标系之间变换点:

LINE

4。引用常量数据

如果您有常量数据(例如,显式数字数据或字符串),则可以在代码中引用此类数据作为文字数据,而无需解释器来评估trans(defun c:curbyourenthusiasm ( / ang ep1 ep2 sp1 sp2 ) (if (and (setq sp1 (getpoint "\nSpecify start point: ")) (setq ep1 (getpoint "\nSpecify end point: " sp1)) ) (progn (setq ang (- (angle sp1 ep1) (/ pi 2)) sp2 (trans (polar sp1 ang 0.5) 1 0) ep2 (trans (polar ep1 ang 0.5) 1 0) sp1 (trans sp1 1 0) ep1 (trans ep1 1 0) ) ;; Continue with program operations ) ) (princ) ) 函数构造数据结构:

例如:

list

可以成为:

cons

由于(cons 0 "line") '(0 . "line") 都是常量数据,因此可能被标记为文字。


为实现上述所有条件,我们需要执行以下操作:

0