Announcements

Starting in December, we will archive content from the community that is 10 years and older. This FAQ provides more information.

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

Move or copy objects in the X or Y direction with a specific distance.

15 REPLIES 15
SOLVED
Reply
Message 1 of 16
ancrayzy
1076 Views, 15 Replies

Move or copy objects in the X or Y direction with a specific distance.

I found this Lisp at www.cadtutor.net
https://www.cadtutor.net/forum/topic/66001-move-objects-specific-distance/

 

(defun c:up50 (/ ss)
  (if (setq ss (ssget "_:L-I"))
    (command "_.MOVE" ss "" "_non" '(0. 0.) "_non" '(0. 5000.))
  )
  (princ)
)

 

 

Is there any way to upgrade this lisp with the following features:

Step 1. Type the command: move/copy in X or Y direction
For example:
- Move in X direction: Move_X
- Move in Y direction: Move_Y
- Copy in X direction: Copy_X
- Copy in Y direction: Copy_Y

Step 2. Type the distance to move/copy (mm) and enter or enter to skip with default distance is 1000mm).

Step 3. Select objects -> enter to execute.

Step 4. When repeat the command, the distance entered in step 2 will be replaced the default distance (1000mm) for the next steps.

15 REPLIES 15
Message 2 of 16
Sea-Haven
in reply to: ancrayzy

Try this written like 30 years ago.

 

(defun C:CHX ()
  (SETVAR "CMDECHO" 0)
  (setq sn (getvar "osmode"))
  (command "osnap" "near")
  (setq x 0)
  (princ "\nalters object in X direction")
  (setq ht (getstring "\n What is amount of change: "))
  (setq newht (strcat ht ",0"))
  (while (= x 0)
    (setq newobj (entsel "\nPoint to object: "))
    (if (/= newobj nil)
    (progn
    (command "move" newobj "" "0,0" newht)
    ))
  (if (= newobj nil)(setq x 1))
  )
)
;
(defun C:CHY ()
  (SETVAR "CMDECHO" 0)
  (setq sn (getvar "osmode"))
  (command "osnap" "near")
  (setq x 0)
  (princ "alters object in Y direction")
  (setq ht (getstring "\n What is amount of change: "))
  (setq newht (strcat  "0," ht))
  (while (= x 0)
  (SETQ NEWobj (entsel "\nPoint to object: "))
  (if (/= newobj nil)
  (progn
  (command "move" newobj "" "0,0" newht)
  ))
  (if (= newobj nil)(setq x 1))
  )
  )
Message 3 of 16
ancrayzy
in reply to: Sea-Haven

Thanks Sea-Haven,
Is there a way to modify this lisp so that the "Point to object" section becomes "Select objects" (Drag to select multiple objects at the same time). And add copy function instead of just move.

Message 4 of 16
ancrayzy
in reply to: Sea-Haven

Thank for your code @Sea-Haven.

I use AI to modify your code to create the lisp which I need and share it with anyone who needs it as below.

But if anyone has any other and more optimal ideas, please still share them with us

 

;;;; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/move-or-copy-objects-in-the-x-or-y-direction-with-a-specific/td-p/12690641

(defun C:CHY ( / sn ht newobj)
  (SETVAR "CMDECHO" 0)
  (setq sn (getvar "osmode"))
  (command "osnap" "near")
  (princ "alters object in Y direction")
  (setq ht (getstring "\n What is the amount of change: "))
  (setq newht (strcat "0," ht))
  (while (setq newobj (ssget '((0 . "*")))) ; Select objects
    (command "copy" newobj "" "0,0" newht) ; Copy objects
  )
  (setvar 'osmode sn)
  (princ)
)

(defun C:CHX ( / sn ht newobj)
  (SETVAR "CMDECHO" 0)
  (setq sn (getvar "osmode"))
  (command "osnap" "near")
  (princ "\nalters object in X direction")
  (setq ht (getstring "\n What is the amount of change: "))
  (setq newht (strcat ht ",0"))
  (while (setq newobj (ssget '((0 . "*")))) ; Select objects
    (command "copy" newobj "" "0,0" newht) ; Copy objects
  )
  (setvar 'osmode sn)
  (princ)
)

(defun C:MHY ( / sn ht newobj)
  (SETVAR "CMDECHO" 0)
  (setq sn (getvar "osmode"))
  (command "osnap" "near")
  (princ "alters object in Y direction")
  (setq ht (getstring "\n What is the amount of change: "))
  (setq newht (strcat "0," ht))
  (while (setq newobj (ssget '((0 . "*")))) ; Select objects
    (command "move" newobj "" "0,0" newht) ; Move objects
  )
  (setvar 'osmode sn)
  (princ)
)

(defun C:MHX ( / sn ht newobj)
  (SETVAR "CMDECHO" 0)
  (setq sn (getvar "osmode"))
  (command "osnap" "near")
  (princ "\nalters object in X direction")
  (setq ht (getstring "\n What is the amount of change: "))
  (setq newht (strcat ht ",0"))
  (while (setq newobj (ssget '((0 . "*")))) ; Select objects
    (command "move" newobj "" "0,0" newht) ; Move objects
  )
  (setvar 'osmode sn)
  (princ)
)

 

Message 5 of 16
paullimapa
in reply to: ancrayzy

Seems like you're still missing this step in your code:

Step 4. When repeat the command, the distance entered in step 2 will be replaced the default distance (1000mm) for the next steps.

Also I noticed AI chose to use this line of code for ssget:

(ssget '((0 . "*")))

Since you're not filtering out any objects but you want to select all kinds of objects, there's no need to indicate a wildcard but instead you can just use this:

(ssget)

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 6 of 16
TomBeauford
in reply to: ancrayzy

With ORTHO on use either MOVE or COPY with the cursor locked in whatever X or Y direction you want and enter the distance. Whatever distance you enter will be the default the next time so if you're using the same distance just hit enter.

64bit AutoCAD Map & Civil 3D 2023
Architecture Engineering & Construction Collection
2023
Windows 10 Dell i7-12850HX 2.1 Ghz 12GB NVIDIA RTX A3000 12GB Graphics Adapter
Message 7 of 16
ancrayzy
in reply to: paullimapa

Your are right@paullimapa ,

It's okay to solve my problem for now. But it would be great if this lisp was added section at Step 4

(When repeat the command, the distance entered in step 2 will be replaced the default distance (1000mm) for the next steps).

Message 8 of 16
paullimapa
in reply to: ancrayzy

Setup a global variable and include this in the statement to enter the new change value...

Here's the changed code on one of the routines...you should be able to implement on the others:

(defun C:CHY ( / sn ht newobj)
  (SETVAR "CMDECHO" 0)
  (setq sn (getvar "osmode"))
  (command "osnap" "near")
  (princ "alters object in Y direction")
;  (setq ht (getstring "\n What is the amount of change: "))
;  (setq newht (strcat "0," ht))
  (if(not *ht*)(setq *ht* 1000)) ; setup global variable
  (setq ht (getdist (strcat"\nWhat is the amount of change <" (rtos *ht* 2 0) ">: "))) ; getdist can enter & point distance on screen
  (if(not ht)(setq ht *ht*)(setq ht (fix ht) *ht* ht)) ; 0 decimal precision
  (setq newht (strcat "0," (itoa ht))) ; convert integer to string
  (while (setq newobj (ssget)) ; Select objects
    (command "copy" newobj "" "0,0" newht) ; Copy objects
  )
  (setvar 'osmode sn)
  (princ)
)

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 9 of 16
ancrayzy
in reply to: paullimapa

It's perfect, thanks you Mr @paullimapa 

Message 10 of 16
paullimapa
in reply to: ancrayzy

glad to have helped...cheers!!!


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 11 of 16
Sea-Haven
in reply to: ancrayzy

 My take on task with updated input dcl entry.

 

 

(defun C:CHY ( / sn  newobj)
  (SETVAR "CMDECHO" 0)
  (setq sn (getvar "osmode"))
  (setvar 'osmode 512)
  (if (not AH:getvalsm)(load "Multi Getvals.lsp"))
  (if (not *ht*)(setq *ht* 1000.0))
  (setq *ht* (atof (car (AH:getvalsm (list "Enter value " "Y dist " 7 6 (rtos *ht* 2 1))))))
(princ "\nPress Enter after selecting objects ")
    (while (setq newobj (ssget))
    (command "copy" newobj "" "0,0" (list 0 *ht*))
(princ "\nSelect objects or press Enter to exit ")
    )
  (setvar 'osmode sn)
  (princ)
)

 

 

SeaHaven_0-1712639718363.png

 

Message 12 of 16
ancrayzy
in reply to: Sea-Haven

Thank you @Sea-Haven 

I saved your code as CHY.lsp

I successfully loaded lisp CHY.lsp

But when loading the Multi GETVALS.lsp file, it gives the following error as below:

Command: CHY ; error: LOAD failed: "Multi Getvals.lsp"
APPLOAD Multi GETVALS.lsp successfully loaded.
Command: ; error: extra right paren on input

 

Message 13 of 16
Sea-Haven
in reply to: ancrayzy

Ok I have a few copies of the program and may have pasted an incorrect one try this one. I sometimes edit to suit a particular requirement.

 

 

Message 14 of 16
ancrayzy
in reply to: Sea-Haven

It works perfectly, thank you so much !
Message 15 of 16
Kent1Cooper
in reply to: ancrayzy

Here's a way to do it in which:

1.  A single default distance is available in all commands -- if you want to go left by a distance you just went right, so the default is positive X, you don't need to re-enter the same distance with a preceding minus sign, but can just use the leftward command and the same default distance.

2.  You don't even need to know that X values are in the left-right direction and Y in the up-down directions, nor which way is positive and which negative in each direction -- it uses [abbreviations for] Up/Down/Left/Right as directions you want to Move or Copy things.

3.  They work with pre-selection [noun-verb mode] if there is one; otherwise they ask you to select objects.

4.  The "heavy lifting" is spelled out only once, instead of most of it repeatedly within multiple command definitions.  The different commands just feed a couple of arguments to the one sub-routine.

5.  [I don't see any reason it should be restricted to whole-number values -- these accept decimals, fractions, feet-and-inches.]

 

(defun MorCO (MorC dir / dirs ss) ; = Move or Copy Orthogonally
  (initget 2); no zero
  (setq
    dirs '((0.5 "up") (1.5 "down") (1 "left") (0 "right")); directions as multiples of pi
    *MorCdisp* ; global variable [Move or Copy displacement, in drawing units]
    (cond
      ( (getdist
          (strcat
            "\nDistance to " MorC " object(s) " (cadr (assoc dir dirs)) " <"
            (rtos (cond (*MorCdisp*) (100))); in current mode/precision <--EDIT desired initial default
            ">: "
          ); strcat
        ); getdist
      ); User-entry condition
      (*MorCdisp*); prior value if present, on Enter
      (100); default on Enter at first use <--EDIT desired initial default
    ); cond
  ); setq
  (cond
    ((setq ss (ssget "_:L-I")); pre-selection of object(s) not on locked Layer(s)
      (sssetfirst nil); un-select [now in ss variable]
    ); pre-selection condition
    ((setq ss (ssget "_:L"))); no pre-selection -- ask User
  ); cond
  (command (strcat "_." MorC) ss "" "_displacement" (polar '(0 0) (* pi dir) *MorCdisp*))
  (prin1)
)

(defun C:MMU () (MorCO "Move" 0.5)); = Move Up

(defun C:MMD () (MorCO "Move" 1.5)); = Move Down

(defun C:MML () (MorCO "Move" 1)); = Move Left

(defun C:MMR () (MorCO "Move" 0)); = Move Right

(defun C:CCU () (MorCO "Copy" 0.5)); = Copy Up

(defun C:CCD () (MorCO "Copy" 1.5)); = Copy Down

(defun C:CCL () (MorCO "Copy" 1)); = Copy Left

(defun C:CCR () (MorCO "Copy" 0)); = Copy Right

 

I used command names with double M's or C's before the directional letters, because ML is already AutoCAD's default command alias for MLINE, and I use CL and CR for other things.  But you can use whatever command names make sense for you.

Kent Cooper, AIA
Message 16 of 16
ancrayzy
in reply to: Kent1Cooper

Thank you for your very detailed explanation.

I tried your new lisp above. It does not keep the last distance entered previously corresponding to each command but uses the last distance entered by the user enter as previous code you shared which use with Multi GETVALS.lsp

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

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report