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

Spacing Blocks evenly

23 REPLIES 23
SOLVED
Reply
Message 1 of 24
Anonymous
6120 Views, 23 Replies

Spacing Blocks evenly

I couldn't find a lisp in the web to space blocks evenly (clear spacing) and need help from this forum.

I want to space different block/s evenly, not from centers but clear spacing between blocks.

 

There could be any random blocks that are in any sequence or order. Insertion point of blocks could be different between blocks.

The first and last block location of that row are good, not to be move. The task is to space those blocks between the first and last.

Most blocks have a text (tag) which is not part of the block. When spacing the blocks, these texts should follow the block location and orientation.

This line of blocks can be orientated any direction define by the first and last block.

 

Attached is an example, what  was Before and what I want in the After. The dimenson here is only to indicate where the clear spacing is measured.

 

Thanks

 

mcmk8

Tags (1)
23 REPLIES 23
Message 2 of 24
ВeekeeCZ
in reply to: Anonymous

I found @_Tharwat 's routine HERE

 

I dared to make a quick modification, hope you don't mind, Tharwat.

 

@Anonymous It makes a bounding box of each block, then it expends the selection window to left and up to cover labels. You can adjust the multiplying coefficients of width/hight of block (different for portrait/landscape shape of block).

 

Spoiler
;; Tharwat Al Shoufi ~ 15. Aug. 2013 ;;
;; http://www.cadtutor.net/forum/archive/index.php/t-81140.html?s=a3b7690756ca3b1605d385510014beb2

;; Mod BeekeeCZ ~ 13. Jul. 2016 ;;

(defun c:BlkDistribute (/ *error* EnoughSpace-p cm a b ss i sn x d l g pt lft r y h w sw
	          stp k u x-d xXx dis)
  
  (defun *error* (x)
    (princ "\n")
    (if cm (setvar 'cmdecho cm) )
    (princ "\n *Cancel*"))
  
  (defun EnoughSpace-p (ss d / l i q lf ur p)
    (setq l 0.)
    (repeat (setq i (sslength ss))
      (vla-getboundingbox (vlax-ename->vla-object (ssname ss (setq i (1- i)))) 'lf 'ur)
      (setq l (+ (distance (setq p (vlax-safearray->list lf))
			   (list (car (vlax-safearray->list ur)) (cadr p) 0.))
		 l)))
    (list (< l d) l))

  
  ; ******************************************************
  
  (if (and (setq dis (getdist "\n Specify total length :"))
	   (setq ss (ssget "_:L" '((0 . "INSERT")))) ;'((0 . "LWPOLYLINE") (-4 . "&=") (70 . 1))))
	   (if (car (setq g (EnoughSpace-p ss dis)))
	     T
	     (progn
	       (alert "Total length is less than the total widths of Rectangles !!")
	       nil))
	   )
    (progn
      (setq cm (getvar 'cmdecho)
	    g (/ (- dis (cadr g)) (1- (sslength ss))))

      (setvar 'cmdecho 0)
      (repeat (setq i (sslength ss))
	(setq sn (ssname ss (setq i (1- i))))
	(vla-getboundingbox (vlax-ename->vla-object sn) 'lft 'r)
	(setq x (vlax-safearray->list lft))
	(setq y (vlax-safearray->list r))
	(setq d (distance x (list (car y) (cadr x))))
	(setq h (distance y (list (car y) (cadr x))))
	(setq w (if (> h d)  ; high > width
		  (list (polar x pi (* 0.8 d)) 
			(polar y (/ pi 2) (* 0.2 (distance y (list (car y) (cadr x))))))
		  (list (polar x pi (* 0.2 d))
			(polar y (/ pi 2) (* 0.6 (distance y (list (car y) (cadr x))))))))
	(setq l (cons (list sn x w d) l)))
      (setq l (vl-sort l '(lambda (q p) (< (car (cadr q)) (car (cadr p)))))
	    k 0
	    stp 0.
	    a (car (cadr (nth 0 l)))
	    b (last (nth 0 l)))
      
      (repeat (1- (length l))
	(setq k (1+ k))
	(vl-cmdf "_.move"
		 (car (nth k l)))
	(if (setq sw (ssget "_c" (car (caddr (nth k l))) (cadr (caddr (nth k l))) '((0 . "*TEXT"))))
	  (vl-cmdf sw))
	(vl-cmdf ""
		 "_non"
		 (cadr (nth k l))
		 "_non"
		 (list (+ a b g stp) (cadr (cadr (nth k l))))
		 )
	(setq stp (+ (last (nth k l)) g stp)))
      (setvar 'cmdecho cm)))
  (princ)
)

(vl-load-com)

 

Message 3 of 24
Anonymous
in reply to: ВeekeeCZ

Thanks BeekeeCZ (and Tharwat)

 

It work's wonder on horizontal arrangement, but Not in vertical arrangement.

 

Try the lisp after you rotate the Before arrangement in my dwg to vertical (90 deg).

 

Hope it's a simple fix.

 

Thanks

 

mcmk8

Message 4 of 24
ВeekeeCZ
in reply to: Anonymous


@Anonymous wrote:

Thanks BeekeeCZ (and Tharwat)

 

It work's wonder on horizontal arrangement, but Not in vertical arrangement.

 

Try the lisp after you rotate the Before arrangement in my dwg to vertical (90 deg).

 

Hope it's a simple fix.

 

Thanks

 

mcmk8


Hmm, I was designed for horizontal distribution. Here is version allows you vertical distribution as well.

 

Spoiler
;; Tharwat Al Shoufi ~ 15. Aug. 2013 ;;
;; http://www.cadtutor.net/forum/archive/index.php/t-81140.html?s=a3b7690756ca3b1605d385510014beb2

;; Mod BeekeeCZ ~ 13. Jul. 2016 ;;

(defun c:BlkDistribute (/ *error* EnoughSpace-p cm a b ss i sn x d l g pt lft r y h w sw
			stp k u x-d xXx dis)
  
  (defun *error* (x)
    (princ "\n")
    (if cm (setvar 'cmdecho cm) )
    (princ "\n *Cancel*"))
  
  (defun EnoughSpace-p (ss d v / l i q lf ur p)
    (setq l 0.)
    (repeat (setq i (sslength ss))
      (vla-getboundingbox (vlax-ename->vla-object (ssname ss (setq i (1- i)))) 'lf 'ur)
      (setq l (+ (distance (setq p (vlax-safearray->list lf))
			   (if v
			     (list (car p) (cadr (vlax-safearray->list ur)) 0.)
			     (list (car (vlax-safearray->list ur)) (cadr p) 0.)))
		 l)))
    (list (< l d) l))
  
  
  ; ******************************************************
  
  
  
  (if (setq dis (getdist "\nSpecify total length for horizontal distribution <vertical>: "))

    ; Horizontal distribution
    (if (and (setq ss (ssget "_:L" '((0 . "INSERT"))))
	     (if (car (setq g (EnoughSpace-p ss dis nil)))
	       T
	       (progn (alert "Total length is less than the total widths of Blocks !!")
		 nil))
	     )
      (progn
	(setq cm (getvar 'cmdecho)
	      g (/ (- dis (cadr g)) (1- (sslength ss))))
	
	(setvar 'cmdecho 0)
	(repeat (setq i (sslength ss))
	  (setq sn (ssname ss (setq i (1- i))))
	  (vla-getboundingbox (vlax-ename->vla-object sn) 'ld 'ru)
	  (setq x (vlax-safearray->list ld))
	  (setq y (vlax-safearray->list ru))
	  (setq d (distance x (list (car y) (cadr x))))
	  (setq h (distance y (list (car y) (cadr x))))
	  (setq w (if (> h d)  ; high > width
		    (list (polar x pi (* 0.8 d))
			  (polar y (/ pi 2) (* 0.2 (distance y (list (car y) (cadr x))))))
		    (list (polar x pi (* 0.2 d))
			  (polar y (/ pi 2) (* 0.6 (distance y (list (car y) (cadr x))))))))
	  (setq l (cons (list sn x w d) l)))
	(setq l (vl-sort l '(lambda (q p) (< (car (cadr q)) (car (cadr p)))))
	      k 0
	      stp 0.
	      a (car (cadr (nth 0 l)))
	      b (last (nth 0 l)))
	
	(repeat (1- (length l))
	  (setq k (1+ k))
	  (vl-cmdf "_.move"
		   (car (nth k l)))
	  (if (setq sw (ssget "_c" (car (caddr (nth k l))) (cadr (caddr (nth k l))) '((0 . "*TEXT"))))
	    (vl-cmdf sw))
	  (vl-cmdf ""
		   "_non"
		   (cadr (nth k l))
		   "_non"
		   (list (+ a b g stp)
			 (cadr (cadr (nth k l))))
		   )
	  (setq stp (+ (last (nth k l)) g stp)))
	(setvar 'cmdecho cm)))

    ; Vertical distribution
    (if (and (setq dis (getdist "\nSpecify total length for vertival distribution: "))
	     (setq ss (ssget "_:L" '((0 . "INSERT"))))
	     (if (car (setq g (EnoughSpace-p ss dis T)))
	       T
	       (progn (alert "Total length is less than the total height of Blocks !!")
		 nil))
	     )
      (progn
	(setq cm (getvar 'cmdecho)
	      g (/ (- dis (cadr g)) (1- (sslength ss))))
	
	(setvar 'cmdecho 0)
	(repeat (setq i (sslength ss))
	  (setq sn (ssname ss (setq i (1- i))))
	  (vla-getboundingbox (vlax-ename->vla-object sn) 'ld 'ru)
	  (setq x (vlax-safearray->list ld))
	  (setq y (vlax-safearray->list ru))
	  (setq d (distance x (list (car y) (cadr x))))
	  (setq h (distance y (list (car y) (cadr x))))
	  (setq w (if (> h d)  ; high > width
		    (list (polar x pi (* 0.8 d))
			  (polar y (/ pi 2) (* 0.2 (distance y (list (car y) (cadr x))))))
		    (list (polar x pi (* 0.2 d))
			  (polar y (/ pi 2) (* 0.6 (distance y (list (car y) (cadr x))))))))
	  (setq l (cons (list sn x w h) l)))
	(setq l (vl-sort l '(lambda (q p) (< (cadr (cadr q)) (cadr (cadr p)))))
	      k 0
	      stp 0.
	      a (cadr (cadr (nth 0 l)))
	      b (last (nth 0 l)))
	
	(repeat (1- (length l))
	  (setq k (1+ k))
	  (vl-cmdf "_.move"
		   (car (nth k l)))
	  (if (setq sw (ssget "_c" (car (caddr (nth k l))) (cadr (caddr (nth k l))) '((0 . "*TEXT"))))
	    (vl-cmdf sw))
	  (vl-cmdf ""
		   "_non"
		   (cadr (nth k l))
		   "_non"
		   (list (car (cadr (nth k l))) ;(+ a b g stp)
			 (+ a b g stp) 		;(cadr (cadr (nth k l)))
			 )
		   )
	  (setq stp (+ (last (nth k l)) g stp)))
	(setvar 'cmdecho cm))))
  (princ)
  )

(vl-load-com)
Message 5 of 24
pbejse
in reply to: Anonymous

Same logic as what BeekeeCZ  posted (and Tharwat)

 

(defun c:demo (/ _BBbox	coll opt e blockInfo sym firstB lastb np_ sp dist)
;;;		pBe July 2014		;; 
  (defun _BBbox	(e / ll ul ur lr)
    (vla-getboundingbox e 'll 'ur)
    (setq ll (vlax-safearray->list ll)
	  ur (vlax-safearray->list ur)
    )
    (list ll
	  (distance ll (setq lr (list (car ur) (cadr ll) 0.0)))
	  (distance ll (setq ul (list (car ll) (cadr ur) 0.0)))
	  ul ur lr
    )
  )
  (if (setq coll nil
	    ss	 (ssget "_:L" '((0 . "INSERT")))
      )
    (progn
      (initget "V H")
      (setq opt (getkword "\nChoose option [Vertical/Horizontal]<H>: "))
      (setq opt	(if (null opt)  "H"  opt ))
      (repeat (setq i (sslength ss))
	(setq blockInfo	(_BBbox	(setq e	(vlax-ename->vla-object
					  (ssname ss (setq i (1- i)))
					))))
	(setq coll (cons
		     (list (car blockInfo) (cdr blockInfo) e)
		     coll
		   )
	)
      )
      (setq sym	(if (setq h (eq "H" opt))
		  '(< (caar a) (caar b))
		  '(< (cadar a) (cadar b))))
      (setq coll    (vl-sort coll '(lambda (a b) (eval sym)))
	    coll2bs coll)
	(setq firstB (car coll)
	    coll   (cdr coll)
	    lastB  (last coll)
	    coll   (vl-remove lastB coll)
      )
      (setq dist (/ (- (distance (if h
				   (last (cadr firstb))
				   (caddr (Cadr firstb))
				 )
				 (car lastb)
		       )
		       (apply '+ (mapcar (if h 'caadr 'cadadr
				      ) coll)))
		    (1+ (length coll))
		 )
      )
      (setq sp nil _np	(lambda	(m p d)
		  (polar p (if m 0.0 (/ pi 2.0) ) d )))
        (mapcar '(lambda (j k l)
			    (setq sp (if sp sp (car j)))
			    (vlax-invoke (last l) 'move (Car l)
			      		(setq sp (_np h sp (+ dist k)))))
			 coll2bs
	      	(mapcar (if h 'caadr 'cadadr ) coll2bs ) coll
		 )
      )
	)	
  (princ)
)

Command: DEMO

Select objects: Specify opposite corner: 6 found

Select objects:
Choose option [Vertical/Horizontal]<H>: 

 

HTH

 

 

Message 6 of 24
pbejse
in reply to: pbejse

 This morning a friend of mine pointed out that the OP stated that TEXT/MTEXT entities should "follow the block location"

 

Attached is the lisp file with a little modification to include TEXT/MTEXT entities

 

Command: SBB

Select objects: 

Specify first corner: Specify opposite corner: 32 found

Select objects:
Choose option [Vertical/Horizontal]<H>: H

 

HTH

 

 

 

Message 7 of 24
Anonymous
in reply to: pbejse

Thanks BeekeeCZ & pbejse. It works great.

Message 8 of 24
pbejse
in reply to: Anonymous

Good for you mcmk8 , we are happy to help 🙂

pBe
Message 9 of 24
StanThe
in reply to: Anonymous

Is there a way to space the blocks evenly and ignore any text that is in the block?

 

SH
Message 10 of 24
pbejse
in reply to: StanThe


@StanThe wrote:

Is there a way to space the blocks evenly and ignore any text that is in the block?

 


Are you referring to SpaceBetweenBlocks.lsp?  then YES.

 

Is that Attribute, Mtext or Text? Are there other conditions that we need to know about?

Message 11 of 24
StanThe
in reply to: pbejse

Thanks for the help! It is never an attribute, only a slight chance of Mtext and 99% text.

Only want to evenly space the polyline portion. Thanks again!

 

SH
Message 12 of 24
pbejse
in reply to: StanThe


@StanThe wrote:

Thanks for the help! It is never an attribute, only a slight chance of Mtext and 99% text.

Only want to evenly space the polyline portion. Thanks again!

 


I see, before we get started, Are these just regular and not Dynamic blocks? any of them rotated, mirrored or scaled?

Message 13 of 24
StanThe
in reply to: pbejse

These aren't dynamic but sometimes they get rotated and mirrored.

Thank you!

SH
Message 14 of 24
Edwin.Saez
in reply to: StanThe

@pbejse@ВeekeeCZ,

 

Maybe something is doing wrong, but select the block and put a distance I get the following warning.

 

comand: blkdistribute

 

grabilla.Ya6784.png

 

 

Edwin Saez


LinkedIn / AutoCAD Certified Professional


EESignature


 


Si mi respuesta fue una solución para usted, por favor seleccione "Aceptar Solución", para que también sirva a otro usuarios.

Message 15 of 24
pbejse
in reply to: StanThe


@StanThe wrote:

These aren't dynamic but sometimes they get rotated and mirrored.

Thank you!


Hmmm, we may need to write an entirely new code. I'll post the code later.

 

Hang in there.

 

pBe

Message 16 of 24
pbejse
in reply to: pbejse



@StanThe wrote:

These aren't dynamic but sometimes they get rotated and mirrored.

Thank you!


 

Try the attached code.

 

 
Command: SBBT
Select objects: Specify opposite corner: 6 found
Choose option [Vertical/Horizontal]<H>: 
 
 
HTH
 
Message 17 of 24
StanThe
in reply to: pbejse

Thank you very much for your time and talent!!! Works great!!! Now I have my work cut out for me to manipulate that to come up with the other lisps we need!!! Thanks again for your help!!!

 

SH
Message 18 of 24
pbejse
in reply to: StanThe


@StanThe wrote:

Thank you very much for your time and talent!!! Works great!!! Now I have my work cut out for me to manipulate that to come up with the other lisps we need!!! Thanks again for your help!!!

 


Good for you stanley. Happy to help

 

Cheers

Message 19 of 24
Anonymous
in reply to: Anonymous

Can you please edit this lisp to arrange the block as per order of individual selection of each blocks . 

Message 20 of 24
Anonymous
in reply to: pbejse

I know that this is an old post, and you don't have to respond here you can respond directly to my email, walterjhowell1997@yahoo.com. I have used this lisp expression you've created and it does almost exactly what I want it to do, the only thing I would like to change is the spacing between the selected blocks. Would I be able to change a specific line of code to change how evenly the block are spaced from each other. Basically I want to use this as a way of creating a Riser diagram, and to be able to add text under the objects without overlapping would be perfect. So basically wondering how I would go about changing a piece of your lisp expression to fit my needs. If you would respond I would be very appreciative.

- Thank you.

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

Post to forums  

Autodesk Customer Advisory Groups


Autodesk Design & Make Report