Convert entitys to multilines and entget transformed multilines.

Convert entitys to multilines and entget transformed multilines.

Browning_Zed
Advocate Advocate
1,064 Views
8 Replies
Message 1 of 9

Convert entitys to multilines and entget transformed multilines.

Browning_Zed
Advocate
Advocate

Hello everyone.
I have some code that converts selected linear entities to multilines. I intended to do the conversion in two ways, depending on a certain condition:
• if the entities are already selected then the program will convert them to multilines.
• if there are no selected entities, then the entsel function is started, and the loop is running for transforming picked entities.
Here's the code:

(defun c:Convert2MLine ( / ss teller en ent PtLst )
	(setq ss (ssget "_I" '((0 . "LINE,LWPOLYLINE"))))
	(setq teller 0)
	(if ss
		(repeat (sslength ss)
			(setq en (ssname ss teller))
			(setq ent (entget en))
			(if (= "LINE" (cdr (assoc 0 ent)))
				(setq PtLst (list (cdr (assoc 10 ent)) (cdr (assoc 11 ent))))
			)
			(if (= "LWPOLYLINE" (cdr (assoc 0 ent)))
				(setq PtLst (LM:MAssoc 10 ent))
			)
			(command "_MLINE" (foreach pt PtLst (command pt)))
			(entdel en)
			(setq teller (1+ teller))
		)
		(while
			(setvar 'errno 0)
			(progn
				(while
					(progn
						(setvar 'errno 0)
						(setq en (car (entsel "\nPick a polyline: ")))
						(cond
							(   (= 7 (getvar 'errno))
								(princ "\nMissed, try again.")
							)
							(   (= 'ename (type en))
								(if (/= (cdr (assoc 0 (entget en))) "LWPOLYLINE")
									(princ "\nInvalid object selected.")
								)
							)
						)
					)
				)
			)
			(if (= "LINE" (cdr (assoc 0 ent)))
				(setq PtLst (list (cdr (assoc 10 ent)) (cdr (assoc 11 ent))))
			)
			(if (= "LWPOLYLINE" (cdr (assoc 0 ent)))
				(setq PtLst (LM:MAssoc 10 ent))
			)
			(command "_MLINE" (foreach pt PtLst (command pt)))
			(entdel en)
		)
	)
	(princ)
)
(defun LM:MAssoc ( key lst / pair return )
 (while (setq pair (assoc key lst))
   (setq return (cons (cdr pair) return) lst (cdr (member pair lst)))
 )
 (reverse return)
)


Now I have achieved that only the first part of the program is executed correctly if the entities were already selected before the command was run. That is, only ssget works, but entsel does not work.
I would like to ask for help to implement the following features in this routine:
1. Correct execution program using entsel method (if the entities were not previously selected before starting the command).
2. If possible, expand the list of objects available for conversion to multilines, namely, I would like the following objects to be available for conversion: AcDbLine, AcDbPolyline, AcDb2dPolyline, AcDb3dPolyline.
3. The most important point. The ability to get the multilines that were created as entities that can be manipulated. That is, roughly speaking, I need to return the created multilines as a set of entities so that can later change their properties using vla methods.
I hope I didn't express my thoughts too chaotically.
Any help would be greatly appreciated.
Thank you in advance!

0 Likes
Accepted solutions (1)
1,065 Views
8 Replies
Replies (8)
Message 2 of 9

Kent1Cooper
Consultant
Consultant

@Browning_Zed wrote:

.... if there are no selected entities, then the entsel function is started, and the loop is running for transforming picked entities....


Clarify:  If there are no pre-selected qualifying objects, do you want to pick them one at a time, and have each converted as you go, as the description seems to say?  Or is it acceptable [or preferred] to go into (ssget) so you can pick multiple objects such as with window or crossing or fence selection, remove option, etc., and have them all converted collectively?

 

EDIT:  And other questions arise....  You won't be able to duplicate the shape of a 3DPolyline with an Mline if it's not planar, nor of a 2D "heavy" or "lightweight" one if it contains any arc segments, so what should happen if those situations occur?  Should it have the setting of the Multiline Style built in, so you don't just get whatever style happens to be current?  Should [presumably] Zero justification be built in, so you don't just get whatever alignment happens to be current?

Kent Cooper, AIA
0 Likes
Message 3 of 9

Browning_Zed
Advocate
Advocate

If no objects have been selected, then the entsel loop is started and the objects are converted one at a time.

EDIT. If a 3D polyline is selected, then it is sufficient that each of its vertices is conventionally accepted as 0, that is, the multiline should be located at the zero level. If 2D or LW polylines with arc segments are selected, then these segments can be replaced as linear ones.
Setting the properties of the created multiline as I indicated in the 3rd paragraph of the top post. That is, get a set of created multilines, and then do something like: vla-put-layer, vla-put-justification, etc. But if you cannot set the style of the multiline with the vla method, then before the multiline is created, change the system variable CMLSTYLE.

0 Likes
Message 4 of 9

Kent1Cooper
Consultant
Consultant

@Browning_Zed wrote:

....

Now I have achieved that only the first part of the program is executed correctly if the entities were already selected before the command was run. That is, only ssget works, but entsel does not work.
....


You are missing the pulling of the entity data list:

....
    (setq en (car (entsel "\nPick a polyline: ")))
....
    ( (= 'ename (type en))
      (if (/= (cdr (assoc 0 (entget en))) "LWPOLYLINE")
....

    (setq ent (entget en)); <-- missing this from selection-set portion
....
    (if (= "LINE" (cdr (assoc 0 ent)))
      (setq PtLst (list (cdr (assoc 10 ent)) (cdr (assoc 11 ent))))
    )
    (if (= "LWPOLYLINE" (cdr (assoc 0 ent)))
      (setq PtLst (LM:MAssoc 10 ent))
    )
....

 

You also have code to convert a Line, but you have disallowed selection of one.

Kent Cooper, AIA
Message 5 of 9

Browning_Zed
Advocate
Advocate

Yes, indeed this is my oversight, I missed a line in the code. Thanks to Kent1Cooper! Code execution with entsel now works as expected. The question remains how to return a set of entities (converted multilines), that it was possible to set properties for them.

0 Likes
Message 6 of 9

Kent1Cooper
Consultant
Consultant

@Browning_Zed wrote:

.... The question remains how to return a set of entities (converted multilines), that it was possible to set properties for them.


Up at the top, start an initially-empty selection set:

....

  (setq teller 0)

  (setq mlines (ssadd))
  (if ss

....

 

Then, immediately after each MLINE command, add the result to that set:

....

  (command "_MLINE" (foreach pt PtLst (command pt)))
  (ssadd (entlast) mlines)

  (entdel en)

....

 

And at the end, you can use that mlines variable to do with them what you want.  If you want it to leave you with all of them selected/highlighted/gripped for you:

 

(sssetfirst nil mlines)

Kent Cooper, AIA
0 Likes
Message 7 of 9

Browning_Zed
Advocate
Advocate

So, I tried to add these lines to the code, but it didn't work. As an example, I changed the multiline scale.

(defun c:Convert2MLine ( / ss teller en ent mlines PtLst )
	(setq ss (ssget "_I" '((0 . "LINE,LWPOLYLINE"))))
	(setq teller 0)
	(setq mlines (ssadd))
	(if ss
		(repeat (sslength ss)
			(setq en (ssname ss teller))
			(setq ent (entget en))
			(if (= "LINE" (cdr (assoc 0 ent)))
				(setq PtLst (list (cdr (assoc 10 ent)) (cdr (assoc 11 ent))))
			)
			(if (= "LWPOLYLINE" (cdr (assoc 0 ent)))
				(setq PtLst (LM:MAssoc 10 ent))
			)
			(command "_MLINE" (foreach pt PtLst (command pt)))

            (ssadd (entlast) mlines)
            (vla-put-mlinescale (vlax-ename->vla-object mlines) 1)

			(entdel en)
			(setq teller (1+ teller))
		)
		(while
			(setvar 'errno 0)
			(progn
				(while
					(progn
						(setvar 'errno 0)
						(setq en (car (entsel "\nPick a polyline")))
						(cond
							(   (= 7 (getvar 'errno))
								(princ "\nMissed, try again.")
							)
							(   (= 'ename (type en))
								(if (/= (cdr (assoc 0 (entget en))) "LWPOLYLINE")
									(princ "\nInvalid object selected.")
								)
							)
						)
					)
				)
			)
			(setq ent (entget en))
			(if (= "LINE" (cdr (assoc 0 ent)))
				(setq PtLst (list (cdr (assoc 10 ent)) (cdr (assoc 11 ent))))
			)
			(if (= "LWPOLYLINE" (cdr (assoc 0 ent)))
				(setq PtLst (LM:MAssoc 10 ent))
			)
			(command "_MLINE" (foreach pt PtLst (command pt)))

            (ssadd (entlast) mlines)
            (vla-put-mlinescale (vlax-ename->vla-object mlines) 1)

			(entdel en)
		)
	)
	(princ)
)
(defun LM:MAssoc ( key lst / pair return )
 (while (setq pair (assoc key lst))
   (setq return (cons (cdr pair) return) lst (cdr (member pair lst)))
 )
 (reverse return)
)
0 Likes
Message 8 of 9

Kent1Cooper
Consultant
Consultant
Accepted solution

The mlines variable holds a selection set.  You can't convert a selection set to a VLA object, only an entity name.  Nor can you assign an MLine scale to a selection set, only [under this method] to a single VLA object.  I think you need to do this:

 

(ssadd (entlast) mlines)
(vla-put-mlinescale (vlax-ename->vla-object (entlast)) 1)

Kent Cooper, AIA
Message 9 of 9

Browning_Zed
Advocate
Advocate

Thanks a lot, Kent1Cooper. It works great now!

0 Likes