如果有隐含的选择
大家好,我使用此例程按层过滤对象:
(defun C:test ( / )
(setvar 'errno 0)
(setq ent (entsel "\nPick object to filter by its Layer"))
(if (= (getvar 'errno) 7)
(progn (princ "\nMissed.. Try again!")
(C:test)
)
nil
);if
(setq layername (cdr (assoc 8 (entget (car ent))))) ;<-LayerName
(if (= layername nil)
(setq layername 256)
)
(princ (strcat "\nLayername to filter \"" layername "\" " ))
(princ "\nSelect objects to filter and press enter OR press enter right away to filter all: \n")
(if (not (setq sset (ssget (list (cons 8 layername)))))
(setq sset (ssget "_X" (list (cons 8 layername) (cons 410 (getvar 'ctab)))))
)
(sssetfirst sset sset)
(princ (strcat "\nSelected " (itoa (sslength sset)) " objects on layer \"" layername "\" "))
(princ)
);defun
可以使用(ssadd)将单个实体添加到选择集。如果要将两个选择集合并在一起,则必须遍历一个选择集,并使用该方法将项目逐个添加到第二个选择集。
要知道的另一件好事是,单独使用ssadd(setq selectionset(ssadd))将创建一个空的选择集,您可以向其中添加实体(同样,使用前面描述的相同方法)。
我不确定我是否完全理解你的目标,但这里有一些想法
(defun c:IsThereASelectionMadeAlready ( / VariableThatWillContainTheSelectionSetIfThereWereObjectsPreviouslySelected)
(if (setq VariableThatWillContainTheSelectionSetIfThereWereObjectsPreviouslySelected (ssget "_I"))
(alert "A selection was already made when this lisp was launched!")
(alert "No objects are selected yet!"))
(princ)
)
这里有很多问题。右键单击(或输入)而不是进行选择将导致errno 52,(错误的参数类型:lentyp nil)。除此之外,它不仅仅重新启动命令,而是递归地重新启动它。让我们以图形化的方式来表达
如果您有如下随机命令
(setq ent (entsel "\nPick object to filter by its Layer"))
(if (= (getvar 'errno) 7)
(progn (princ "\nMissed.. Try again!")
(C:test)
)
nil
)
在这个例子中,很明显
现在让我们以同样的例子来改变一件事,将函数命名为A,而不是randomcommand
(defun c:randomcommand ()
(conditionnally execute command A)
(execute command B)
(execute command C)
)
假设第一次满足有条件执行命令A的条件
命令A将执行命令B
命令A将执行命令C
命令A结束
当递归命令A结束时,命令A将继续运行。基本上,对于您的代码,每次错误点击,代码的其余部分都会被计算一次。
在下面的代码中,我修复了这个问题,并将每次启动时的活动选择集与新选择合并。
(defun c:A ()
(conditionnally execute command A)
(execute command B)
(execute command C)
)
在开始时,在将隐含选择存储到变量中后,我取消了它(在代码中注释为“required”),因为引用M.Lee Mac注意,默认情况下,如果PICKFIRST=1,ssget将尊重隐含选择。,这意味着如果您使用(ssget(list(cons 8“0”)),它将要求进行选择。如果您使用它时选中了第1、2和3层上的内容,它将删除选择并提示您进行另一个选择。。。但是,如果您使用它时选择了层0 1和层2上的内容,它将不会提示用户进行选择,而是使用已经进行的选择,并删除层0以外的所有内容。
尽管如此,我认为你还没有收到任何回复的另一个原因是,我个人认为这是一个典型的X-Y问题。你有一个问题X。由于Y是你认为最合适的解决方案(使用隐含选择并将其与将要进行的任何其他选择合并),你询问Y时没有谈论问题X。我们不知道你到底需要/正在尝试实现什么(我的感觉是,你想做一个全局选择,然后一个接一个地选择东西,让嘴唇做出/返回一个选择,选择到目前为止与所选对象在同一层上的所有东西,在原始全局选择中。如果我对你试图实现的感觉是错误的,那么很可能我在“错误的方向”上浪费了一些时间. 如果我对你想要实现的感觉是对的,那么大多数情况下。。。我也在“错误的方向”上浪费了一些时间。我不会使用隐含选择并连续多次运行lisp例程,而是使用while语句来实现相同的结果,只运行一次命令。我提供的代码可能可以完成这项工作,但事实上,如果出于任何原因,在启动命令时,您有一个非自愿的手动选择(甚至可能在屏幕之外),您将得到奇怪和不想要的结果(甚至可能不知道原因)。。。这是我的2美分,我认为你正在努力实现。迷你rant#2以上
尽管如此,我还是回答了这个问题,因为很长一段时间以来,我想玩并尝试隐含选择,想做一些关于选择合并/处理的练习,因为我想使用我刚刚发现的errno变量(多亏了李!),因为我想做我的两个小咆哮(哈哈哈),因为它很有趣,因为。。。。
我希望这(多少)有帮助!
干杯 Jef!,你的回复是我收到的最好的回复!
当然,我会把你加入学分!
也许你已经注意到了,我从你那里得到了第一个例子——编写代码似乎并不难:
实际上,这个例程是我的更大的(selecion filter例程)的一小部分,所以它的信息将是这样的(我希望每个人都在学分中感到高兴):
(defun c:test ( / SelectedFirst ent layername sset sspos e)
;Jef! 2016-02-25
(vl-load-com)
(setvar 'errno 0)
(if (setq SelectedFirst (ssget "_I"))
(sssetfirst nil nil);required
)
(while (not (and (setq ent (car(entsel "\nSelect an object of the required layer: ")))
(setq layername (cdr (assoc 8 (entget ent))))
)
)
(cond
( (= 52 (getvar 'errno))
(princ "\nYou must select an object.")
)
( (null ent)
(princ "\nYou missed, try again.")
)
)
)
(princ (strcat "\nLayername to filter \"" layername "\" " ))
(princ "\nSelect objects to filter and press enter OR press enter right away to filter all: \n")
(if (not (setq sset (ssget (list (cons 8 layername)))))
(setq sset (ssget "_X" (list (cons 8 layername) (cons 410 (getvar 'ctab)))))
)
(if SelectedFirst
(progn
(setq sspos (sslength SelectedFirst))
(while (setq e (ssname SelectedFirst (setq sspos (1- sspos))))
(ssadd e sset)
)
)
)
(sssetfirst nil sset)
(vla-Regen (vla-get-ActiveDocument (vlax-get-acad-object)) acActiveViewport)
(princ)
)
我刚刚发布了其中的一部分,以澄清我的问题-因为它对我很重要。
整个程序仍在进行中,完成后我会发布。
我不是一个英俊的程序员,但我一点一点地学习,我擅长从其他代码/示例中组装东西。
是的,李·麦克无处不在(在每一段代码中),即使你没有预料到。我还从他那里学到了errno变量(和许多其他东西)
最后,对我来说唯一重要的是最后一个例程(因为我们都是ACAD用户/起草者)。如果不是全部,至少我是!
我可能会重读你的帖子几次(因为编码很难),但你发布的最终结果正是我想要的!
编辑:
我读得越多,我就越明白我问的问题有多复杂(嗯,回答得慢或没有回答都证实了这一点)。
好吧,用一个例子来回答你的感受(这是对的):
1、运行例程
2.选择实体以存储其层(将其命名为layer1)
3、按该层过滤对象
4.现在过滤后,用户保留该选择
5、重新运行例程
6.根据实体类型选择要存储的实体(假设这是一个圆)
7、按该实体类型过滤对象
8.选择包含第1层上的实体和圆形实体(无论层如何)
该方法提供了过滤选择的无限堆叠,其中包含各种对象。
下一种可能是隔离/擦除/另存为新的SELSET/etc。。。最后的选择和其他程序。
这就是整个概念。。。
谢谢你,杰夫! 您好,Grrr。
嗯,你们在这一部分的学分非常。。。友善的你忘了妻子->支持和妈妈->美食!
也许我的措辞选择不是最好的(英语是我的第二语言)。。。Addind“他们的许多例子,关于代码的不同部分”没有说哪部分来自谁。假设有人想使用你最终代码的一部分,谁制作了那个特定的部分?这并不是说我太过火了,比如说我用jeff sanders教程学会了如何制作“if”函数,我不会每次用“if”时都感谢jeff。如果我使用某个人编写的函数,我会保留作者的原始标题。其他的例子,有一天我请求帮助,我做了一个很小的函数(5行),速度很慢。我把它贴在这里,有人帮我把速度提高了50倍。在defun上方的标题中,我添加了该评论
;; 感谢克林特(cwake)帮助优化
有时以前,我做了一个(找不到它,bravo microsoft on win7 content:x search不工作),我处理对象的方式是由某人输入的,所以我添加了
;灵感来自peter jamtgaard wathever函数(来源:w.xxx)
它可以帮助我跟踪从哪里来的东西,如果需要的话可以找到它,是谁写的,如果我把它贴在这里寻求帮助,让别人也知道它。。。并从一开始就确定,而不是在线程末尾发布的最终代码上。
也许我有一部分是对的,但现在我正在阅读这个列表,你编写它的方式-进行选择,通过拾取对象选择1层,通过拾取对象选择实体类型(我没有预见到的部分)让我想:为什么不使用quickselect/filter本机函数?
可能会提供无限的“和”选择(选择x层上的实体,这些实体是圆和…)如果所有的“过滤器”都必须应用于相同的原始选择,我宁愿让用户完成他的选择,并用逻辑运算符(和/或/不…)进行ssget而不是让他们一次处理1个。假设您在第1层上收集所有内容,然后收集所有圆,最后在第1层的圆上得到一个选择集(a)。然后你想在第2层上添加所有矩形,需要选择B。如果你这样做,你需要每个“和”一个选择集。在A中包含B。一旦B被创建,如果你点击错误,你就失去了返回的选择。你必须从头开始。我不确定独立保存它们是否更好,这取决于您想要实现的目标,因为选择集集合可以容纳多少个选择集是有限制的。这两种方法似乎都导致了死胡同或非最优方法。当然,X有一个解决方案
你没有提到在你的8个步骤中你在哪里进行全局选择(或选择?)(适用不同过滤器的选择)
如果所有过滤器都应用于同一选择,并假设您要进行选择以包括
-层0上的多重引线
-层1上的多重引线
-在坐标55.0,45.0,0.0上开始或结束的任何直线
-位于第0层和第1层上的半径为1的圆
您可以使用一个唯一的ssget/ssget“x”来检索它
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Routine Information ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Author: Grrr ;
; Credits to: Lee Mac, Tharwat - I had(and took) many examples from them, about different parts of the code ;
; AlanJT, CAB - They made the first filter routines of this kind, I took that idea and decided to develop it ;
; Jef! - He gave me the best examples, for storing the Implied selection - which is a big deal, and the selection options (window sel or sel all) ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
虽然您的代码可以实现手动制作和过滤器的无限堆叠,但其他一些方法可能比要求用户单击每个几何体/层样本更快。想想在第0层、第1层和第2层上选择圆以及第0层、第1层和第2层上的所有线所需的所有单击。使用ssget上的“AND”过滤器执行此操作看起来是这样的。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Routine Information ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Author: Grrr ;
; Credits to: Lee Mac, Tharwat - I had(and took) many examples from them, about different parts of the code ;
; AlanJT, CAB - They made the first filter routines of this kind, I took that idea and decided to develop it ;
; Jef! - He gave me the best examples, for storing the Implied selection - which is a big deal, and the selection options (window sel or sel all) ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
少数“或”可以节省很多“和”,这将完成与前面代码相同的工作
(ssget "_x"
'(
(-4 . "<OR")
(-4 . "<AND") (0 . "CIRCLE")(8 . "0") (-4 . "AND>")
(-4 . "<AND") (0 . "CIRCLE")(8 . "1") (-4 . "AND>")
(-4 . "<AND") (0 . "CIRCLE")(8 . "2") (-4 . "AND>")
(-4 . "<AND") (0 . "LINE") (8 . "0") (-4 . "AND>")
(-4 . "<AND") (0 . "LINE") (8 . "1") (-4 . "AND>")
(-4 . "<AND") (0 . "LINE") (8 . "2") (-4 . "AND>")
(-4 . "OR>")
)
)
如果不是通过拾取来制作ssget,而是使用类似qselect菜单的菜单来制作ssget,那么可以更快地制作,甚至可以将ssget字符串存储在本地,制作一个“最喜欢的”ssget字符串列表(选择过滤器堆栈),立即选择,而不是每次都重写它们。现在它可能开始听起来很有趣了,对吗?让我向您介绍与上述2个ssget done with filter命令相同的结果http://s7.postimg.org/mcu1mwzkb/sel_set_filter.png
你可以建立自定义和复杂的过滤器,保存和加载它们。。。有时我们需要的是在我们眼皮底下,开箱即用
我很高兴你没有亲自接受小咆哮,我可以帮你!
干杯 Hi, Jef!
Sorry for late reply
Well, about the credits stuff, maybe I'll shorten them - I just want to make everyone happy in there.
I don't see any english/wording mistakes from you - so no need to apologize (by the way english is my 2nd (or 3rd) language aswell)
Thank you for the tutorial (actually I'm not that familiar with FILTER command, but I know about QSELECT)
Do you think the examples you showed will work with dynamic block's names also?
I have tested with QSELECT (for example combine some objects on layer, some other objects, and a block by name), but I haven't succeeded.
I'm not sure how faster and easier would be with FILTER to do this, but I'll learn more about this command.
The reason I want the routine to "read" for the first picked entity's LAYER/TYPE/etc.. because I find it faster and easier.
Also sometimes I have to correct some exported drawings from programs like REVIT so I end up with a bunch of layers and blocks (and I think it will be slower to organize those filters in FILTER)
Well I could answer with re-running the routine S times, until statisfied with the(stacked) global selection.
However, I'll check for the alternate solutions you gave me.
But my developed theory about working faster in autocad is to:
avoid populating and using such (alert)menus,
avoid typing strings in the routine
Simply to say the fastest way would be by "picking" objects (for example like MATCHPROP command is structured).
How I can get offended when providing so much help and information?
Cheers! Hi again!
As your routine is right now, it asks for the "global selection to apply the filter you chose will apply to, then add it to the cumulative filtered selection. One thing I think might be more efficient would be to prompt for the global selection only once, unless you really need different global selections for each added filter. Using a while statement instead of inplied selection could have simplified things. Relaunching the command can look at the implied selection, but only allow 1 implied selection to be used. Using a while statement instead, since you would be running the command only once, you could then reuse the global selection to which apply the next filter, or redefine it only if you need to, instead of systematically having to query the user again and again to maybe indicate the same global selection time after time.
mmm. maybe yes maybe no. That is an example of where a different approach might be required, depending on what you are trying to filter. Dynamic blocks are special. When you have a dynamic block, it has a "default state" (the one you see in the block editor. You can also use the "resetblock" command on any dynamic block to reset it, but you would of course "loose" any information that could be given by its state.) If you use lets say (ssget (list (cons 8 "0"))). If dynamic blocks are on layer 0, they will be in the selection set. The thing would not work the same way if you would want to grab all the dynamic blocks of the same name. Why? LEts say I have a dynamic block called "title". If I (entget(car(entsel))) it on its default state, i get that Now, if I alter it dynamically, and entget it again, here's what I getIt is now an anonymous block. The assoc 2 of a block is its name. If you would ssget every block having the same name as a dynamic block at its default state, you would only retrieve all other occurences of the block that currently are on their default state as well. If you would ssget every block having the same name as a dynamic block that is NOT at its default state, you would always end up with a selection of 1 (the original selection) as every anonymous block has a different number. And you don'T see anything to identify them if you entget them...
If you use (dumpAllProperties (car(entsel))) on a dyn block, you see that blocks have a IsDynamicBlock property. That is, I think, the only thing you can do with them using lisp. The only way to find these blocks would be by Visual-Lisp, which has some more properties and methods you can use for dynamic blocks. If you (vlax-dump-object (vlax-ename->vla-object(car(entsel)))) on a dynamic block, you can see..
Command: (vlax-dump-object (vlax-ename->vla-object(car(entsel))))Select object: ; IAcadBlockReference: AutoCAD Block Reference Interface; Property values:; Application (RO) = #; Document (RO) = #; EffectiveName (RO) = "TITLE" Hi again Jef! , sorry for my late reply
Well I agree about that, the problem is I'm not that skilled yet.
I am aware of the method you described about geting the dynamic's block effective name,
infact I've already assembled (took from Lee Mac's and Tharwat's codes) a routine that works in the same way (using selections only):
(defun C:FilterByBlockname ( / sel blkname blk );(princ "\nFunction Filter By Blockname is runned!" ) (vl-load-com)(if (setq CLIPROMPTLINES-old (getvar "CLIPROMPTLINES" )) (setvar "CLIPROMPTLINES" 4)) (setvar 'errno 0) (prompt "\nSelect source block to filter by its EffectiveName" ) (if (and (setq sel (ssget "_:S:E" '((0 . "INSERT")))) (setq blkname (LM:al-effectivename (ssname sel 0))) ; Hi GRrr
Your skill level is beside the point. Implied selection were beyond what you had learned so far, yet you asked about them. (My question is if I have pre-selected objects, how do I add them to my new filtered selection (sset) ?) The problem is that you just asked about what you thought was the best solution without giving us any clear hints that it was just a wild guess. Different goal also quite often means different path... tell us your destination. Add what is the best path you think of if you can, and maybe we will prevent going into unessarly detours (and dead ends).
Caricature of XY problem
-I want to learn to pilot an helicopter
-Ok, come, i'll show you.
(few months later)
-Thanks! Now that I know how to pilot the helicopter, tell me how to get to the moon.
You seem like a good learner, I have faith!
I'm not sure which modifications you are talking about, and yes i can sometimes be hard to read and understand someone elses code... but it can be a great way to learn. Trying to literally evaluate and solve it 1 expression at a time. I used to add alerts everywhere in codes. alerts pause the execution, and you can use them to monitor some variables, and know exactly what line of the code is executed. Vlide can also help, with animation of step by step, and possibility to monitors variables and expressions.
Not using (command "regen") if my feeling is right...
Avoiding any commands whenever possible, they always are the slowest way to go). Also regen-ing only a viewport is always faster then the whole document. You're welcome!
Seriously, i'm no god, just an alien with a keyboard, walking in somebody else's footsteps I appreciate the thought, and i'm glad I could help you.
页:
[1]