Move in x or y only issue

Move in x or y only issue

bh111DJVGK
Contributor Contributor
888 Views
11 Replies
Message 1 of 12

Move in x or y only issue

bh111DJVGK
Contributor
Contributor

I've been using several Lisp macros for well over a decade to move or copy in a chosen x, y, or z direction only. Recently, the X copy and X move ones have not been functioning consistently. I'm posting for two reasons. First, is there a better way to snap only in a particular direction, and/or, second, is there a better macro out there for my needs? 

 

I personally don't often use the extended autosnap tools or dynamic input that allow you work only in one direction, etc., simply because I have all the transparent snaps (and select macros and symbols) programmed into my keyboard (i.e., a embedded function call in a single key stroke that enters a series of keystrokes: "_from + enter", "end + enter", ".xy + enter", "_m2p + enter", "\u+2205", etc.). Many of my work collogues over the years have asked if I could show them how to use these functions after watching me work, and I've learned to defer to our firms CAD manager, who, I know, will simply remind them of the firms "no third party macros" and tell them to be a good boy or girl and get back to work (they stopped cleaning out my personal macros years ago after I successfully argued that the uninstalling and reinstalling of my macros just wasted the company money, or else they should just fire me...). While I myself will watch my colleagues work intuitively with the improved selection tools AutoCAD has offered over the years, and think, maybe I should learn to use those better. That is, say, until I'm watching someone trying desperately to snap to a particular line, and you remind them they can just enter "per" and it will stop grabbing the d*mn end of the vector... Often it's so much better to have instantaneous old-fashion simple absolute control.

 

The directional move and copy macros all work just fine when you enter a distance and the error only happens when you pick a second point. 

 

Here's the error that comes up with the CopyX macro:

Command: cx
CopyX
Select objects: 1 found
Select objects:
Base X point of copy <(0)> end
of end
of ; error: bad argument type: lselsetp nil
Command: Specify opposite corner or [Fence/WPolygon/CPolygon]:

 

Here's the Lisp program:

; CX -- CopyX.lsp -- Copies objects in xy direction only -------------

;function to save system variable settings----------------------------------
(defun GETMODE (mod1)
(setq *mod2 '()) ;create global variable to store settings
(repeat (length mod1) ;find length of variable list and repeat
(setq *mod2 ;build *mod2 list
(append *mod2
(list (list (car mod1) (getvar (car mod1))))
)
)
(setq mod1 (cdr mod1)) ;go to next element in list
);end repeat
)

;function to restore system variable settings-------------------------------
(defun SETMODE (mod1)
(repeat (length mod1) ;find length of list and repeat
(setvar (caar mod1) (cadar mod1)) ;extract setting info and reset
(setq mod1 (cdr mod1)) ;go to next element in list
);end repeat
)

;function for error trap ---------------------------------------------------
(defun *error* (msg)
(setmode *mod2) ;reset system variables
(princ msg) ;print error message
(princ)
)

;CXY -- primary function--------------------------

(defun c:CX (/
Oblist ;list of objects
Y Z ;x & z coordinates for appending filter list
Ex-Xpt ;global variable for old elevation
;*New-Xpt global variable for new elevation
New-Xpt-Tmp ;temporary assingnment of *New-Xpt for selction
Ex-Xpt-Tmp ;temporary assingnment of Ex-Xpt for selction
Ex-X ;y component of Ex-Xpt
Ex-Y ;y component of Ex-Xpt
Ex-Z ;y component of Ex-Xpt
New-X ;y component of *New-Xpt
New-Y ;y component of *New-Xpt
New-Z ;y component of *New-Xpt
TstX
)

(getmode '("osmode" "orthomode" "cmdecho")) ;saves system var.
(mapcar 'setvar '("osmode" "orthomode" "cmdecho") ;set var for funct.
'(0 0 0 )
)
(princ "\nCopyX")
(setq ObList (ssget))
(setq Y (list 0))
(setq Z (list 0))
(setq Ex-Xpt (list 0))
(setq Ex-Xpt-Tmp (list 0))
(if (or (= *New-Xpt nil) (= (type *New-Xpt) 'STR))
(setq *New-Xpt (list 0))
)
(setq TstY nil)
(princ "\nBase X point of copy <")
(princ Ex-Xpt)
(princ "> ")
(initget 128)
(setq Ex-Xpt (getpoint))
(if (= Ex-Xpt nil)
(setq Ex-Xpt Ex-Xpt-Tmp)
)
(if (= (type Ex-Xpt) 'STR)
(setq Ex-X (distof (car Ex-Xpt) 4))
(progn
(setq Ex-X (car Ex-Xpt))
(setq Ex-Y (cadr Ex-Xpt))
(setq Ex-Z (caddr Ex-Xpt))
)
)
(if (= Ex-Y nil)
(setq TstY "Yes")
)
(if (= TstY "Yes")
(progn
(setq Ex-Xpt (list 0 0 0))
(setq New-Xpt-Tmp *New-Xpt)
(setq New-X (car *New-Xpt))
(princ "\nEnter new X component of displacement <")
(princ *New-Xpt)
(princ "> ")
(initget 128)
(setq *New-Xpt (getpoint))
(if (= (type *New-Xpt) 'STR)
(progn
(setq New-X (distof *New-Xpt 4))

(setq *New-Xpt (append (list New-X) Y Z))
)
)
(if (= *New-Xpt nil)
(setq *New-Xpt New-Xpt-Tmp)
)
(command "copy" ObList "" Ex-Xpt *New-Xpt)
) ;end progn
) ;end TstY if
(if (/= TstY "Yes")
(progn
(setq ent (entlast))
(command "copy" ObList "" Ex-Xpt pause)
(setq Tmp-Xpt (getvar "lastpoint"))
(setq New-X (car Tmp-Xpt))
(setq New-Y (cadr Tmp-Xpt))
(setq *New-Xpt (append (list New-X) (list Ex-Y) (list Ex-Z)))
(setvar "osmode" 0)
(setq Oblist (ssadd))
(while (setq ent (entnext ent))
(if ent
(setq Oblist (ssadd ent Oblist))
)
)

(command "move" ObList "" Tmp-Xpt *New-Xpt)
) ;end progn
) ;end TstY if
(setq *New-Xpt (append (list (- New-X Ex-X)) Y Z))
(princ "Copy done")
(setmode *mod2)
(princ)
) ; end CX.lsp

0 Likes
889 Views
11 Replies
Replies (11)
Message 2 of 12

Sea-Haven
Mentor
Mentor

Hmmm ; CX -- CopyX.lsp -- Copies objects in xy direction only -

the no code option

Ortho on F8

cp

click object drag mouse for direction

type distance

 

similar for move.

 

I wrote like 30 years ago chx chy chz

(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))
  )
  )


;simple routine to change objects in the z direction
(defun C:CHZ ()
  (SETVAR "CMDECHO" 0)
  (setq sn (getvar "osmode"))
  (command "osnap" "near")
  (setq x 0)
  (princ "alters object in Z direction")
  (setq ht (getstring "\n What is amount of change: "))
  (setq newht (strcat "0,0," ht))
  (while (= x 0)
  (SETQ NEWobj (entsel "\nPoint to object: "))
  (if (/= newobj nil)
  (progn
  (command "move" newobj "" "0,0,0" newht)
  ))
  (if (= newobj nil)(setq x 1))
  )
  )

 

A third for say move is L123 R23.34 U45 D67.87 it uses a reactor and pulls apart the left right etc and the distance. Just type any distance as part of command.

 

Another would be to select object enter distance as L123 or R23.34 or U45 or D67.87. 

Another would be to select object enter distance, then press a arrow for direction, this one I know method exists but I would have to find.

0 Likes
Message 3 of 12

bh111DJVGK
Contributor
Contributor

Thanks for the reply Haven.

Forget distances - I do the F8 and type the distance to move objects all the time. I mentioned typing distance to show that the program is still working if you enter a distance, but it's not working consistently if you move by picking points.

 

Here's what it looks like when it works - worked perfectly previously. Restarting AutoCAD does not help either.

 

Command: my
MoveY
Select objects: 1 found
Select objects:
Base Y point of displacement <(0)> end
of *-end
of **-New-Y =674.455Ex-Y =857.954***-Delta Y =(0 -183.499 0)move done

 

This MoveY version of the program is a four step process (as is the copy version):

1. enter command 

2. pick objects

3. pick start point

4. pick end point

Done

 

I use these functions constantly - I would imagine all users do must do some version of the same thing. Everyone I've asked so far at work says they use "from" - and when they show me how they use it, it requires extra commands and picks. One of the reason I wrote my keyboard shortcut description in my original post was that I was trying to describe that I'm constantly attempting to eliminate keystrokes and use mostly shortcuts - it's the beauty of AutoCAD that you can customize it. When I see people picking icons or using the ribbon to execute commands, I sometimes wonder how they get anything done. 

 

So, here's a question: Say, you have some text, you want to move it from the end of a leader arrow to be even with a point that is approximately 50' below in the Y direction but the point is 1000' to the X direction.  How do you most efficiently move it only in the Y direction? 

 


@Sea-Haven wrote:

 

A third for say move is L123 R23.34 U45 D67.87 it uses a reactor and pulls apart the left right etc and the distance. Just type any distance as part of command.

 

Another would be to select object enter distance as L123 or R23.34 or U45 or D67.87. 


Not sure what this describes - can you direct me to a tutorial?

 

0 Likes
Message 4 of 12

ВeekeeCZ
Consultant
Consultant

First - FIX your *error* function!, *error* HAS TO be localized! You also should localize all the other functions.

 

Then, unfortunately, can't help. It's working flawlessly at my end.

 

Command: CX

CopyX
Select objects: 1 found

Select objects:

Base X point of copy <(0)> end of end of Copy done

 

Try something simple, as PICKFIRST... or something like that.

 

0 Likes
Message 5 of 12

CADaSchtroumpf
Advisor
Advisor

And combine the 3 functions into one?

For instance

 

(defun c:C_xyz ( / acadObj doc modelSpace js mod delta x y z pt1 pt2 n obj copyObj)
  (princ "\nSelect objects: ")
  (setq js (ssget))
  (cond
    (js
      (setq
        acadObj (vlax-get-acad-object)
        doc (vla-get-ActiveDocument acadObj)
        modelSpace (vla-get-ModelSpace doc)
      )
      (if (not (member (getvar "USERS1") '("X" "Y" "Z"))) (setvar "USERS1" "X"))
      (initget "X Y Z")
      (setq mod (getkword (strcat "\nDisplacement of the copy to [X/Y/Z]? <" (getvar "USERS1") ">: ")))
      (if (not mod)
        (setq mod (getvar "USERS1"))
        (setvar "USERS1" mod)
      )
      (initget 33)
      (setq delta (getdist "\nDistance of displacement?: "))
      (cond
        ((eq mod "X") (setq x delta y 0 z 0))
        ((eq mod "Y") (setq x 0 y delta z 0))
        ((eq mod "Z") (setq x 0 y 0 z delta))
      )
      (setq
        pt1 (vlax-3d-point 0 0 0)
        pt2 (vlax-3d-point x y z)
      )
      (repeat (setq n (sslength js))
        (setq
          obj (vlax-ename->vla-object (ssname js (setq n (1- n))))
          copyObj (vla-Copy obj)
        )
        (vla-Move copyObj pt1 pt2)
      )
    )
  )
  (prin1)
)

 

0 Likes
Message 6 of 12

bh111DJVGK
Contributor
Contributor

@CADaSchtroumpf wrote:

And combine the 3 functions into one?

For instance


Thanks Schtoumpf, that works almost perfectly.

It only moves in the positive direction, however. 

I'm not a programmer (my original post was an attempt to find a simple equivalent to what I've been doing for years, whether that involved a standard AutoCAD command I was not aware existed, or a better macro - the forum moderator must have moved this post here because it contained code), so I don't know how to fix that or make it work with only four actions like the previous program. 

 

These modifications simplify it to be equivalent to what I have now: 

(defun c:CX ( / acadObj doc modelSpace js mod delta x y z pt1 pt2 n obj copyObj)
(princ "\nSelect objects: ")
(setq js (ssget))
(cond
(js
(setq
acadObj (vlax-get-acad-object)
doc (vla-get-ActiveDocument acadObj)
modelSpace (vla-get-ModelSpace doc)
)
(if (not (member (getvar "USERS1") '("X" "Y" "Z"))) (setvar "USERS1" "X"))
(initget "X Y Z")
;(setq mod (getkword (strcat "\nDisplacement of the copy to [X/Y/Z]? <" (getvar "USERS1") ">: ")))
(if (not mod)
(setq mod (getvar "USERS1"))
(setvar "USERS1" mod)
)
(initget 33)
(setq delta (getdist "\nDistance of displacement?: "))
(cond

;I switched the Y and X
((eq mod "Y") (setq x delta y 0 z 0))
((eq mod "X") (setq x 0 y delta z 0))
((eq mod "Z") (setq x 0 y 0 z delta))
)
(setq
pt1 (vlax-3d-point 0 0 0)
pt2 (vlax-3d-point x y z)
)
(repeat (setq n (sslength js))
(setq
obj (vlax-ename->vla-object (ssname js (setq n (1- n))))
copyObj (vla-Copy obj)
)
(vla-Move copyObj pt1 pt2)
)
)
)
(prin1)
)

0 Likes
Message 7 of 12

CADaSchtroumpf
Advisor
Advisor


It only moves in the positive direction, however. 

If you use (getdist) providing the distance with two points clicked successively; the distance will always be positive, but nothing prevents you from providing a negative real to make a negative displacement

0 Likes
Message 8 of 12

Sea-Haven
Mentor
Mentor

Just a little confused about result when you talk about pick second point and it has different X Y required. Or is it confirm what value you want say X diff = 1015.45 when you want 1000, same for Y check diff. 

 

1. enter command 

2. pick objects

3. pick start point

4. pick end point

Done

 

I dont know how you can get around start pt end pt. If your happy with get say a central point of objects as start pt this is solved by Lee-mac bounding box multiple objects then just pick second pt and confirm X Y.

SeaHaven_0-1655259234010.png

 

 

0 Likes
Message 9 of 12

ВeekeeCZ
Consultant
Consultant

I do like this simple version. Nice orthogonal preview...

 

(defun c:cx ( / s)
  (if (setq s (ssget "_:L"))
    (command "_.copy" s "" pause ".y" "@" pause))
  (princ)
  )

 

Possibly .yz if you wish. 

0 Likes
Message 10 of 12

matthewobrn
Enthusiast
Enthusiast

I used to struggle with moving in X, Y, or Z only and then I discovered the "." command when moving or copying.

 

I it a little confusing to use at the start but once you get your head around the queries it works on move or copy on all or any axis'.

 

Simply enter the move or copy command and select the first snap point.

The enter ".x (Enter)" the next point you click will be locked to the X coordinate only.

Autocad will then query you for the remaining "yz" coordinates.

You can select another point on screen or simply type "0 (Enter)"

 

This works on any and all coordinates.

 

I created a small screen share to show it working.

 

I hope this helps make modelling a bit simpler.

Message 11 of 12

ВeekeeCZ
Consultant
Consultant

@matthewobrn wrote:

I used to struggle with moving in X, Y, or Z only and then I discovered the "." command when moving or copying.

 

I it a little confusing to use at the start but once you get your head around the queries it works on move or copy on all or any axis'.

 

Simply enter the move or copy command and select the first snap point.

The enter ".x (Enter)" the next point you click will be locked to the X coordinate only.

Autocad will then query you for the remaining "yz" coordinates.

You can select another point on screen or simply type "0 (Enter)"

 

This works on any and all coordinates.

 

I created a small screen share to show it working.

 

I hope this helps make modelling a bit simpler.


 

If you want to save some strokes, use the routine that I posted just 2 mins ago. The exact same workflow... 🙂 . hmm or at least the similar idea.

0 Likes
Message 12 of 12

bh111DJVGK
Contributor
Contributor

A follow up on how I resolved the coding glitch - I noticed that there were several lines of code that were different in the Copy Y from the Copy X. I switched out the lines from the program, replaced x, y, and z as needed, and it has worked ever since. I've been using the X Y and Z routines for over 20 years, but, like with this one, every once and a while with a new AutoCAD upgrade, some older routine will stop working. 

 

BeekeeCZ, thanks for the suggestion - makes perfect sense. I still like to have the option of entering numbers too (old habits die hard) and one routine that does it all.