Scale lisp for Blocks in X-Axes

Scale lisp for Blocks in X-Axes

Garga
Contributor Contributor
3,443 Views
16 Replies
Message 1 of 17

Scale lisp for Blocks in X-Axes

Garga
Contributor
Contributor

Hi
I search for a Lisp, which can scale Blocks on X-Axes and keep the ratio.
For instace:  I have blocks with the size with (x-Axes) / height-y    1x2     2x3   4x6  3x9 I want select them all and set x-Axes to 2.5  all the blocks should have the same with but the height should should keep his ratio and should scaled automaticly

0 Likes
Accepted solutions (2)
3,444 Views
16 Replies
Replies (16)
Message 2 of 17

Kent1Cooper
Consultant
Consultant

With their insertion points remaining where they are?  If so, it would involve a simple SCALE command [which will preserve the X-Y ratio], with the insertion point as the base, and a scale factor of 2.5 ÷ the current X scale factor.  Does that sound like what you want?

Kent Cooper, AIA
0 Likes
Message 3 of 17

Garga
Contributor
Contributor

I attached a test.dwg file. Is there any lisp which can scale all blocks in X axes but keep the ratio of all blocks?

0 Likes
Message 4 of 17

ВeekeeCZ
Consultant
Consultant

Not attached.

0 Likes
Message 5 of 17

Garga
Contributor
Contributor
I have corrected it thanks
0 Likes
Message 6 of 17

ВeekeeCZ
Consultant
Consultant

How the routine will recognize which ratio of  1x2, 2x3, 4x6, 3x9 should be used?

 

0 Likes
Message 7 of 17

Garga
Contributor
Contributor

in CSS  you can say  X-value = number  y-value= % 

so if I have 5 rectangels  as blocks with different x/y numbers, is it not possible in the lisp to say  x= 1,5  but y =%  ?

0 Likes
Message 8 of 17

ВeekeeCZ
Consultant
Consultant

We can set anything. 

If you select 5 blocks, the user specifies ratio y/x to 1.5 then the routine would read the current X-scale and changes Y-scale to 1.5*X-scale. But it would be upon the user to tell the ratio...

 

I must amid that I don't understand your dwg at all. Would you do some more clear example? States before and after.

0 Likes
Message 9 of 17

Garga
Contributor
Contributor

Ok I have explaind it more detailed.

 

0 Likes
Message 10 of 17

ВeekeeCZ
Consultant
Consultant

So you want to scale all selected blocks to match the given x-length? 

0 Likes
Message 11 of 17

Garga
Contributor
Contributor
yes 🙂
0 Likes
Message 12 of 17

ВeekeeCZ
Consultant
Consultant

Try this one. You need to select blocks one by one.

 

(vl-load-com)

(defun c:BScaleToX ( / s d i e l r ur lf)

  (if (setq d (getdist "\nSpecify X-distance: "))
    (while (setq en (nentsel "\nSelect decisive horizontal entity of block: "))
      (if (not (vl-catch-all-error-p (vl-catch-all-apply 'vla-getboundingbox (list (vlax-ename->vla-object (car en)) 'll 'ur))))
	(progn
	  (setq e (car (last en))
		l (- (car (vlax-safearray->list ur))
		     (car (vlax-safearray->list ll)))
		r (/ d (* l (getpropertyvalue e "ScaleFactors/X"))))
	  (setpropertyvalue e "ScaleFactors/X" (* r (getpropertyvalue e "ScaleFactors/X")))
	  (setpropertyvalue e "ScaleFactors/Y" (* r (getpropertyvalue e "ScaleFactors/Y")))))))
  (princ)
  )
0 Likes
Message 13 of 17

Kent1Cooper
Consultant
Consultant
Accepted solution

With a BIG PROVISO [see below], try this, which uses a different approach [just a Scale command, which means there's no need to calculate what the new XY scale factors should be, and if there's a Z component, also changes that accordingly], and also lets you select as many as you want at once, not one at a time:

(defun C:SBXS ; = Scale Blocks to same X-direction Size
  (/ xs2 ss n blk xs1)
  (if
    (and
      (setq xs2 (getdist "\nSize in X direction <exit>: "))
      (setq ss (ssget '((0 . "INSERT"))))
    ); and
    (repeat (setq n (sslength ss)); then
      (setq blk (ssname ss (setq n (1- n))))
      (vla-getboundingbox (vlax-ename->vla-object blk) 'minpt 'maxpt)
      (setq xs1 (- (car (vlax-safearray->list maxpt)) (car (vlax-safearray->list minpt))))
      (command "_.scale" blk "" "_non" (cdr (assoc 10 (entget blk))) (/ xs2 xs1))
    ); repeat
  ); if
  (princ)
); defun

The BIG PROVISO is that you need to do something about your Block definitions.  Both @ВeekeeCZ 's suggestion and mine depend on the bounding boxes of the Blocks.  But those are wacky, much larger than the drawn content of the Blocks [hugely larger in some cases].  Here are some of them with their [white] bounding boxes drawn around them and the bounding boxes all the same width [I used the routine to scale them for that same width, and another routine I have to draw the bounding boxes around the results]:

Kent1Cooper_0-1613739728003.png

The second and fourth are some of your green arrow things [almost invisibly small in the middle], and the third is the thing with the two yellow triangles [the actual content is invisibly small down along the bottom edge].

I haven't dug in to figure out why their bounding boxes are so much bigger than they themselves are, but you'll need to fix that for either of our routines to work as you expect.

Kent Cooper, AIA
Message 14 of 17

ВeekeeCZ
Consultant
Consultant

Fixed the issue if a block has a nested block. Also little bit enhanced.

 

(vl-load-com)

(defun c:BScaleToX ( / s i e l r ur lf)

  (or *bstx-d* (setq *bstx-d* 1))

  (if (setq *bstx-d* (cond ((getdist (strcat "\nSpecify X-distance <" (rtos *bstx-d*) ">: ")))
			   (*bstx-d*)))
    (while (setq en (nentsel "\nSelect decisive horizontal entity of block: "))
      (if (not (vl-catch-all-error-p (vl-catch-all-apply 'vla-getboundingbox (list (vlax-ename->vla-object (car en)) 'll 'ur))))
	(progn
	  (setq e (last (last en))
		l (- (car (vlax-safearray->list ur))
		     (car (vlax-safearray->list ll)))
		r (/ *bstx-d* (* l (getpropertyvalue e "ScaleFactors/X"))))
	  (setpropertyvalue e "ScaleFactors/X" (* r (getpropertyvalue e "ScaleFactors/X")))
	  (setpropertyvalue e "ScaleFactors/Y" (* r (getpropertyvalue e "ScaleFactors/Y")))))))
  (princ)
  )

 

0 Likes
Message 15 of 17

pbejse
Mentor
Mentor
Accepted solution

@Garga wrote:

Ok I have explaind it more detailed.

 


 

(defun c:SithLord ( / acBlocks _HowBigAmI d ss e xy factor)
(setq acBlocks (vla-get-blocks (vla-get-ActiveDocument (vlax-get-acad-object))))
(Defun _HowBigAmI (adb bn / pts)	;<--- excluding none visible objects
	(vlax-for obj (vla-item adb bn)
		  (if (and
			(not (vl-catch-all-error-p
				(vl-catch-all-apply
				  'vla-getboundingbox (list obj 'll 'ur )))
				)
			(not (member (vla-get-ObjectName obj)
				     '("AcDbAttribute" "AcDbMText"	;<-- exclusding objects 
				       "AcDbText" "AcDbHatch")))	
			(minusp (vlax-get obj 'Visible)))		;<-- excluding none visible objects
		     (setq pts (cons (mapcar 'car (mapcar 'vlax-safearray->list
					 (list ll ur) )) pts))
		    )
		  )
	      (list bn (apply '- (mapcar '(lambda (q r) (apply q (mapcar r pts)))
					 '(max min) '(cadr car) ))
		    )
	      )  
(setq d (cond
    ((getdist (strcat "\nSpecify X-distance: <"
		      (rtos (setq d (cond ( d ) ( 1.00 ))))
          ">: " )))
    ( d )
  )
)
 (if (Setq ss (ssget "_:L" '((0 . "INSERT"))))
(repeat (setq i (sslength ss))
      (setq e (vlax-ename->vla-object (ssname ss (setq i (1- i))))
	    xy (mapcar '(lambda (s)(vlax-get e s))
		       '("XScaleFactor" "YScaleFactor")))
	(setq factor 
	      (if (setq f (assoc (setq fn (vla-get-EffectiveName e)) WithData))(cadr f)
			 (cadar (setq WithData (Cons (_HowBigAmI acBlocks fn) WithData)))))
	(setq r ( / d (* factor (car xy))))		
       (mapcar '(lambda (n m)
		 (vlax-put e n (* r m))) '("XScaleFactor" "YScaleFactor") xy)
      )
    )(princ)
  )

 

HTH

 

Message 16 of 17

Garga
Contributor
Contributor

thank you all for the solution, I will test those lisps on Monday at work.
My Test-Blocks were small because I add them in layout with 7x7mm

0 Likes
Message 17 of 17

E_kazagrandi
Explorer
Explorer

Hi Pbejse, and thank you for this interesting SythLord program. I am trying to find the way to resize blocks to a given length in X- and Y- directions. After I removed the "YScaleFactor" from your "SithLord" program it does exactly that, for the X-direction only, keeping Y-direction size unchanged. I renamed it from SythLord.lsp to BScale-X.lsp (attached). Works really well on single, multiple and dynamic blocks. Excellent! And I was hoping to be able to copy / save this program as BScale-Y.lsp and then modify it for resizing blocks in Y-direction, keeping the X-direction unchanged. But I failed... Would you please help me to acheve this? I am half way through, but really need the same  program for resizing blocks in Y-direction. I would very appreciate your reply, thank you!

 

 

0 Likes