Jump to content

While loop inside a while loop


broncos15

Recommended Posts

I had a quick question in regards to what would be the most efficient way to write a code that would keep asking the user for a source and destination object. I know how to write this for a single selection like the following:

(while whilestop
   (setvar 'errno 0)
   (setq ent (entsel "\nSelect object to break: "))
   (cond
     ((= 52 (getvar 'errno))
      (setq whilestop nil)
     )
     ((null ent)
      (princ "\nYou missed. Try again.")
     )
     ((not (wcmatch (setq typ (cdr (assoc 0 (entget (car ent)))))
                    "LINE,ARC,CIRCLE,LWPOLYLINE,POLYLINE,RAY,XLINE,AECC_FEATURE_LINE"
           )
      )
      (princ "\nNot a valid object, try again.")
     ) 
    ;...Rest of code 

My issue is how to write this efficiently for two objects (i.e. you would get the missed prompt or not valid object for both, then after each is selected, a code would run, then repeat until user hits escape or the space bar. I already have all my code written, it is just this while loop that I can't get to work correctly.

Link to comment
Share on other sites

I usually do it like this:


[b][color=BLACK]([/color][/b]defun *error* [b][color=FUCHSIA]([/color][/b] msg [b][color=FUCHSIA])[/color][/b] [color=#8b4513]; sometimes we need an error handler, for example the osmode variable[/color]
[b][color=FUCHSIA]([/color][/b]if osm [b][color=NAVY]([/color][/b]setvar 'osmode osm[b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b]
[b][color=FUCHSIA]([/color][/b]if [b][color=NAVY]([/color][/b]not [b][color=MAROON]([/color][/b]member msg '[b][color=GREEN]([/color][/b][color=#2f4f4f]"Function cancelled"[/color] [color=#2f4f4f]"quit / exit abort"[/color][b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
	[b][color=NAVY]([/color][/b]princ [b][color=MAROON]([/color][/b]strcat [color=#2f4f4f]"\nError: "[/color] msg[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
[b][color=FUCHSIA])[/color][/b]
[b][color=FUCHSIA]([/color][/b]princ[b][color=FUCHSIA])[/color][/b]
[b][color=BLACK])[/color][/b]

[b][color=BLACK]([/color][/b]setq osm [b][color=FUCHSIA]([/color][/b]getvar 'osmode[b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b]
[b][color=BLACK]([/color][/b]setvar 'osmode 0[b][color=BLACK])[/color][/b]

[b][color=BLACK]([/color][/b]while T [color=#8b4513]; start the overall loop[/color]
[b][color=FUCHSIA]([/color][/b]setvar 'errno 0[b][color=FUCHSIA])[/color][/b]
[b][color=FUCHSIA]([/color][/b]while [color=#8b4513]; source object loop[/color]
	[b][color=NAVY]([/color][/b]not
		[b][color=MAROON]([/color][/b]and
			[b][color=GREEN]([/color][/b]setq ent1 [b][color=BLUE]([/color][/b]car [b][color=RED]([/color][/b]entsel [color=#2f4f4f]"\nSelect source object: "[/color][b][color=RED])[/color][/b][b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b]
			[b][color=GREEN]([/color][/b]eq [b][color=BLUE]([/color][/b]cdr [b][color=RED]([/color][/b]assoc 0 [b][color=PURPLE]([/color][/b]setq elist1 [b][color=TEAL]([/color][/b]entget ent1[b][color=TEAL])[/color][/b][b][color=PURPLE])[/color][/b][b][color=RED])[/color][/b][b][color=BLUE])[/color][/b] [color=#2f4f4f]"INSERT"[/color][b][color=GREEN])[/color][/b] [color=#8b4513]; optional filter[/color]
		[b][color=MAROON])[/color][/b]
	[b][color=NAVY])[/color][/b]
	[b][color=NAVY]([/color][/b]if [b][color=MAROON]([/color][/b]or [b][color=GREEN]([/color][/b]= [b][color=BLUE]([/color][/b]getvar 'errno[b][color=BLUE])[/color][/b] 7[b][color=GREEN])[/color][/b] [b][color=GREEN]([/color][/b]null ent1[b][color=GREEN])[/color][/b] [b][color=MAROON])[/color][/b] [b][color=MAROON]([/color][/b]princ [color=#2f4f4f]"\nYou missed try again!"[/color][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
[b][color=FUCHSIA])[/color][/b]

[b][color=FUCHSIA]([/color][/b]while [color=#8b4513]; destination object loop[/color]
	[b][color=NAVY]([/color][/b]not
		[b][color=MAROON]([/color][/b]and
			[b][color=GREEN]([/color][/b]setq ent2 [b][color=BLUE]([/color][/b]car [b][color=RED]([/color][/b]entsel [color=#2f4f4f]"\nSelect destination object: "[/color][b][color=RED])[/color][/b][b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b]
			[b][color=GREEN]([/color][/b]eq [b][color=BLUE]([/color][/b]cdr [b][color=RED]([/color][/b]assoc 0 [b][color=PURPLE]([/color][/b]setq elist2 [b][color=TEAL]([/color][/b]entget ent2[b][color=TEAL])[/color][/b][b][color=PURPLE])[/color][/b][b][color=RED])[/color][/b][b][color=BLUE])[/color][/b] [color=#2f4f4f]"INSERT"[/color][b][color=GREEN])[/color][/b] [color=#8b4513]; optional filter[/color]
		[b][color=MAROON])[/color][/b]
	[b][color=NAVY])[/color][/b]
	[b][color=NAVY]([/color][/b]if [b][color=MAROON]([/color][/b]or [b][color=GREEN]([/color][/b]= [b][color=BLUE]([/color][/b]getvar 'errno[b][color=BLUE])[/color][/b] 7[b][color=GREEN])[/color][/b] [b][color=GREEN]([/color][/b]null ent2[b][color=GREEN])[/color][/b] [b][color=MAROON])[/color][/b] [b][color=MAROON]([/color][/b]princ [color=#2f4f4f]"\nYou missed try again!"[/color][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
[b][color=FUCHSIA])[/color][/b]

[b][color=FUCHSIA]([/color][/b]progn
	[color=#8b4513]; [b][color=NAVY]([/color][/b]we got the source and destination objects, do the rest of your stuff here[b][color=NAVY])[/color][/b][/color]
[b][color=FUCHSIA])[/color][/b]
[b][color=BLACK])[/color][/b] [color=#8b4513]; end the overall loop[/color]

Link to comment
Share on other sites

If I understand correctly, there are lots of ways to approach these types of selections :

 

[b][color=BLACK]([/color][/b]defun c:pick2 [b][color=FUCHSIA]([/color][/b]/ s1 e1 s2 e2[b][color=FUCHSIA])[/color][/b]
 [b][color=FUCHSIA]([/color][/b]and
    [b][color=NAVY]([/color][/b]princ [color=#2f4f4f]"\nSelect Source INSERT"[/color][b][color=NAVY])[/color][/b]
    [b][color=NAVY]([/color][/b]setq s1 [b][color=MAROON]([/color][/b]ssget [b][color=GREEN]([/color][/b]list [b][color=BLUE]([/color][/b]cons 0 [color=#2f4f4f]"INSERT"[/color][b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
    [b][color=NAVY]([/color][/b]= [b][color=MAROON]([/color][/b]sslength s1[b][color=MAROON])[/color][/b] 1[b][color=NAVY])[/color][/b]
    [b][color=NAVY]([/color][/b]setq e1 [b][color=MAROON]([/color][/b]ssname s1 0[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b]
 [b][color=FUCHSIA]([/color][/b]redraw e1 3[b][color=FUCHSIA])[/color][/b]
 [b][color=FUCHSIA]([/color][/b]while
   [b][color=NAVY]([/color][/b]and
     [b][color=MAROON]([/color][/b]princ [color=#2f4f4f]"\nSelect 1 Target INSERT"[/color][b][color=MAROON])[/color][/b]
     [b][color=MAROON]([/color][/b]setq s2 [b][color=GREEN]([/color][/b]ssget [b][color=BLUE]([/color][/b]list [b][color=RED]([/color][/b]cons 0 [color=#2f4f4f]"INSERT"[/color][b][color=RED])[/color][/b][b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b]
     [b][color=MAROON]([/color][/b]= [b][color=GREEN]([/color][/b]sslength s1[b][color=GREEN])[/color][/b] 1[b][color=MAROON])[/color][/b]
     [b][color=MAROON]([/color][/b]setq e2 [b][color=GREEN]([/color][/b]ssname s2 0[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b]
     [b][color=MAROON]([/color][/b]not [b][color=GREEN]([/color][/b]eq e1 e2[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]

   [b][color=NAVY]([/color][/b]prin1 e2[b][color=NAVY])[/color][/b]

 [b][color=FUCHSIA])[/color][/b]
   [b][color=FUCHSIA]([/color][/b]redraw[b][color=FUCHSIA])[/color][/b]
   [b][color=FUCHSIA]([/color][/b]prin1[b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b]

 

Replace the (prin1 e2) call with the actions that you are wanting to accomplish.

 

-David

Link to comment
Share on other sites

I usually do it like this:


[b][color=black]([/color][/b]defun *error* [b][color=fuchsia]([/color][/b] msg [b][color=fuchsia])[/color][/b] [color=#8b4513]; sometimes we need an error handler, for example the osmode variable[/color]
   [b][color=fuchsia]([/color][/b]if osm [b][color=navy]([/color][/b]setvar 'osmode osm[b][color=navy])[/color][/b][b][color=fuchsia])[/color][/b]
   [b][color=fuchsia]([/color][/b]if [b][color=navy]([/color][/b]not [b][color=maroon]([/color][/b]member msg '[b][color=green]([/color][/b][color=#2f4f4f]"Function cancelled"[/color] [color=#2f4f4f]"quit / exit abort"[/color][b][color=green])[/color][/b][b][color=maroon])[/color][/b][b][color=navy])[/color][/b]
       [b][color=navy]([/color][/b]princ [b][color=maroon]([/color][/b]strcat [color=#2f4f4f]"\nError: "[/color] msg[b][color=maroon])[/color][/b][b][color=navy])[/color][/b]
   [b][color=fuchsia])[/color][/b]
   [b][color=fuchsia]([/color][/b]princ[b][color=fuchsia])[/color][/b]
[b][color=black])[/color][/b]

[b][color=black]([/color][/b]setq osm [b][color=fuchsia]([/color][/b]getvar 'osmode[b][color=fuchsia])[/color][/b][b][color=black])[/color][/b]
[b][color=black]([/color][/b]setvar 'osmode 0[b][color=black])[/color][/b]

[b][color=black]([/color][/b]while T [color=#8b4513]; start the overall loop[/color]
   [b][color=fuchsia]([/color][/b]setvar 'errno 0[b][color=fuchsia])[/color][/b]
   [b][color=fuchsia]([/color][/b]while [color=#8b4513]; source object loop[/color]
       [b][color=navy]([/color][/b]not
           [b][color=maroon]([/color][/b]and
               [b][color=green]([/color][/b]setq ent1 [b][color=blue]([/color][/b]car [b][color=red]([/color][/b]entsel [color=#2f4f4f]"\nSelect source object: "[/color][b][color=red])[/color][/b][b][color=blue])[/color][/b][b][color=green])[/color][/b]
               [b][color=green]([/color][/b]eq [b][color=blue]([/color][/b]cdr [b][color=red]([/color][/b]assoc 0 [b][color=purple]([/color][/b]setq elist1 [b][color=teal]([/color][/b]entget ent1[b][color=teal])[/color][/b][b][color=purple])[/color][/b][b][color=red])[/color][/b][b][color=blue])[/color][/b] [color=#2f4f4f]"INSERT"[/color][b][color=green])[/color][/b] [color=#8b4513]; optional filter[/color]
           [b][color=maroon])[/color][/b]
       [b][color=navy])[/color][/b]
       [b][color=navy]([/color][/b]if [b][color=maroon]([/color][/b]or [b][color=green]([/color][/b]= [b][color=blue]([/color][/b]getvar 'errno[b][color=blue])[/color][/b] 7[b][color=green])[/color][/b] [b][color=green]([/color][/b]null ent1[b][color=green])[/color][/b] [b][color=maroon])[/color][/b] [b][color=maroon]([/color][/b]princ [color=#2f4f4f]"\nYou missed try again!"[/color][b][color=maroon])[/color][/b][b][color=navy])[/color][/b]
   [b][color=fuchsia])[/color][/b]
   
   [b][color=fuchsia]([/color][/b]while [color=#8b4513]; destination object loop[/color]
       [b][color=navy]([/color][/b]not
           [b][color=maroon]([/color][/b]and
               [b][color=green]([/color][/b]setq ent2 [b][color=blue]([/color][/b]car [b][color=red]([/color][/b]entsel [color=#2f4f4f]"\nSelect destination object: "[/color][b][color=red])[/color][/b][b][color=blue])[/color][/b][b][color=green])[/color][/b]
               [b][color=green]([/color][/b]eq [b][color=blue]([/color][/b]cdr [b][color=red]([/color][/b]assoc 0 [b][color=purple]([/color][/b]setq elist2 [b][color=teal]([/color][/b]entget ent2[b][color=teal])[/color][/b][b][color=purple])[/color][/b][b][color=red])[/color][/b][b][color=blue])[/color][/b] [color=#2f4f4f]"INSERT"[/color][b][color=green])[/color][/b] [color=#8b4513]; optional filter[/color]
           [b][color=maroon])[/color][/b]
       [b][color=navy])[/color][/b]
       [b][color=navy]([/color][/b]if [b][color=maroon]([/color][/b]or [b][color=green]([/color][/b]= [b][color=blue]([/color][/b]getvar 'errno[b][color=blue])[/color][/b] 7[b][color=green])[/color][/b] [b][color=green]([/color][/b]null ent2[b][color=green])[/color][/b] [b][color=maroon])[/color][/b] [b][color=maroon]([/color][/b]princ [color=#2f4f4f]"\nYou missed try again!"[/color][b][color=maroon])[/color][/b][b][color=navy])[/color][/b]
   [b][color=fuchsia])[/color][/b]
   
   [b][color=fuchsia]([/color][/b]progn
       [color=#8b4513]; [b][color=navy]([/color][/b]we got the source and destination objects, do the rest of your stuff here[b][color=navy])[/color][/b][/color]
   [b][color=fuchsia])[/color][/b]
[b][color=black])[/color][/b] [color=#8b4513]; end the overall loop[/color]

Grr, this is a cool use of another while loop! I am trying to figure out how to make it exit by pressing the space bar as well, but I can't figure it out. I have tried to do a conditional where if the entity is null, then I put nil, but this isn't working. Can you think of anyway to do this? David, I haven't seen ssget with a while loop before, that is pretty slick (unfortunately I have to use nentsel because I am getting information from objects in an xref).
Link to comment
Share on other sites

I would suggest compartmentalising the selection operation as a separate function, e.g.:

(defun c:test ( / des prd src )
   (setq prd
      '(lambda ( x )
           (wcmatch
               (cdr (assoc 0 (entget x)))
               "LINE,ARC,CIRCLE,LWPOLYLINE,POLYLINE,RAY,XLINE,AECC_FEATURE_LINE"
           )
       )
   )
   (if
       (and
           (setq src (selectif "\nSelect source object: "      prd))
           (setq des (selectif "\nSelect destination object: " prd))
       )
       (princ "\nDo stuff.")
   )
   (princ)
)
(defun selectif ( msg prd / ent )
   (while
       (progn (setq ent (car (entsel msg)))
           (cond
               (   (= 7 (getvar 'errno))
                   (princ "\nMissed, try again.")
               )
               (   (not ent) nil)
               (   (not (apply prd (list ent)))
                   (princ "\nInvalid object selected.")
               )
           )
       )
   )
   ent
)

Link to comment
Share on other sites

I would suggest compartmentalising the selection operation as a separate function, e.g.:
(defun c:test ( / des prd src )
   (setq prd
      '(lambda ( x )
           (wcmatch
               (cdr (assoc 0 (entget x)))
               "LINE,ARC,CIRCLE,LWPOLYLINE,POLYLINE,RAY,XLINE,AECC_FEATURE_LINE"
           )
       )
   )
   (if
       (and
           (setq src (selectif "\nSelect source object: "      prd))
           (setq des (selectif "\nSelect destination object: " prd))
       )
       (princ "\nDo stuff.")
   )
   (princ)
)
(defun selectif ( msg prd / ent )
   (while
       (progn (setq ent (car (entsel msg)))
           (cond
               (   (= 7 (getvar 'errno))
                   (princ "\nMissed, try again.")
               )
               (   (not ent) nil)
               (   (not (apply prd (list ent)))
                   (princ "\nInvalid object selected.")
               )
           )
       )
   )
   ent
)

Lee, thank you so much for the help! What I am having trouble with now is adding in another while loop that would keep going until the space bar is hit or escape. For example, the user would select source object, then select destination object, then select source object, then select destination... until they have done everything they want, then they would hit space or escape.
Link to comment
Share on other sites

So I ended up accomplishing this by doing:

(while
     (and
(setq sent (selectif "\nSelect source object: "))
(setq dent (selectif "\nSelect destination object: "))
     )
;...Rest of code

Is there any problem with using an and function like this?

Link to comment
Share on other sites

Lee, thank you so much for the help! What I am having trouble with now is adding in another while loop that would keep going until the space bar is hit or escape. For example, the user would select source object, then select destination object, then select source object, then select destination... until they have done everything they want, then they would hit space or escape.

By reading this, I think that you must go with other method - Prompt the user for constant selection of source and destination objects within a loop, and while doing it construct an assoc list like this:

(<source ent1> . <destination ent1>) (<source ent2> . <destination ent2>) ... (<source entN> . <destination entN>)

Then do your secret stuff for each pair of that list.

Unfortunately I can't figure out how to code this (but I'm interested about it as there are similar ideas with this method in my head).

Link to comment
Share on other sites

Lee, thank you so much for the help!

 

You're welcome!

 

What I am having trouble with now is adding in another while loop that would keep going until the space bar is hit or escape. For example, the user would select source object, then select destination object, then select source object, then select destination... until they have done everything they want, then they would hit space or escape.

 

So I ended up accomplishing this by doing:
(while
     (and
(setq sent (selectif "\nSelect source object: "))
(setq dent (selectif "\nSelect destination object: "))
     )
;...Rest of code

Is there any problem with using an and function like this?

 

Implementing the while loop in the way you have posted would have been my suggestion - that should perform exactly as you have described.

Link to comment
Share on other sites

Hi broncos15

was intrested how you work out '..rest of the code' finishing the breaking.

Think this might be intresting for other commands as well.

Are you willing to share this with us?

Link to comment
Share on other sites

Hi broncos15

was intrested how you work out '..rest of the code' finishing the breaking.

Think this might be intresting for other commands as well.

Are you willing to share this with us?

Sure, my code is as follows:

(defun c:matchxreflayer (/ *error* sent dent sobj dobj aDoc LayCol slayer dlayer oldecho)
 (defun *error* (msg)
   (if oldecho
     (setvar 'cmdecho oldecho)
   )
   (if (not
  (member msg '("Function cancelled" "quit / exit abort"))
)
     (princ (strcat "\nError: " msg))
   )
   (princ)
 )
 (setq oldecho (getvar 'cmdecho))
 (setvar 'cmdecho 0)
 (while
   (and
     (setq sent (selectif "\nSelect source layer object: "))
     (setq dent (selectif "\nSelect destination layer object: "))
   )
    (setq sobj   (vlax-ename->vla-object sent)
   dobj   (vlax-ename->vla-object dent)
   aDoc   (vla-get-activedocument (vlax-get-acad-object))
   LayCol (vla-get-layers aDoc)
   slayer (vla-item LayCol (vla-get-layer sobj))
   dlayer (vla-item LayCol (vla-get-layer dobj))
    )
    (vla-put-color dlayer (vla-get-color slayer))
    (vla-put-linetype dlayer (vla-get-linetype slayer))
    (vla-put-lineweight dlayer (vla-get-lineweight slayer))
    (vla-put-plotstylename
      dlayer
      (vla-get-plotstylename slayer)
    )
    (command "._regen")
 )
 (setvar 'cmdecho oldecho)
 (princ)
)
;;;Select if function written by Lee Mac
;;;Edited by broncos15 to not require argument
(defun selectif (msg / ent)
 (while
   (progn (setq ent (car (nentsel msg)))
   (cond
     ((= 7 (getvar 'errno))
      (princ "\nMissed, try again.")
     )
     ((not ent) nil)
   )
   )
 )
 ent
)

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