entity selection in command extend / trim
Comments
-
Vit, there's a minor problem with no. 23, as Greg pointed out: If you use Esc to exit the command, it could change your system settings. It would be better to use this version, which incorporates all the changes Greg suggested (thanks, Greg!), and also solves the problem that sometimes clicking twice in the same place ends the command.Plus it includes EX, which is an Extend command with the same automatic fence mode. If you don't want EX, just leave out everything after ;;; EXTEND.You can use it just as it's posted here, or you can remove the double-spacing with a word processor, or you can get the code without double-spacing at the Swamp
;;; sub-routine to highlight a selection set (without grips)(defun hilite (set33 OnOff / N ObjN)(if (= (type set33) 'PICKSET) (progn (setq N 0) (repeat (sslength set33) (and (setq ObjN (vlax-ename->vla-object (ssname set33 N))) (vlax-method-applicable-p ObjN "Highlight") (vla-highlight ObjN OnOff) ) ;; end And (setq N (1+ N)) ) ;; end Repeat ) ;; end Progn ) ;; end IF) ;-----------------------------------------------------------;;; subroutine to handle errors(defun IfAbort (emsg)(prompt "\n-- Abnormal termination due to: ")(prompt emsg)(setvar "CMDECHO" SaveCE) ;; restore command echo status(setvar "OSMODE" SaveOS) ;; restore Object Snap setting(setq *error* SaveErr) ;; restore previous error-handling function(hilite ss1 0) ;; turn off highlighting) ;-----------------------------------------------------------;;; TRIM command with Fence mode automatically turned on and off(defun c:TR (/ )(setq SaveCE (getvar "CMDECHO")) ;; save Command Echo status(setq SaveOS (getvar "OSMODE")) ;; save Object Snap setting(setq SaveErr *error*) ;; save current error-handling function(setq *error* IfAbort) ;; make IfAbort the error-handling function(princ "Select cutting objects: ")(setq ss1 (ssget)) ;; select cutting edges(sssetfirst nil ss1) (sssetfirst nil) ;; turn off grips of any pre-selected set;------------------------------------------------------(setvar "CMDECHO" 0) ;; suppress command echo(setvar "OSMODE" 0) ;; turn off object snap(setq pt1 nil pt2 nil NewPt nil) ;; clear fence points & pick point(setq LoopFlag 1) ;; set Loop flag;------------------------------ Begin Loop, get user input(while (equal LoopFlag 1) ;; Loop till no point is picked (setq e1 nil) (setq NewPt nil) (hilite ss1 1) ;; highlight cutting edges (if pt1 ;;----------1: Is there a fence start point? (progn ;; If so, look for a new fence vertex. (setq NewPt (getpoint pt1 "Next fence point, or object to trim: ")) (if NewPt ;;---------2: Did the user actually pick a new point? (progn ;; If so, (if (ssget NewPt) ;;---------3: Is there an object at NewPt? (progn ;; If so, (setq e1 (ssname (ssget NewPt) 0)) ;; make it e1, (setq ObjFound 1) ;; set the Object Found flag, (setq pt1 nil pt2 nil) ;; and clear the fence points. ) ;; end Progn. (setq ObjFound 0) ;; If not, clear the Object Found flag. ) ;;---end IF-3. ) ;; end Progn. (progn ;; If not (no new point because user hit Enter), (setq pt1 nil pt2 nil) ;; clear the fence points, (setq LoopFlag 0) ;; and prepare to end the loop. ) ;;end Progn. ) ;;---end IF-2. ) ;; end Progn (progn ;; If not (no fence start point), look for an object to trim (setvar "ErrNo" 0) ;; (entsel) error 7 = none found, error 52 = Enter (setq e1 (entsel "Object to trim, or start point of fence: ")) (setq NewPt (getvar "LASTPOINT")) (if (equal (getvar "ErrNo") 7) ;;-------4: Was an object found? (setq ObjFound 0) ;; If not, clear the Object Found flag. (progn ;; If one was found (no errror 7), (setq ObjFound 1) ;; set the Object Found flag, (setq pt1 nil pt2 nil) ;; and clear the fence points. ) ;;end Progn. ) ;;---end IF-4 (if (equal (getvar "ErrNo") 52) ;;-------5: Did the user hit Enter? (progn ;; If so, (setq pt1 nil pt2 nil) ;; clear the fence points, (setq LoopFlag 0) ;; and prepare to end the loop. ) ;;end Progn. ) ;;---end IF-5 ) ;; end Progn ) ;;---end IF-1;;;-------------------------- Continue Loop, process user input (if (= ObjFound 1) ;;--------6: Was an object found during user input? (command "Trim" ss1 "" NewPt "") ;; If so, trim the object, (progn ;; If not (no object found), (if pt1 ;;---------7: Is there a fence start point? (progn ;; If so, (setq pt2 NewPt) ;; make the new point the fence end point, (command "Trim" ss1 "" "F" pt1 pt2 "" "") ;; trim the fence objects, (setq pt1 pt2) ;; allow continuation of the fence line, (setq pt2 nil) ;; and get rid of the old end point. ) ;; end Progn (progn ;; If not (no fence start point), (setq pt1 NewPt) ;; make this pt1, (setq pt2 nil) ;; and get rid of the old pt2. ) ;; end Progn ) ;;---end IF-7 ) ;; end Progn ) ;;---end IF-6) ;; end WHILE loop(setvar "CMDECHO" SaveCE) ;; restore Command Echo status(setvar "OSMODE" SaveOS) ;; restore Object Snap setting(setq *error* SaveErr) ;; restore previous error-handling function(hilite ss1 0) ;; turn off highlighting) ;-----------------------------------------------------------;;; EXTEND command with Fence mode automatically turned on and off(defun c:EX (/ )(setq SaveCE (getvar "CMDECHO")) ;; save Command Echo status(setq SaveOS (getvar "OSMODE")) ;; save Object Snap setting(setq SaveErr *error*) ;; save current error-handling function(setq *error* IfAbort) ;; make IfAbort the error-handling function(princ "Select boundary objects to extend to: ")(setq ss1 (ssget)) ;; select boundary objects(sssetfirst nil ss1) (sssetfirst nil) ;; turn off grips of any pre-selected set;------------------------------------------------------(setvar "CMDECHO" 0) ;; suppress command echo(setvar "OSMODE" 0) ;; turn off object snap(setq pt1 nil pt2 nil NewPt nil) ;; clear fence points & pick point(setq LoopFlag 1) ;; set Loop flag;------------------------------ Begin Loop, get user input(while (equal LoopFlag 1) ;; Loop till no point is picked (setq e1 nil) (setq NewPt nil) (hilite ss1 1) ;; highlight cutting edges (if pt1 ;;----------1: Is there a fence start point? (progn ;; If so, look for a new fence vertex. (setq NewPt (getpoint pt1 "Next fence point, or object to extend: ")) (if NewPt ;;---------2: Did the user actually pick a new point? (progn ;; If so, (if (ssget NewPt) ;;---------3: Is there an object at NewPt? (progn ;; If so, (setq e1 (ssname (ssget NewPt) 0)) ;; make it e1, (setq ObjFound 1) ;; set the Object Found flag, (setq pt1 nil pt2 nil) ;; and clear the fence points. ) ;; end Progn. (setq ObjFound 0) ;; If not, clear the Object Found flag. ) ;;---end IF-3. ) ;; end Progn. (progn ;; If not (no new point because user hit Enter), (setq pt1 nil pt2 nil) ;; clear the fence points, (setq LoopFlag 0) ;; and prepare to end the loop. ) ;;end Progn. ) ;;---end IF-2. ) ;; end Progn (progn ;; If not (no fence start point), look for an object to extend (setvar "ErrNo" 0) ;; (entsel) error 7 = none found, error 52 = Enter (setq e1 (entsel "Object to extend, or start point of fence: ")) (setq NewPt (getvar "LASTPOINT")) (if (equal (getvar "ErrNo") 7) ;;-------4: Was an object found? (setq ObjFound 0) ;; If not, clear the Object Found flag. (progn ;; If one was found (no errror 7), (setq ObjFound 1) ;; set the Object Found flag, (setq pt1 nil pt2 nil) ;; and clear the fence points. ) ;;end Progn. ) ;;---end IF-4 (if (equal (getvar "ErrNo") 52) ;;-------5: Did the user hit Enter? (progn ;; If so, (setq pt1 nil pt2 nil) ;; clear the fence points, (setq LoopFlag 0) ;; and prepare to end the loop. ) ;;end Progn. ) ;;---end IF-5 ) ;; end Progn ) ;;---end IF-1;;;-------------------------- Continue Loop, process user input (if (= ObjFound 1) ;;--------6: Was an object found during user input? (command "Extend" ss1 "" NewPt "") ;; If so, extend the object, (progn ;; If not (no object found), (if pt1 ;;---------7: Is there a fence start point? (progn ;; If so, (setq pt2 NewPt) ;; make the new point the fence end point, (command "Extend" ss1 "" "F" pt1 pt2 "" "") ;; extend fence objects, (setq pt1 pt2) ;; allow continuation of the fence line, (setq pt2 nil) ;; and get rid of the old end point. ) ;; end Progn (progn ;; If not (no fence start point), (setq pt1 NewPt) ;; make this pt1, (setq pt2 nil) ;; and get rid of the old pt2. ) ;; end Progn ) ;;---end IF-7 ) ;; end Progn ) ;;---end IF-6) ;; end WHILE loop(setvar "CMDECHO" SaveCE) ;; restore Command Echo status(setvar "OSMODE" SaveOS) ;; restore Object Snap setting(setq *error* SaveErr) ;; restore previous error-handling function(hilite ss1 0) ;; turn off highlighting) ;-----------------------------------------------------------
0 -
Looks good Anthony. My personal preference is to create the error handler as a local function so I can keep all my variable local in scope. Otherwise they live on after the routine. Perhaps another option is to set the globals to NIL prior to termination, both in the main routine and the error handler. Or just ignore them :-)
0 -
Hi, yes very good for me - thank you very much Greg and Anthony.
0 -
Local function? Does that mean the subroutine will only work in one specific main routine? That would be good, since the error handler is only appropriate to these 2 commands. How do you do that?I started to make the main routine variables local, but wanted to wait till after debugging, and then forgot. I should have added a comment line to remind myself to do it. Or maybe it would have been better to temporarily add something that displays the values of all the variables on termination. Maybe a subroutine with a pause, so I could insert it at any point along the way to find where the problem is.Vit, I'm glad you could use it. I've gotten many useful Lisp-generated commands from this forum and others. It's nice to be able to give something back.
0 -
Anthony, yes the local function would only be available within the scope it is defined...i.e.: below the error being defined locally will make the global error "invisible" during the execution of MYFUNC and will not have replaced the global error.
(defun MYFUNC ( input_arg1 input arg2 / *error* local_arg1 local_arg2) (defun *error* (msg) ;; input and local args are available here ))
0 -
Please disregard my comments about a local error function. I have just realized this style is in fact redefining the global error.Sorry for the confusion!
0 -
I don't understand. Isn't it necessary to re-define error temporarily in order to make it trap errors? And any error-trapping routine should include re-setting error to what it was on entry to the main routine, and that's how you avoid re-defining the global error routine permanently?When you suggested making the error-trapping routine local, I thought you just meant putting (defun IfAbort) inside the main routine, so that no other routines will have access to it. And if I do that, how is this:(defun IfAbort () ....my error routine here...)(setq error IfAbort)any different from this:(defun error () ....my error routine here...)In both cases the local error routine avoids replacing the global one by including this:(setq error SaveErr)Or am I misunderstanding the whole thing?
0 -
Hi Anthony... I was expecting something like:(defun my_func (arg1 arg2 / error local_arg1 local_arg2) (defun error (msg) ... do stuff to clean up ... ) ... do stuff useful ...)would create a local symbol named error that would be the first found when execution is in my_func. However, it seems Bricscad defines ALL functions in the global namespace.Similarly:(defun my_func ( arg1 / local_func local_arg) (defun local_func () ... do some local stuff with access to my_func local variables ... ) ... do stuff and make calls to local_func ...)works fine. local_func does indeed have access to my_func variables without having to pass them in BUT once my_func terminates and you are back at the Bricscad command prompt, local_func still exists and can be called. The problem is the variables defined local to my_func to not exist any more and will thus generate an error upon access and I end up polluting the global namespace with functions that I thought were local. This can create unintended side effects by overwriting an identically named function that had been intended to be a long living global animal.This is different from recent Autocad releases and therefore caught me unaware.Your approach of saving the original error and restoring it both at the successful completion of your routines and in the new error handler will work fine.For me... I need to figure out where I may be clobbering my intended long living global functions with what I thought were locals and change my error handlers. Probably should be setting all my local functions to NIL before finishing also.Enough of my mindless mutterings now!!!Have fun!
0 -
Greg, I can't replicate that. It seems to work the way you say it should work.If I define a subroutine inside the main routine, and include the name of the subroutine in the main routine's list of local symbols, then the subroutine isn't available after the main routine exits. If I try to run the subroutine on its own, I get a "no function definition" error.
0 -
Anthony, I have received a reply from support regarding this. It is only happens when an error condition is encountered so if no error was raised when you tested then the local function do not remain. If, however, an error is raised then the local functions do remain.The reply also indicated this behaviour will be corrected for the case where and error is raised.
0