Repeating move command

Repeating move command

Anonymous
Not applicable
2,346 Views
8 Replies
Message 1 of 9

Repeating move command

Anonymous
Not applicable

Hello again everyone,

 

I often find myself having to repeatedly move a number of objects by the same distance.  I have been through the forums here and did find some lisp routines that were close but not exactly what I'm after.  The particular one that was closest first required the user to enter the move distance as x,y,z values and would then remember these values for future moves.

 

What I'm chasing is more like how the push/pull (and many other) tool works in SketchUp.  A simple double click on the selected item will push/move/scale etc it, the same distance as was last used.

 

For those that don't know what I'm, talking about with SketchUp.  I would like a routine to move a selected object by the last distance that was used. i.e it either does this automatically or stores the last moved distance as the default option.  I don't want to have to type in x,y,z values when using the tool.

 

Really the only thing that has prevented me from making this myself is that I would like to include the option to select which direction to move in (up, down, left or right [relative to selected object]).  The same way the OFFSET command asks which side.

 

Hopefully this makes enough sense to someone to try and help.

 

Thanks for reading everyone.

 

Brad

0 Likes
Accepted solutions (1)
2,347 Views
8 Replies
Replies (8)
Message 2 of 9

ВeekeeCZ
Consultant
Consultant

 

 

(defun c:MoveBy ( / s b p done)
  
  (if (and (setq s (ssget ":L"))
	   (setq b (getpoint "\nSpecify base point: "))
	   (or *mb-d*
	       (setq *mb-d* (getdist "\nSpeficy polar distance: ")))
	   (progn
	     (while (not done)
	       (initget "dOwn S Up W Left A Right D ")
	       (setq p (getpoint b (strcat "\nSpecify second point [Up/dOwn/Left/Right] <change distance of " (rtos *mb-d* 2 2) ">: ")))
	       (cond ((not p)
		      (setq *mb-d* (getdist "\nSpeficy polar distance: ")))
		     
		     ((= 'STR (type p))
		      (setq p (polar b
				     (cond ((or (= p "dOwn") (= p "S")) (* 1.5 pi))
					   ((or (= p "Up")   (= p "W")) (* 0.5 pi))
					   ((or (= p "Left") (= p "A")) pi)
					   ((or (= p "Right")(= p "D")) 0.))
				     *mb-d*)
			    done T))
		     
		     (T
		      (setq p (polar b (angle b p) *mb-d*)
			    done T))))
	     p))
    (command "_.move" s "" "_non" b "_non" p))
  (princ)
  )

Read the code. You might find more than it tells.

Message 3 of 9

Anonymous
Not applicable

Thank you so much for the quick response.  This fits the bill almost exactly.  It works perfectly after I enter the initial distance for the first time.  Is there any way to avoid having to enter this and just use automatically use the last moved distance?  I would always be using the regular move tool before using this 'repeating' lisp...so the distance doesn't need to be recalled or retained throughout multiple commands and tool changes etc.  Perhaps this means it may be easier to retrieve and use that previous distance..? (says the guy who can't write lisp to save himself).

 

Hopefully this is not too difficult to implement as I am already super grateful for what you've done.

 

Much appreciated.

0 Likes
Message 4 of 9

ВeekeeCZ
Consultant
Consultant

Not possible. Can't retrieve the distance from the original command. 

 

Unless you'll define your own MOVE command. Try this version. If it works for you, you can UNDEFINE/REDEFINE the original command. Then still, the original would be available with dot prefix.

 

(defun c:Move+ ( / s b)
  (and (setq s (ssget ":L"))
       (setq b (getpoint "\nSpecify base point: "))
       (not (command-s "_.move" s "" "_non" b))
       (setq *mb-d* (distance b (getvar 'lastpoint))))
  (princ)
  )

 

0 Likes
Message 5 of 9

CodeDing
Advisor
Advisor

@ВeekeeCZ wrote:

Not possible. Can't retrieve the distance from the original command. 


Well... That's not true. We can save the variable from the original command into a dictionary / xrecord and search for it when we call the command each time.

 

Clearly this wouldn't transfer between drawings. But it's still better than nothing.

 

Or maybe we could use a blackboard variable to transfer between drawings?

 

Best,

~DD

0 Likes
Message 6 of 9

Kent1Cooper
Consultant
Consultant

@CodeDing wrote:

@ВeekeeCZ wrote:

Not possible. Can't retrieve the distance from the original command. 


Well... That's not true. We can save the variable from the original command ....


Well... that is  true if I understand correctly what @ВeekeeCZ meant by it, and what I think @Anonymous  was describing -- saving the move displacement not from preceding use of this command, but from a preceding native MOVE command, to quote from Message 3:  "I would always be using the regular move tool before using this...."   I don't know of any way to save the displacement, or even just the distance regardless of direction, from that, i.e. there's no "variable" that holds that information.

Kent Cooper, AIA
0 Likes
Message 7 of 9

CodeDing
Advisor
Advisor

@Kent1Cooper wrote:

@CodeDing wrote:

@ВeekeeCZ wrote:

Not possible. Can't retrieve the distance from the original command. 


Well... That's not true. We can save the variable from the original command ....


Well... that is  true

"I would always be using the regular move tool before using this...."


^^ Whoops! I missed this! ^^

Well... That's not true.

Message 8 of 9

Sea-Haven
Mentor
Mentor

Was going to suggest (setenv 'dist but like before would need a seed value. 

 

A suggestion ML123 would move an object to the left 123 units, MU56 56 units up.

 

This can be done using a reactor when you type MLxxxx Autocad will return unknown command, but the error message can be checked so if 1st character is m then do sub routine.

 

I have Circle and Offset and Fillet done this way type C123 and it asks for centre point and draws a circle with radius 123. Decimal values supported.

 

I have attached code if someone wants to think about going that way. Maybe M0,100 as command this is a move y. I have an oldy done like 30 years ago CHY CHX as defuns, pick multiple objects. 

 

 

0 Likes
Message 9 of 9

BB8x
Advocate
Advocate
Accepted solution

Someone from this forum wrote this for me:

 

;; Mods by BeekeeCZ to honor the OSNAPZ setting
;; Added QuickMode2d to force OSNAPZ 1

;; QuickMOVE originaly written by CAB
;;  Version 1.2  -  02.11.2010
;;  No UCS support
;;  If set to Loop, Press ENTER or ESCape to exit.
;;  Use DXF 10 if it exist except for Hatch
;;  Else use Pick Point of LL of bounding box if flag is set
;;
;;  Note that the DXF code 10 my not be desirable on some objects
;;
;(defun c:p () (c:Quickmove))
(defun c:Quickmove (/ ent elst BasePt minpt maxpt Loop pkPoint NoDXF10)
  (setq loop t) ; set to nil to make routine not Loop
  (setq pkPoint nil) ; t = use pickpoint if no dxf 10
  ;; nil = use lower left of bounding box if no dxf 10
  (setq NoDXF10 '("HATCH" "LWPOLYLINE")) ; list to exclude use of DXF 10
  (command "._undo" "_begin")
  (while
    (and
      (setq ent (entsel "\nSelect object to move: "))
      (progn
	(setq BasePt (cadr ent)) ; default move point
	(setq elst (entget (car ent)))
	(if (and (assoc 10 elst)
		 (not (member (cdr(assoc 0 elst)) NoDXF10)))
	  (setq BasePt (cdr (assoc 10 elst)))
	  (if (not pkPoint)
	    (progn
	      (vla-getboundingbox (vlax-ename->vla-object (car ent)) 'minpt 'maxpt)
	      (and (setq minpt (vlax-safearray->list minpt))
		   (setq BasePt minpt)))))
	(command "._undo" "_mark")
	(if (= (getvar 'osnapz) 1) ; added by BeekeeCZ to honor OSNAPZ setting.
	  (setq BasePt (reverse (cdr (reverse BasePt)))))
	(command "._move" (car ent) "" "_non" BasePt pause)
	;;  Test for ENTER pressed ILO point picked
	(if (equal 0.0 (distance BasePt (getvar "lastpoint")) 0.0001)
	  (command "._undo" "_back") ; & exit
	  t))
      Loop))
  (princ)
  )

(defun c:p ( / *error* z)  ;; added by BeekeeCZ to force OSNAPZ to 1
  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
    (if z (setvar 'osnapz z))
    (princ))
  (setq z (getvar 'osnapz)) (setvar 'osnapz 1)
  (c:Quickmove)
  (*error* "end"))

Maybe will be useful for you
0 Likes