lisp - 如何在 AutoLisp 中访问带引号的变量数据?
问题描述
我无法访问存储在列表中的信息,STPT1
这些信息ENDPT1
是x(0)
、y(1)
和z(2)
坐标。
例如,在得到一个点之后:(45.4529 21.6384 0.0)
当我使用 Visual LISP 检查时,(-(NTH 1 STPT1) 0.5)
我得到一个 REAL 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 个单位的平行线。
如何访问列表不同位置的信息,然后将它们分配到列表STPT1
和?ENDPT1
STPT2
ENDPT2
(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. 不平衡的括号
您的代码第 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
and-
函数不会被计算,而是被简单地解释为嵌套列表结构中的符号。有关文字表达式的更多信息,您可能希望参考我描述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. 用户输入验证
在继续对从用户获得的数据进行操作之前,您应该测试有效的用户输入:如果用户在不提供点的情况下关闭提示,则对列表值的任何算术运算都会出错,因为这些值将是nil
.
您可以通过简单地使用if
语句来避免此类错误:
(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)
)
2. 线角变化
当前,您的代码将始终在负 y 方向上偏移第二行,这将导致行距随着行角度的变化而变化 - 当行角度垂直时,两条行将重叠。
为避免这种情况,您可以使用该polar
函数计算与指定起点和终点相距预定距离的点偏移量,其方向与直线角度垂直,您可以使用以下angle
函数计算:
(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)
)
3. UCS会计
该getpoint
函数将返回点,其坐标相对于在评估程序时活动的当前 UCS(用户坐标系)表示。
但是,与图形数据库中实体的 DXF 组 10 和 11 关联的点LINE
预计将相对于 WCS(世界坐标系)表示。
trans
我们可以使用 AutoLISP函数在两个坐标系之间转换点:
(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)
)
4.引用常量数据
如果您有常量数据(例如显式数字数据或字符串),您可以在代码中引用这些数据作为文字数据,避免解释器评估list
和cons
函数来构造数据结构:
例如:
(cons 0 "line")
可以变成:
'(0 . "line")
因为0
和"line"
都是常量数据,因此可以标记为文字。
实现上述所有内容,我们有以下内容:
(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)
)
(entmake (list '(0 . "LINE") '(8 . "concrete") (cons 10 sp1) (cons 11 ep1)))
(entmake (list '(0 . "LINE") '(8 . "concrete") (cons 10 sp2) (cons 11 ep2)))
)
)
(princ)
)
推荐阅读
- c# - 如何在 Windows 窗体应用程序安装期间读取文本文件
- r - 旋转马赛克图的标签
- python - 为什么重复 pd.series 不能按预期工作?
- python - 如何为 `scipy.interpolate.splev` 提供特定的 x 值?
- sql - 创建存储过程以将输入参数与请求中的一些值匹配,并在输出参数上返回一些值
- c# - 如何使用实体框架创建复杂类型?(包含或部分视图)
- java - 使用 orika 从多个来源映射到目的地
- android - 错误OpenGLRenderer:GL错误:内存不足
- r - 如何使用 ifelse 和缺失值进行变异?
- dart - 如何从 Dart 中的 Json 创建一个 zip 文件?