Reassign Entity Materials

Reassign Entity Materials

Bryan.McLoughlin5CF88
Participant Participant
885 Views
17 Replies
Message 1 of 18

Reassign Entity Materials

Bryan.McLoughlin5CF88
Participant
Participant

Hi all

 

I have a situation with AutoCAD model imports from inventor whereby I am needing to move AutoCAD entities (3d solids) to predefined AutoCAD layers (all currently on layer 0) based on the entities material property. The AutoCAD material property is transferred from Inventor (part appearance) but in some cases the transfer will result in duplication of materials in AutoCAD. So for example I am looking for an AutoCAD material of "Beams" but might have "Beams(1), beams(2) etc". The lisp I have will successfully move objects to the correct layer (which will have the same name as the material property) but fails for the duplications. These duplications will always have a (*) tagged onto the end of what I need, * being some random number.

I am now trying to iterate through the AutoCAD model and change materials from say "Beams(1), beams(*)" to the correct material "Beams" so that I can then process with my working lisp.

my knowledge of lisp is shaky at best so below is my latest attempt which is not working. Any help, ideas, suggestions are much appreciated.

 

 

0 Likes
Accepted solutions (4)
886 Views
17 Replies
Replies (17)
Message 2 of 18

paullimapa
Mentor
Mentor

Could you also share a sample drawing file along with these assigned materials ?


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 3 of 18

Bryan.McLoughlin5CF88
Participant
Participant

hi Paul Li

 

Thanks for your response. dwg included which contains all my required layers and a sample of the model. items in the model which are colored are on the correct layer with matching material, others are all still on layer 0 and have (*) appended to the material field. these I am trying to work out how to reassign to the correct material.

 

Thanks

0 Likes
Message 4 of 18

paullimapa
Mentor
Mentor

Can you also post a dwg before you run the lisp so we can all compare what happens before vs after?

Taking a quick glance at your code:

Questions:

1. What is this function for which you've included but I don't see it used any where:

(get-material-name)

2. You have this condition statement which checks names of materials:

(cond
	((wcmatch mat "(")
	 (Setq pos (vl-string-position (ascii "(") mat)
	 (Setq matNew (substr mat 1 pos)
	 )
	 (vla-put-material ent matNew)
	)
	(t
	 (princ "\nNothing changed.")
	)
      )

I don't see how you can have a match with the first condition as:

(wcmatch mat "(")

Since you say a material name actually contains multiple letters like "Gratings" "Gratings(1)" "Gratings(2)"

To match a pattern that includes an open parenthesis, the code would change to look like this:

(wcmatch mat "*(*")

Once a match is found you can use the following function to get the material name before the open parenthesis:

;;;--- aec_sb_txt function returns only portion of txt before found pattern
; txt = text string
; pat = text pattern
; Usage: 
; (aec_sa_txt "This is before [width] and after" "[width]")
; Returns:
; "This is before "
(defun aec_sb_txt (txt pat / pos tmp)
  (if (wcmatch txt (strcat "*" pat "*"))
   (progn
    (setq pos (vl-string-search pat txt))
    (setq tmp (substr txt 1 pos)) ; txt before
   )
  )
  tmp
)

so do the following:

(setq matnew (aec_sb_txt mat "(")) ; retrieves material name before open parenthesis

 

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 5 of 18

komondormrex
Mentor
Mentor

hey there,

check this one

 

;*****************************************************************************************************************************************************

(defun check_layer (layer_name)
	(if (vl-catch-all-error-p (vl-catch-all-apply 'vla-item (list (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))) layer_name)))
			(vla-add (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))) layer_name)
	)
	layer_name
)

;*****************************************************************************************************************************************************

(defun check_material (material_name)
	(if (vl-catch-all-error-p (vl-catch-all-apply 'vla-item (list (vla-get-materials (vla-get-activedocument (vlax-get-acad-object))) material_name)))
			(vla-add (vla-get-materials (vla-get-activedocument (vlax-get-acad-object))) material_name)
	)
	material_name
)

;*****************************************************************************************************************************************************

(defun c:set_material (/ 3dsolid_sset material_name layer_name material_list count)
	(setq count 0)
	(if (setq 3dsolid_sset (ssget "_x" '((0 . "3dsolid"))))
		(foreach 3dsolid (mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr (ssnamex 3dsolid_sset))))
			(if (= "0" (vla-get-layer 3dsolid)) 
				(progn
					(if (or 
							(wcmatch (setq material_name (vla-get-material 3dsolid)) "*(#)")
							(wcmatch (setq material_name (vla-get-material 3dsolid)) "*(##)")
							(wcmatch (setq material_name (vla-get-material 3dsolid)) "*(###)")
						)
							(setq material_list (if (not (member material_name material_list)) (cons material_name material_list) material_list) 
								  layer_name (substr material_name 1 (vl-string-position (ascii "(") material_name))
							)  
							(setq layer_name material_name)
					)
					(vla-put-layer 3dsolid (check_layer layer_name)) 
					(vla-put-material 3dsolid (check_material layer_name))
					(princ (strcat "\rMaterial set to 3dsolids: " (itoa (setq count (1+ count))))) 
				)
			)	

		)
	)
	(foreach material material_list (vla-delete (vla-item (vla-get-materials (vla-get-activedocument (vlax-get-acad-object))) material)))
	(princ (strcat "\rMaterial set to 3dsolids: " (itoa count)))
	(princ)
)

;*****************************************************************************************************************************************************

 

updated_2

0 Likes
Message 6 of 18

Bryan.McLoughlin5CF88
Participant
Participant

Hi Paul

Answers below

1. I suspect that bit of code relates to the layer creation which is not included in what i have posted

2. I have tried various options using wcmatch with no success so i agree your suggestion to use wcmatch mat "*(*" makes more sense

3. Your function looks like wizardry to me, is this used as is? being called up by this line 

(setq matnew (aec_sb_txt mat "(")) ; retrieves material name before open parenthesis

 

drawing attached with no layer changes (first open after export from inventor)

 

Thanks 

0 Likes
Message 7 of 18

paullimapa
Mentor
Mentor

As long as you include the entire defun aec_sb_txt code I posted earlier then the setq newmat line of code will work. Give it a try. 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 8 of 18

Bryan.McLoughlin5CF88
Participant
Participant

Hi

Thanks for the code. I am getting the following error when running - 

"Select objects:
; error: Automation Error. Calling method SetObjectId of interface IAcadBaseObject failed". I am not sure what your code is doing (or at least all of it) but does it rely on there being a predefined layer to match the material (after any of the "(*)" have been stripped out? or does it create layers from the material list?

I am wondering if the required layers should be checked / created (along with their colors, linetypes etc) prior to your code running? if so would I just add these at the top (example attached). Also if there happens to be an object with a material that is not defined can this be put onto a layer called "undefined" or such?

 

many thanks

0 Likes
Message 9 of 18

Bryan.McLoughlin5CF88
Participant
Participant

Hi Paul Li

 

Thanks for your assistance. I am having no luck here unfortunately as I get this error

"Command: SORTBYMATERIAL Nothing changed.; error: bad function: T" when running. I'm sure its something I have done or not done. I have included the Layer creation in the code (see attached) which does work when run (layers get created).

any ideas / advice are much appreciated.

 

Cheers

 

bryan

 

0 Likes
Message 10 of 18

paullimapa
Mentor
Mentor

attached is SortByMaterial.lsp by itself for you to test which worked for me.

also attached is Mat_Translation.lsp which includes the above and everything else when you're ready to run that.


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 11 of 18

Bryan.McLoughlin5CF88
Participant
Participant

Hi Paul Li

 

I got SortByMaterial to work on the dwg you included but then tried to paste in a larger dataset and rerun with failures. I am including the dwg with dataset in the hope you can identify the error.

 

"Nothing changed.; error: Automation Error. Key not found" this the last line when running.

 

 

many thanks by the way for your assistance.

 

Cheers

 

Bryan

0 Likes
Message 12 of 18

komondormrex
Mentor
Mentor

hey,

your welcome.

the code does the following.

1. user selects manually 3dsolids (may be automated to select all)

2. checks the layer name of the 3dsolid. if it holds the pattern like (1) or (12) or (123) where 1,2,3 are any numerical, it strips that pattern from the layer name and changes the layer and material of the 3dsolid to that name. checks if the layer and material is existed in the drawing is performed.

3. gathers the material with pattern in the list.

4. upon completion code deletes materials gathered in the list.

layers setting has no difference to the code.

 

check update above.

0 Likes
Message 13 of 18

Bryan.McLoughlin5CF88
Participant
Participant
Brilliant,
Where would i change to auto select all 3d solids and did you work out where my error was coming from?

Cheers
0 Likes
Message 14 of 18

komondormrex
Mentor
Mentor
Accepted solution

change line 23 to this. changed the selection method to entire database -> "_x"

 

(if (setq 3dsolid_sset (ssget "_x" '((0 . "3dsolid"))))

 

 

0 Likes
Message 15 of 18

paullimapa
Mentor
Mentor
Accepted solution

Looks like the problem had to do with materials that actually had open & closed parenthesis in them.

So I changed the wcmatch criteria to only look for #s within the parenthesis and that worked.

(wcmatch mat "*([1234567890]*")

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 16 of 18

Bryan.McLoughlin5CF88
Participant
Participant
Accepted solution
Excellent, many thanks Komondormrex.
0 Likes
Message 17 of 18

Bryan.McLoughlin5CF88
Participant
Participant
Thanks Paull Li

That worked, genius.
0 Likes
Message 18 of 18

paullimapa
Mentor
Mentor
Accepted solution

glad to have helped...cheers!!!


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes