Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Two routines in one LISP

14 REPLIES 14
SOLVED
Reply
Message 1 of 15
dicra
1065 Views, 14 Replies

Two routines in one LISP

Hi, everyone

 

I would like to write a routine, in which I need ename of polyline (for example), 

actually, I need to repeat "entsel" until user select polyline.

I know how to defun routine for that, Iwas thinking something like this:

 

(defun c:gp ()

  (setq code "T")

  (while code

    (if(setq enamepoly (car (entsel "\nChoose polyline: ")))

      (setq enlst  (entget enamepoly)    

               entype (cdr (assoc 0 enlst))

               code   (if (= entype "LWPOLYLINE")     nil     "T"   )

      )

    )

  )

 

 

What I would like to do is to call this routine in another lisp (I saw it in some lisps)

and to save in variable ename of selected polyline.

 

For example lets just say that I only want to draw a circle whit center in start point of selected polyline.

 

 

(defun c:pol ()

  (setq poly (getpline))

  (command "circle" (cdr (assoc 10 (entget poly))) 10 "")

  (defun getpline ()

    (setq code "T")

    (while code

      (setq enamepoly (car (entsel "\nChoose polyline: ")))

      (setq enlst (entget enamepoly)

               entype (cdr (assoc 0 enlst))

               code (if (= entype "LWPOLYLINE") nil "T")

        )

      )

    (enamepoly)

   )

  )

 

I wanted to routine getpline return me "enamepoly" and save it in "poly".

 

But it is obvious that I am making some mistake, because there is an error mesage on commandline.

 

It  is first time that I am doing something like this, 

so I would be very grateful for any help.

 

Thanks at advance

14 REPLIES 14
Message 2 of 15
_Tharwat
in reply to: dicra

Is this what you are after ?

 

(defun c:test (/ ss e p)
  ;; Tharwat 09. 07. 2011
  (while
    (not (and
           (setq ss (car (entsel "\n Select a Polyline :")))
           (member (cdr (assoc 0 (setq e (entget ss))))
                   '("POLYLINE" "LWPOLYLINE")
           )
         )
    )
  )
  (entmakex (list '(0 . "CIRCLE")
                  '(100 . "AcDbCircle")
                  '(100 . "AcDbEntity")
                  (cons 10 (cdr (assoc 10 e)))
                  (cons 40 10.)
            )
  )
  (princ)
)

 Tharwat

Message 3 of 15
Moshe-A
in reply to: dicra

take a look at this Buddy

 

(defun gp_ename (/ flag ent ename elist)
  
 (while (not flag)
  (setvar "errno" 0)				; clear error number
  (setq ent (entsel))
   
  (cond
   ((= (getvar "errno") 7)			; user missed selecting an object
    (prompt "\nNoting selected, try again...")	; loop again
   )
   ((= (getvar "errno") 52)			; user reply to (entsel) by just pressing ENTER to exit the function
    (setq ename ent flag t)			; this will return nil
   )
   ((not (wcmatch (strcase (cdr (assoc '0 (entget (car ent))))) "POLYLINE,LWPOLYLINE")) ; wrong object selected
    (prompt "\nObject selected is not a polyline, try again...")			; loop again
   )
   ( t
    (setq ename (car ent) flag t)		; a pline selected
   )
  )
 ); while

 ename ; return
)


(defun c:addCirc (/ ename elist p0)
 (if (setq ename (gp_ename))
  (progn
   ; enter here only if ename has a value (not nil)
   (setq elist (entget ename))
   (setq p0 (cdr (assoc '10 elist)))
   (command "_.circle" p0)
  )
 )

 (princ)
)



 

cheers

moshe

 

 

Message 4 of 15
Kent1Cooper
in reply to: _Tharwat


@TharwaT313 wrote:

Is this what you are after ?

 

(defun c:test (/ ss e p)
  ;; Tharwat 09. 07. 2011
  (while
    (not (and
           (setq ss (car (entsel "\n Select a Polyline :")))
           (member (cdr (assoc 0 (setq e (entget ss))))
                   '("POLYLINE" "LWPOLYLINE")
           )
         )
    )
  )
  (entmakex (list '(0 . "CIRCLE")
                  '(100 . "AcDbCircle")
                  '(100 . "AcDbEntity")
                  (cons 10 (cdr (assoc 10 e)))
                  (cons 40 10.)
            )
  )
  (princ)
)

 Tharwat


That's about the way I'd do it, but I would suggest a couple of simplifications, and an elaboration.

 

On the object-type-limited selection, if you want to accept either lightweight or heavy Polylines, (wcmatch) can handle both possibilities together, avoiding the need to list them separately.  And I usually put in a notification of why the user is being asked again to pick something, so they don't just see the same prompt and think nothing has happened:
 
(while
  (not

    (and
      (setq ent (car (entsel "\nSelect a Polyline: ")))
      (wcmatch (cdr (assoc 0 (setq edata (entget ent)))) "*POLYLINE")
    )
  )

  (prompt "\nNothing selected, or incorrect object type;")
)
 

On the making of the Circle, if you want to use (entmake) [I don't see any reason to use (entmakex), and see Help for reasons not to], the entity type, center and radius are all you need:

 

(entmake

  (list

    '(0 . "CIRCLE")

    ;;;; [100-code entries not needed]
    (cons 10 (cdr (assoc 10 edata)))
    '(40 . 10)
  )
)
 

But I'd be inclined to just use the Circle command, similar to what you did in the original post, since you obviously are not in any of the situations in which you can't use (command), and you would never detect the milliseconds of time difference.

Kent Cooper, AIA
Message 5 of 15
Moshe-A
in reply to: Kent1Cooper

 

(while
  (not

    (and
      (setq ent (car (entsel "\nSelect a Polyline: ")))
      (wcmatch (cdr (assoc 0 (setq edata (entget ent)))) "*POLYLINE")
    )
  )

  (prompt "\nNothing selected, or incorrect object type;")
)

 

------------------------------------------------------------------------

Kent,

 

i'll agree that this is a shorted way of doing it but...

if the user just want to exit the command quietly by pressing enter

 

how would you revise it?

 

Moshe

 

Message 6 of 15
_Tharwat
in reply to: Kent1Cooper

Hello Kent.

 

You did commented the routine as if it is completely wrong and I shoud change the way I go with coding , although I do agree

with some of what you have written .

 

To add a prompt to while function that would never cancel the process until the right entity being selected or by pressing

cancel and to press that would raise an error to the command line which would put the user ( user whom facing this for

the first time or non having programming backgound ) in confusion , so that's why I did not add the prompt to it , otherwise

we should add a sub-routine error to the routine .

 

In regard to command and entmake(x) , for me I do not like using command in lisp unless being having no way out in coding .

 

Thanks.

 

Tharwat

Message 7 of 15
Kent1Cooper
in reply to: _Tharwat


@TharwaT313 wrote:

Hello Kent.

 

You did commented the routine as if it is completely wrong and I shoud change the way I go with coding ....

 

To add a prompt to while function that would never cancel the process until the right entity being selected or by pressing cancel and to press that would raise an error to the command line which would put the user ... in confusion , so that's why I did not add the prompt to it ....


A.  Hardly -- re-read the first sentence of my post.

 

B.  The same error message also appears on canceling without the prompt, so I don't understand any benefit to not including it.

Kent Cooper, AIA
Message 8 of 15
Kent1Cooper
in reply to: Moshe-A


@Moshe-A wrote:

....

if the user just want to exit the command quietly by pressing enter

 

how would you revise it?

....


Looking for a similar method of operation, in an offset-and-erase-the-selected-object routine I made, I have two varieties:

1. one ends quietly [no error message] with Enter or space, but also ends if you miss in selecting;

2. the other does not end if you miss, but requires Escape to end it -- Enter/space don't.

 

I haven't found a way to have it work like ordinary Offset, which ends with Enter or space or Escape, but does not end if you miss.

 

Here's a way you can have a routine let you continue to pick more Polylines to add Circles to, and end quietly with Enter/space, but it will also end if you miss, and it doesn't have entity-type control, so it really doesn't meet the OP's needs:

 

(while (setq poly (entsel "\nSelect a Polyline or <exit>: "))

  (command "circle" (cdr (assoc 10 (entget poly))) 10)

)

Kent Cooper, AIA
Message 9 of 15
Moshe-A
in reply to: Kent1Cooper


@Kent1Cooper wrote:

@Moshe-A wrote:

....

if the user just want to exit the command quietly by pressing enter

 

how would you revise it?

....


Looking for a similar method of operation, in an offset-and-erase-the-selected-object routine I made, I have two varieties:

1. one ends quietly [no error message] with Enter or space, but also ends if you miss in selecting;

2. the other does not end if you miss, but requires Escape to end it -- Enter/space don't.

 

I haven't found a way to have it work like ordinary Offset, which ends with Enter or space or Escape, but does not end if you miss.

 

Here's a way you can have a routine let you continue to pick more Polylines to add Circles to, and end quietly with Enter/space, but it will also end if you miss, and it doesn't have entity-type control, so it really doesn't meet the OP's needs:

 

(while (setq poly (entsel "\nSelect a Polyline or <exit>: "))

  (command "circle" (cdr (assoc 10 (entget poly))) 10)

)


You know Kent, i am supprised of you...do you know why? because you did not look a bit at my solution.

if you were? you would have seen that with ERRNO you can distinguish between a missed pick and

just pressing enter to (entsel)

 

Smiley Happy Smiley Very Happy

 

Moshe

 

 

Message 10 of 15
scot-65
in reply to: Kent1Cooper

Want something that will not terminate the program using ENTSEL when the user did not select anything?

 

Try this derivative:

 

 (setq osm (getvar "OSMODE"))(setvar "OSMODE" 512) ;nea
 (setq p1 (getpoint "\nSelect object to offset: "))
 (while (and p1 (not (ssget p1))) (setq p1 (getpoint "\nSelect object to offset: ")) );while
 

An alternative to this can be OSNAP and provide a prompt.

 

I have also tried SSGET ":S", but with not much luck...

 

???

 


Scot-65
A gift of extraordinary Common Sense does not require an Acronym Suffix to be added to my given name.


Message 11 of 15
dicra
in reply to: dicra

And one more think, thanks again for solutions whit error when nothing is selected, that was one step further than I was.

First I would like to thank you for so many quick replies, and please excuse me because I did not thanked earlier.


Some of you did not understand what was I trying to do, my problem was not to select select poly ant to draw a circle, thatwas only example, misunderstandings was probably because my English is not the best.


What I was trying is to make two forms in one lisp, like Moshe did,he made gp_ename, an the called this function in addCirc.

 

But looking in to his solution I figured my mistakes,

 

First my problem was because I put getpoly inside c: pol, 

I supposed to first close the parentheses from pol , and than to defun getpline, like this:

 

 

  

 

(defun c: pol ()

  (setq poly (getpline))

  (command "circle" (cdr (assoc 10 (entget poly))) 10 "")

 

);first to close c: pol and I needed to separated defun getpline, like form for it self

;because of this I was having  error mesage ; error: no function definition: GETPLINE


  (defun getpline ()

    (setq code "T")

    (while code

      (setq enamepoly (car (entsel "\nChoose polyline: ")))

      (setq enlst (entget enamepoly)

               entype (cdr (assoc 0 enlst))

               code (if (= entype "LWPOLYLINE") nil "T")

        )

      )

    (enamepoly) ;this was my second mistake I did not needed parentheses,

;this was returning me:; error: bad function: <Entity name: 7ef034f0>


   )

 

Atleast I think that this two problems was my mistakes, anyway whit yours help I managed to fix problems.

 

Message 12 of 15
Moshe-A
in reply to: dicra


@dicra wrote:

And one more think, thanks again for solutions whit error when nothing is selected, that was one step further than I was.

First I would like to thank you for so many quick replies, and please excuse me because I did not thanked earlier.


Some of you did not understand what was I trying to do, my problem was not to select select poly ant to draw a circle, thatwas only example, misunderstandings was probably because my English is not the best.


What I was trying is to make two forms in one lisp, like Moshe did,he made gp_ename, an the called this function in addCirc.

 

But looking in to his solution I figured my mistakes,

 

First my problem was because I put getpoly inside c: pol, 

I supposed to first close the parentheses from pol , and than to defun getpline, like this:

 

 

  

 

(defun c: pol ()

  (setq poly (getpline))

  (command "circle" (cdr (assoc 10 (entget poly))) 10 "")

 

);first to close c: pol and I needed to separated defun getpline, like form for it self

;because of this I was having  error mesage ; error: no function definition: GETPLINE


  (defun getpline ()

    (setq code "T")

    (while code

      (setq enamepoly (car (entsel "\nChoose polyline: ")))

      (setq enlst (entget enamepoly)

               entype (cdr (assoc 0 enlst))

               code (if (= entype "LWPOLYLINE") nil "T")

        )

      )

    (enamepoly) ;this was my second mistake I did not needed parentheses,

;this was returning me:; error: bad function: <Entity name: 7ef034f0>


   )

 

Atleast I think that this two problems was my mistakes, anyway whit yours help I managed to fix problems.

 


dicra,

 

wrong, the reson you got ; error: no function definition: GETPLINE is an extra "" in (command) function and because of that your lisp did not fully load [(getpline) was not loaded]

 

there is no limitation in autolisp in putting a defun inside a defun (nested functions).

 

the only reson in defining a nested function is declare it locally along with other local variables and protect it from being accessed or run over from outside function calls.

 

your function will fail at (entsel) if you respond with ENTER or miss to select the pline

i encourage you to give a try to my solution

 

anyhow i fixed your code as it is and it's now working

note the local symbols declaration

 

 

(defun c:pol (/ poly getpline enamepoly)
  (setq poly (getpline))
  (command "circle" (cdr (assoc 10 (entget poly))) 10)

  (defun getpline (/ code enlst entype)
   (setq code T)
   (while code
    (setq enamepoly (car (entsel "\nChoose polyline: ")))
    (setq enlst (entget enamepoly)
          entype (cdr (assoc 0 enlst))
    )

    (setq code (if (= entype "LWPOLYLINE") nil T))
   ); while
    
   enamepoly ; return
  ); defun getpline

 (princ)  
); defun c:pol

 

by the way:T is a build-in symbol in autolisp and it evaluate as TRUE  that means not nil

and "T" evaluate as string T

 

(setq code T) ; is a better approch

(while code    ; means while code is still T loop again

 ....

 ....

)

 

cheers

moshe


 

Message 13 of 15
Kent1Cooper
in reply to: Moshe-A


@Moshe-A wrote:
....

You know Kent, i am supprised of you...do you know why? because you did not look a bit at my solution.

if you were? you would have seen that with ERRNO you can distinguish between a missed pick and

just pressing enter to (entsel)

....


You're right -- I had been responding only to TharwaT313's use of

 

(member .... '("POLYLINE" "LWPOLYLINE")

 

and suggesting making that more concise with

 

(wcmatch .... "*POLYLINE")

 

[and that string with a wildcard * could also be used in your routine], and otherwise left the surrounding code alone.  I hadn't looked closely at other aspects of yours, because I didn't know before what ERRNO is for, really, and what it can do.  Maybe if you had mentioned ERRNO in your question about how I would further revise that piece of TharwaT313's code, I would have gotten the clue that it was the key to the solution.  But since you pointed that out, I have looked into it further, and sure enough, I've been able to fix my offset-and-erase routine, and make it work just as regular Offset does in regard to not ending with a missed selection but ending with Enter/space.  So I've learned my new thing for the month!

Kent Cooper, AIA
Message 14 of 15
Moshe-A
in reply to: Kent1Cooper

Hey Kent,

 

where have been? i been wating for this long Smiley Wink  

well, it better now than ever

 

you were responding to me my friend (check again i colored your respond in red)

 

happy to see that you have learned something from me and i see it as payback

cause i am leaering alot from you every week.

 

and here is something that you offen won't get from peoples here:

 

Thank you very much for what you are doing to this DG 

 

Moshe

 

Message 15 of 15
Kent1Cooper
in reply to: Moshe-A


@Moshe-A wrote:

....

where have been? i been wating for this long .... 

Thank you very much for what you are doing to this DG 

....


I was waiting to reply until I got my Offset-and-Erase routine "fixed," so that I could say with certainty that the ERRNO System Variable was the key to making it work as I wanted it to.  And thank you for your contributions.

Kent Cooper, AIA

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost