Bend Angles

Bend Angles

ishaq03
Advocate Advocate
3,512 Views
20 Replies
Message 1 of 21

Bend Angles

ishaq03
Advocate
Advocate

Hello All,

I'm looking to see if anyone has a lisp routine that will automatically Calculated the quantity of bends. In my project I have a lot of unclosed polylines, and my target is to check the quantity of different angles means 11.25,22.5,45,&90 along with tee connections. for more clarification please check my attached drawing.

0 Likes
Accepted solutions (1)
3,513 Views
20 Replies
Replies (20)
Message 2 of 21

hak_vz
Advisor
Advisor

@ishaq03  I've checked your sample. You polylines  are really have different bend angles, so  90° is either 89.55 or 90.22   and so on. Angles are not created with precision.

Also, you didn't responded to https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/create-the-center-line-horizontally-... 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 3 of 21

hak_vz
Advisor
Advisor

Work in segments. Hide all unnecessary objects. This will count all bends except T joints. Since angles are inconsistent they are all treated as nearest value to 0 11.25 22.5 45 60 90 Small bends are added to value 0 and can be ignored. You can mark t joints with some symbol in separate layer and can count them later with simple selection.

This is code to start with since your information provided is really insufficient. 

Its not tested and result may be wrong

 

 

(defun c:count-bends ( / 
	take pointlist2d deg_to_rad rad_to_deg vect unique asin acos angles_two_vect to_counter_clockwise
	bends bends_count ss i j eo pts p1 p2 p3 v1 v2 ang cnt
	)
	(defun *error* ()
		(setvar 'cmdecho 1)
		(princ)
	)
	(defun take (amount lst / ret)(repeat amount (setq ret (cons (car lst) (take (1- amount) (cdr lst))))))
	(defun pointlist2d (lst / ret) (while lst (setq	ret (cons (take 2 lst) ret) lst (cddr lst))) (reverse ret))
	(defun deg_to_rad (deg)(* PI (/ deg 180.0)))
	(defun rad_to_deg (rad)(* 180.0 (/ rad PI)))
	(defun vect (p1 p2)(mapcar '- p2 p1))
	(defun unique(lst)(if lst (cons (car lst) (Unique (vl-remove (car lst) (cdr lst))))))
	(defun asin (x)
	  (cond 
		((and(> x -1.0)(< x 1.0)) (atan (/ x (sqrt (- 1.0 (* x x))))))
		((= x -1.0) (* -1.0 (/ PI 2)))
		((= x  1) (/ PI 2))
	  )
	)
	(defun acos (x)
	  (cond 
		((and(>= x -1.0)(<= x 1.0)) (-(* PI 0.5) (asin x)))
	  )
	) 
	(defun angles_two_vect (v1 v2 / ang xa ya za xb yb zb) 
		(if (= (length v1) 2) (setq v1 (append v1 (list 0.0))))
		(if (= (length v2) 2) (setq v2 (append v2 (list 0.0))))
		(mapcar 'set '(xa ya za xb yb zb) (append v1 v2))
		(setq ang 
			(acos 
				(/
					(+ (* xa xb)(* ya yb)(* za zb)) 
					(* (sqrt (+(* xa xa)(* ya ya)(* za za)))(sqrt (+(* xb xb)(* yb yb)(* zb zb))))
				)
			)
		)
		(if (< zb za) (setq ang (- (* PI 2.0) ang)))
		ang
	)
	(setvar 'cmdecho 0)
	(setq bends '(0.0 11.25 22.5 45.0 60.0 90.0))
	(setq bends_count '((0.0 . 0) (11.25 . 0) (22.5 . 0) (45.0 . 0) (60.0 . 0) (90.0 . 0)))
	(setq ss (ssget '((0 . "LWPOLYLINE")(-4 . ">")(90 . 2))) j -1)
	(while (< (setq j (1+ j)) (sslength ss))
		(setq eo (vlax-ename->vla-object (ssname ss j)))
		(cond 
			((= (vlax-get eo 'ObjectName) "AcDbPolyline") 
				(setq pts (pointlist2d(vlax-get eo 'Coordinates)))
				(cond
					((= (vlax-get eo 'Closed) -1)(setq pts (append (unique pts) (take 2 pts))))
					((<= (distance (vlax-curve-getStartPoint eo)(vlax-curve-getEndPoint eo)) 1e-8)(setq pts (append (unique pts) (cdr(take 2 pts)))))
				)
				(setq i 1)
				(while (< i (1- (length pts)))
					(setq p1 (nth (1- i) pts) p2 (nth i pts) p3 (nth (1+ i) pts) v1 (vect p1 p2) v2 (vect p2 p3) ang (rad_to_deg (-  PI (angles_two_vect v1 v2))))
					(if (> ang 90.0) (setq ang (- 180.0 ang)))
					(setq ang (car (vl-sort bends '(lambda (x y)(< (abs(- x ang))(abs(- y ang)))))))
					(setq cnt (1+(cdr (assoc ang bends_count))))
					(setq bends_count (subst (cons ang cnt) (assoc ang bends_count) bends_count))
					(setq i (1+ i))
				)	
			)
		)
	)
	(foreach ent bends_count
		(princ (strcat "\n" (rtos (car ent) 2 2) " --> " (itoa (cdr ent))))
	)
	(setvar 'cmdecho 1)
	(princ)
)

 

 

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 4 of 21

ishaq03
Advocate
Advocate

I used your code it's not working properly when I am selecting all the polylines the error appearing as a too many Arguments.  can you provided me as a text at the bend locations, I will count the bends quantity with text object.

0 Likes
Message 5 of 21

hak_vz
Advisor
Advisor

I've told in my post that you have to work in small batches. Something is causing an error and I don't know what. Take few polylines aside a and it works ok.

Also, take a time and create a write down all you want. Changes later today.

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 6 of 21

ishaq03
Advocate
Advocate

Yes hak It's working fine if I will do few polylines aside, And it's ok to me to count the bend quantities. But Please provide me a code where  I can get the the angle text on the bend locations.

0 Likes
Message 7 of 21

hak_vz
Advisor
Advisor
I have to look into your drawing what causes an error. Code works OK with a lot of elements if they are created correctly. About showing text I'll work on it. Provide sample how you like the text to be created.

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 8 of 21

ishaq03
Advocate
Advocate

hak, check the attached Pic for angle text.

0 Likes
Message 9 of 21

hak_vz
Advisor
Advisor

Do you want real angle values or rounded to 11.25 22.5 45 60 90?

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 10 of 21

ishaq03
Advocate
Advocate

I don't  want the real values I need as a round values for 11.25 22.5 45 60&90 less than 11.25 ignore it please.

0 Likes
Message 11 of 21

hak_vz
Advisor
Advisor

I asked this since in your sample they are not rounded. Also, what to do with small bending angles less then 5° ?

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 12 of 21

ishaq03
Advocate
Advocate

less then 5° ignore it please no need to be text there. 

0 Likes
Message 13 of 21

hak_vz
Advisor
Advisor
Accepted solution

Here is your code. Drawing repaired because of some  error in polylines. Attached corrected one with bend angles.

Previous code was OK.

(defun c:count-bends ( / 
	take pointlist2d deg_to_rad rad_to_deg vect unique asin acos angles_two_vect to_counter_clockwise
	bends bends_count ss i j eo pts p1 p2 p3 v1 v2 ang cnt
	)
	(defun *error* ()
		(setvar 'cmdecho 1)
		(princ)
	)
	(defun take (amount lst / ret)(repeat amount (setq ret (cons (car lst) (take (1- amount) (cdr lst))))))
	(defun pointlist2d (lst / ret) (while lst (setq	ret (cons (take 2 lst) ret) lst (cddr lst))) (reverse ret))
	(defun deg_to_rad (deg)(* PI (/ deg 180.0)))
	(defun rad_to_deg (rad)(* 180.0 (/ rad PI)))
	(defun vect (p1 p2)(mapcar '- p2 p1))
	(defun unique(lst)(if lst (cons (car lst) (Unique (vl-remove (car lst) (cdr lst))))))
	(defun asin (x)
	  (cond 
		((and(> x -1.0)(< x 1.0)) (atan (/ x (sqrt (- 1.0 (* x x))))))
		((= x -1.0) (* -1.0 (/ PI 2)))
		((= x  1) (/ PI 2))
	  )
	)
	(defun acos (x)
	  (cond 
		((and(>= x -1.0)(<= x 1.0)) (-(* PI 0.5) (asin x)))
	  )
	) 
	(defun angles_two_vect (v1 v2 / ang xa ya za xb yb zb) 
		(if (= (length v1) 2) (setq v1 (append v1 (list 0.0))))
		(if (= (length v2) 2) (setq v2 (append v2 (list 0.0))))
		(mapcar 'set '(xa ya za xb yb zb) (append v1 v2))
		(setq ang 
			(acos 
				(/
					(+ (* xa xb)(* ya yb)(* za zb)) 
					(* (sqrt (+(* xa xa)(* ya ya)(* za za)))(sqrt (+(* xb xb)(* yb yb)(* zb zb))))
				)
			)
		)
		(if (< zb za) (setq ang (- (* PI 2.0) ang)))
		ang
	)
	(setvar 'cmdecho 0)
	(setq bends '(0.0 11.25 22.5 45.0 60.0 90.0))
	(setq bends_count '((0 . 0) (11.25 . 0) (22.5 . 0) (45.0 . 0) (60.0 . 0) (90.0 . 0)))
	(setq ss (ssget '((0 . "LWPOLYLINE")(-4 . ">=")(90 . 3))) j -1)
	(cond 
		((and ss)
			(while (< (setq j (1+ j)) (sslength ss))
				(setq eo (vlax-ename->vla-object (ssname ss j)))
				(cond 
					((= (vlax-get eo 'ObjectName) "AcDbPolyline") 
						(setq pts (pointlist2d(vlax-get eo 'Coordinates)))
						(cond
							((= (vlax-get eo 'Closed) -1)(setq pts (append (unique pts) (take 2 pts))))
							((<= (distance (vlax-curve-getStartPoint eo)(vlax-curve-getEndPoint eo)) 1e-8)(setq pts (append (unique pts) (last(take 2 pts)))))
						)
						(setq i 0)
						(while (< (setq i (1+ i)) (1- (length pts)))
							(setq p1 (nth (1- i) pts) p2 (nth i pts) p3 (nth (1+ i) pts) v1 (vect p1 p2) v2 (vect p2 p3) ang (rad_to_deg (-  PI (angles_two_vect v1 v2))))
							(if (> ang 90.0) (setq ang (- 180.0 ang)))
							(setq ang (car (vl-sort bends '(lambda (x y)(< (abs(- x ang))(abs(- y ang)))))))
							(if (> ang 0.0)
								(entmake
									(list
										(cons 0 "TEXT")
										(cons 100 "AcDbText")
										(cons 10 p2)
										(cons 40 4)
										(cons 1 (rtos ang 2 2))
										(cons 50 0)
										(cons 100 "AcDbText")
									)
								)								
							)
							(setq cnt (1+(cdr (assoc ang bends_count))))
							(setq bends_count (subst (cons ang cnt) (assoc ang bends_count) bends_count))
						)	
					)
				)
			)
			(setq bends_count (cdr bends_count))
			(foreach ent bends_count
				(princ (strcat "\n" (rtos (car ent) 2 2) " --> " (itoa (cdr ent))))
			)
		)
	)
	(setvar 'cmdecho 1)
	(princ)
)

 

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 14 of 21

ishaq03
Advocate
Advocate

Thanks hak it's working fine as per my need.

0 Likes
Message 15 of 21

hiraram_prajapati
Contributor
Contributor

Hi @hak_vz @ishaq03 @Sea-Haven @Kent1Cooper 

 

Dear All,

 

Can you please modify the same lisp?

I have change from Decimal to "DDMMSS", but angle inserting wrong in "SS".

Image is attached for your reference.

Red color by lisp & angle by manually both are different...  

hiraram_prajapati_0-1744287437620.png

 

 

0 Likes
Message 16 of 21

Kent1Cooper
Consultant
Consultant

It's overkill to convert an angle to a text string and from there to a decimal value and from there back to a string in DMS format:

;; Round to 2 decimals and convert to DMS
(setq ang (atof (rtos ang 2 2)))
(setq dms-str (format_dms ang))

Instead, try getting it directly into DMS format, substituting ° for the d:

(setq dms-str (vl-string-subst "°" "d" (angtos ang 1 4)))

Kent Cooper, AIA
0 Likes
Message 17 of 21

Sea-Haven
Mentor
Mentor

Good answer @Kent1Cooper, 1 second of bearing. A rtos 2 2 would give an answer of "0".

 

(/ 1. 3600)
0.000277777777777778

0 Likes
Message 18 of 21

hiraram_prajapati
Contributor
Contributor

Can you please update the lisp and sent to me, i am not able to update...please 

Value not correct coming.

hiraram_prajapati_0-1744348284662.png

 

0 Likes
Message 19 of 21

Kent1Cooper
Consultant
Consultant

@Sea-Haven wrote:

.... A rtos 2 2 would give an answer of "0".

....


You can have it give an answer of "0.00" if that's what you want, with an appropriate setting of the DIMZIN System Variable.

Kent Cooper, AIA
0 Likes
Message 20 of 21

Kent1Cooper
Consultant
Consultant

@hiraram_prajapati wrote:

Can you please update the lisp and sent to me, i am not able to update.....


Before I try, looking more closely I see your (format_dms) function is to convert decimal degrees, whereas I had assumed the 'ang' argument would be in radians as is so typically done.  I suggest sticking with radians all the way to the point where you need the text string.  Try replacing this:

...

  ang (rad_to_deg (- pi (angles_two_vect v1 v2)))
)
(if (> ang 90.0) (setq ang (- 180.0 ang)))

...

with this:

...

  ang (- pi (angles_two_vect v1 v2))
)
(if (> ang (/ pi 2)) (setq ang (- pi ang)))

...

[and also use my earlier suggested change]. 

 

Or instead, maybe simply change my earlier suggestion to this:

(setq dms-str (vl-string-subst "°" "d" (angtos (cvunit ang "degree" "radian") 1 4)))

Kent Cooper, AIA
0 Likes