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

Layer Legend

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
tmullins
7052 Views, 11 Replies

Layer Legend

I have a lisp routine that creates a layer legend in your drawing. My apologies to the source who wrote it, I simply can't recall where I ran across it. It works pretty well, and with a couple tweaks it would be great.

 

It basically reads the layer table and creates a legend in your drawing. You have to have a height assigned first to your current text style, not a big deal (I can take care of that in the code) but it would be nice to not have to remember to do that but the main issue is that it sorts (possibly) on the order the layers were created in the file. It would be great if it sorted based on name, alphabetically. So can it be sorted first before it reads tblnext "Layer"?

 

I'm not technically a programmer so any help would be greatly appreciated. Again my apologies to the source. Thanks.

 

It is attached and here is the code:

 

 

(defun c:layerlegend (/ osm ortho clayer celtype cecolor start-point line-length text-height *error*)
(defun *error* (msg)
(setvar "osmode" osm)
(setvar "orthomode" ortho)
(setvar "clayer" clayer)
(setvar "celtype" celtype)
(setvar "cecolor" cecolor)
(princ msg)
)

(defun mfp (pt pa) (list (+ (car pt) (car pa)) (+ (cadr pt) (cadr pa)) (+ (caddr pt) (caddr pa))))

(setq osm (getvar "osmode"))
(setq ortho (getvar "orthomode"))
(setq clayer (getvar "clayer"))
(setq celtype (getvar "celtype"))
(setq cecolor (getvar "cecolor"))
(setq start-point (getpoint "\nSelect point to start legend: "))
(setvar "orthomode" 1)
(setq line-length (getdist start-point "\nEnter length of line or click end point: "))
(setq text-height (cdr (assoc 40 (tblsearch "style" (getvar "textstyle")))))
(setvar "osmode" 0)
(setvar "clayer" (cdr (assoc 2 (tblnext "Layer" T))))
(setvar "celtype" "ByLayer")
(setvar "cecolor" "ByLayer")
(command "_line" start-point (mfp start-point (list line-length 0 0)) "")
(command "-text" (mfp start-point (list 0 1 0)) "0" (getvar "clayer"))
(while (setq layer (tblnext "Layer"))
(setvar "clayer" (cdr (assoc 2 layer)))
(setq start-point (mfp start-point (list 0 (- 0 (+ text-height 4)) 0)))
(command "_line" start-point (mfp start-point (list line-length 0 0)) "")
(command "-text" (mfp start-point (list 0 1 0)) "0" (getvar "clayer"))
)
(setvar "osmode" osm)
(setvar "orthomode" ortho)
(setvar "clayer" clayer)
(setvar "celtype" celtype)
(setvar "cecolor" cecolor)
)

11 REPLIES 11
Message 2 of 12
Kent1Cooper
in reply to: tmullins


@tmullins wrote:

I have a lisp routine that creates a layer legend in your drawing. ....

 

It basically reads the layer table and creates a legend in your drawing. ....the main issue is that it sorts (possibly) on the order the layers were created in the file. It would be great if it sorted based on name, alphabetically. So can it be sorted first before it reads tblnext "Layer"?....


I don't think there's any way to sort the Layer table before stepping through it.  You would need to make a list of Layer names, sort that, and step through it, using a name from the sorted list rather than from the Layer table at each step, something like this [untested]:

 

....

(while (setq lay (cdadr (tblnext "layer" (not lay)))); make list of Layer names
  (setq laylist (cons lay laylist))
)
(foreach
  lay
  (vl-sort laylist '<); sorted alphabetically
  (setvar 'clayer lay)
  (setq start-point (mfp start-point (list 0 (- 0 (+ text-height 4)) 0)))
  (command

    "_line" start-point (mfp start-point (list line-length 0 0)) ""
    "-text" (mfp start-point (list 0 1 0)) "0" lay ; [could leave (getvar 'clayer) in there]

  )
); foreach

....

Kent Cooper, AIA
Message 3 of 12
tmullins
in reply to: Kent1Cooper

Thanks Kent, worked great!

 

Here is the revised code if anyone wants it:

 

 

 

(defun c:layerlegend (/ osm ortho clayer celtype cecolor start-point line-length text-height *error*)
(defun *error* (msg)
(setvar "osmode" osm)
(setvar "orthomode" ortho)
(setvar "clayer" clayer)
(setvar "celtype" celtype)
(setvar "cecolor" cecolor)
(princ msg)
)

(defun mfp (pt pa) (list (+ (car pt) (car pa)) (+ (cadr pt) (cadr pa)) (+ (caddr pt) (caddr pa))))


(setq osm (getvar "osmode"))
(setq ortho (getvar "orthomode"))
(setq clayer (getvar "clayer"))
(setq celtype (getvar "celtype"))
(setq cecolor (getvar "cecolor"))
(setq start-point (getpoint "\nSelect point to start legend: "))
(setvar "orthomode" 1)
(setq line-length (getdist start-point "\nEnter length of line or click end point: "))
(setq text-height (cdr (assoc 40 (tblsearch "style" (getvar "textstyle")))))
(setvar "osmode" 0)
(setvar "celtype" "ByLayer")
(setvar "cecolor" "ByLayer")
(command "_line" start-point (mfp start-point (list line-length 0 0)) "")
(command "-text" (mfp start-point (list 0 1 0)) "0" (getvar "clayer"))
(while (setq lay (cdadr (tblnext "layer" (not lay)))); make list of Layer names
  (setq laylist (cons lay laylist))
)
(foreach
  lay
  (vl-sort laylist '<); sorted alphabetically
  (setvar 'clayer lay)
  (setq start-point (mfp start-point (list 0 (- 0 (+ text-height 4)) 0)))
  (command
    "_line" start-point (mfp start-point (list line-length 0 0)) ""
    "-text" (mfp start-point (list 0 1 0)) "0" lay ; [could leave (getvar 'clayer) in there]
  )
); foreach


(setvar "osmode" osm)
(setvar "orthomode" ortho)
(setvar "clayer" clayer)
(setvar "celtype" celtype)
(setvar "cecolor" cecolor)
)

Message 4 of 12
lai
Advocate
in reply to: tmullins

hi, just come across this topic, and i give it a try to the lisp..after load the lisp and at command prompt, i type "layerlegend", somehow i see the end resut is just a line and a text above it..i just dun see any purpose or maybe i have misunderstand something..

Message 5 of 12
Kent1Cooper
in reply to: lai


@lai wrote:

hi, just come across this topic, and i give it a try to the lisp..after load the lisp and at command prompt, i type "layerlegend", somehow i see the end resut is just a line and a text above it..i just dun see any purpose or maybe i have misunderstand something..


I haven't loaded it and run it, but some possibilities come to mind:

 

Does your drawing have more than one Layer in it?  Is your current Text Style defined with 0 height?  [I think the code is built for a fixed-height style.]  Or, could it be a metric-vs.-imperial units issue?  Is it truly "just a line," or might it be multiple lines very close together?  And is it just one Text entity, or multiples on top of each other, or nearly so?

Kent Cooper, AIA
Message 6 of 12
RFCengr
in reply to: Kent1Cooper

You need to change the "-text" command line to at least the following

 

(command "-text" (mfp start-point (list 0 1 0)) 5 "E" (getvar "clayer"))

 

and the line

 

"-text" (mfp start-point (list 0 1 0)) 5 "E" lay ; [could leave (getvar 'clayer) in there]

 

the 0 that was there is not setting the size of the text like it used to (Style override). (At least for AutoCAD 2010)

Message 7 of 12
Kent1Cooper
in reply to: RFCengr


@RFCengr wrote:

You need to change the "-text" command line to at least the following

 

(command "-text" (mfp start-point (list 0 1 0)) 5 "E" (getvar "clayer"))

 

and the line

 

"-text" (mfp start-point (list 0 1 0)) 5 "E" lay ; [could leave (getvar 'clayer) in there]

 

the 0 that was there is not setting the size of the text like it used to (Style override). (At least for AutoCAD 2010)


The 0's involved were not for "setting the size of the text" [a Text command won't accept 0 for a height] -- they were for its rotation [you can use E instead if that fits your Units angular settings].  The code was written for use with a Text Style with fixed height, in which case there will be no height prompt, but you're obviously using a Style without that [with 0 defined height], in which case, yes, you will need to add something to answer the height prompt.

Kent Cooper, AIA
Message 8 of 12
d.volo
in reply to: tmullins

Hi, really thanks for the code!! It save me a lot of time!! Smiley Wink

 

I found a problem in the code if you run it more than a time.

It duplicate the layer with the same name

 

I modified the first line of the code in this way to clean all the variable at the end of the routine.

 

(defun c:layerlegend (/ osm ortho clayer celtype cecolor start-point line-length text-height lay laylist *error*)

 

the entire code is now:

 

(defun c:layerlegend (/ osm ortho clayer celtype cecolor start-point line-length text-height lay laylist *error*)
(defun *error* (msg)
(setvar "osmode" osm)
(setvar "orthomode" ortho)
(setvar "clayer" clayer)
(setvar "celtype" celtype)
(setvar "cecolor" cecolor)
(princ msg)
)

(defun mfp (pt pa) (list (+ (car pt) (car pa)) (+ (cadr pt) (cadr pa)) (+ (caddr pt) (caddr pa))))


(setq osm (getvar "osmode"))
(setq ortho (getvar "orthomode"))
(setq clayer (getvar "clayer"))
(setq celtype (getvar "celtype"))
(setq cecolor (getvar "cecolor"))
(setq start-point (getpoint "\nSelect point to start legend: "))
(setvar "orthomode" 1)
(setq line-length (getdist start-point "\nEnter length of line or click end point: "))
(setq text-height (cdr (assoc 40 (tblsearch "style" (getvar "textstyle")))))
(setvar "osmode" 0)
(setvar "celtype" "ByLayer")
(setvar "cecolor" "ByLayer")
(command "_line" start-point (mfp start-point (list line-length 0 0)) "")
(command "-text" (mfp start-point (list 0 1 0)) "0" (getvar "clayer"))
(while (setq lay (cdadr (tblnext "layer" (not lay)))); make list of Layer names
  (setq laylist (cons lay laylist))
)
(foreach
  lay
  (vl-sort laylist '<); sorted alphabetically
  (setvar 'clayer lay)
  (setq start-point (mfp start-point (list 0 (- 0 (+ text-height 4)) 0)))
  (command
    "_line" start-point (mfp start-point (list line-length 0 0)) ""
    "-text" (mfp start-point (list 0 1 0)) "0" lay ; [could leave (getvar 'clayer) in there]
  )
); foreach


(setvar "osmode" osm)
(setvar "orthomode" ortho)
(setvar "clayer" clayer)
(setvar "celtype" celtype)
(setvar "cecolor" cecolor)
)

 

 

It is still necessary to set manually the hight of the text

ACP Revit Architecture - CAD/BIM Coordinator
Message 9 of 12
Patrick.G
in reply to: d.volo

This is a really great Lisp, Thank you @d.volo , @tmullins 

 

One small request if it is easy enough.  Can you modify the Lisp to 25 or so layer, then move to another column of 25?  Instead of one long column that is 300+ layers? 

 

My company is looking at moving from ctb to stb and reevaluating all our layer styles, etc. so I'm using this lisp a bunch of times. 

 

Thanks Again! 

Message 10 of 12
Kent1Cooper
in reply to: Patrick.G


@Patrick.G wrote:

....  Can you modify the Lisp to 25 or so layer, then move to another column of 25?  Instead of one long column that is 300+ layers? 

.... 


That would probably mean having some notion of the lengths of your Layer names  in the current text font & height [in drawing units, not in characters].  Or possibly it could get the bounding box of each Layer name as it goes, and determine the right-most extent of any Layer name, to decide how far over to move for the next column.  Would it be acceptable for the column spacings to vary, affected by the lengths of Layer names in each column?

Kent Cooper, AIA
Message 11 of 12
Patrick.G
in reply to: Kent1Cooper

 @Kent1Cooper   It didn't occur to me that the layer names could get in the way, I see your point.  I was keeping the line length well beyond the text so that you can really see the style.  I was thinking a default same distance between columns based on 0.15 times the length of the line entered?  If that makes sense.   So if you enter 15 units for the line length it makes the spacing 2.25.   

If the name becomes too long, the user could make the line longer?

Message 12 of 12
Sea-Haven
in reply to: Patrick.G

AS you do the cons make layer list do a strlen this gives number of characters multiply by Height or a fuzzy factor of height, monotext is widest. Save max length.

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

Post to forums  

Autodesk Design & Make Report

”Boost