Author Topic: looping and undo functions  (Read 5866 times)

0 Members and 1 Guest are viewing this topic.

ELOQUINTET

  • Guest
looping and undo functions
« on: August 17, 2005, 01:50:56 PM »
i got the root of my code working so now i am going back and adding loops and undo functions. first question is how do i get routine to stop without hitting escape. could i introduce a keyword to exit? second question where do i put the undo functions so only one instance gets undone?
 

Code: [Select]
;;;===================================================================;
;;; UNDO GROUPING FUNCTIONS                                           ;
;;;===================================================================;
(defun vl-UndoBegin ()
  (vla-StartUndoMark
    (vla-get-activedocument
      (vlax-get-acad-object)
    )
  )
)

(defun vl-UndoEnd ()
  (vla-EndUndoMark
    (vla-get-activedocument
      (vlax-get-acad-object)
    )
  )
)
(defun c:MTO (/ osm txtentity txtlist pt1 x1 y1 dimentity dimlist pt2 x2 y2 txtxcoord txtycoord pt3 new old)
(vl-UndoBegin);<<<<<<<<<<<<<<<<<<<<<<<<<<<<
(while
  (setq osm (getvar 'osmode))
  (setvar "osmode" 0)
       (while (not (setq txtentity (car (entsel "\nSelect text: "))))
(princ "\nYou missed. Try again.")
     )
      (setq txtlist   (entget txtentity)
   pt1      (cdr (assoc 11 txtlist))
   x1        (car pt1)
            y1        (cadr pt1)
      )  
    (while (not (setq dimentity (car (entsel "\nSelect dimension: "))))
(princ "\nYou missed. Try again.")
    )      
      (setq dimlist   (entget dimentity)
   pt2      (cdr (assoc 11 dimlist))
   x2        (car pt2)
   y2        (cadr pt2)
      )
  (if (= (cdr (assoc 50 dimlist)) 0.0)
  (setq     txtxcoord (car pt2)
            txtycoord (cadr pt1)
            pt3 (list txtxcoord txtycoord 0)
            new (cons 11 pt3)
   old (cons 11 pt1)
            txtlist (subst new old txtlist)
)
  (setq   txtxcoord (car pt1)
            txtycoord (cadr pt2)
            pt3 (list txtxcoord txtycoord 0)
   new (cons 11 pt3)
   old (cons 11 pt1)
            txtlist (subst new old txtlist)
  )
    )
      (entmod txtlist)
      (setvar 'osmode osm)
      (princ)
  )
  (vl-UndoEnd);;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  )

JohnK

  • Administrator
  • Seagull
  • Posts: 10649
looping and undo functions
« Reply #1 on: August 17, 2005, 02:31:18 PM »
...
(while
  (setq osm (getvar 'osmode))
  (setvar "osmode" 0)
...

Yeah, i wouldnt do that if i were you!

The while function goes untill the test returns nil.

The test in your code is: (setq osm (getvar 'osmode))
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

ELOQUINTET

  • Guest
looping and undo functions
« Reply #2 on: August 17, 2005, 03:08:23 PM »
se7en i tried moving the while around to different places but it appears to still be looping because it interprets it as an empty response or "miss". that's my interpretation of what's going on anyway???

whdjr

  • Guest
looping and undo functions
« Reply #3 on: August 17, 2005, 03:46:42 PM »
Dan,

My first comment is that your statement:     (setq osm (getvar 'osmode))      should really come before the while loop so that the original value of 'osmode' is not affected.

ELOQUINTET

  • Guest
looping and undo functions
« Reply #4 on: August 17, 2005, 04:26:19 PM »
i believe i tried putting it there intially but it was screwing up my text selection. see below:

Code: [Select]
 (setq osm (getvar 'osmode))
  (setvar "osmode" 0)
  (while
       (while (not (setq txtentity (car (entsel "\nSelect text: "))))
(princ "\nYou missed. Try again.")
     )


Command: mto

Select text: nil  :?

JohnK

  • Administrator
  • Seagull
  • Posts: 10649
looping and undo functions
« Reply #5 on: August 17, 2005, 04:49:54 PM »
Lets take a second to step back and examine a looping construct. If we do this we can better understand what we need to do in order to make things work as we want them to.

'while' is a "looping construct".
A basic definition of a looping construct would be:
<function> <predicate> <consequent>

In this construct the predicate has to be either affirmed or denied. (True or False, On or Off.)

Whether or not the consequent is ever evaluated depends on the predicate. -i.e. "if the predicate is false, then do this" or "Do this as long as the predicate is true"

In the case of 'while'; the consequent is evaluated until the predicate is false.

Therefore if you use a predicate such as (setvar osmode) --which is never affirmed nor denied-- your never going to be able to truly control your application.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

whdjr

  • Guest
looping and undo functions
« Reply #6 on: August 17, 2005, 05:10:43 PM »
Quote from: ELOQUINTET
i believe i tried putting it there intially but it was screwing up my text selection. see below:

Code: [Select]
 (setq osm (getvar 'osmode))
  (setvar "osmode" 0)
  (while
       (while (not (setq txtentity (car (entsel "\nSelect text: "))))
(princ "\nYou missed. Try again.")
     )


Command: mto

Select text: nil  :?


That is the right way but in addition the last 'setvar and 'princ statements need to be outside the first while statement as well.  

This does not fix your routine however it does eliminate the error.  What it gives you in return is a never ending loop because as Se7en stated the while loop never gets to validate itself.

The point I am trying to make is when you are changing variables you want to store them and restore them outside of your main objectives.
Code: [Select]
((setq osm (getvar 'osmode))
(setvar 'osmode 0)
(
 (
  (do all functions here)
 )
)
(setvar 'osmode osm)
(princ)
)

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
looping and undo functions
« Reply #7 on: August 17, 2005, 05:48:12 PM »
In addition to what Will & John are saying, let me clarify one thing.....this portion of your code:
Code: [Select]
(while
       (while (not (setq txtentity (car (entsel "\nSelect text: "))))
   (princ "\nYou missed. Try again.")
     )

Is saying "While While is nil"....does that really make sense to you? You would normally want something like this:
While this is true, do this.....

JohnK

  • Administrator
  • Seagull
  • Posts: 10649
looping and undo functions
« Reply #8 on: August 17, 2005, 08:43:09 PM »
Eloquintet,

Have you read my article on creating your own named abstractions?...

There's no reason why you cant keep--or make--your problems simple and derive solutions arround those simplified problems. For instance, if your confused by the 'while' loop then build simple names to use in your construct.

-e.g.

If we create two simple procedures and name them like so:

Code: [Select]
(defun ThisIsTrue ()
  (if (eq (getvar "cmdactive") 1) 'T 'nil))

Code: [Select]
(defun DoThis ()
  (command "_end") (command PAUSE))


Then we can use simple words to create a looping construct like so:

Code: [Select]
(while (ThisIsTrue) (DoThis))

Now you have a very simplified looping construct you can easily understand.

You have to be carefull about just putting process' inside or outside certian functions. (like loops) you must be carefull because you could be processing information several--if not hundereds--of times unnecessarly. (And that would cause your application to be bloated and very slow. ...Or even toss an error)

Does that help at all?
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Jürg Menzi

  • Swamp Rat
  • Posts: 599
  • Oberegg, Switzerland
looping and undo functions
« Reply #9 on: August 18, 2005, 04:51:41 AM »
Eloquintet,

I would do it like this (didn't test the rest of the code):
Code: [Select]
;;;===================================================================;
;;; UNDO GROUPING FUNCTIONS                                           ;
;;;===================================================================;
(defun vl-UndoBegin ()
 (vla-StartUndoMark
  (vla-get-activedocument
   (vlax-get-acad-object)
  )
 )
)

(defun vl-UndoEnd ()
 (vla-EndUndoMark
  (vla-get-activedocument
   (vlax-get-acad-object)
  )
 )
)

(defun MeExtEntSel (Pmt Lst / CurEnt ExLoop TmpStr)
 (while (not ExLoop)
  (initget " ")
  (setq CurEnt (entsel Pmt))
  (cond
   ((= CurEnt "") (setq ExLoop T CurEnt nil))
   (CurEnt
    (if (member
         (cdr (assoc 0 (entget (car CurEnt))))
         (mapcar 'strcase Lst)
        )
     (setq ExLoop T)
     (progn
      (setq TmpStr (apply 'strcat
                    (cons
                     (car Lst)
                     (mapcar
                     '(lambda (l)
                       (strcat " or " l)
                      ) (cdr Lst)
                     )
                    )
                   )
      )
      (princ (strcat "selected entity is not a " TmpStr ". "))
     )
    )
   )
   ((princ "1 selected, 0 found"))
  )
 )
 CurEnt
)

(defun c:MTO ( / osm txtentity txtlist pt1 x1 y1 dimentity dimlist pt2
                 x2 y2 txtxcoord txtycoord pt3 new old ExLoop)
 (vl-UndoBegin)
 (setq osm (getvar 'osmode))
 (setvar "osmode" 0)
 (while (not ExLoop)
  (cond
   ((not (setq txtentity (MeExtEntSel "\nSelect text <exit>: " '("Text"))))
    (setq ExLoop T)
   )
   ((not (setq dimentity (MeExtEntSel "\nSelect dimension <exit>: " '("Dimension"))))
    (setq ExLoop T)
   )
   (T
    (setq txtlist (entget (car txtentity))
          pt1     (cdr (assoc 11 txtlist))
          x1      (car pt1)
          y1      (cadr pt1)
          dimlist (entget (car dimentity))
          pt2     (cdr (assoc 11 dimlist))
          x2      (car pt2)
          y2      (cadr pt2)
    )
    (if (= (cdr (assoc 50 dimlist)) 0.0)
     (setq txtxcoord (car pt2)
           txtycoord (cadr pt1)
           pt3       (list txtxcoord txtycoord 0)
           new       (cons 11 pt3)
           old       (cons 11 pt1)
           txtlist   (subst new old txtlist)
     )
     (setq txtxcoord (car pt1)
           txtycoord (cadr pt2)
           pt3       (list txtxcoord txtycoord 0)
           new       (cons 11 pt3)
           old       (cons 11 pt1)
           txtlist   (subst new old txtlist)
     )
    )
    (entmod txtlist)
   )
  )
 )
 (setvar 'osmode osm)
 (vl-UndoEnd)
 (princ)
)
A computer's human touch is its unscrupulousness!
MENZI ENGINEERING GmbH
Current A2k16... A2k24 - Start R2.18

ELOQUINTET

  • Guest
looping and undo functions
« Reply #10 on: August 18, 2005, 09:22:25 AM »
i understand the bits about keeping the variables outside of the function i believe. jeff i understand what you're saying about the double while but was wondering what to put in the first while. i was under the impression that i had to test something i had already changed in the routine which is why i chose while osmode=0 keep looping. se7en, actually i got my first exposure to absractions yesterday. my boss has a little code which converts (cdr (assoc to    just (dxf. so maybe i'll get into that once i understand things a bit more. jurg i'll have to study yours and will ask questions later. thanks guys for the input i appreciate it

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
looping and undo functions
« Reply #11 on: August 21, 2005, 10:33:53 AM »
Dan,
One simple way is to use a True/False var to control the main loop
Then decide what condition will set the loop var to nil to force exit.
Jürg had a good example. My example uses the loop var as true to stay in the loop.

Code: [Select]
 (setq loop t); stay in main loop
  (while loop
    *************
    Do your stuff
    Set exit flag when condition is met
    *************
  ) ; end main while loop
  (setvar 'osmode osm)
  (princ)


Then find a way to signal the exit.
You have two entsel so the user may have two chances to signal the exit.
So the choices are to exit when:
User presses Enter
User selects wrong object
User misses an object

The choice is yours.
Read this thread..... http://www.theswamp.org/phpBB2/viewtopic.php?t=4617&highlight=dan+escape

Stig has given an example of how to catch the Escape key press & to look at other options.

In his example any of the conditions that end with T exit the while loop, not to be confused with
the main while loop. To exit that loop & the main while loop you must (setq loop nil)
Also consider that setting loop nil will not immediately exit the loop so you must find a way to
prevent any unwanted code from being executed. see Jürg's example again. He used the cond statement
to test for this condition.

That's all I have...
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

ELOQUINTET

  • Guest
looping and undo functions
« Reply #12 on: August 30, 2005, 01:51:16 PM »
jurg i'm just getting around to looking at your lisp and figuring out what's going on. what would be useful for me to know would be what the variables names represent. ie unabbreviated. then i could analyze it a little easier. i'll still try to make an educated guess but it would be helpful. thanks works beautiful.

[/code](defun MeExtEntSel (Pmt Lst / CurEnt ExLoop TmpStr)
Code: [Select]

Jürg Menzi

  • Swamp Rat
  • Posts: 599
  • Oberegg, Switzerland
looping and undo functions
« Reply #13 on: August 30, 2005, 02:39:41 PM »
Quote from: ELOQUINTET
what would be useful for me to know would be what the variables names represent
I'm using something like 'talking' shortcuts:
Code: [Select]

Arguments:
Pmt = Prompt
Lst = List
Local Vars:
CurEnt = CurrentEntity
ExLoop = ExitLoop
TmpStr = TemporaryString
A computer's human touch is its unscrupulousness!
MENZI ENGINEERING GmbH
Current A2k16... A2k24 - Start R2.18

ELOQUINTET

  • Guest
looping and undo functions
« Reply #14 on: August 30, 2005, 03:08:43 PM »
that's what i thought just wanted to make sure so i could analyze it properly thanks i'll have a look again

Jürg Menzi

  • Swamp Rat
  • Posts: 599
  • Oberegg, Switzerland
looping and undo functions
« Reply #15 on: August 31, 2005, 03:32:01 AM »
Hi Dan

To help to understand, I've attached some comments...
Code: [Select]
;
; -- Function MeExtEntSel

; Extended (entsel) function.
; Arguments [Typ]:
;   Pmt = Prompt [STR]
;         eg. "\nSelect Arc or Circle: "
;   Lst = Entity filter list (uppercase) [LIST]
;         eg. '("ARC" "CIRCLE")
; Return [Typ]:
;   > List of (ENAME '(PickPoint)) [LIST]
;   > nil if user press enter/space key
; Notes:
;   None
;
(defun MeExtEntSel (Pmt Lst / CurEnt ExLoop TmpStr)
 ;while not exit loop...
 (while (not ExLoop)
  ;allow enter/space key
  (initget " ")
  ;select entity
  (setq CurEnt (entsel Pmt))
  (cond
   ;case enter/space key... exit loop & set return to nil
   ((= CurEnt "") (setq ExLoop T CurEnt nil))
   ;case entity...
   (CurEnt
    (if (member (cdr (assoc 0 (entget (car CurEnt)))) Lst)
     ;if entity name in filter list exit loop
     (setq ExLoop T)
     ;else build and show error message
     (progn
      (setq TmpStr (apply 'strcat
                    (cons
                     (car Lst)
                     (mapcar
                     '(lambda (l)
                       (strcat " or " l)
                      ) (cdr Lst)
                     )
                    )
                   )
      )
      (princ (strcat "selected entity is not a " TmpStr ". "))
     )
    )
   )
   ;case nothing selected... show message
   ((princ "1 selected, 0 found"))
  )
 )
 ;return entsel list (or nil)
 CurEnt
)
A computer's human touch is its unscrupulousness!
MENZI ENGINEERING GmbH
Current A2k16... A2k24 - Start R2.18

ELOQUINTET

  • Guest
looping and undo functions
« Reply #16 on: August 31, 2005, 09:30:47 AM »
that's helpful jurg thanks. i still need to get a grip on alot of functions and how to structure code so it behaves properly. i guess that come with time and practice.