Scale object in one direction

Scale object in one direction

Lukasvop1
Advocate Advocate
5,456 Views
19 Replies
Message 1 of 20

Scale object in one direction

Lukasvop1
Advocate
Advocate

Hi guys, I would need to create a lisp that allows me scale object only in one direction (X/Y).

Only option I found in AutoCAD default, is create block and in properties change scale factor X, Y and after that explode block.

My idea is create tool similar like "Align" command but scale object only in one direction, not uniformly.
It would be great if lisp automatically recognized in which direction objects scale by selected reference points.

SCXY.png

Is possible create something like this?
Thank you.

 

@komondormrex

0 Likes
Accepted solutions (2)
5,457 Views
19 Replies
Replies (19)
Message 2 of 20

paullimapa
Mentor
Mentor
0 Likes
Message 3 of 20

Kent1Cooper
Consultant
Consultant

In addition to @paullimapa 's link, you will find a number of scale-in-one-direction routines with some Searching, but I believe all of them will do it by way of a temporary Block to change the scale factors of, and I don't know that any of them will do everything you want, particularly recognize which axis you want to scale by the points you pick.  But maybe....

 

But if you're starting with something at scale factors of 1, it's easy enough to just Scale it normally to get the size in the direction you want as you want it, and then in Properties just set the other axes' scale factors back to 1.

 

I hope you realize that in your example, after such a procedure [however you accomplish it], the widths of the vertical and horizontal frame members will no longer be equal, and the widths of the curved members [assuming you're curving a metal rod or something] will no longer be constant.

Kent Cooper, AIA
0 Likes
Message 4 of 20

Lukasvop1
Advocate
Advocate

I hope you realize that in your example, after such a procedure [however you accomplish it], the widths of the vertical and horizontal frame members will no longer be equal, and the widths of the curved members [assuming you're curving a metal rod or something] will no longer be constant.

 

I understand, in this case it is a part of railing around arc in perspective in elevation view. It's assumed that it will not be 100% accurate but best possible can be.

0 Likes
Message 5 of 20

Sea-Haven
Mentor
Mentor

Why not make it a block say 1000 x 1000 then its easy to scale in either X or Y. Or both. It looks like some of the line work is 2 lines so scaling will make bar diameters bigger or smaller, could draw from 1st principles using a lisp. Then bar dia is correct.

0 Likes
Message 6 of 20

Lukasvop1
Advocate
Advocate

Well it's not so easy. In this example I use it for scaling individual parts of railing around arc in perspective in elevation view. But vertical bars are scaling too but in different ratio than horizontally parts etc. It's quite dificuilt and time consuming do it acurrate in 2D. Cause of that I looking for lisp, that alows me quick scale selcted object in only one direction without manualy creating block before. I understand it won't be 100% accurate, but best ratio time/accurate.

 

SCXY_2.png

0 Likes
Message 7 of 20

Kent1Cooper
Consultant
Consultant

Model a segment of it in 3D.  Then set the UCS so you can do a polar Array of them, and the elements will all be the right size from all variable oblique angles they are viewed from.  You can leave it in 3D, or Flatten the completed arrangement into 2D if you want.

Kent Cooper, AIA
0 Likes
Message 8 of 20

Lukasvop1
Advocate
Advocate

I know model it in 3D is best solution (e.g. create in BIM in revit) , but in this case is more important do it fast nobody care if it will be accurate. It's not paid enough.

0 Likes
Message 9 of 20

Sea-Haven
Mentor
Mentor

If you draw an arc then can do facets that are the width of the frames then work out the X values x1-x2 so it will reveal the scale for you. An example attached can change to use chord distance say from center of arc.

 

SeaHaven_0-1703461083129.png

 

0 Likes
Message 10 of 20

komondormrex
Mentor
Mentor

hey there,

i think the better way is avoid whatever non-uniform scaling in favor of making sort of dynamic block with X, Y stretching (quicker) or developing a lisp code for drawing each instance of fence (slower).

Message 11 of 20

Lukasvop1
Advocate
Advocate

Well it's not about only fence, but all stuff whith aren't parallel with the elevation view, at some angle or around arc (doors, windows, roofs, stairs, ornaments on walls,..)
Cause of that I want lisp for quick scale lot of stuff individually.

 

I thought little bit more about that, and I got this :

SCXY_routine.png

0 Likes
Message 12 of 20

ВeekeeCZ
Consultant
Consultant
Accepted solution

 

 

 

 

(defun c:bscalex ( / e p1 p2 p3 p4 s cx cy bx by)
  
  (if (and (setq e (ssget "_:S" '((0 . "INSERT"))))
	   (setq e (ssname e 0))
	   (setq p1 (getpoint "\nLower-Left point: "))
	   (setq p2 (getpoint "\nUpper-Right point: "))
	   )

    (if (>= (setq bx (abs (- (car p1) (car p2)))) (setq by (abs (- (cadr p1) (cadr p2)))))

      (if (and (setq cx (getpropertyvalue e "ScaleFactors/X"))
	       (setq p3 (getpoint "\nLeft destination point: "))
	       )
	(while (setq p4 (getpoint p3 "\nRight destination point: "))
	  (command "_.copy" e "" "_non" p1 "_non" p3)
	  (setpropertyvalue (entlast) "ScaleFactors/X" (* cx (/ (abs (- (car p4) (car p3))) bx)))
	  (setq p3 p4)))

      (if (and (setq cy (getpropertyvalue e "ScaleFactors/Y"))
	       (setq p3 (getpoint "\nLower destination point: "))
	       )
	(while (setq p4 (getpoint p3 "\nUpper destination point: "))
	  (command "_.copy" e "" "_non" p1 "_non" p3)
	  (setpropertyvalue (entlast) "ScaleFactors/Y" (* cy (/ (abs (- (cadr p4) (cadr p3))) by)))
	  (setq p3 p4)))))

  (princ)
  )

 

Message 13 of 20

Lukasvop1
Advocate
Advocate

Nice work, this help a lot thank you. 

0 Likes
Message 14 of 20

Lukasvop1
Advocate
Advocate

I find a problem in Y direction, scale factor is right but don't proper align  , can you check it?
Thank you.

0 Likes
Message 15 of 20

Lukasvop1
Advocate
Advocate
0 Likes
Message 16 of 20

Kent1Cooper
Consultant
Consultant

@Lukasvop1 wrote:

I find a problem in Y direction, scale factor is right but don't proper align  , can you check it? ...


I'm guessing that has everything to do with where the insertion point is in the Block.  One of your images looks like it's at the top of the left post element.  It should be at some place on the Block that is on one of those green reference lines.

Kent Cooper, AIA
Message 17 of 20

ВeekeeCZ
Consultant
Consultant
Accepted solution

It seems you're right. I guess it needs to be rewritten to make the block on the fly with an insertion point where it is needed. Do not leave it up to the user. My bad. And perhaps make p1 and p2 points interchangeable, as the OP inadvertently demonstrated. I'll fix it at some point. thx.

 

 

 

Edit: Ok, here it is. Any objects can be selected, not just blocks. If both points are not orthogonal, the major one takes precedence.

 

(vl-load-com)

(defun c:scalexy ( / *error* s p1 p2 p3 p4 s cx cy bx by)
  
  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
    (if (tblsearch "BLOCK" "SCALEXYTEMPBLOCK")
      (command-s "_.-purge" "_blocks" "SCALEXYTEMPBLOCK" "_n"))
    (setvar 'cmdecho 1)
    (vla-endundomark doc)
    (princ))
  
  (defun :createblock (s p n)
    (and (or (not (tblsearch "BLOCK" n))
	     (command "_.-purge" "_blocks" n "_n")
	     (not (tblsearch "BLOCK" n))
	     (alert (strcat "\nError: Temporary block creation failed. \n'" n "' blockname is already in use.")))
	 (not (command "_.-block" n p s "" "_.oops"))
	 (tblsearch "BLOCK" n)))
  
  
  (if (and (setq s (ssget "_:L"))
	   (setq p1 (getpoint "\nMajor reference point: "))
	   (setq p2 (getpoint p1 "\nSecond reference point: "))
	   (not (vla-startundomark (setq doc (vla-get-activedocument (vlax-get-acad-object)))))
	   (setvar 'cmdecho 0)
	   )
    
    (if (>= (setq bx (abs (- (car p1) (car p2)))) (setq by (abs (- (cadr p1) (cadr p2)))))
      
      (if (and (setq pt (list (/ (+ (car p1) (car p2)) 2) (cadr p1) (last p1)))
	       (setq p3 (getpoint "\nMajor destination point: "))
	       (:createblock s pt "SCALEXYTEMPBLOCK")
	       )
	(while (setq p4 (getpoint p3 "\nSecond destination point: "))
	  (setq po (list (/ (+ (car p3) (car p4)) 2) (cadr p3) (last p3)))
	  (command "_.-insert" "SCALEXYTEMPBLOCK" "_s" 1 "_r" 0 "_non" po)
	  (setpropertyvalue (entlast) "ScaleFactors/X" (/ (abs (- (car p4) (car p3))) bx))
	  (command "_.explode" "_l")
	  (setq p3 p4)))
      
      (if (and (setq pt (list (car p1) (/ (+ (cadr p1) (cadr p2)) 2) (last p1)))
	       (setq p3 (getpoint "\nMajor destination point: "))
	       (:createblock s pt "SCALEXYTEMPBLOCK")
	       )
	(while (setq p4 (getpoint p3 "\nSecond destination point: "))
	  (setq po (list (car p3) (/ (+ (cadr p3) (cadr p4)) 2) (last p3)))
	  (command "_.-insert" "SCALEXYTEMPBLOCK" "_s" 1 "_r" 0 "_non" po)
	  (setpropertyvalue (entlast) "ScaleFactors/Y" (/ (abs (- (cadr p4) (cadr p3))) by))
	  (command "_.explode" "_l")
	  (setq p3 p4)))
      ))
  
  (*error* "end")
  (princ)
  )

 

0 Likes
Message 18 of 20

Lukasvop1
Advocate
Advocate

Sorry I didn't get notification you updated code. It seem's works perfect both directions, thank you.

0 Likes
Message 19 of 20

sander.van.pelt
Advocate
Advocate

Hello @ВeekeeCZ 


Very convenient lisp to use. But if I now have a block with attributes that I want to scale with this function, then these attributes also scale.
How could I avoid this?

Now I have found a lisp with which I can adjust attribute heights, but I cannot use this for multiple blocks at the same time and this is only for the height, not for the width. This must be done per block.
Any idea how I change this into multiple blocks and could adjust this so that my width always remains at 1 and I can adjust the attribute height to any desired height?

(defun c:ATH ( / obj ht atts)
(setq obj (vlax-ename->vla-object (car  (entsel "Pick block "))))
(setq ht (getreal "\nSpecify height: "))
(setq atts (vlax-invoke obj 'Getattributes))
(repeat (setq x (length atts))
(vlax-put (nth (setq x (1- x)) atts) 'height ht)
)
(princ)
)


 

0 Likes
Message 20 of 20

ВeekeeCZ
Consultant
Consultant

All atts height setting and width to 1.

 

(defun c:AttHeight ( / s a i e)
  
  (if (and (setq s (ssget '((0 . "INSERT") (66 . 1))))
	   (setq a (getreal "\nSpecify height: "))
	   )
    (repeat (setq i (sslength s))
      (setq e (ssname s (setq i (1- i))))
      (while (and (setq e (entnext e))
		  (= "Attribute" (getpropertyvalue e "LocalizedName")))
	(setpropertyvalue e "Height" a)
	(setpropertyvalue e "WidthFactor" 1))))
  (princ)
  )

 

0 Likes