Polyline lisp

Polyline lisp

ricc_donofrio
Participant Participant
890 Views
12 Replies
Message 1 of 13

Polyline lisp

ricc_donofrio
Participant
Participant
 

 Hi everyone! I need a lisp that is able to export the length of the segments of an open polyline and the vertex angles into a .csv file. Can you help me? Thank you.

0 Likes
Accepted solutions (2)
891 Views
12 Replies
Replies (12)
Message 2 of 13

paullimapa
Mentor
Mentor

look at my updated code below

 

 

 

 

 


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

ronjonp
Mentor
Mentor
Accepted solution

@ricc_donofrio 

Give this a try .. it breaks up the information per *POLYLINE selected. If you have arc segments it pulls the angle from the middle of it.

 

(defun c:foo (/ _writefile n s r)
  ;; RJP » 2023-02-23
  ;; Outputs distances and angles of *POLYLINE segments
  (defun _writefile (fn l / f)
    (cond ((and (eq 'str (type fn)) (setq f (open fn "w")))
	   (foreach x l (write-line (vl-princ-to-string x) f))
	   (close f)
	   fn
	  )
    )
  )
  (cond
    ((setq s (ssget '((0 . "*POLYLINE"))))
     (foreach e	(vl-remove-if 'listp (mapcar 'cadr (ssnamex s)))
       (setq n (vlax-curve-getendparam e))
       (repeat (fix n)
	 (setq
	   r (cons (list (- (vlax-curve-getdistatparam e n) (vlax-curve-getdistatparam e (1- n)))
			 (angle '(0 0 0) (vlax-curve-getfirstderiv e (- n 0.5)))
		   )
		   r
	     )
	 )
	 (setq n (1- n))
       )
       (setq r (cons (list (cdr (assoc 0 (entget e))) (cdr (assoc 5 (entget e)))) r))
     )
     (_writefile
       (print (strcat (getvar 'dwgprefix) "DistanceAngles.csv"))
       (append
	 '("DISTANCE, ANGLE (RADIANS)")
	 (mapcar
	   '(lambda (x) (strcat (vl-princ-to-string (car x)) ", " (vl-princ-to-string (cadr x))))
	   r
	 )
       )
     )
    )
  )
  (princ)
)

 

Output:

DISTANCE  ANGLE (RADIANS)
LWPOLYLINE  BB
5 0
12 1.5708
4 3.14159
3 4.71239
2 3.14159
9.05539 4.82305
LWPOLYLINE  C0
7.92077 4.71239
6.38016 0
2.95331 1.35204
1.43899 2.76875
7.2558 2.4702
LWPOLYLINE  C1
5.21002 3.53752
7.33387 5.47554
3.6774 0.616361
2.56326 1.59353
LWPOLYLINE  C2
4.20891 3.86802
3.46686 5.27029
4.05178 0.383026
2.00952 1.5563
LWPOLYLINE  C5
5 0
5 1.5708
5 3.14159
5 4.71239
0 Likes
Message 4 of 13

ricc_donofrio
Participant
Participant
Thanks for the reply. Unfortunately the values ​​of angles and lengths are wrong :(
0 Likes
Message 5 of 13

paullimapa
Mentor
Mentor

I've corrected the error of my ways.  If you're still looking for an alternative, this version will return the angle in both Radians & Degrees:

 

; PlnLenAng places distance of segment length & angle at pline's vertex
; Response to OP:
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/polyline-lisp/m-p/11777166#M444164
(defun c:PlnLenAng 
  (/
   *error* adoc ang del dst corect_ang csv csvfil eo 
   i lst luprec p0 p1 pick_poly_chk rad RtD text_height txtstr
  )
  (if(not(car (atoms-family 1 '("vl-load-com"))))(vl-load-com))
  ; error function
	(defun *error* (msg)
		(and
		  msg
		  (not (wcmatch (strcase msg) "*CANCEL*,*QUIT*,*BREAK*,*EXIT*"))
		  (princ (strcat "\nError: " msg))
		)
		(if
		  (= 8 (logand (getvar 'undoctl) 8))
		  (vla-endundomark acdoc)
		)
    (princ)
  ) ; defun *error*
  ; converts radians to degrees
  (defun RtD (r) (* 180.0 (/ r pi)))
  ; select pline validation
	(defun pick_poly_chk (/ e)
		(setq e (car(entsel "\nSelect Open Polyline: ")))
		(if 
      (or 
        (not e) 
        (= (getvar 'Errno) 7)
        (not (eq "LWPOLYLINE"(cdr(assoc 0 (entget e)))))
        (not (zerop (cdr(assoc 70 (entget e))))) ; not closed
      ) 
      (pick_poly_chk) 
      e
    )
	) ; defun pick_poly_chk
  ; angle adjustment
	(defun corect_ang (ang)(if (and (>= ang (* 0.5 pi))(< ang (* 1.5 pi))) (setq ang (+ ang pi))) ang)	
  ; main function
	(setq adoc (vla-get-activedocument (vlax-get-acad-object))) 
	(vla-endundomark adoc)
	(vla-startundomark adoc)
  (if(not *csv*)(setq *csv* (strcat(getvar"dwgprefix")(vl-filename-base (getvar"dwgname")))))
  (setq csv(getfiled "Enter Name of CSV File To Save Segment Distances & Angles" *csv* "csv" 1))
  (if csv
    (progn
     (setq *csv* csv)
     (setq csvfil (open *csv* "w")) ; open csv to write info
     (write-line (strcat"Length, Angle <Radians>, Angle <Degrees>") csvfil) ; segment length & angle Column Title
     (if(not *text_height*)(setq *text_height* (getvar"textsize")))
     (setq text_height (getreal (strcat"\nText height <" (rtos *text_height* 2 (getvar"luprec"))">: ")))
     (if(not text_height)(setq text_height *text_height*)(setq *text_height* text_height))
     (if(setq eo (pick_poly_chk)) ; pick pline
       (progn
        (foreach x (entget eo) ; get pline entity's data
         (if (= (car x) 10)
          (setq lst (append lst (list (cdr x)))) ; get pline vertices
         )
        )
        (setq luprec (getvar"luprec")) ; get current unit decimal precision
        (setq dst(mapcar 'distance lst (cdr lst))) ; get distance between vertices         
        (setq p0 (nth 0 lst)) ; get 1st point
        (setq p1 (nth 1 lst)) ; get 2nd point
        (setq ang (corect_ang(+ (angle p0 p1) (* 0.5 pi))))
        (setq i 0 del 0)
        (repeat (length dst)
         (setq p0 (nth i lst)) ; get point 
         (setq p1 (nth (1+ i) lst)) ; get next point 
         (setq del (nth i dst)) ; get distance value item from list
         (setq ang (rtd (setq rad (angle p0 p1)))) ; get angle
         (setq txtstr (strcat (rtos del 2 luprec)","(rtos rad 2 luprec)","(rtos ang 2 luprec))) ; segment length & angle in radians & degrees
        ; create text
         (entmakex
          (list
           (cons 0 "TEXT")	
           (cons 100 "AcDbEntity")
           (cons 100 "AcDbText")
           (cons 1 txtstr)
           (cons 10 p1)
           (cons 40 *text_height*)
           (cons 7 "STANDARD")
           (cons 8 "PlnLenAng")
           (cons 50 (corect_ang(+ (angle p0 p1) (* 0.5 pi))))
          )
         ) ; entmake
          (write-line txtstr csvfil) ; write info to csv
          (setq i (1+ i)) ; next list item
        ) ; repeat cycle through list of distances
        (close csvfil) ; close csv 
        (startapp "Notepad" *csv*) 
       ) ; progn
       (progn
         (princ"\nNo Open Pline Selected.")(princ)
       )
     ) ; if
    ) ; progn
    (progn
      (princ"\nNo CSV File Entered.")(princ)
    )
  ) ; if
	(vla-endundomark adoc)
  (princ)
) ; defun

 


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

ronjonp
Mentor
Mentor

@paullimapa You should update your previous post with this code. No reason to leave incorrect code around IMO.

0 Likes
Message 7 of 13

paullimapa
Mentor
Mentor

good thinking..I just didn't want to confuse the OP. But now how do I delete the 2nd post after updating the 1st?


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

ronjonp
Mentor
Mentor

@paullimapa Put a note for a moderator to remove it. Don't think you can do it.

0 Likes
Message 9 of 13

Sea-Haven
Mentor
Mentor

Replace all of post with "look at updated code below" rather than delete.

Message 10 of 13

ricc_donofrio
Participant
Participant

@paullimapa 

you were very kind to help me, I'd rather use your code, however it still doesn't provide the correct values ​​for lengths and angles. 
I am sending you a file to better show you what I need.
0 Likes
Message 11 of 13

paullimapa
Mentor
Mentor

I just ran FOO.lsp (left) & my PlnLenAng.lsp (right) and Distance/Length matches as well as Angle in Radians.

paulli_apa_0-1677254047460.png

 


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

paullimapa
Mentor
Mentor
Accepted solution

I again modified PlnLenAng.lsp code to meet your dwg angle requirements...give this a try:

; PlnLenAng places distance of segment length & angle at pline's vertex
; Response to OP:
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/polyline-lisp/m-p/11777166#M444164
(defun c:PlnLenAng 
  (/
   *error* adoc ang ang_lst del dst DtR corect_ang csv csvfil eo 
   i lst lst2 luprec p0 p1 pick_poly_chk rad RtD text_height txtstr w_ang?
  )
  (if(not(car (atoms-family 1 '("vl-load-com"))))(vl-load-com))
  ; error function
	(defun *error* (msg)
		(and
		  msg
		  (not (wcmatch (strcase msg) "*CANCEL*,*QUIT*,*BREAK*,*EXIT*"))
		  (princ (strcat "\nError: " msg))
		)
		(if
		  (= 8 (logand (getvar 'undoctl) 8))
		  (vla-endundomark acdoc)
		)
    (princ)
  ) ; defun *error*
  ; w_ang? function by CADaSchtroumpf modified to return angle in degrees using lunit prec
  ; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/list-polyline-angles/m-p/3019110#M296526
  (defun w_ang? ( p1 px p2 / l_pt l_d p ang)
	 (setq
		l_pt (mapcar '(lambda (x) (list (car x) (cadr x))) (list px p1 p2))
		l_d (mapcar 'distance l_pt (append (cdr l_pt) (list (car l_pt))))
		p (/ (apply '+ l_d) 2.0)
	 )
	 (if (zerop (* p (- p (cadr l_d))))
		(setq ang pi)
		(setq ang (* (atan (sqrt (/ (* (- p (car l_d)) (- p (caddr l_d))) (* p (- p (cadr l_d)))))) 2.0))
 	)
; 	 (angtos (- pi ang) (getvar "AUNITS") (getvar "AUPREC"))
   (angtos (- pi ang) 0 (getvar "LUPREC")) ; return angle in degrees as string
  ) ; defun w_ang?
  ; converts radians to degrees
  (defun RtD (r) (* 180.0 (/ r pi)))
  ; converts degrees to radians
  (defun DtR (d) (* pi (/ d 180.0)))
  ; select pline validation
	(defun pick_poly_chk (/ e)
		(setq e (car(entsel "\nSelect Open Polyline: ")))
		(if 
      (or 
        (not e) 
        (= (getvar 'Errno) 7)
        (not (eq "LWPOLYLINE"(cdr(assoc 0 (entget e)))))
        (not (zerop (cdr(assoc 70 (entget e))))) ; not closed
      ) 
      (pick_poly_chk) 
      e
    )
	) ; defun pick_poly_chk
  ; angle adjustment
	(defun corect_ang (ang)(if (and (>= ang (* 0.5 pi))(< ang (* 1.5 pi))) (setq ang (+ ang pi))) ang)	
  ; main function
	(setq adoc (vla-get-activedocument (vlax-get-acad-object))) 
	(vla-endundomark adoc)
	(vla-startundomark adoc)
  (if(not *csv*)(setq *csv* (strcat(getvar"dwgprefix")(vl-filename-base (getvar"dwgname")))))
  (setq csv(getfiled "Enter Name of CSV File To Save Segment Distances & Angles" *csv* "csv" 1))
  (if csv
    (progn
     (setq *csv* csv)
     (setq csvfil (open *csv* "w")) ; open csv to write info
     (write-line (strcat"Length, Angle <Radians>, Angle <Degrees>") csvfil) ; segment length & angle Column Title
     (if(not *text_height*)(setq *text_height* (getvar"textsize")))
     (setq text_height (getreal (strcat"\nText height <" (rtos *text_height* 2 (getvar"luprec"))">: ")))
     (if(not text_height)(setq text_height *text_height*)(setq *text_height* text_height))
     (if(setq eo (pick_poly_chk)) ; pick pline
       (progn
        (foreach x (entget eo) ; get pline entity's data
         (if (= (car x) 10)
          (setq lst (append lst (list (cdr x)))) ; get pline vertices
         )
        )
        ; for angle calc
        ; code by CADaSchtroumpf 
        ; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/list-polyline-angles/m-p/3019110#M296526
        (setq lst2 lst) 
        (while (and (car lst2) (cadr lst2) (caddr lst2))
         (setq
          ang_lst (cons (w_ang? (car lst2) (cadr lst2) (caddr lst2)) ang_lst)
          lst2 (cdr lst2)
         )
        ) ; while          
        (setq ang_lst (append (list"0") (reverse ang_lst))) ; set first angle = 0
         
        (setq luprec (getvar"luprec")) ; get current unit decimal precision
        (setq dst(mapcar 'distance lst (cdr lst))) ; get distance between vertices         
        (setq p0 (nth 0 lst)) ; get 1st point
        (setq p1 (nth 1 lst)) ; get 2nd point
        (setq i 0 del 0)
        (repeat (length dst)
         (setq p0 (nth i lst)) ; get point 
         (setq p1 (nth (1+ i) lst)) ; get next point 
         (setq del (nth i dst)) ; get distance value item from list
         (setq ang (distof (nth i ang_lst)))
         (setq rad (DtR ang))
         (setq txtstr (strcat (rtos del 2 luprec)","(rtos rad 2 luprec)","(rtos ang 2 luprec))) ; segment length & angle in radians & degrees
        ; create text
         (entmakex
          (list
           (cons 0 "TEXT")	
           (cons 100 "AcDbEntity")
           (cons 100 "AcDbText")
           (cons 1 txtstr)
           (cons 10 p1)
           (cons 40 *text_height*)
           (cons 7 "STANDARD")
           (cons 8 "PlnLenAng")
           (cons 50 (corect_ang(+ (angle p0 p1) (* 0.5 pi))))
          )
         ) ; entmake
          (write-line txtstr csvfil) ; write info to csv
          (setq i (1+ i)) ; next list item
        ) ; repeat cycle through list of distances
        (close csvfil) ; close csv 
        (startapp "Notepad" *csv*) 
       ) ; progn
       (progn
         (princ"\nNo Open Pline Selected.")(princ)
       )
     ) ; if
    ) ; progn
    (progn
      (princ"\nNo CSV File Entered.")(princ)
    )
  ) ; if
	(vla-endundomark adoc)
  (princ)
) ; defun

paulli_apa_0-1677285699064.png

 


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

ricc_donofrio
Participant
Participant
The angle values ​​in the dwg are shown on the next vertex, for example i read 0 degrees on the 2nd vertex,
but your script works great! :D