Visual LISP, AutoLISP and General Customization

Visual LISP, AutoLISP and General Customization

Reply
Distinguished Contributor
kameron1967
Posts: 186
Registered: ‎09-05-2008
Message 1 of 10 (305 Views)
Accepted Solution

Converting objects of certain linetype to a new layer based on that linetype.

305 Views, 9 Replies
10-26-2012 04:13 PM

Hi,

 

I would like help with converting all objects that has forced linetype to be on a linetype layer.

 

So if there are objects that have forced linetypes - dashed/hidden/phantom, etc., those entities would be moved to a linetype layer based on their forced linetype.   The entities would all be chaned to color bylayer, linetype bylayer.

 

So if there is a rectangle that is sitting on an EQUIPMENT layer, the routine would put that rectangle on a new layer called DASHED and change its forced linetype to BYLAYER.

 

Lastly, once that's done, the next and final step is to locate a the existing layers with matching linetype - say, OBJECTS with DASHED as a linetype, and merging it to that layer.

 

Hope I communicated clearly enough.  Thank you in advance!  :smileyvery-happy:


kameron1967 wrote:

.... 

Q:For the last step, what if there are more than one Layer with a given Linetype? 

A: If there are 2 or 3, then we can move all to the first layer created under that linetype name

....

Q:What if there are none

A: No layers or no linetypes - except for continuous?  If there is none, then don't do anything.

Q:And if there is one and only one, would it not be better to just move the objects directly to it, and skip the middle-man of the linetype-named Layer?

A: If there is only one layer, a routine could be used to create just one linetype layer.

 

I have a plan to further rename these layers to different sets of standard layers after.  I just wanted to first consolidate the lines according to their linetypes.

....


What I meant by "What if there are none?" was "What if there are no existing Layers with that Linetype assigned?"  I think from other answers that you would still want a Layer made that is named for the Linetype.

 

What I meant by "...if there is one and only one..." was "...if there is one and only one existing Layer with that Linetype assigned...".  Say your example Layer called OBJECTS with Dashed Linetype is the only Dashed-Linetype Layer in the drawing [other than the new one that's called DASHED].  I was asking whether it would be better to move things with an override Dashed Linetype directly to the OBJECTS Layer, rather than to a middle-man DASHED Layer that's later going to be merged into OBJECTS.  But since you're planning to rename Layers anyway, I have an idea.  Just determine for each entity whether it has a Linetype override.  If it does, change its Layer to the name of the Linetype.  If it doesn't, change its Layer to the name of the Linetype assigned to its Layer.  No merging required, and you can rename the Layers from the Linetype-based names rather than from names like OBJECTS.

 

This seems to do that, in very limited testing:

 

(foreach ent
  (mapcar 'cadr (ssnamex (ssget "_X"))); list of all entities
  (setq
    edata (entget ent)
    ltype
      (cond
        ((cdr (assoc 6 edata))); if there's a Linetype override
        ((cdr (assoc 6 (tblsearch "layer" (cdr (assoc 8 edata)))))); if there isn't -- Layer's Linetyp
      ); cond & ltype
  ); setq
  (if (not (member ltype laylist)) (setq laylist (cons ltype laylist)))
  (entmod (subst (cons 8 ltype) (assoc 8 edata) edata))
    ; puts Linetype name in as Layer name, and creates Layer if it doesn't exist
); foreach
(foreach lay laylist
  (command "_.layer" "_ltype" lay lay ""); gives matching Linetype to each Layer
); foreach
(command "chprop" "all" "" "_ltype" "BYLAYER" "_color" "BYLAYER" "")

 

That won't take care of entities nested in Block definitions, nor change the Linetype and Color to ByLayer for entities not in the current space.  But barring those complications [which can be handled], you should then be able to Purge Layers and get rid of all those not named for Linetypes.


kameron1967 wrote:

.... 

I ... would like to add 2 things to the routines.  After the layers are sorted, can you move any texts (not within blocks) - mtext/text - to be on a TEXT layer and move any blocks on a SYMBOL layer?  These two layers should have continous linetype.

.... 


Rather than moving them after sorting things into Layers [which would mean putting each one into some Linetype-named Layer first, and then finding them all again later and changing the Layer they're on again], it would be far more efficient to just move them to those TEXT or SYMBOL Layers right off the bat.  This [untested this time] ought to do that:

 

(defun chlay (layname)
  (entmod (subst (cons 8 layname) (assoc 8 edata) edata))
); defun

 

(foreach ent (mapcar 'cadr (ssnamex (ssget "_X"))); list of all entities
  (setq edata (entget ent))
  (cond
    ((wcmatch (cdr (assoc 0 edata)) "*TEXT"); [will also take Rtext, if you ever use that]
      (chlay "TEXT")
    ); Text/Mtext/Rtext condition
    ((= (cdr (assoc 0 edata)) "INSERT")
        ; will also take Xrefs, Windows Metafiles, old-style Hatch patterns
      (chlay "SYMBOL")
    ); Block/etc. condition
    (T ; all other entity types
      (setq ltype
        (cond
          ((cdr (assoc 6 edata))); if there's a Linetype override
          ((cdr (assoc 6 (tblsearch "layer" (cdr (assoc 8 edata)))))); if there isn't -- Layer's Linetype
        ); cond & ltype
      ); setq
      (if (not (member ltype laylist)) (setq laylist (cons ltype laylist)))
      (chlay ltype)
        ; puts Linetype name in as Layer name, and creates Layer if it doesn't exist
    ); everything-else condition
  ); cond
); foreach
(foreach lay laylist
  (command "_.layer" "_ltype" lay lay ""); gives matching Linetype to each Layer
); foreach
(command
  "_.layer" "_ltype" "Continuous" "TEXT,SYMBOL" ""
    ; [above line needed only if Layer(s) might already exist with other Linetype, which doesn't seem likely]
  "chprop" "all" "" "_ltype" "BYLAYER" "_color" "BYLAYER" ""
); command

*Expert Elite*
Kent1Cooper
Posts: 5,872
Registered: ‎09-13-2004
Message 2 of 10 (298 Views)

Re: Converting objects of certain linetype to a new layer based on that linetype

10-26-2012 07:10 PM in reply to: kameron1967

kameron1967 wrote:

... 

I would like help with converting all objects that has forced linetype to be on a linetype layer.

 

So if there are objects that have forced linetypes - dashed/hidden/phantom, etc., those entities would be moved to a linetype layer based on their forced linetype.   The entities would all be chaned to color bylayer, linetype bylayer.

.... 

.... the next and final step is to locate a the existing layers with matching linetype - say, OBJECTS with DASHED as a linetype, and merging it to that layer.

....


This does all but the last step [in limited testing], and changes the Linetype of each such Layer to match its name:
 

(foreach ent
  (mapcar 'cadr (ssnamex (ssget "_X"))); list of all entities
  (if (setq ltype (cdr (assoc 6 (setq edata (entget ent))))); has non-ByLayer Linetype
    (progn
      (if (not (member ltype laylist)) (setq laylist (cons ltype laylist))); list of override Linetypes/Layer names
      (entmod (subst (cons 8 ltype) (assoc 8 edata) edata))
        ; puts Linetype name in as Layer name, and creates Layer if it doesn't exist!
      (command "chprop" ent "" "_ltype" "BYLAYER" "_color" "BYLAYER" "")
    ); progn
  ); if
); foreach
(foreach lay laylist
  (command "_.layer" "_ltype" lay lay ""); gives matching Linetype to each Layer
); foreach
(command "_.regen")

 

For the last step, what if there are more than one Layer with a given Linetype?  Would you want to put things on any one of them?  What if there are none?  And if there is one and only one, would it not be better to just move the objects directly to it, and skip the middle-man of the linetype-named Layer?

Kent Cooper
Distinguished Contributor
kameron1967
Posts: 186
Registered: ‎09-05-2008
Message 3 of 10 (292 Views)

Re: Converting objects of certain linetype to a new layer based on that linetype

10-26-2012 08:48 PM in reply to: kameron1967

Hi Kent1Cooper,

 

Thank you so much for whipping up this nice routine.  I tested it on a drawing with only 0 layer and it generated the layers fine, based on the existing linetype.  I then brought in a new set of lines with hard coded linetypes and it merged successfully into the existing layers.

 

Now to answer you last questions below:

 

 

Q:For the last step, what if there are more than one Layer with a given Linetype? 

A: If there are 2 or 3, then we can move all to the first layer created under that linetype name

 

Q:Would you want to put things on any one of them? 

 

A: We'll move all similar linetypes to the first linetype name and purge out the rest.

Q:What if there are none

A: No layers or no linetypes - except for continuous?  If there is none, then don't do anything.

Q:And if there is one and only one, would it not be better to just move the objects directly to it, and skip the middle-man

of the linetype-named Layer?

A: If there is only one layer, a routine could be used to create just one linetype layer.

 

I have a plan to further rename these layers to different sets of standard layers after.  I just wanted to first consolidate the lines according to their linetypes.

 

Thank you for these wonderful questions.  I hope I've answered enough to give you an idea of what I needed, Kent1Cooper!  :smileyhappy:

 

 

*Expert Elite*
Kent1Cooper
Posts: 5,872
Registered: ‎09-13-2004
Message 4 of 10 (275 Views)

Re: Converting objects of certain linetype to a new layer based on that linetype

10-27-2012 05:34 AM in reply to: kameron1967

kameron1967 wrote:

.... 

Q:For the last step, what if there are more than one Layer with a given Linetype? 

A: If there are 2 or 3, then we can move all to the first layer created under that linetype name

....

Q:What if there are none

A: No layers or no linetypes - except for continuous?  If there is none, then don't do anything.

Q:And if there is one and only one, would it not be better to just move the objects directly to it, and skip the middle-man of the linetype-named Layer?

A: If there is only one layer, a routine could be used to create just one linetype layer.

 

I have a plan to further rename these layers to different sets of standard layers after.  I just wanted to first consolidate the lines according to their linetypes.

....


What I meant by "What if there are none?" was "What if there are no existing Layers with that Linetype assigned?"  I think from other answers that you would still want a Layer made that is named for the Linetype.

 

What I meant by "...if there is one and only one..." was "...if there is one and only one existing Layer with that Linetype assigned...".  Say your example Layer called OBJECTS with Dashed Linetype is the only Dashed-Linetype Layer in the drawing [other than the new one that's called DASHED].  I was asking whether it would be better to move things with an override Dashed Linetype directly to the OBJECTS Layer, rather than to a middle-man DASHED Layer that's later going to be merged into OBJECTS.  But since you're planning to rename Layers anyway, I have an idea.  Just determine for each entity whether it has a Linetype override.  If it does, change its Layer to the name of the Linetype.  If it doesn't, change its Layer to the name of the Linetype assigned to its Layer.  No merging required, and you can rename the Layers from the Linetype-based names rather than from names like OBJECTS.

 

This seems to do that, in very limited testing:

 

(foreach ent
  (mapcar 'cadr (ssnamex (ssget "_X"))); list of all entities
  (setq
    edata (entget ent)
    ltype
      (cond
        ((cdr (assoc 6 edata))); if there's a Linetype override
        ((cdr (assoc 6 (tblsearch "layer" (cdr (assoc 8 edata)))))); if there isn't -- Layer's Linetyp
      ); cond & ltype
  ); setq
  (if (not (member ltype laylist)) (setq laylist (cons ltype laylist)))
  (entmod (subst (cons 8 ltype) (assoc 8 edata) edata))
    ; puts Linetype name in as Layer name, and creates Layer if it doesn't exist
); foreach
(foreach lay laylist
  (command "_.layer" "_ltype" lay lay ""); gives matching Linetype to each Layer
); foreach
(command "chprop" "all" "" "_ltype" "BYLAYER" "_color" "BYLAYER" "")

 

That won't take care of entities nested in Block definitions, nor change the Linetype and Color to ByLayer for entities not in the current space.  But barring those complications [which can be handled], you should then be able to Purge Layers and get rid of all those not named for Linetypes.

Kent Cooper
Distinguished Contributor
kameron1967
Posts: 186
Registered: ‎09-05-2008
Message 5 of 10 (262 Views)

Re: Converting objects of certain linetype to a new layer based on that linetype

10-27-2012 12:47 PM in reply to: Kent1Cooper

Kent,

 

Thank you for the second option.  I have one question though, when you say "If it does have a linetype override, change its Layer to the name of the Linetype.." - does that mean that once the layer name has been changed because it contains one or more entities that have forced linetype but in truth is a layer containing only continuos linetypes.  So that when the layer has been changed to have DASHED linetype, then all other objects that do not have any linetype override will automatically inherit the DASHED linetype, which might not be what we wanted.  I hope I'm making myself clear.

 

Basically, the few entities that have forced linetypes residing on an OBJECT layer which has a continuous linetype, should be moved to the DASHED linetype.  This way the entities on OBJECT layer with no forced linetype will continue to have continous linetype because OBJECT layer will not be modified to accommodate the few forced linetypes.

 

Hope that's clear.

 

Thanks for all your effort, Kent.  Kudos.

*Expert Elite*
Kent1Cooper
Posts: 5,872
Registered: ‎09-13-2004
Message 6 of 10 (257 Views)

Re: Converting objects of certain linetype to a new layer based on that linetype

10-27-2012 12:58 PM in reply to: kameron1967

kameron1967 wrote:

.... when you say "If it does have a linetype override, change its Layer to the name of the Linetype.." - does that mean that once the layer name has been changed because it contains one or more entities that have forced linetype but in truth is a layer containing only continuos linetypes.  ....


Maybe I should have been more long-winded about it.  I meant if an entity has a linetype override, put it on the Layer that has that Linetype name as its Layer name.  "Change its Layer" was intended to mean "change [or, move] it to a different Layer" rather than change anything about the Layer it's on to begin with.  And that's how the routine does it -- it doesn't change anything about any existing Layers, but only moves each entity to a Layer with the name of its Linetype, whether that Linetype comes from the Layer it's on via ByLayer, or is a Linetype override.

Kent Cooper
Distinguished Contributor
kameron1967
Posts: 186
Registered: ‎09-05-2008
Message 7 of 10 (252 Views)

Re: Converting objects of certain linetype to a new layer based on that linetype

10-27-2012 05:28 PM in reply to: Kent1Cooper

Excellent.  I think we're set now.  Thanks again for the routine, Kent.  Wonderful support you're providing!

Distinguished Contributor
kameron1967
Posts: 186
Registered: ‎09-05-2008
Message 8 of 10 (217 Views)

Re: Converting objects of certain linetype to a new layer based on that linetype

10-29-2012 09:56 AM in reply to: Kent1Cooper

Kent,

 

I finally had a chance to test the routine on actual drawings and would like to add 2 things to the routines.  After the layers are sorted, can you move any texts (not within blocks) - mtext/text - to be on a TEXT layer and move any blocks on a SYMBOL layer?  These two layers should have continous linetype.

 

Thanks in advance, Kent.

 

 

*Expert Elite*
Kent1Cooper
Posts: 5,872
Registered: ‎09-13-2004
Message 9 of 10 (202 Views)

Re: Converting objects of certain linetype to a new layer based on that linetype

10-29-2012 12:48 PM in reply to: kameron1967

kameron1967 wrote:

.... 

I ... would like to add 2 things to the routines.  After the layers are sorted, can you move any texts (not within blocks) - mtext/text - to be on a TEXT layer and move any blocks on a SYMBOL layer?  These two layers should have continous linetype.

.... 


Rather than moving them after sorting things into Layers [which would mean putting each one into some Linetype-named Layer first, and then finding them all again later and changing the Layer they're on again], it would be far more efficient to just move them to those TEXT or SYMBOL Layers right off the bat.  This [untested this time] ought to do that:

 

(defun chlay (layname)
  (entmod (subst (cons 8 layname) (assoc 8 edata) edata))
); defun

 

(foreach ent (mapcar 'cadr (ssnamex (ssget "_X"))); list of all entities
  (setq edata (entget ent))
  (cond
    ((wcmatch (cdr (assoc 0 edata)) "*TEXT"); [will also take Rtext, if you ever use that]
      (chlay "TEXT")
    ); Text/Mtext/Rtext condition
    ((= (cdr (assoc 0 edata)) "INSERT")
        ; will also take Xrefs, Windows Metafiles, old-style Hatch patterns
      (chlay "SYMBOL")
    ); Block/etc. condition
    (T ; all other entity types
      (setq ltype
        (cond
          ((cdr (assoc 6 edata))); if there's a Linetype override
          ((cdr (assoc 6 (tblsearch "layer" (cdr (assoc 8 edata)))))); if there isn't -- Layer's Linetype
        ); cond & ltype
      ); setq
      (if (not (member ltype laylist)) (setq laylist (cons ltype laylist)))
      (chlay ltype)
        ; puts Linetype name in as Layer name, and creates Layer if it doesn't exist
    ); everything-else condition
  ); cond
); foreach
(foreach lay laylist
  (command "_.layer" "_ltype" lay lay ""); gives matching Linetype to each Layer
); foreach
(command
  "_.layer" "_ltype" "Continuous" "TEXT,SYMBOL" ""
    ; [above line needed only if Layer(s) might already exist with other Linetype, which doesn't seem likely]
  "chprop" "all" "" "_ltype" "BYLAYER" "_color" "BYLAYER" ""
); command

Kent Cooper
Distinguished Contributor
kameron1967
Posts: 186
Registered: ‎09-05-2008
Message 10 of 10 (178 Views)

Re: Converting objects of certain linetype to a new layer based on that linetype

10-30-2012 08:43 AM in reply to: Kent1Cooper

Finally tested it and it worked like a charm.  Thanks for the awesome routine, Kent! :smileyhappy:

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Do you have 60 seconds to spare? The Autodesk Community Team is revamping our site ranking system and we want your feedback! Please click here to launch the 5 question survey. As always your input is greatly appreciated.