Jump to content

AutoLISP Beginner Part II - automatic layouts from block items


highrise_uk

Recommended Posts

Hi LISP dons, 

 

Thanks for the help with my last thread, learning a lot and it's very much appreciated! Lots of knowledge on here. 

 

I'm sure an automatic layout builder is a very regular request, but I was keen to go through the different parts of what it needs to do and why/how, to help learn (and have something specific for my job haha).

 

I usually use a mixture of DATAEXTRACT, Excel and Scripts to do this task, and it does the job just fine and relatively quickly (especially compared to doing it manually when there are many many layouts!)

 

For example, there's a drawing with 36 layouts, and the viewport block on each as below:

 

image.thumb.png.2caba76e584f2eb28260dd3c37841624.png

 

The basepoint of every block is bang in the centre. So when I do a DATAEXTRACT for the points, it's the middle and that enables me to write a script to put in all the text, and also automatically build all of the viewports with them in the right location and zoom amount. 

 

image.png.14536b4d173e25487ac0bf8fc329251d.png

 

See below for the Excel/script examples

 

Text:

image.png.f6ae073ab408871621322df4580eb1d9.png

 

Layouts

image.thumb.png.b16e7743227e696e1e86f5b32b073679.png

 

So this copies the template layout, selects the new layout, goes into the viewport and zooms into the centre of each block in turn. 

 

As said, this works perfectly well but is obviously a bit clunky and can be annoying if you have to re-do everything when things have moved in the drawing. 

 

I've basically done no real work today as I've been trying to make a smarter LISP setup which would do all of this on a single click of a block. 

 

The code below won't run but I've split the process up into all the parts I think are necessary. Some of them are already working but the real complicated stuff is still evading me.

 

The main thing I'm struggling to get my head around is getting a list of each blocks co-ordinate and then having the process run for each of those individually. I've taken a few bits from other LISPS here and there, and tried to put them in the right order. 

 

I'm assuming there's ways to list the co-ords of every block, sort them, then run the process for as many blocks as there are in the drawing. 

I figure some combination of the variant and counter to keep updating a co-ordinate variant is what's needed but can't work out how to set that up. 

 

Also would be nice to maintain the 01 02 03 format instead of 1 2 3, but that is beyond me too haha. 

 

There are plenty of notes in the code so I probably don't need to explain any more what I want this to do. But I'm happy to clear things up for anyone willing to have a go :)

 

See attached the DWG with blocks and the LISP/notes as they currently are. This is only my second real go at this so im sure there's loads of clunky nonsense in the file lol

 

Thanks!

 

AutoLayoutTest.dwg

 

DW AUTOLAYOUT.lsp

 

;;; VIEWPORT UNLOCKER
					; working!

(setq clay (getvar "CLAYER"))
(command "-VPORTS" "L" "OFF" "ALL" "")
(setvar "CLAYER" clay)
(princ)
)

;;;GET VP BLOCK NAME AND LAYER
					; working!

(setq blk      (entsel "\nSelect viewport block: ")
      blkname  (vla-get-effectivename (vlax-ename->vla-object (car blk)))
      blklayer (vla-get-layer (vlax-ename->vla-object (car blk)))
    
)


;;;SELECTION SET - ALL BLOCKS ON VP LAYER
					; working!

(setq ss_blk (ssget "_X"			      ;SELECT ALL
		    (list
		      (cons 8 blklayer)		      ;;LAYER FILTER
		      (cons 2 blkname)		      ;;BLOCK NAME FILTER
		    )
	     )
)
(sslength ss_blk)

;;;GET CO-ORDS OF BLOCKS

(setq blk-coord (cdr blk)) ;;; shows co-ord of first selected block

;;;LIST CO-ORDS

;;;SORT CO-ORDS X small to big AND THEN Y big to small in list

;;; CHANGE CO-ORD PER CYCLE

(setq vp-coord1 (???))


;;;COUNTER
(setq count 1)

;;WHILE
(while (< count (sslength ss_blk))
;do text insert and layout

;;;NUMBER TEXT INSERT
					;working ! just need co-ords info from list

  (setq num-txt (rtos count 2 0)) ;;;counter value for text
  (command "-TEXT"
	   "J" "M" ;;;TEXT POSITION MIDDLE
	   vp-coord1 ;;; textLOCATION
	   "100"			;TEXT SIZE
	   "90"				;TEXT ANGLE
	   num-txt)			;TEXT CONTENT 1 2 3....
  (command "_chprop" "_last" "" "_layer" blklayer "") ;;;text to VP layer



;;; LAYOUT MAKER
  ;working !
  (setq zoom 281)
  (setq lay0 (getstring "\nType in template layout name..."))
  (setq laynew (rtos count 2 0))
  (command "_-LAYOUT"  "C"	 lay0	    laynew     "_-LAYOUT" "s"
	   laynew     "MSPACE"	 "ZOOM"	    "C"	       vp-coord1
	   zoom      "PSPACE"
	  )
)

;;; 1:500 ZOOM = 281 (maybe add scale choice as part of LISP)
;;; 1:1000 = 562
;;; 1:250 = 140.5

;;;COUNTER +1
(setq count (+ count 1))


;;;ENDWHILE


;;; LOCK ALL VIEWPORTS
					;working!

(setq clay (getvar "CLAYER"))
(command "-VPORTS" "L" "ON" "ALL" "")
(setvar "CLAYER" clay)
(princ)
)


 

 

 

Link to comment
Share on other sites

I managed to get this working better now, though im sure it's still kinda janky in many ways haha. 

 

DW AUTOLAYOUT reverse.lsp

 

Added lines to ensure all numbers under 10 are represented as 01 02... 

 

Added a reverse counter for adding said numbers so that the first made entity is tagged 01 instead of the last number. 

 

One thing that I still can't get my head around is how to force the SelSet to order itself based on the co-ords of the objects.

 

Very much enjoying learning this but a little nudge on how to organise the set by x/y position so that blocks inserted anywhere will number correctly left to right would be appreciated. 

 

Cheers

Link to comment
Share on other sites

A couple of suggestions as your using a block to define the area of interest yes do a what scale required 1st, then insert the block using a scale. You read the scale so know what scale the mview needs to be, you can use "zoom c Point scale" to set the correct scale of the newly made Viewport.

 

When using copy layout I use Template option so read from another dwg the correct layout size which has a viewport already made see image above.

 

The ssget add (cons 410 "Model") if block is always in Model space. Saves finding the odd one in a layout.

 

"set by x/y position" you can do a double sort on a list of block insertion points. Then number.

; sorts on 1st two items
(vl-sort lst
	 '(lambda (a b)
	    (cond
	      ((< (car a) (car b)))
	      ((= (car a) (car b)) 
		  (< (cadr a) (cadr b)))
	    )
	  )
)

 

Just a final comment I look for something similar it can have any rotation also, and a mix of sheet sizes and /or scales. Layouts are made to suit.

layout1.png.9d03ab6cd7fbd5b4a128c15fbe0c31bf.png

 

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...