Lisp to [check and close Polylines selected, Add a vertex in the longer straight side and make it the first vertex]

Lisp to [check and close Polylines selected, Add a vertex in the longer straight side and make it the first vertex]

VincenzoPepe
Explorer Explorer
1,245 Views
13 Replies
Message 1 of 14

Lisp to [check and close Polylines selected, Add a vertex in the longer straight side and make it the first vertex]

VincenzoPepe
Explorer
Explorer

Hi everyone,

I'm very new to lisp and need for your help,

I need for a lisp function to help me check polylines before sending to CNC machine.

I'm current working on autocad 2021 (don't know if lisp language is different by Autocad version) 

 

I would like to achive this:

Sending parts to the CNC, to let the tool start from the middle of a long side, i need to check polylines i select to:

  • Close them if open,
  • Insert a vertex in the longest straight line,
  • make that vertex the first vertex,

here a example draft of the problem i need to solve.

 

Thanks in advance for helping.

Enzo

acad_48cNNtiKbE.png

0 Likes
Accepted solutions (2)
1,246 Views
13 Replies
Replies (13)
Message 2 of 14

ВeekeeCZ
Consultant
Consultant

Possibly something like this.

 

(vl-load-com)

(defun c:PForCNC ( / s i j d e x m y)
  
  (if (setq s (ssget "_:L" '((0 . "LWPOLYLINE"))))
    
    (repeat (setq i (sslength s))
      (setq e (ssname s (setq i (1- i)))
	    d (entget e)
	    m (cdr (assoc 90 d))
	    x '(0 . 0)
	    j 0)
      
      (repeat (if (zerop (getpropertyvalue e "Closed")) (1- m) m)
	(and (setq j (1+ j))
	     (zerop (getpropertyvalue e "Vertices" (1- j) "Bulge"))
	     (setq y (- (vlax-curve-getdistatparam e j) (vlax-curve-getdistatparam e (1- j))))
	     (> y (cdr x))
	     (setq x (cons j y))))
      
      (setq d (append (vl-remove-if '(lambda (x) (vl-position (car x) '(10 40 41 42 91 90))) d)		; core
		      (list (cons 90 (1+ m)))
		      (list (cons 10 (vlax-curve-getpointatparam e (- (car x) 0.5))))   ; new vertex
		      (vl-member-if '(lambda (q) (equal q (cons 10 (reverse (cdr (reverse (vlax-curve-getpointatparam e (car x)))))) 1e-6)) d) ; from new vertex to the end
		      (reverse (cdr (vl-member-if '(lambda (q) (equal q (cons 10 (reverse (cdr (reverse (vlax-curve-getpointatparam e (car x)))))) 1e-6))
				      (reverse (vl-remove-if-not '(lambda (x) (vl-position (car x) '(10 40 41 42 91))) d))))))) 	; from core to new vertex.
      (vl-catch-all-apply 'entmod (list d))
      (vl-catch-all-apply 'setpropertyvalue (list e "Closed" 1))))
  (princ)
  )

 

0 Likes
Message 3 of 14

ronjonp
Mentor
Mentor

What is the 'correct' solution for closing this example?

ronjonp_0-1707233482160.png

 

0 Likes
Message 4 of 14

Kent1Cooper
Consultant
Consultant

I would suggest forcing the closing of an open Polyline before looking for where to add a vertex, which would mean:

1.  You don't need to figure the number for that second (repeat) function differently depending on whether it's open or closed; and

2.  It allows for the possibility that the added closing segment could be the longest one, such as with an initial Polyline something like this:

Kent1Cooper_0-1707233744068.png

Kent Cooper, AIA
Message 5 of 14

Sea-Haven
Mentor
Mentor
0 Likes
Message 6 of 14

komondormrex
Mentor
Mentor
Accepted solution

hey there,

another one

(defun c:pline_cnc (/ param_index pline_object param_list max_length_index segment_list vertex_bulge_list)
	(foreach pline (vl-remove-if 'listp (mapcar 'cadr (ssnamex (ssget '((0 . "lwpolyline"))))))
		(setq param_index -1 param_list nil)
		(vla-put-closed (setq pline_object (vlax-ename->vla-object pline)) :vlax-true)
		(repeat (fix (vlax-curve-getendparam pline))
			(setq param_list (append param_list (list (setq param_index (1+ param_index)))))
		)
		(vla-setbulge pline_object (last param_list) 0)
		(if (vl-some '(lambda (parameter) (zerop (vla-getbulge pline_object parameter))) param_list)
			(progn
				(setq max_length_index (car (vl-sort-i (mapcar '(lambda (segment) (if (zerop (vla-getbulge pline_object (car segment))) 
															  						  (apply 'distance 
																					  		 (mapcar '(lambda (param) (vlax-curve-getpointatparam pline param)) 
																							 		  segment
																							 )
																					  ) 
															  						  0
														  						  )
																)   
																(setq segment_list (mapcar 'list param_list (append (cdr param_list) '(0))))
							   						   )
							   						   '>=
											)
				   					   )
				)
				(vlax-invoke pline_object 'addvertex 
										  (1+ max_length_index) 
										  (mapcar '* '(0.5 0.5) 
										  			  (mapcar '+ (vlax-curve-getpointatparam pline max_length_index)
																 (vlax-curve-getpointatparam pline (1+ max_length_index))
													  )
										  )
				)
				(setq param_list (append param_list (list (1+ (last param_list))))
					  param_list (append (member (1+ max_length_index) param_list) (reverse (cdr (member (1+ max_length_index) (reverse param_list)))))   
					  vertex_bulge_list (mapcar '(lambda (param) (list (vlax-curve-getpointatparam pline param) (vla-getbulge pline_object param))) param_list)  
				)
				(vlax-put pline_object 'coordinates (apply 'append (mapcar '(lambda (element) (mapcar '+ '(0 0) (car element))) vertex_bulge_list))) 
				(mapcar '(lambda (bulge param) (vla-setbulge pline_object param bulge)) 
						 (mapcar 'cadr vertex_bulge_list)
						 (vl-sort param_list '<)
				)
			)
		)
	)
	(princ)
)
0 Likes
Message 7 of 14

VincenzoPepe
Explorer
Explorer

Hi ВeekeeCZ,

thanks a lot for your help,

I tested your code and I got some errors.

 

I've selected the three polylines together,

the first on the list (I think) has been closed,

then got this error:

 

"Select objects: 1 found, 2 total
Select objects: 1 found, 3 total
Select objects:
; error: bad argument type: lentityp nil"

 

I also tested the command one polyline by one and worked perfectly except on this polyline.

Here it did something strange, I can't understand.

text "current 1° vertex" indicates 1° vertex before the command is applied.

acad_J7UK7J7umu.png

0 Likes
Message 8 of 14

VincenzoPepe
Explorer
Explorer
hi ronjonp, thanks for the reply
the red one is the correct solution.
0 Likes
Message 9 of 14

VincenzoPepe
Explorer
Explorer

Hi komondormrex,

thanks a lot for your help too,

I've tested your code too and I got again some errors.

 

once selected together the three polylines,

all three were closed, but the one on the left side with fillets on the corner with the 1° vertex, closed the polyline unexpectedly compared to if manually closed by Pedit command:

 

Pedit command recreates the fillet disappeared as I Opened the polyline on purpose for this demo test file.

I hope my explanation is clear.

 

acad_d7ZwRxA6QE.png

0 Likes
Message 10 of 14

komondormrex
Mentor
Mentor
Accepted solution

hey there,

i have done it purposely to avoid some unpredictable pline closings with unknown arc segment. you have tried a synthetic test of opening a closed  with certain arc pline. to retain a bulge of that arc segment comment out or delete line 8 in the code) 

0 Likes
Message 11 of 14

ВeekeeCZ
Consultant
Consultant

Try the updated code. If you find more issues, post the dwg, not an image.

Message 12 of 14

VincenzoPepe
Explorer
Explorer
tnx,
I will try as soon as i can.
0 Likes
Message 13 of 14

VincenzoPepe
Explorer
Explorer

here it is,

Excuse me if didn’t do it before.

tnx again

 

0 Likes
Message 14 of 14

VincenzoPepe
Explorer
Explorer

Hi All,

I didn't pass the test I did on the cnc machine, but so far all the tests done worked perfectly with the komondormrex code with line 8 commented.

many thanks again to all of you.

Enzo

0 Likes