cadman6735 Posted June 22, 2010 Share Posted June 22, 2010 I am new to lisp and need some help. What I want to do is create a new vertex for a poly element. My code is a little messy, so sorry for that. I want my command "break" at the end of the code to cycle thru my ptCATCH variable and run the command on each item in the list. I think the Foreach function would do this for me but I can't seem to get it to work. Please help me with my foreach statment so I can see how it works. Or if I am way off base can someone explain to me what function I should use and explain to me why I am wrong to use the foreach function here. ;;Adds a vertex to a polly line (defun c:TEST ( / ) (setq object (entsel)) (command "select" "l" "") (command) ;=========================================================== (setq ptCATCH nil) (while (setq ptGET (getpoint "\nPick Point for New Vertices")) (setq ptCATCH (cons ptGET ptCATCH)) ) (setq ptCATCH (reverse ptCATCH)) ;=========================================================== (Foreach CATCH (ptCATCH) ((command "break" object "f" ptCATCH "@") (command "join" "l" "p" "")) (princ) ) Thanks Quote Link to comment Share on other sites More sharing options...
alanjt Posted June 22, 2010 Share Posted June 22, 2010 This process is a little more complicated. Give this link a read. http://www.theswamp.org/index.php?topic=18720.0 There's also PEdit. Quote Link to comment Share on other sites More sharing options...
cadman6735 Posted June 23, 2010 Author Share Posted June 23, 2010 Alan Thanks for the link, I gave it a try and it add a vertex one point at a time, but so does my code. ;;Adds a vertex to a polly line (defun c:vertex (/ object breakpoint) ;(terpri) ;(command) (setq object (entsel)) (command "select" "l" "") (command) (setq breakpoint (getpoint "Pick Point for New Vertices")) (command "break" object "f" breakpoint "@") (command "join" "l" "p" "") (princ) ) What I want to do is select many points and create many vetexes at one time. And learn why my foreach does not work I really don't understand the (foreach) statement. It seems to me that the (foreach) statement does not work on a varable containing a list. It seems that I have to provide the (foreach) stament a written list, example (list 1 2 3 4 5) instead of a variable (CATCH) that contains the (list 1 2 3 4 5) Now I am thinking I will need to loop thru and pull pieces of my list out of the variable one at a time to run my command on each pulled piece of list. Also you mentioned the Pedit. I am familiar with pedit but when adding a vertex to a polly element I have to choose next to cycle thru each existing vertex to add a new one. I dont' want to do that, I just want to select a point and bam, there is my new vertex. Am I missing a something with the pedit? Thanks Quote Link to comment Share on other sites More sharing options...
jammie Posted June 23, 2010 Share Posted June 23, 2010 why my foreach does not work There is a syntax error (Foreach CATCH [b][color="red"] ([/color][/b]ptCATCH[color="Red"][b])[/b][/color] ... ptCATCH is already a list so there is no need for the extra brackets. Otherwise, in this instance, AutoCAD interoperates ptCATCH as a function, as it is enclosed with brackets. This causes a runtime error ;=========================================================== (setq ptCATCH nil) (while (setq ptGET (getpoint "\nPick Point for New Vertices")) (setq ptCATCH (cons ptGET ptCATCH)) ) (setq ptCATCH (reverse ptCATCH)) ;=========================================================== (Foreach CATCH ptCATCH (princ CATCH) (terpri) ) Quote Link to comment Share on other sites More sharing options...
cadman6735 Posted June 23, 2010 Author Share Posted June 23, 2010 Thanks Jammie It worked, sort of, I am one step closer though. This was the (foreach) statement example I was trying to mimic (foreach a (list 1 2 3)(princ (+ a 5))) As you can see the (list 1 2 3) is enclosed. So I enclosed mine too. but in this example, the list is being created inside the (foreach) statement and in mine my list is already in a variable created earlier, so I don't have to enclose the ptCATCH because it is already a list. (am I on the right thought process?) The foreach works, but get hung up on the command "join" because of the "l" for pick last object. I think I can figure this out from here, may have to work at it for a bit. The syntex error threw me, it all looked correct to me. Thanks again Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted June 23, 2010 Share Posted June 23, 2010 CADman, Command calls are unreliable - why not entmod the polyline, as per the link Alan has provided? Quote Link to comment Share on other sites More sharing options...
jammie Posted June 23, 2010 Share Posted June 23, 2010 am I on the right thought process? Indeed you are! Another way of writing your example could be (setq MyList (list 1 2 3)) (foreach a MyList (princ (+ a 5))) If this makes sense Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted June 23, 2010 Share Posted June 23, 2010 A quick modification to Ron's code: (defun c:AddVertex ( / e p pt nLst ) ;; RJP Mod by Lee Mac 2010 (if (setq e (LM:SelectifFoo (lambda ( x ) (eq "LWPOLYLINE" (cdr (assoc 0 (entget x)))) ) "\nSelect LWPolyline: " ) ) (while (setq p (getpoint "\nPick New Vertex: ")) (setq pt (vlax-curve-getPointatParam e (fix (vlax-curve-getParamatPoint e (vlax-curve-getClosestPointto e (setq p (trans p 1 0)) ) ) ) ) nLst nil ) (mapcar '(lambda ( x ) (setq nLst (if (equal x (list 10 (car pt) (cadr pt)) 0.0001) (cons (list 10 (car p) (cadr p)) (cons x nLst)) (cons x nLst) ) ) ) (entget e) ) (entmod (reverse nLst)) ) ) (princ) ) (defun LM:SelectifFoo ( foo str / sel ent ) ;; © Lee Mac ~ 12.06.10 (while (progn (setq sel (entsel str)) (cond ( (vl-consp sel) (if (not (foo (setq ent (car sel)))) (princ "\n** Invalid Object Selected **") ) ) ) ) ) ent ) Quote Link to comment Share on other sites More sharing options...
VVA Posted June 23, 2010 Share Posted June 23, 2010 a couple more examples Adding vertexes to a polyline Add vertex to polyline Quote Link to comment Share on other sites More sharing options...
cadman6735 Posted June 23, 2010 Author Share Posted June 23, 2010 CADman, Command calls are unreliable - why not entmod the polyline, as per the link Alan has provided? LeeMac I probably will in the end, but I was more curiouse about the (foreach)statement and that was my focus of this post. I am new to Lisp and programming in general and I am trying to strugle thru my own code to see what works and does not work and why they do or don't work. (plus I learn a lot by the struggle and usually has nothing to do with my goal, go figure) I feel if I am given the code I will never learn the code. You have given me some insite by informing me about the command calls are unreliable. But I must start with what I feel comfortable with and grow from there. I have copied the code Alan gave me, to study and now I have learned of entmod too. So I dont' want anyone to think I am being difficult by not using the code given to me or by keep asking question about my code, I am just trying to learn. Thanks for the help and the advice... I look forward to more. Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted June 23, 2010 Share Posted June 23, 2010 Not a problem, and your response is much better than most who are willing to just take code and not learn from it - I just wanted to point you in the right direction: your method is flawed as the the break/join method will introduce new entities and the process becomes messy. Quote Link to comment Share on other sites More sharing options...
cadman6735 Posted June 23, 2010 Author Share Posted June 23, 2010 Indeed you are! Another way of writing your example could be (setq MyList (list 1 2 3)) (foreach a MyList (princ (+ a 5))) If this makes sense Jamee It make sense to me now. But I do want to make sure I understand. MyList is the list. the "a" after the (foreach) is a temporary hold for each of the list items pulled from MyList to be evaluated or functioned on by the function (princ (+ a 5)) "a" is nothing more than a temporary house for (1) to be worked on then it becomes temp house for (2) to be worked on and then "a" is the temp house for (3) to be worked on, and so on? If I am correct here, I think I got it. Thanks Quote Link to comment Share on other sites More sharing options...
cadman6735 Posted June 23, 2010 Author Share Posted June 23, 2010 Not a problem, and your response is much better than most who are willing to just take code and not learn from it - I just wanted to point you in the right direction: your method is flawed as the the break/join method will introduce new entities and the process becomes messy. My function is flawed (so I am beginning to find out) and very messy but I did learn something. I will continue to work on it. Thanks again, I just understood what you was saying to me "will introduce new entities " as the polly element gets broken a new entity is created so when the join is joined back I still have two entities but joined? they don't go back to one entname? I can see how this would cause a problem... hmmmmm..... Quote Link to comment Share on other sites More sharing options...
jammie Posted June 23, 2010 Share Posted June 23, 2010 Just working with the code you have supplied so far. Maybe this could give you some ideas as a reference (defun c:TEST ( / ptCATCH ) (if ;;Entsel returns a list (<Ename> <Point>) (setq pickSelection (entsel)) (progn ;;Extract the <Ename> (setq sourceEname (car pickSelection)) (setq ptCATCH nil) (while (setq ptGET (getpoint "\nPick Point for New Vertices")) (setq ptCATCH (cons ptGET ptCATCH)) ) (setq ptCATCH (reverse ptCATCH)) ;;Store the last object added to the AutoCAD drawing Database ;;The next object added will be a segment from the polyone break (setq lastEname (entlast)) ;=========================================================== (Foreach CATCH ptCATCH (command "break" pickSelection "f" CATCH CATCH) ;;Get the newly created segment from the break (setq nextSegment (entnext lastEname)) ;;Join the segment to the original polyline (command "join" sourceEname nextSegment "") ;;Store this for the next iteration of the looop (setq lastEname (entlast)) ) ) (princ) ) ) the links posted by other members will certainly help with this task Quote Link to comment Share on other sites More sharing options...
jammie Posted June 23, 2010 Share Posted June 23, 2010 If I am correct here, I think I got it. You summed it up very well, thats pretty much it Quote Link to comment Share on other sites More sharing options...
cadman6735 Posted June 23, 2010 Author Share Posted June 23, 2010 Just working with the code you have supplied so far. Maybe this could give you some ideas as a reference (defun c:TEST ( / ptCATCH ) (if ;;Entsel returns a list (<Ename> <Point>) (setq pickSelection (entsel)) (progn ;;Extract the <Ename> (setq sourceEname (car pickSelection)) (setq ptCATCH nil) (while (setq ptGET (getpoint "\nPick Point for New Vertices")) (setq ptCATCH (cons ptGET ptCATCH)) ) (setq ptCATCH (reverse ptCATCH)) ;;Store the last object added to the AutoCAD drawing Database ;;The next object added will be a segment from the polyone break (setq lastEname (entlast)) ;=========================================================== (Foreach CATCH ptCATCH (command "break" pickSelection "f" CATCH CATCH) ;;Get the newly created segment from the break (setq nextSegment (entnext lastEname)) ;;Join the segment to the original polyline (command "join" sourceEname nextSegment "") ;;Store this for the next iteration of the looop (setq lastEname (entlast)) ) ) (princ) ) ) the links posted by other members will certainly help with this task Super cool Thanks Jamee You literally wrote the code the way I was trying to think of it after reading Lee Mac’s post about my method being flawed and will introduce new entities. But was a little overwhelmed where to start. The only thing that erks me, is that, I did not write it and it only took you an hour (or less, I don't know) to do it. J You get five stars from me. I will study this code Thanks for the help. Quote Link to comment Share on other sites More sharing options...
jammie Posted June 23, 2010 Share Posted June 23, 2010 Your welcome It was actually a learning curve for me. I had assumed that by splitting an object in two, the original object is deleted & two new entities are added to the database. From observation, AutoCAD retains the original entity pre the split point & adds a new object to the database post split point. Don't worry about how fast you can code. Its more important that you understand what you are doing & why. For further improvements on your code, consider a test to make sure a polyline is selected. Also maybe consider a different approach to the code logic. Why not split & join the polyine as your are picking the points? That will eliminate the FOREACH part of the code & there may no longer be a need to store the points in ptCATCH Just food for thought. Happy coding! Quote Link to comment Share on other sites More sharing options...
cadman6735 Posted June 24, 2010 Author Share Posted June 24, 2010 Your welcome It was actually a learning curve for me. I had assumed that by splitting an object in two, the original object is deleted & two new entities are added to the database. From observation, AutoCAD retains the original entity pre the split point & adds a new object to the database post split point. Don't worry about how fast you can code. Its more important that you understand what you are doing & why. For further improvements on your code, consider a test to make sure a polyline is selected. Also maybe consider a different approach to the code logic. Why not split & join the polyine as your are picking the points? That will eliminate the FOREACH part of the code & there may no longer be a need to store the points in ptCATCH Just food for thought. Happy coding! Jammie (I just realalized I was misspelling your name, sorry about that) Couple of question about your code First: I notice you are using and (if) statement and one (progn) that closes at the end before the (princ). Why? and thanks because this openned my eyes on how to use the (prong) statment. You can put an entire program in the (prong) stament which I did not grasp this concept in my study of the examples in this book I am reading. Second: I noticed you place the (princ) inside the (if)stamenent. Why? I have only seen the (princ) before the last closing ) at the end of the program thus far. I reworked the code you gave me and took your advise to break and join the line at the pick point (and it works, I'm so happy). (defun c:vertex ( / ptCATCH ) ;;Entsel returns a list (<Ename> <Point>) (setq pickSelection (entsel)) ;;Extract the <Ename> (setq sourceEname (car pickSelection)) ;;Break each point at selection (while (setq ptGET (getpoint "\nPick Point for New Vertices")) (setq lastEname (entlast)) (command "break" pickSelection "f" ptGET ptGET) ;;Get the newly created segment from the break (setq nextSegment (entnext lastEname)) ;;Join the segment to the original polyline (command "join" sourceEname nextSegment "") ;;Store this for the next iteration of the loop (setq lastEname (entlast)) ) (princ) ) Quote Link to comment Share on other sites More sharing options...
jammie Posted June 24, 2010 Share Posted June 24, 2010 Lee Mac has put a great collections of links together in the Useful Links section of this forum http://www.cadtutor.net/forum/showthread.php?t=49515 I would suggest having a look at the links under Explanation of Conditionals (CAB/Lee Mac) First:I notice you are using and (if) statement and one (progn) that closes at the end before the (princ). PROGN allows multiple lines of code to be evaluated in response to a positive or negative evaluation after an IF test. ;Without PROGN AutoCAD aould evaluate the function as follows (if ;Test (setq pickSelection (entsel)) ;Positive result (setq sourceEname (car pickSelection)) ;Negative result (setq ptCATCH nil) ;Unexpected additional arguments suplied. Error will be created here (while... Second:I noticed you place the (princ) inside the (if)stamenent. Why? It was just for a negative result for the IF statemet. It isn't necessary. Probably a more appropiate use of the princ would be to prompt the user if an object has not been selected (defun c:TEST ( / ptCATCH ) (if ;Test (setq pickSelection (entsel)) ;Positive result (progn (setq sourceEname ...) ) ;Negative result (princ "\nNo Object selected) ) ) Apologies if I am not explaining these items very well Quote Link to comment Share on other sites More sharing options...
jammie Posted June 25, 2010 Share Posted June 25, 2010 I reworked the code you gave me and took your advise to break and join the line at the pick point (and it works, I'm so happy). Good work with the code! Just as an idea I have added 4 extra lines to it to allow the vertex grips of the selected object to be shown while picking the points (defun c:vertex ( / ptCATCH pickSelection sourceEname ptGET lastEname nextSegment tempSelectionSet) (command "Undo" "BEgin") ;;Entsel returns a list (<Ename> <Point>) (setq pickSelection (entsel)) ;;Extract the <Ename> (setq sourceEname (car pickSelection)) ;Create a temporary selection set (setq tempSelectionSet (ssadd)) ;Add the picked ojbect to it (SSADD sourceEname tempSelectionSet) ;;Break each point at selection (while (progn ;Turn on grips (sssetfirst NIL tempSelectionSet ) (setq ptGET (getpoint "\nPick Point for New Vertices")) ) (setq lastEname (entlast)) (command "break" pickSelection "f" ptGET ptGET) ;;Get the newly created segment from the break (setq nextSegment (entnext lastEname)) ;;Join the segment to the original polyline (command "join" sourceEname nextSegment "") ;;Store this for the next iteration of the loop (setq lastEname (entlast)) ) ;Turn off grips (sssetfirst tempSelectionSet) (command "Undo" "End") (princ) ) To further your understanding of conditionals maybe try incorporating an IF statement into the code, it allow only certain objects to be selected. Otherwise the routine could generate an error when selecting certain objects like inserts etc... Quote Link to comment Share on other sites More sharing options...
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.