SwChilly Posted June 7, 2011 Posted June 7, 2011 I'm a student and I need help with my assignment and the teacher is no where to be found. I know this is asking for alot but please bear with me. I'm so lost with entities and selection sets. Ok first I put a bunch of random circles, lines, points, arcs, rectangles etc. in my drawing. I am to make a selection set out of these entities. My code so far is this: (defun lyr_ext () (setq p1 (getpoint "\nFirst corner: ")) ;; Create two points that define selection set window (setq p2 (getcorner p1 "\nOther corner: ")) (setq all_entities (ssget "C" p1 p2)) (princ) ) K so I believe I have the selection set with all my entities that the user "crosses" called all_entities. So now I'm stuck.. I am to build a sting list of these unique object types from the selection set (ie point, line, circle etc.) Then put each drawing object type onto a user-defined layer, one object at a time: - If layer doesnt exist (M)ake it - If layer exists (s)et focus to the layer - then loop through string and ask for a destination layer for each object type. (by extracting a second global selection set from drawing with currrent unique object type) - Put the entities with the new selection set onto the destination layer I hope that makes sense to someone because it doesn't to me!! I'm not asking for someone to write it all out for me but if there is an answer or a link to a place I can get answers or any kind of help that would be muchly appreciated. It's my last program assignment so it's the last time you'll hear from me about LISP! Thanks again! Quote
SwChilly Posted June 7, 2011 Author Posted June 7, 2011 or even a gentle push into the right direction I owe u a beer Quote
Lee Mac Posted June 7, 2011 Posted June 7, 2011 To get you started... Firstly be sure to test for a valid user input - this can be as simple as an IF statement: (if (and (setq p1 (getpoint "\nFirst Corner: ")) (setq p2 (getcorner p1 "\nOther Corner: ")) (setq ss (ssget "_C" p1 p2)) ) ... ) Then you can iterate through this SelectionSet using either a while/repeat loop: (if (and (setq p1 (getpoint "\nFirst Corner: ")) (setq p2 (getcorner p1 "\nOther Corner: ")) (setq ss (ssget "_C" p1 p2)) ) (progn (setq i 0 sslen (sslength ss) ) (while (< i sslen) (setq ent (ssname ss i)) (setq i (1+ i)) ) ) ) There are many different ways to do the above, but I have tried to demonstrate the most intuitive to understand. The Entity type is DXF group 0. Oh and make sure you Localise your Variables! See here to understand why this is important. Quote
SwChilly Posted June 8, 2011 Author Posted June 8, 2011 Lee - Thank you for your quick reply and expertise! Question tho, what is the purpose of the iteration and why have sslen and i ? Quote
Lee Mac Posted June 8, 2011 Posted June 8, 2011 If you need to make a list of each object type in the selection you would need to query the DXF data of each entity in the SelectionSet. To do this requires iterating through the SelectionSet. The method I have described uses the ssname function to retrieve the entity at a specific index in the SelectionSet, and I iterate through these indexes using the counter variable 'i' a number of times equal to the number of entities in the SelectionSet, or the SelectionSet Length, sslength. Quote
SwChilly Posted June 8, 2011 Author Posted June 8, 2011 ok thats makes more sense to me than how my teacher explained things. I really appreciate you helping me out with this. So to now make a list of each object type I would have to use ssget I'm assuming.. Quote
BIGAL Posted June 8, 2011 Posted June 8, 2011 A bit further on, you now need to work out what you have is it a line circle arc etc and what layer is it on as a 2nd step. As per Lee above the code increases (setq ent (ssname ss i)) (setq whatisit (cdr (assoc 0 (entget ent)))) the variable is now a "line" "arc" "circle" etc a block is "insert" (setq objlay (cdr (assoc 8 (entget ent)))) the variable holds the layer name (princ whatisit) Next step would be to change the objects layer if not correct say all lines on the "LINE" layer we can not do all your homework only help Look up "entmod" in help the example in Autocad help is how to change an objects layer. It also describes why I have used 0 and 8 above check out 2 also these numbers are known as the "dxf group code" numbers. Regarding the layer does it exist you need to check the acad help for tblsearch it will describe how to create a list of existing layers you can then search through them and add your layer if it does not exists. A cheat here just make the layers even if they exsit you will not see an error but your teacher may not like this method. Almost forgot if you can lay your hands on a old autocad lisp reference book it is much easier to use than autocad help my bible is a R12 version. Quote
Lee Mac Posted June 8, 2011 Posted June 8, 2011 Here is the DXF reference that I use: http://docs.autodesk.com/ACD/2011/ENU/filesDXF/WSfacf1429558a55de185c428100849a0ab7-5df0.htm Quote
alanjt Posted June 8, 2011 Posted June 8, 2011 http://images.autodesk.com/adsk/files/acad_dxf2.pdf Quote
SwChilly Posted June 8, 2011 Author Posted June 8, 2011 Thanks for your help everyone, but I'm a lost cause. I stare at this going, whaaa??? I guess I'll just hand in an uncompleted assignment. I just don't understand it well enough to write code! Quote
Lee Mac Posted June 8, 2011 Posted June 8, 2011 Here's another nudge forward: (defun c:test ( / p1 p2 ss counter entity entitydata entitytype ) (if (and (setq p1 (getpoint "\nFirst Corner: ")) (setq p2 (getcorner p1 "\nOther Corner: ")) (setq ss (ssget "_C" p1 p2)) ) (progn (setq counter 0 sslen (sslength ss) ) (while (< counter sslen) (setq entity (ssname ss counter) entitydata (entget entity) entitytype (cdr (assoc 0 entitydata)) counter (1+ counter) ) ) ) ) (princ) ) When you have the entitytype (a string, i.e. "CIRCLE"), you can proceed in a number of ways to change the layer for entities of each type, I would be inclined to create an association list of enames for each type and then, after iterating through the SelectionSet, iterate through each entity type, ask the user for a layer name and change the layer for each entity for that type. Quote
Lee Mac Posted June 8, 2011 Posted June 8, 2011 BTW, also note that you can collect your initial selectionset using: (ssget) And the user can still make a crossing selection by typing 'C' at the prompt. Quote
Lee Mac Posted June 8, 2011 Posted June 8, 2011 After re-reading your first post, from the way the assignment is written it looks as though they want you to approach it a different way. From reading the wording of the assignment I may be misinterpreting the goal since they mention a 'global selection' indicating that for each object type in the initial selection they appear to want to retrieve another selection set from the whole drawing and move those objects onto a layer specified by the user. In which case, if I've understood the task correctly, I would advise you take the following route: * Make an initial selection * Iterate through this selection and make a list of all the object types * For each object type in the list, make a selection of all objects of that Object Type and prompt the user for the name of a layer. * If the layer doesn't exist, make it. * Change the layer of all objects of the selected type to the layer as specified. Quote
Lee Mac Posted June 8, 2011 Posted June 8, 2011 Following the above route, here's a nudge to get you going: (defun c:test ( / p1 p2 ss sslen counter entity entitydata entitytype typelist ) (if (and (setq p1 (getpoint "\nFirst Corner: ")) (setq p2 (getcorner p1 "\nOther Corner: ")) (setq ss (ssget "_C" p1 p2)) ) (progn (setq counter 0 sslen (sslength ss) ) (while (< counter sslen) (setq entity (ssname ss counter) entitydata (entget entity) entitytype (cdr (assoc 0 entitydata)) counter (1+ counter) ) (if (not (member entitytype typelist)) (setq typelist (cons entitytype typelist)) ) ) (print typelist) ) ) (princ) ) I would love to write the whole thing for you, but it would be wrong of me and unfair to do your assignment for you. Lee Quote
SwChilly Posted June 9, 2011 Author Posted June 9, 2011 Following the above route, here's a nudge to get you going: I would love to write the whole thing for you, but it would be wrong of me and unfair to do your assignment for you. Lee Oh, I know... I completely understand. I don't want it just written out for, I want to understand it...... By the way, you just earned yourself "god" status ha! I tried out your code and I believe I actually know what's going on (once I take it step by step and debug). Now I got a good push in the right direction, so I thank you for that. Quote
BIGAL Posted June 9, 2011 Posted June 9, 2011 Following on ; dont think Lee will mind me doing this ; defun C:test means you can run it by typing test after you load it (defun c:test ( / p1 p2 ss sslen counter entity entitydata entitytype typelist ) (if (and (setq p1 (getpoint "\nFirst Corner: ")) ; select the first corner point (setq p2 (getcorner p1 "\nOther Corner: ")) ; select the second corner point (setq ss (ssget "_C" p1 p2)) ; select all the objects within the box ) (progn ; progn is joined to the if so you have picked a box (setq counter 0 ; initailise a counter so when run again works again sslen (sslength ss) ; how many objects picked ) (while (< counter sslen) ; keep looping trough all the objects to end (setq entity (ssname ss counter) ; get the counter number entity from the list entitydata (entget entity) ; get the entity entitytype (cdr (assoc 0 entitydata)) ; what is entity type line arc counter (1+ counter) ; add 1 to counter ) ; at this point add in what you actually want to do say change circle to circle layer ; the if not is an example of doing something with what you have now (if (not (member entitytype typelist)) ; if doesnt exist in the list of typelist then add it in (setq typelist (cons entitytype typelist)) ; make a list of the object types found arc line text etc ) ) (print typelist) ; print out to the screen the type of objects found ) ) (princ) ; exit quitely ) Quote
Lee Mac Posted June 9, 2011 Posted June 9, 2011 Oh, I know... I completely understand. I don't want it just written out for, I want to understand it...... By the way, you just earned yourself "god" status ha! I tried out your code and I believe I actually know what's going on (once I take it step by step and debug). Now I got a good push in the right direction, so I thank you for that. You're very welcome SwChilly, happy I could help you Quote
irneb Posted June 9, 2011 Posted June 9, 2011 To go on from there, after you've got the list into typelist you want to ask the user for a new / existing layer to place all the entities of that type on, correct? So the idea here is (where Lee's made the (princ typelist) to show the list on the command line) to step through this list. I'd go with the foreach function. Ask the user through something like getstring to specify the layer (tip, you can use strcat to include the entity type in the message for getstring). Next you'll need to test if the layer exists, easiest is using (tblsearch "LAYER" layername). If it's nil, then the layer doesn't exist. In which case look at this thread. If you need to "set focus to layer", I'm a bit unsure as to what's meant by this. Closest I can imagine is setting the current layer through (setvar "CLAYER" layername) Then inside this you want to again use ssget, but with a filter list - which is basically a list similar to the DXF codes (but only those which should comply to what you want). E.g. (ssget "X" '((0 . "LINE"))) will get all the lines in the entire drawing (Model- and Paper Spaces). To create the '((0 . "LINE")) from a variable - since you'll obtain each entity type in the foreach loop (say the variable is entitytype) you can do this by: ([url="http://docs.autodesk.com/ARCHDESK/2011/ENU/filesALR/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-69c6.htm"]list[/url] ([url="http://docs.autodesk.com/ARCHDESK/2011/ENU/filesALR/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-6a78.htm"]cons[/url] 0 entitytype)) Again I'd place the ssget in an if check, to see if there was any selected. Then you again need to iterate through that selection set, get the ename and dxf in the same way. Then use subst to modify the DXF-code-8 to include for the new layer name. And finally use entmod to modify the entity to the change DXF list. As another thing: Please set the ss variable to nil and force a garbage collection (gc) when you're performing selection sets inside of loops. You only have a finite amount of selection sets before ACad starts erroring out - and since Lisp doesn't imediately release them, you could run into such cases in loops. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.