LISP needed to Scale block definitions

LISP needed to Scale block definitions

JGranata_GdB
Enthusiast Enthusiast
3,519 Views
9 Replies
Message 1 of 10

LISP needed to Scale block definitions

JGranata_GdB
Enthusiast
Enthusiast

I have a drawing template with about 200 block definitions. We need to adjust the scale of all these blocks. Currently the process is to edit each block, select all entities and then run the scale command and then move on to the next block.

 

I would like to be able to run a lisp that would allow me to scale each block definition based on an inputted value. 

The scale basepoint would be the block insertion point/ origin point (0,0) when in the block edit.

 

Does anyone know if a code like this exists somewhere already? 

0 Likes
Accepted solutions (1)
3,520 Views
9 Replies
Replies (9)
Message 2 of 10

davinatkins
Advocate
Advocate

Bear with me here... I want to make sure you get what you're looking for. Do you want it to do this same scale to ALL the blocks in the drawing? Or do you want to select the specific blocks to scale first?

 

In other words, do all the blocks need the same scale factor, or do some need different scales applied?

0 Likes
Message 3 of 10

ronjonp
Mentor
Mentor

Here's one to scale ALL block definitions by a factor:

 

(defun c:foo (/ a bp sc d)
  ;; RJP » 2021-02-26
  (initget 6)
  (setq	sc (cond ((getreal "\nEnter scale factor:<0.5> "))
		 (0.5)
	   )
  )
  (setq bp '(0. 0. 0.))
  (vlax-for l (vla-get-layers (setq d (vla-get-activedocument (vlax-get-acad-object))))
    (cond ((= -1 (vlax-get l 'lock)) (vlax-put l 'lock 0) (setq a (cons l a))))
  )
  (vlax-for b (vla-get-blocks d)
    (if	(= 0 (vlax-get b 'isxref) (vlax-get b 'islayout))
      (vlax-for o b (vl-catch-all-apply 'vlax-invoke (list o 'scaleentity bp sc)))
    )
  )
  (foreach l a (vlax-put l 'lock -1))
  (vla-regen d 0)
  (princ)
)
(vl-load-com)

 

If there are definition with attributes you'll need to use attsync as well.

 

 

Message 4 of 10

JGranata_GdB
Enthusiast
Enthusiast

I guess the safest way would be to scale blocks from a selection set. The drawing has a 'legend' in the model space that has the block names and block symbols that need to be adjusted, along with some blocks on layouts such as title block information.

 

The ideal workflow I had in mind would be to run the command, select all blocks in the 'legend' (i would use a box selection method by dragging my mouse over the area) and then enter in the scale factor.  At this point the code would then apply this scale factor to all entities within the block definition based around the blocks origin.  

0 Likes
Message 5 of 10

ronjonp
Mentor
Mentor
Accepted solution

@JGranata_GdB wrote:

I guess the safest way would be to scale blocks from a selection set. The drawing has a 'legend' in the model space that has the block names and block symbols that need to be adjusted, along with some blocks on layouts such as title block information.

 

The ideal workflow I had in mind would be to run the command, select all blocks in the 'legend' (i would use a box selection method by dragging my mouse over the area) and then enter in the scale factor.  At this point the code would then apply this scale factor to all entities within the block definition based around the blocks origin.  


Try this to be able to select the blocks to scale 🍻

(defun c:foo (/ a c bd bp d n r s sc)
  ;; RJP » 2021-02-26
  (cond	((setq s (ssget '((0 . "insert"))))
	 (initget 6)
	 (setq sc (cond	((getreal "\nEnter scale factor:<0.5> "))
			(0.5)
		  )
	 )
	 (vlax-for l (vla-get-layers (setq d (vla-get-activedocument (vlax-get-acad-object))))
	   (cond ((= -1 (vlax-get l 'lock)) (vlax-put l 'lock 0) (setq a (cons l a))))
	 )
	 (setq c (vla-get-blocks d))
	 (foreach b (vl-remove-if 'listp (mapcar 'cadr (ssnamex s)))
	   (setq n (vla-get-effectivename (vlax-ename->vla-object b)))
	   (setq bp (vlax-get (setq bd (vla-item c n)) 'origin))
	   (or (vl-position n r)
	       (vlax-for o bd (vl-catch-all-apply 'vlax-invoke (list o 'scaleentity bp sc)))
	   )
	   (setq r (cons n r))
	 )
	 (foreach l a (vlax-put l 'lock -1))
	 (vla-regen d 0)
	 (princ)
	)
  )
)
(vl-load-com)
Message 6 of 10

JGranata_GdB
Enthusiast
Enthusiast
This works perfectly! Thank you for the help and quick responses.
0 Likes
Message 7 of 10

ronjonp
Mentor
Mentor

@JGranata_GdB wrote:
This works perfectly! Thank you for the help and quick responses.

Glad to help 🍻

Message 8 of 10

Kent1Cooper
Consultant
Consultant

@JGranata_GdB wrote:

I guess the safest way would be to scale blocks from a selection set. .... run the command, select all blocks in the 'legend' (i would use a box selection method by dragging my mouse over the area) and then enter in the scale factor.  ....  


If they don't include duplicates, nor dynamic Blocks, this quickie should do it:

(defun C:SBD ; = Scale Block Definitions
  (/ ss sf n)
  (command "_.layer" "_thaw" "*" "_unlock" "*" "_on" "*" "")
  (if
    (and
      (setq ss (ssget '((0 . "INSERT"))))
      (setq sf (getreal "\nScale factor: "))
    ); and
    (repeat (setq n (sslength ss)); then
      (command
        "_.-bedit" (cdr (assoc 2 (entget (ssname ss (setq n (1- n))))))
        "_.scale" "_all" "" "0,0" sf
        "_.bclose" "_save"
      )
    ); repeat
  ); if
  (command "_.layerp")
  (princ)
); defun

If there's more than one of the same Block among the selection, it will apply the scale factor to its ingredients as many times.  If there could be dynamic Blocks, a different way would need to be used to get their Block names.

 

Another possible complication would be if any of them contain any nested Blocks inside that are also in the selection on their own -- such nested ones would be scaled within themselves, and then again within any Blocks they're nested in.  [For instance, I have a Block of a duplex receptacle symbol for electrical plans, and I have a Block for a GFI receptacle that has the "plain" receptacle nested in it, plus the GFI Text.]  That could probably be avoided, but would take a bunch more code.

Kent Cooper, AIA
Message 9 of 10

JGranata_GdB
Enthusiast
Enthusiast
To my knowledge there does not seem to be any nested blocks. I will keep that in mind and an eye out for any. We do have attributed blocks, but an attsync should resolve those.

There are a handful of dynamic blocks. With this warning, it would just be a manual change since we are talking on the order of under 10 dynamic blocks. 

Thanks for the help.
0 Likes
Message 10 of 10

ronjonp
Mentor
Mentor

@JGranata_GdB wrote:
......

There are a handful of dynamic blocks. With this warning, it would just be a manual change since we are talking on the order of under 10 dynamic blocks. 

....

FWIW my code will process dynamic blocks correctly.

0 Likes