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

Endpoint selection only for getpoint

16 REPLIES 16
SOLVED
Reply
Message 1 of 17
gccdaemon
1818 Views, 16 Replies

Endpoint selection only for getpoint

I have a routine that I'm working on and it works great except that it currently uses getpoint which is too broad of an option for other users. How would I get an endpoint only selection for getpoint? Also, If an endpoint is not selected, prompt "Endpoint not selected" and not move on to the next part of the routine until endpoint is selected or exit command option entered? Here is an examploe of what I currently have:

 

    (setq YN (getkword "\nMove detail sheets? [Yes/No]: "))
    (if    (= "Yes" YN)
        (progn    (while    (and    (setq gp1 (getpoint "Pick LOWER LEFT corner of sheet to move <Done>: ")))
                (princ "\n ")
                (setq gp2 (getpoint "Pick LOWER RIGHT corner to move sheet to: " ))
                (princ "\n ")
                (if    (setq sel (ssget "_C" (mapcar '- gp1 '(0.0500 0.05 0.0)) (mapcar '+ gp1 '(5.1725 7.1 0.0))))
                    (command "._zoom" "E"
                         "_.move" sel "" "_non" gp1 "_non" gp2
                         "_.move" sel "" "_non" '(0.0 0.0) "_non" '(0.25 0.0))
                    (princ "\nNo objects found."))
            )
        (setq YN nil)
    )    )
    (princ)

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
16 REPLIES 16
Message 2 of 17
hgasty1001
in reply to: gccdaemon

Hi,

 

As a general advice, the following workflow it's the usual way to deal with points in  Autolisp:

 

1.- Get the current osnap settings via (getvar "OSMODE")

2.- Store the current "OSMODE" value: (setq oldOsmode (getvar "OSMODE"))

3.- Set the prefered "OSMODE" value (1 in this case) :(setvar "OSMODE" 1)

4.- Do the pick

5.- .Your stuff here...maybe set "OSMODE" to 0 in order to create geometry based on points passed through Autolisp, otherwise AutoCAD use the closest point that honor the OSMODE value, and not the value from AutoLisp

6.- Restore the old "OSMODE" to respect the current user settings.

 

By the way, you don't need the (progn before the (while...) if there is no other statement after.

 

Gaston Nunez

 

Message 3 of 17
gccdaemon
in reply to: hgasty1001

The problem with OSMODE is that in this case it doesn't force the user to pick an endpoint, it just sets the object snaps to endpoint.

 

Also the reason for the (PROGN is because it's wrapped in an (IF. There is a statenment after that sets the YN variable back to NIL to complete the (WHILE loop.

 

This code works fine, it's that I don't know how to go about forcing the user to pick an endpoint only.

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 4 of 17
dbroad
in reply to: gccdaemon

Not that I advocate doing this but input checking within a loop is what you want.  For example, if you want only an endpoint, then use the pick point as input to the osnap function.  If it can't find an endpoint it returns nil.  You can use that as a test expression to continue the input loop with an additional prompt.

 

(osnap pickpoint "end")

returns nil if no endpoint found.

Architect, Registered NC, VA, SC, & GA.
Message 5 of 17
Kent1Cooper
in reply to: gccdaemon


@gccdaemon wrote:

I have a routine that ... currently uses getpoint which is too broad of an option for other users. How would I get an endpoint only selection for getpoint? Also, If an endpoint is not selected, prompt "Endpoint not selected" and not move on to the next part of the routine until endpoint is selected or exit command option entered? ....


Set OSMODE to 1 for Endpoint as gasty1001 suggested.  Then you can try something like this, not that there aren't other ways to do it [untested]:

 

(while

  (and

    (not gotgp1); haven't picked a valid point yet

    (not (initget "Done")); must re-do for every loop; with (not) wrapper to return T [(initget) always returns nil]

    (setq gp1 (getpoint "\nPick LOWER LEFT corner of sheet to move <Done>: "))

      ; above will return nil on Enter, a point if picked, or "Done" if User types D [or more of the word]

  ); and

  (if (= gp1 "Done"); non-nil -- did User type D/Done?

    (exit); then -- get out

    (if (osnap gp1 "_end"); else -- User picked a point -- Osnapped to an Endpoint?

      (setq gotgp1 T); then -- valid; will stop (while) loop in check above, and go on for gp2

      (prompt "\nEndpoint not selected."); else -- ask again and go back

    ); if [inner]

  ); if [outer]

); while

(if gp1 ; User picked an Endpoint-Osnapped point for gp1

  (while ; then -- similarly for gp2:

    (and

      (not gotgp2)

      (not (initget "Done"))

      (setq gp2 (getpoint "\nPick LOWER RIGHT corner to move sheet to <Done>: "))

    ); and

    (if (= gp2 "Done")

      (exit)

      (if (osnap gp2 "_end")

        (setq gotgp2 T)

        (prompt "\nEndpoint not selected.")

      ); if [inner]

    ); if [outer]

  ); while

  (exit); else [User Enter at gp1 prompt for Done as default]

); if

(if gp2 ; User also picked an Endpoint-Osnapped point for gp2

  (progn ; then

    (if (setq sel (ssget "_C" ...

      ; ... blah blah blah ....

  ); progn

  (exit); else [User Enter at gp2 prompt for Done as default]

); if

 

If you might use this more than once in the same editing session of the same drawing [doesn't seem likely, but I don't know your entire situation], make sure those gotgp1 and gotgp2 variables are localized within the routine.

Kent Cooper, AIA
Message 6 of 17
hmsilva
in reply to: gccdaemon

Andrew,

 

you prompt:
"Pick LOWER LEFT corner of sheet to move"


Is there a frame in the sheet to move?
If so you can ask the user to select the frame and get your points using the object boundingbox.
Just a thought...

 

Henrique

EESignature

Message 7 of 17
dbroad
in reply to: Kent1Cooper

I was thinking of a simpler construct.

;GEPT Get endpoint Form: (getp <prompt1><followup  prompt>)

(defun gept ( pr1 prn / ept)
(while (not (and (setq ept (getpoint pr1))
(setq ept (osnap ept "_end"))
))
(setq pr1 prn)
)
ept)

 

(setq mypoint (gept "\nSelect lower corner"  "\nBe sure to select the actual corner. Select lower corner"))

Architect, Registered NC, VA, SC, & GA.
Message 8 of 17
Kent1Cooper
in reply to: dbroad


@dbroad3 wrote:

I was thinking of a simpler construct.

....


Yeah, I started out simpler like that, but mine is more complicated in order to allow "Done" as an option the User could type and also as the default on hitting Enter instead of picking a point.  [I assumed that from the capital D, as is done with options in most AutoCAD commands, and the angle-bracket surround of it, as is typically done with defaults, though maybe that's not what they intended.  If they want exiting to be the default on Enter without the type-in-D/Done option, I'd switch the D to lower-case, and I think the code could be simplified somewhat.]  As yours does it, Enter would result in being prompted again, just as picking a non-Osnappable-to-Endpoint location would, and only Escape would get you out of it.

Kent Cooper, AIA
Message 9 of 17
gccdaemon
in reply to: hmsilva

This is just a portion of a bigger routine, so I like the options that create a seperate routine.

 

As you can see, this routine uses the first point "GP1" to create a selection box around a "Detail sheet" embedded in a Detail block. Then it moves those objects from "GP1" (the left corner of the second detail sheet) to the second point "GP2" (the right corner of the first detail sheet), and loops this process to handle detail sheets 3,4,5,etc.

 

Being able to replace the getpoint command is optimal because I have other instances in the rest of my routine that need endpoint only selection.

 

Thanks again to everyone who contributed. KUDOS TO ALL!

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 10 of 17
phanaem
in reply to: dbroad


@dbroad3 wrote:

I was thinking of a simpler construct.


I was thinking of something similar, but as Kent said, I'd like a clean exit on right click too.

I hope you do not mind if I alter your code a little bit:

(defun gept (p msg err / ept)
  (while
    (and
      (setq ept (if p (getpoint p msg) (getpoint msg)))
      (not (setq ept (osnap ept "_end")))
      (princ err)
    )
  )
  ept
)

(if
  (and
    (setq p1 (gept nil "\nSelect lower left corner"  "\nNo Endpoint found for specified point."))
    (setq p2 (gept p1 "\nSelect lower right corner"  "\nNo Endpoint found for specified point."))
    )
  (progn
    ...
    )
  )

 

 

 

 

 

Message 11 of 17
gccdaemon
in reply to: phanaem

OK, so I'm testing this routine in my LISP and I'm getting odd results. When trying to pick the first point, I get caught in a loop to pick the first point.

 

(defun GETPT (/ PR1 PRN EPT)
    (while    (not    (and    (setq EPT (getpoint PR1))
                (setq EPT (osnap EPT "_end"))
        )    )
    (setq PR1 PRN)
    )
EPT
)

 

Also Instead of worrying about 2 points, lets look at the getpoint as a single point so I can apply it for each other instance in my LISP. Any other ideas on how to achieve this?

 

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 12 of 17
dbroad
in reply to: phanaem

Yes, the routine should definitly have a point prompt. Good rewrite and addition, since any routine that calls the getpoint function should pass through its options.

Architect, Registered NC, VA, SC, & GA.
Message 13 of 17
Kent1Cooper
in reply to: gccdaemon


@gccdaemon wrote:

OK, so I'm testing this routine in my LISP and I'm getting odd results. When trying to pick the first point, I get caught in a loop to pick the first point.

.... 



That's just what I was talking about at the end of Message 8.  Have you tried my suggestion?  You'd need to fill in the real workings where I have ... blah blah blah ... , but before you do that, just for the purpose of evaluating whether the point selection process works as you want, try replacing this part at the end:

 

(if gp2 ; User also picked an Endpoint-Osnapped point for gp2

  (progn ; then

    (if (setq sel (ssget "_C" ...

      ; ... blah blah blah ....

  ); progn

  (exit); else [User Enter at gp2 prompt for Done as default]

); if

 

with something like this:

 

(if gp2 ; User also picked an Endpoint-Osnapped point for gp2

  (progn ; then

    (prompt "\nThat did it.")

    (princ)

  ); progn

  (exit); else [User Enter at gp2 prompt for Done as default]

); if

 

An error handler will be able to suppress the message you get that "looks like" an error when you hit Enter or type D/Done, and thereby invoke the (exit) function..

Kent Cooper, AIA
Message 14 of 17
dbroad
in reply to: gccdaemon

@gccdaemon
Thanks for the solution flag. I think you may have copied my routine incorrectly if it is as you just posted. I had included 2 arguments and some local variables. Your version has no arguments.

My version which has 2 arguments and does not support a point pick argument:

;GEPT Get endpoint Form: (getp <prompt1><followup  prompt>)
(defun gept ( pr1 prn / ept)
(while (not (and (setq ept (getpoint pr1))
(setq ept (osnap ept "_end"))
))
(setq pr1 prn)
)
ept)

 

phanaem's version was better in that it supported a point pick argument to the getpoint function without requiring it. It has 3 arguments:

(defun gept (p msg err / ept)
  (while
    (and
      (setq ept (if p (getpoint p msg) (getpoint msg)))
      (not (setq ept (osnap ept "_end")))
      (princ err)
    )
  )
  ept
)

 Cutting and pasting from either of these, as I did in this post,  is suggested.

 

Good luck in completing your routine. As for error handling, this should probably be handled in the calling routine.  Adding an error handler within such a small routine makes it less flexible.

 

Architect, Registered NC, VA, SC, & GA.
Message 15 of 17
gccdaemon
in reply to: phanaem

So I made the necessary changes and it doesn't loop on first point input. I removed the (IF from in front of the "(and setq GP1" and it seems to be working propperly now. Here is the working code. Thanks again to everyone who helped out.

 

(defun C:DETAILMOVE (/ YN GP1 GP2 SEL)
	(initget "Yes No")
	(setq YN (getkword "\nMove detail sheets? [Yes/No]: "))
	(if	(= "Yes" YN)
		(progn	(while	(and	(setq GP1 (GETEND nil	"\nPick LOWER LEFT corner of sheet to move <Done>: "
								"\nNo corner selected: "))
					(setq GP2 (GETEND GP1	"\nPick LOWER RIGHT corner to move sheet to: "
								"\nNo corner selected: ")))
				(if	(setq sel (ssget "_C" (mapcar '- GP1 '(0.0500 0.05 0.0)) (mapcar '+ GP1 '(5.1725 7.1 0.0))))
					(command "._zoom" "E"
						 "_.move" sel "" "_non" GP1 "_non" GP2
						 "_.move" sel "" "_non" '(0.0 0.0) "_non" '(0.25 0.0))
					(princ "\nNo objects found."))
	)	)	)
	(setq YN nil)
)
(princ)

;;
;;
;;

(defun GETEND (P MSG1 MSG2 / PNT)
	(while	(and	(setq PNT (if P (getpoint P MSG1) (getpoint MSG1)))
			(not (setq PNT (osnap PNT "_end")))
			(princ MSG2)
	)	)
PNT)

 

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 16 of 17
slanda.diom
in reply to: phanaem

Sorry guys.
I am connecting the dots because I don't know much about lisp.
So, in the end, would look like?

 

 

Message 17 of 17
gccdaemon
in reply to: gccdaemon

It should look like this:

 

(defun GETEND (P MSG1 MSG2 / PNT)
	(while (and	(setq PNT (if P (getpoint P MSG1) (getpoint MSG1)))
			(not (setq PNT (osnap PNT "_end")))
			(princ MSG2)
	)	  )
PNT)

 Then when you want to use it instead of using getpoint, you call GETEND like this:

 

(setq YOURPOINT (GETEND nil "\nYour Get Endpoint Message Here: " "\nYour No Endpoint Selected Message Here: "))

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram

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

Post to forums  

Autodesk Design & Make Report

”Boost