一点背景知识: 我正在创建一个模板供我的起草团队使用。我们有一组常用的对象(不要称它们为“标记”),例如节标记、引线、尺寸、标题栏等,所有这些都设置在表格中(不是真正的“表格”,只是整齐地排列在一个矩形)。所有标记都是注释性的,因此我们不需要为我们所处理的每个操作系统使用一组单独的标记。
现在我们遇到了问题:虽然标记是注释性的,当注释比例改变时可以正确缩放,但它们都围绕自己的基点缩放(正如它们应该的那样)。问题是,如果这些标记由于比例变化而变得太大,它们就会开始严重重叠,以致完全无法使用。我希望它们彼此远离,以便它们保持相对距离不变。换句话说,我有点希望整个表格表现得像注释性的。 我知道只需将整个表格放入注释块即可轻松解决,但标记需要易于起草者使用。我不希望他们每次需要获取标记时都必须分解表块,或者必须进入该块内部,复制所需的标记,从块中出来然后才使用它们。
我试图想出一组步骤来实现我想要的行为,这就是我认为每当模型空间中的注释比例发生变化时 LISP 应该做的事情:
这是展示问题简化版本的图像的链接:
您可以看到橙色表格边框内的各种标记。选择图片中的边框,使其基点可见(我认为使用该基点作为整个表格“缩放”的中心点可能是最简单的)
如果有任何不清楚或有人需要更多信息,请询问。请帮助我
编辑:我可能应该补充一点,我对编写 LISPS(或与此相关的一般编程)几乎一无所知,所以如果您能在回答中尽可能明确,我真的很感激。
编辑 2:我开始特别了解 AutoLISP 和反应器。我编写了以下代码作为开始:
(vlr-sysvar-reactor
"CANNOSCALEVALUE"
'((:vlr-sysvarchanged . MoveMarkersOnScaleChange))
)
(defun MoveMarkersOnScaleChange (calling-reactor :vlr-sysVarChanged)
(princ "Hello")
)
据我了解,每次更改比例(CANNOSCALEVALUE 变量更改)时,应该在命令行中简单地打印“Hello”。它有点像那样工作,但我注意到,一旦 .lsp 加载到我的文件中,它就会在我所做的几乎所有事情(例如绘制折线、移动某些东西等等)之后开始打印“Hello”,而不仅仅是在规模变化(尽管这也有效)。有时它甚至会快速连续打印(HelloHelloHello 等)。有人可以告诉我这里发生了什么吗......?
我怀疑它与
(calling-reactor :vlr-sysVarChanged)
部分有关,因为这是我真正不明白的代码的唯一部分。是的,我知道:
“除对象反应器之外的所有反应器的回调函数必须定义为接受两个参数:
第一个参数标识调用该函数的 Reactor 对象。
第二个参数是 AutoCAD 设置的参数列表。”
但我真的不知道这意味着什么,所以没有太大帮助。
您可以通过反应器捕获更改注释比例的事件
( vlr-sysvar-reactor data functionToRun )
让它监视变量CANNOSCALE
,如下所示:
(defun OnSysvarChanged (reactorObject dane / )
(if (= (strcase (car dane)) "CANNOSCALE") (progn
(setq CANNOSCALE (getvar 'CANNOSCALE ))
(setq scaledata (String:Split CANNOSCALE ":"))
(setq scalefactor (/ (atof (car scaledata) ) (atof (cadr scaledata))))
(print scalefactor)
))
)
(defun String:Split (txt separator / index result)
(setq index(vl-string-search separator txt))
(while index
(progn
(setq result (append result (list(substr txt 1 index))))
(setq txt (substr txt (+ index 1 (strlen separator))))
(setq index(vl-string-search separator txt))
)
)
(setq result (append result (list txt)))
result
)
(vlr-editor-reactor nil '((:VLR-sysVarChanged . OnSysvarChanged)))
桌子的中心点你可以这样得到。
我不知道你如何识别表 - 为了简化,我们假设我们有一个它的句柄:
(setq frame (handent "24E" ))
(setq bbox (BoundingBox:Get frame ) )
(setq center (BoundingBox:Center bbox))
(print center)
(defun BoundingBox:Get (object / )
(cond
( (null object) nil)
( (=(type object) 'ENAME ) (BoundingBox:Get (vlax-ename->vla-object object)))
( (=(type object) 'VLA-OBJECT ) ( progn
(vla-GetBoundingBox object 'minpoint 'maxpoint)
(list (cons 'MIN (list(List:Factory minpoint ))) (cons 'MAX (list(List:Factory maxpoint))
) )
) )
( t nil )
)
)
(defun BoundingBox:Center (bbox / )
(cond
( (null bbox) nil)
( (or (not(listp bbox)) (/=(length bbox) 2) ) nil)
( (or (null (assoc 'MIN bbox )) (null (assoc 'MAX bbox ) ) ) nil )
( t (progn
(setq minpoint (cadr (assoc 'MIN bbox))
maxpoint (cadr (assoc 'MAX bbox)) )
(Point:Calculate:Middle minpoint maxpoint)
) )
)
)
(defun Point:Calculate:Middle ( p1 p2 / )
(mapcar '(lambda (a b ) (+ a (* (- b a ) 0.5))) p1 p2)
)
(defun List:Factory (InVal / OutVal AsList result i )
(cond
( ( = (type InVal) nil) nil)
( (vl-catch-all-error-p InVal) (progn (princ "Error trapped:" ) (princ InVal ) nil))
( ( = (type InVal) 'LIST) InVal)
( ( = (type InVal) 'SAFEARRAY) (progn
(setq AsList (vl-catch-all-apply 'vlax-safearray->list (list InVal )))
(if (vl-catch-all-error-p AsList) ( progn
( princ (vl-catch-all-error-message AsList ) )
nil
) ( progn
AsList
) )
) )
( ( = (type InVal) 'VARIANT) (progn
(List:Factory (vlax-variant-value InVal) )
) )
( (= (type InVal) 'PICKSET ) (progn
(setq i 0 )
(repeat (sslength InVal)
(setq result (append result (list (vlax-ename->vla-object(ssname InVal i)))))
(setq i (1+ i ) )
)
result
) )
( t (list InVal ) )
)
)
确定表格内的对象您可以通过
(ssget )
来完成此操作。 - 不会提示用户任何内容。