TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: jaydee on August 04, 2011, 08:25:05 AM

Title: How to reset variables in the get midpoint functions
Post by: jaydee on August 04, 2011, 08:25:05 AM
There are tones of ways to get the midpoint between 2points.
The link below show a few of them
http://www.theswamp.org/index.php?topic=2587.msg32773#msg32773 (http://www.theswamp.org/index.php?topic=2587.msg32773#msg32773)

I used these function from a accelerator pop menu for transparent function call.

My question is how to code these functions to reset variables after getmidpoints, i have tried
(while (> (getvar "cmdactive") 0) (command pause))
and it not working.

The code below always go straight to osmode=0 instead of 131
What i would like to do is to provide *error* trapping just incase cancel out before picking the 2 points so all the vars can be reset.

Code: [Select]
;;;this one from ronjonp
(defun c:mm (/ pt1 pt2)

[color=red](setvar "osmode" 131)[/color]

  (setq pt1 (getpoint)
        pt2 (getpoint)
  )
  (polar pt1 (angle pt1 pt2) (/ (distance pt1 pt2) 2.))
[color=red](setvar "osmode" 0)[/color]
)

Code: [Select]
(defun c:GETMID ( / pt1 pt2 inspt)
[color=red](setvar "osmode" 131)[/color]
(setq pt1 (getpoint "\nSelect First Point : ")
         pt2 (getpoint pt1 "\nSelect Second Point : "))
(setvar "osmode" osm)
(setq inspt
   (mapcar '+ pt1
      (mapcar '/
         (mapcar '- pt2 pt1)
         '(2.0 2.0 2.0)
      )
   )
)
[color=red](setvar "osmode" 0)[/color]
)

Thankyou. Your advice are much appriciated
Title: Re: How to reset variables in the get midpoint functions
Post by: irneb on August 04, 2011, 08:52:56 AM
I think the "best" way to do it is to save the OSMode before changing it into some variable, e.g.:
Code: [Select]
(defun c:whatever (/ other-args osmode)
  (setq osmode (getvar "OSMODE"))
  (setvar "OSMODE" 131)
  ;; The rest of the code
  (setvar "OSMODE" osmode)
  (princ)
)
Of course you might then also want some error handling for in case the user presses ESC.
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 04, 2011, 09:12:12 AM
Irneb's already pointed you in the right direction  8-)

Below is a brief explanation of an example which includes an error handler:

Code: [Select]
(defun c:test ( / *error* osm p1 p2 pm )

  ;; Redefine *error* function to reset value of
  ;; OSMODE System Variable should the routine error or
  ;; the user hit Esc.
  ;;
  ;; Notice that the *error* symbol is localised so that
  ;; it assumes its previous value after program evaluation is
  ;; complete.

  (defun *error* ( msg )
    (if osm (setvar 'OSMODE osm))
    (if (not (member (strcase msg t) '("function cancelled" "quit / exit abort")))
      (princ (strcat "\nError: " msg))
    )
    (princ)
  )

  ;; Store value of OSMODE System Variable before
  ;; changing it, so that it may be reset either in the
  ;; error handler or at the end of the program.

  (setq osm (getvar 'OSMODE))

  ;; Set OSMODE to a desired setting. I use the
  ;; (+ bit bit bit) arrangement to make it clearer
  ;; as to which bits are being set.
 
  (setvar 'OSMODE (+ 1 2 128))

  (if

    ;; If the following expression returns non-nil

    (and

      ;; AND will continue evaluating expressions supplied to it
      ;; until an expression returns nil.
      ;; If all expressions return non-nil, AND will return T
      ;; otherwise AND will return nil.

      (setq p1 (getpoint "\nSpecify First Point: "))
      (setq p2 (getpoint "\nSpecify Second Point: "))

    ) ;; End AND

    (progn

      ;; Use the progn function to wrap the following statements into a single
      ;; expression that we can pass to the IF function to constitute the 'Then' argument
     
      (setq pm (mapcar '(lambda ( a b ) (/ (+ a b) 2.)) p1 p2))

      ;; Calculate Midpoint.

      (setvar 'OSMODE 0)

      ;; Set OSMODE to zero, ready for the rest of your code...

      (command "_.point" pm)

      ;; ^^ Just as an example.

    ) ;; End Progn
   
  ) ;; End IF

  (setvar 'OSMODE osm)

  ;; Reset OSMODE

  (princ) ;; Exit Quietly
)

I have also written a small tutorial on error handling here (http://lee-mac.com/errorhandling.html) which may be of help.
Title: Re: How to reset variables in the get midpoint functions
Post by: ribarm on August 04, 2011, 09:27:11 AM
Irneb, why do you use variable osmode as local variable when it is sysvar... Just posted Lee is correct - osm is OK...

Or this has no sense?

M.R.
Title: Re: How to reset variables in the get midpoint functions
Post by: irneb on August 04, 2011, 09:33:15 AM
Irneb, why do you use variable osmode as local variable when it is sysvar... Just posted Lee is correct - osm is OK...

Or this has no sense?

M.R.
It doesn't matter what you call it, it's a localized lisp variable. You could call it by any name you wish. I just used a name which looks the same as the system variable. I could have used o or os or osm or just-another-variable-which-i-dont-want-to-think-about  ;)
Title: Re: How to reset variables in the get midpoint functions
Post by: MP on August 04, 2011, 09:44:55 AM
It doesn't matter what you call it, it's a localized lisp variable. You could call it by any name you wish. I just used a name which looks the same as the system variable. I could have used o or os or osm or just-another-variable-which-i-dont-want-to-think-about  ;)

... and I personally think it's good practice, self documenting code et al. (http://www.theswamp.org/screens/mp/thumbsup.gif)
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 04, 2011, 09:49:29 AM
It doesn't matter what you call it, it's a localized lisp variable. You could call it by any name you wish. I just used a name which looks the same as the system variable. I could have used o or os or osm or just-another-variable-which-i-dont-want-to-think-about  ;)

... and I personally think it's good practice, self documenting code et al. (http://www.theswamp.org/screens/mp/thumbsup.gif)

1+  And I'm just a lazy typist  :lol:
Title: Re: How to reset variables in the get midpoint functions
Post by: MP on August 04, 2011, 09:53:25 AM
I'm just a lazy typist  :lol:

Refuted by thousands of lines of code me thinks.
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 04, 2011, 09:56:12 AM
I'm just a lazy typist  :lol:

Refuted by thousands of lines of code me thinks.

 :-P
Title: Re: How to reset variables in the get midpoint functions
Post by: irneb on August 04, 2011, 10:24:29 AM
Refuted by thousands of lines of code me thinks.
But that's why he's a lazy typist!  ;)
Title: Re: How to reset variables in the get midpoint functions
Post by: MP on August 04, 2011, 10:34:49 AM
But that's why he's a lazy typist!  ;)

Should have said: "Refuted by thousands of lines of carefully crafted code me thinks."

Subtitle: The dude is anal about his coding. I say that affectionately as it looks very much like my coding style, which (acknowledging hubris) is not a bad thing imo.
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 04, 2011, 10:42:17 AM
Subtitle: The dude is anal about his coding. I say that affectionately as it looks very much like my coding style, which (acknowledging hubris) is not a bad thing imo.

I'll confess that I spend far too much time on code formatting and tend to sacrifice program functionality over having 'clean' code. But I would say that a great deal has been gleaned from your plentiful examples Michael, I hope this is evident without demonstrating plagiarism.
Title: Re: How to reset variables in the get midpoint functions
Post by: MP on August 04, 2011, 10:51:12 AM
I'll confess that I spend far too much time on code formatting and tend to sacrifice program functionality over having 'clean' code.

Nonsense, to be succinct it will make you employable.

But I would say that a great deal has been gleaned from your plentiful examples Michael

It has been my great pleasure and honor to be able to share some of my coding over the years. While thanks are not needed it's truly great when someone acknowledges it. Thank you Lee. The only thing better is when one grabs the baton and reciprocates in kind -- which you have done in spades my friend. You have produced an enviable library of work; kudos.

I hope this is evident without demonstrating plagiarism.

I've never had a sense of plagiarism. You're doing your own thing, and well, as noted above.

PS: My own style was the result of programming in many different languages and finding a style that worked for all of them. Reviewing work from masters like Nesterovsky, Petzold, Tanzillo et all did not hurt one bit either.
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 04, 2011, 11:06:18 AM
Thanks for your kind words & advice Michael, I feel flattered.  :-)
Title: Re: How to reset variables in the get midpoint functions
Post by: MP on August 04, 2011, 11:09:07 AM
You're very welcome Lee. Apologies to everyone else for the tangent. :)
Title: Re: How to reset variables in the get midpoint functions
Post by: alanjt on August 04, 2011, 11:13:19 AM
You're very welcome Lee. Apologies to everyone else for the (http://www.theswamp.org/lilly_pond/alanjt/kissAss.gif)
fixed it for ya.  :-D


j/k
Title: Re: How to reset variables in the get midpoint functions
Post by: MP on August 04, 2011, 11:17:11 AM
fixed it for ya.

(http://i56.tinypic.com/2qmog9l.jpg)
Title: Re: How to reset variables in the get midpoint functions
Post by: alanjt on August 04, 2011, 11:19:25 AM
fixed it for ya.

(http://i56.tinypic.com/2qmog9l.jpg)
  :lol:
Title: Re: How to reset variables in the get midpoint functions
Post by: jaydee on August 04, 2011, 07:14:00 PM
Hi All.
Thankyou for the advice. I think i over explain on my post. Heres a simple one

Please test the code tansparently  'gm   and  'mm  (with and without the (setvar "osmode" 0))  at the end

command line - pick start point then
'mm   =  this is where it fails with the setvar at the end of code, it runs as normal without the setvar.

I can set anything i want before (setq pt1), but once i put any variable setting at the end just before the last closing bracket, the get midpoint will fails.

Code: [Select]
(defun c:gm ( / pt1 pt2 inspt)

(setq pt1 (getpoint "\nSelect First Point : ")
         pt2 (getpoint pt1 "\nSelect Second Point : "))
(setvar "osmode" 1)
(setq inspt
   (mapcar '+ pt1
      (mapcar '/
         (mapcar '- pt2 pt1)
         '(2.0 2.0 2.0)
      )
   )
)
(setvar "osmode" 0)
)
Code: [Select]
(defun c:mm (/ pt1 pt2)
(setvar "osmode" 1)
  (setq pt1 (getpoint)
        pt2 (getpoint)
  )
  (polar pt1 (angle pt1 pt2) (/ (distance pt1 pt2) 2.))
(setvar "osmode" 0)
)

Once i put this line in, it fails (setvar "osmode" 0)
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 04, 2011, 07:48:08 PM
The midpoint calculation is not 'failing', but the point is not returned since it is not the last evaluated expression in the function definition.

All functions will return the result of evaluating the last expression in the function definition. Usually, this last expression is the 'princ' function, called without any arguments to return a null symbol. In this case the function 'exits quietly', returning this null symbol: e.g.:

Code: [Select]
(defun c:test ( )
    (command "_.line" "_non" '(0. 0. 0.) "_non" '(1. 0. 0.) "")
    (princ)
)

Code: [Select]
_$ (type (c:test))
SYM

However, sometimes we want a function to return a value, for example, consider the following code:

Code: [Select]
(defun Add2 ( x ) (+ x 2))
When called with a numerical argument, the above function will return that argument + 2, since the '+' statement is the last expression evaluated in the function definition:

Code: [Select]
_$ (Add2 3)
5

In your code you have:

Code: [Select]
(defun c:mm (/ pt1 pt2)
(setvar "osmode" 1)
  (setq pt1 (getpoint)
        pt2 (getpoint)
  )
  (polar pt1 (angle pt1 pt2) (/ (distance pt1 pt2) 2.))
(setvar "osmode" 0)
)

Which, when called, will return 0 since the return of the 'setvar' function is the value to which the System Variable is set:

Quote from: VLIDE Help Docs
setvar
Sets an AutoCAD system variable to a specified value

(setvar varname value)

Arguments

varname
A string or symbol naming a variable.

value
An atom or expression whose evaluated result is to be assigned to varname. For system variables with integer values, the supplied value must be between -32,768 and +32,767.

Return Values

If successful, setvar returns value.

To return the calculated point, the variable with the point value can be the last expression, which, when evaluated will return the value of the variable and return the point.

Code: [Select]
(defun c:mm (/ pt1 pt2)
(setvar "osmode" 1)
  (setq pt1 (getpoint)
        pt2 (getpoint)
  )
  (polar pt1 (angle pt1 pt2) (/ (distance pt1 pt2) 2.))
(setvar "osmode" 0)
  pt1
)

However, I would strongly recommend you read Irneb's and my earlier posts regarding changing System Variables and the use of Error Handlers.

Title: Re: How to reset variables in the get midpoint functions
Post by: jaydee on August 04, 2011, 08:29:25 PM
Thankyou verymuch Lee
very well explain. now i know why the code failed. before your detailed explaination i just dont understand why once i throw in any setvar function at the end of the code, it stop working.

I actually read every single reply carefully, I just dont want to complicate things, as you pointed out the function require to return an avaluation, in this case the midpoint.

IOU1+

Code corrected as below with the addition of the (setq pt3.. to return the midpoint of pt1 and pt2
Code: [Select]
(defun c:mm (/ pt1 pt2)
(setvar "osmode" 1)
  (setq pt1 (getpoint)
        pt2 (getpoint)
  )
  (setq pt3 (polar pt1 (angle pt1 pt2) (/ (distance pt1 pt2) 2.)))
(setvar "osmode" 0)
  pt3
)
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 04, 2011, 08:31:57 PM
You're welcome jaydee, I'm glad you could understand my explanations  :-)
Title: Re: How to reset variables in the get midpoint functions
Post by: irneb on August 05, 2011, 04:33:30 AM
You know, actually the way your gm & mm is working forces you to set the osmode to 0 at the end. Otherwise the returned point will use the running OSnap. To get it to reset the OSMode back after the defun has completed would require some reactors ... which I think is a total over-complicated method!

I'd actually re-write the MM thus:
Code: [Select]
(defun c:MM (/ pt1 pt2)
  (if (and (= (logand (getvar 'CmdActive) 1) 1)
           (setq pt1 (getpoint "Pick first point for mid-point: "))
           (setq pt2 (getpoint pt1 "Pick second point for mid-point: "))
    )
    (command "_None" (mapcar '(lambda (v1 v2) (/ (+ v1 v2) 2)) pt1 pt2))
  )
  (princ)
)
That way it simply discontinues the function if not called while another command is running. And it doesn't even try to set the OSMode at all.
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 05, 2011, 09:13:05 AM
Good call Irneb, a much better solution. I think I needed to take a step back and look at the goal itself, I couldn't see the wood for the trees :ugly:

But at least jaydee has learnt something about function returns along the way  :-)
Title: Re: How to reset variables in the get midpoint functions
Post by: chlh_jd on August 05, 2011, 10:53:37 AM
Hi Landlord , what I understand in your thinks is get 2 points's midpoint for transparent use .
If I understand right, the following code may be help  .
Code: [Select]
(defun SendKeys (keys / ws)
  (setq ws (vlax-create-object "WScript.Shell"))
  (vlax-invoke-method ws (quote sendkeys) keys)
  (vlax-release-object ws)
  (princ)
) ;_end SendKeys
;;translate a point or point-set into 'SendKeys' string
(defun ss-pt->str (pts / str)
  (if (numberp (car pts))
    (progn
      (setq str "")
      (foreach a pts
(setq str (strcat str (strcat (rtos a 2 6) ",")))
      )
      (setq str (vl-string-right-trim "," str))
      (strcat str " ")
    )
    (mapcar (function ss-pt->str) pts)
  )
)
;;;for  transparent 
(defun c:md (/ p1 p2 pm)
  ;;This just for test ,
  ;;error case must be deal .
  (if
    (and
      (setq p1 (getpoint "Selcet First Point for MidPoint :"))
      (while (not p2)
(setq p2 (getpoint p1 "Selcet Second Point for MidPoint :")
)
      )
      (setq pm (mapcar (function (lambda (x y) (/ (+ x y) 2.0))) p1 p2))
      (= (getvar "CMDACTIVE") 1)
    )
     (Sendkeys (ss-pt->str pm))
     (if pm (setvar "LASTPOINT" pm))
  )
)
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 05, 2011, 11:03:19 AM
Or just type M2P or MTP  :-)
Title: Re: How to reset variables in the get midpoint functions
Post by: chlh_jd on August 05, 2011, 11:11:35 AM
There is a problem, how to determine system access point device in use .
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 05, 2011, 11:15:30 AM
There is a problem, how to determine system access point device in use .

Sorry, I don't understand.
Title: Re: How to reset variables in the get midpoint functions
Post by: chlh_jd on August 05, 2011, 11:34:02 AM
I mean that , I use (getvar "CMDACTIVE") to judge whenever to 'sendkeys' ;
however , if 'MD' command is used , the system variable "CMDACTIVE" allways equal 1 , so the routine 'MD' always run
(if (and ...) (Sendkeys ...) ) .
if use "CMDNAMES" we must register the command name 'MD' before use , the cost is higher .
that's what I think .
Title: Re: How to reset variables in the get midpoint functions
Post by: irneb on August 05, 2011, 11:36:59 AM
Or just type M2P or MTP  :)
I've actually got that set up in my CUI as a keyboard shortcut: Ctrl+M

All I can figure from the "System Access Device" ...  :o ... perhaps the OSnap? Strange though ... I've never run into such situation where the midpoint picked an endpoint. Maybe I've just been "lucky".
Title: Re: How to reset variables in the get midpoint functions
Post by: chlh_jd on August 05, 2011, 11:39:06 AM
Sorry , I must go out now .  I 'll discuss with you tomorrow .
Title: Re: How to reset variables in the get midpoint functions
Post by: gile on August 05, 2011, 11:50:28 AM
Quote
I've actually got that set up in my CUI as a keyboard shortcut: Ctrl+M
1+
Title: Re: How to reset variables in the get midpoint functions
Post by: jaydee on August 05, 2011, 01:11:19 PM
Thankyou all reponding to my post. your advice help me alot.
Have a good weekend.
Title: Re: How to reset variables in the get midpoint functions
Post by: chlh_jd on August 06, 2011, 01:32:38 AM
Sorry , I must go out now .  I 'll discuss with you tomorrow .
Or just type M2P or MTP  :)
I've actually got that set up in my CUI as a keyboard shortcut: Ctrl+M

All I can figure from the "System Access Device" ...  :o ... perhaps the OSnap? Strange though ... I've never run into such situation where the midpoint picked an endpoint. Maybe I've just been "lucky".

I'm sorry for my poor English . 'System Access Point Device in use'  perhaps is that
The CommandLine Now allow to input a point  or point coordinates .
Title: Re: How to reset variables in the get midpoint functions
Post by: irneb on August 06, 2011, 01:55:15 AM
Oh! That's fine I suppose, but you're converting a point's XYZ into a string to pass to the SendKeys method. The accuracy is not going to be a good as when you pass the value directly from lisp through the command/vl-cmdf functions.

Also you don't prefix the point with the forced None object snap. Though I'm unsure why I've never had such a problem with using M2P instead.
Title: Re: How to reset variables in the get midpoint functions
Post by: chlh_jd on August 06, 2011, 02:26:14 AM
Oh! That's fine I suppose, but you're converting a point's XYZ into a string to pass to the SendKeys method. The accuracy is not going to be a good as when you pass the value directly from lisp through the command/vl-cmdf functions.

Also you don't prefix the point with the forced None object snap. Though I'm unsure why I've never had such a problem with using M2P instead.

The accuracy can be set higher through (rtos a 2 8) or higher
Title: Re: How to reset variables in the get midpoint functions
Post by: Lee Mac on August 06, 2011, 08:37:13 AM
I'm sorry for my poor English . 'System Access Point Device in use'  perhaps is that
The CommandLine Now allow to input a point  or point coordinates .

Does this not work for you:

Code: [Select]
Command:
Command: _line Specify first point:
Specify next point or [Undo]: m2p
First point of mid: Second point of mid:
Specify next point or [Undo]:
Specify next point or [Close/Undo]:
Title: Re: How to reset variables in the get midpoint functions
Post by: chlh_jd on August 07, 2011, 08:09:45 AM
I'm sorry for my poor English . 'System Access Point Device in use'  perhaps is that
The CommandLine Now allow to input a point  or point coordinates .

Does this not work for you:

Code: [Select]
Command:
Command: _line Specify first point:
Specify next point or [Undo]: m2p
First point of mid: Second point of mid:
Specify next point or [Undo]:
Specify next point or [Close/Undo]:
the command m2p or mtp can be use in my ACAD2010, but not for ACAD2004
Title: Re: How to reset variables in the get midpoint functions
Post by: irneb on August 08, 2011, 03:24:11 AM
The accuracy can be set higher through (rtos a 2 8 ) or higher
Just not sure why you'd want to go that route! It seems a lot of extra just so you can send a piece of converted text (which is unnecessary with command) through an ActiveX Script-Object to the running command. I can understand using it when your running command is also a lisp routine, but not for normal commands / non-lisp addons.