Jump to content

?Foreach Vertex?


cadman6735

Recommended Posts

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

Link to comment
Share on other sites

  • Replies 22
  • Created
  • Last Reply

Top Posters In This Topic

  • cadman6735

    10

  • jammie

    8

  • Lee Mac

    3

  • alanjt

    1

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

Link to comment
Share on other sites

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)
   )

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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
)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.....

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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!

Link to comment
Share on other sites

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)
 )

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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...

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...