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

Identifying the closest number to actual input AutoLISP

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
bart_van_tuyl
1210 Views, 6 Replies

Identifying the closest number to actual input AutoLISP

Hi,

 

I have a situation where the user can pick litturally 10's of diffrent sizes of a particular product. the user would thus be very bright to remember every single size. the idea I had was to create a lisp that promts the user for a size, if equal go to insert the block of that size, if less than x but greater than y prompt the user that bla is the closes size available 

 

eg of prompt:

 

Your specifide size of  102mm is not available, the closest mesurment is 100mm would you like to use this instead?: [yes/ No] <yes>:

 the code i had a look at and was thinking of is the following:

 

(defun c:testand ()
	(setq a (getreal "\nEnter a Number : "))
	(if
	    (and
		(>= a 5.0)
		(<= a 10.0)
	    );and
		(prompt "\nNumber is between 5 and 10")
		(prompt "\nNumber is less than 5 or greater than 10")
	);if
   (princ)
);defun
(princ)

 However i tried to modify this to the following but to no avail?

 

(defun c:testand ()
	(setq a (getreal "\nEnter a hight : "))
	(if
	    (and
                (= a 100.0)
		((>= a 100.0)<= a 110)
	   );and
                (prompt "\nNumber is 100")
		(prompt "\nNumber is between 100 and 110")
	);if
   (princ)
);defun
(princ)

 but this dose not cater for numbers in a way that says if greater than but less than (eg: if greater than 100 but less than 110, then do or goto)?

6 REPLIES 6
Message 2 of 7
Shneuph
in reply to: bart_van_tuyl

Try starting with this.

 

(defun c:testand ()
  (setq a (getreal "\nEnter a hight : "))
  (cond
    (;cond1
     (= a 100.0)
     (prompt "\nNumber is 100")
     );cond1
    (;cond2
     (and (> a 100.0) (<= a 110))
     (prompt "\nNumber is between 100 and 110")
     );cond2
    );cond
  (princ)
  );defun

AfraLISP Using COND

Message 3 of 7
hmsilva
in reply to: bart_van_tuyl

Something like this perhaps

(defun c:test ( / a ans)
   (initget 6)
   (if (and (setq a (getreal "\nEnter a Number <exit>: "))
	    (= (type a) 'REAL)
	    )
	(cond ((and (<= 5.0 a 10.0) (/= a 7.5))
	       (prompt (strcat "\nYour specifide size of " (rtos a) "mm is not available, " ))
	       (initget "Yes No")
	       (setq ans (getkword "would you like to use 7.5 instead? [Yes/No] <yes>:" ))
	       (if (or (not ans)(= ans "Yes"))
		     (command "_.insert" "the 7.5 block...")
		     )
	       )
	      ((= a 7.5)
	       (command "_.insert" "the 7.5 block...")
	       )
	      ((and (<= 10.0 a 15.0) (/= a 12.5))
	       (prompt (strcat "\nYour specifide size of " (rtos a) "mm is not available, " ))
	       (initget "Yes No")
	       (setq ans (getkword "would you like to use 12.5 instead? [Yes/No] <yes>:" ))
	       (if (or (not ans)(= ans "Yes"))
		     (command "_.insert" "the 12.5 block...")
		     )
	       )
	      ((= a 12.5)
	       (command "_.insert" "the 12.5 block...")
	       )
	      );; cond
     );; if
   (princ)
   )

 

HTH

Henrique

EESignature

Message 4 of 7
Kent1Cooper
in reply to: bart_van_tuyl

I would think, with all the size possibilities you have, that it could be cumbersome to spell out all the (cond)-function conditions for each range between available sizes.  Consider making a list of available sizes, and after getting the number from the User,

 

(if (member a YourSizeList); i.e. it's an available size

  (... then -- Insert the appropriate Block ...); i.e. no need to step through lots of possible conditions

  (... else -- offer adjacent sizes or closest size ...); see below

); if

 

I haven't quite figured it out yet, but there's got to be a comparatively simple way to find what are the adjacent available sizes on either side of a User's unavailable size, and offer a choice between them, or just the closest one if the User's size isn't halfway between two of them.  If that sounds like a good approach, I'll think about how it might be done, with some kind of incrementing through the list.

Kent Cooper, AIA
Message 5 of 7
Kent1Cooper
in reply to: Shneuph


@Shneuph wrote:

.... 

....
(and (> a 100.0) (<= a 110)) (prompt "\nNumber is between 100 and 110") );cond2 ....

I'm not sure how your actual size options relate to your sample numbers, but if both 100 and 110 are available sizes, then I assume you don't want that = sign in there -- if they enter 110, that isn't a number between available sizes as that test would claim.  If that's the case, I would use:

 

  (< 100 a 110)

 

for the condition's test expression.

Kent Cooper, AIA
Message 6 of 7
Lee_Mac
in reply to: bart_van_tuyl

I would suggest the following example:

 

(defun c:selsize ( / ans lst tmp )
    ;; List of available sizes
    (setq lst
       '(
             10
             20
             30
             40
             50
             60
             70
             80
             90
            100
        )
    )
    ;; Sort list in ascending order
    (setq lst (vl-sort lst '<))
    ;; Is there a default? Is it in the list?
    (if (not (and selsize:size (member selsize:size lst)))
        (setq selsize:size (car lst)) ;; If not, use the first item
    )
    (while ;; While the following is true
        (progn ;; Use the result from the following evaluated expressions
            (initget 6) ;; Disallow zero & negatives
            ;; Prompt the user for a size, indicating the default:
            (setq ans (getreal (strcat "\nSpecify size <" (itoa selsize:size) ">: ")))
            (cond
                (   (null ans) ;; User pressed Enter
                    (setq ans selsize:size) ;; Set size to default
                    nil ;; Exit loop
                )
                (   (setq tmp (car (member ans lst))) ;; User has specified a valid size
                    (setq selsize:size tmp ;; Set default to selected size
                          ans tmp ;; Set the variable to the selected size
                    )
                    nil ;; Exit loop
                )
                (   (progn ;; Use the result from the following evaluated expressions
                        (initget "Yes No") ;; Initialise the keywords
                        ;; Prompt the user whether to use the nearest size
                        (/= "No"
                            (getkword
                                (strcat
                                    "\nYour specified size of " (rtos ans 2)
                                    "mm is not available, the closest measurement is "
                                    ;; Sort the sizes by their numerical distance from the specified size, choose the closest
                                    (itoa (setq tmp (nth (car (vl-sort-i (mapcar '(lambda ( x ) (abs (- x ans))) lst) '<)) lst)))
                                    "mm\nWould you like to use this instead? [Yes/No] <Yes>: "
                                )
                            )
                        )
                    )
                    (setq selsize:size tmp ;; Set the default to the selected size
                          ans tmp ;; Set the variable to the selected size
                    )
                    nil ;; Exit loop
                )
                (   t   ) ;; 'No' selected, stay in loop
            )
        )
    )
    (princ (strcat "\nYou have selected the size: " (itoa ans)))
    (princ) ;; Suppress the return of the last evaluated expression
)
Message 7 of 7
Hallex
in reply to: Lee_Mac

would be good to check as well
(apply 'min lst) and (apply 'max lst) if you want to input
alternate value ?
_____________________________________
C6309D9E0751D165D0934D0621DFF27919

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

Post to forums  

Autodesk Design & Make Report

”Boost