Creating a list of angles based off of vertices

Creating a list of angles based off of vertices

wian.meier
Enthusiast Enthusiast
2,366 Views
25 Replies
Message 1 of 26

Creating a list of angles based off of vertices

wian.meier
Enthusiast
Enthusiast

Good day all,

 

I've been sharpening my ax and I've almost created a functioning program, so close but so far.

 

I'm struggling to create a loop that goes through a vertices list and converts them to angles.

 

What I'm trying to do (visualized, I'm just trying to make a list that is usable in lisp):

 

1.PNG

 

This is what I've done so far:

 

(defun rtd (a)
(/ (* a 180.0) pi)
)

(while
(and
	(setq pt1 (car ptlist) pt2 (cadr ptlist))
);and
	(setq ang1 (angle pt1 pt2))
	(setq AngLst (abs rtd ang1))
	(setq ptlist (cdr ptlist))
);while

 

And this is where the code will be placed, right below

;------------------------------
;Angle list

 

In the place of - (setq AngLst '(180 175 170 163 170 90 63))

 

(defun C:CoordList (/ plent plobj coords num pt Ang1 Ang2 Ang3 AngLst pt1 pt2 pt3 ptlist Dif1 Dif2)
  (setq
    plent (car (entsel "\nSelect Polyline: "))
    plobj (vlax-ename->vla-object plent)
    coords (vlax-get plobj 'Coordinates); un-differentiated list of X Y [& Z if applicable] coordinate values
  ); setq
  (setq num (if (= (cdr (assoc 0 (entget plent))) "LWPOLYLINE") 2 3))

    ; LW Polylines have only X & Y; "heavy" 2D & 3D have X Y & Z
  (repeat (/ (length coords) num)
    (repeat num ; number of coordinates to separate into a point list
      (setq
        pt (append pt (list (car coords)))
        coords (cdr coords)
      )
    ); repeat
    (setq
      ptlist (cons pt ptlist); put that point into list of points
      pt nil ; reset for next point
    ); setq
  ); repeat
  (setq ptlist (reverse ptlist)); list of coordinates divided up into point lists
  ;; The above was originally made by Kent1Cooper https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/pick-a-polyline-and-create-a-list-of-its-coordinates/td-p/4934230
  ;; PS he is a legend
;------------------------------
;Angle list
;It depends on your "Angle" of approach

(setq AngLst '(180 175 170 163 170 90 63))


;------------------------------
;Insert the first pole

(command "insert" "5m 150-175" (car ptlist) "" "")

;------------------------------
;Insert the last pole

(command "insert" "5m 150-175" (last ptlist) "" "")

;------------------------------
;Insert the poles in between
;That's what she said....anyway code is below....the belt

(while
(and
(setq
	Ang1 (car AngLst)
	Ang2 (cadr AngLst)
	Ang3 (caddr AngLst)
);setq

(setq 
	pt1 (car ptlist)
	pt2 (cadr ptlist)
	pt3 (caddr ptlist))

(setq 
	Dif1 (- Ang1 Ang2);This is to determine angle difference between ponit 1&2
	Dif2 (- Ang2 Ang3);This is to determine angle difference between ponit 2&3
);setq
);and
; "IF" there is a better way to do the below script please let me know, sorry "IF" it looks a bit "IF"fy
			(if (>= Dif1 -15);1st angle constriction
				(progn
					(if (<= Dif1 15);2nd angle constriction
						(progn
							(if (<= Dif2 15);3rd angle constriction
								(progn
									(if (>= Dif2 -15);4th angle constriction
										(progn
											(command "insert" "5m 100-125" pt2 "" "")
										);progn
										(progn
											(command "insert" "5m 150-175" pt2 "" "")
										);progn
									);4th layer of IF function					
								);progn
								(progn
									(command "insert" "5m 150-175" pt2 "" "")
								);progn
							);3rd layer IF function
						);progn		
						(progn
							(command "insert" "5m 150-175" pt2 "" "")
						);progn
					);2nd layer IF function
				);progn
				(progn
				(command "insert" "5m 150-175" pt2 "" "")
				);progn
			);1st layer IF function
					
(setq ptlist (cdr ptlist));This will set the next point in the list for the loop
(setq AngLst (cdr AngLst));This will set the next angle in the list for the loop
);while
(princ);Everytime I see this I think of princles, maybe I was born to be fat.
);defun

 

So in short what this routine does, you select a polyline and a block will be on each vertices, the type of block will be determined by the angle of each vertices.

 

So far the whole experience feels like I'm giving birth, long and painful, but in the end it will be worth it! Though I do believe the code can be optimized especially at the "if" functions.

 

I would really appreciate any input! This is my first lisp, though I did use one of @Kent1Cooper  routines to determine the polyline vertices 

0 Likes
Accepted solutions (1)
2,367 Views
25 Replies
Replies (25)
Message 21 of 26

dlanorh
Advisor
Advisor

Hmm. Worked OK for me in testing, on both LWPolylines and 3DPolylines, and I have no idea what causes that error! The only thing I didn't include was (vl-load-com)

 

Are you running AutoCAD on a Mac?

 

Can anyone reproduce the error?

 

Attached is my test drawing with simple required blocks

 

 

I am not one of the robots you're looking for

0 Likes
Message 22 of 26

Kent1Cooper
Consultant
Consultant

I'm inclined to go at this in a different way from the "legendary" code.  I suspect maybe you pulled some of that from my PLDiet.lsp routine.  Whether from there or elsewhere, that had a specific reason for the approach of extracting a list of points from the 'Coordinates VLA Property.  Its goal is to remove vertices  from the Polyline.  That's easier to do by taking their point entries out of that list, and when done, putting the list back together into a replacement 'Coordinates Property, than by [for example] trying to modify entity data, where removing a vertex involves taking out 5 data entries, and making sure you get the right 5 when a lot of them will be duplicates of entries associated with other vertices.

 

But in this case, with no affecting of vertices but only using their locations, I think it's easier/simpler/shorter to work with the vertices as (vlax-curve...)-function parameters, as @dlanorh does in Message 13.  [Each vertex is represented by an integer parameter value, starting with 0 for the start point.]  It can get at the vertex locations more directly, without the need to pull the VLA Property and from that make a list of them.  And it doesn't need to convert the Polyline into a VLA object -- the (vlax-curve...) functions will take either that or just an entity name.

 

I did steal from PLDiet the test for whether a bend is less than or equal to 15 degrees [which coincidentally is its default for the maximum bend to straighten].

 

I didn't test this, not having your Block names and not taking time to set up the situation, but see whether it works:

 

(vl-load-com); if needed
(defun C:POLES (/ pl n v1 v2 v3 ang1 ang2)
  (setq
    pl (car (entsel "\nSelect Polyline: "))
    n 1
  ); setq
  (command ; poles at ends
    "_.insert" "5m 125-175" "_none" (vlax-curve-getStartPoint pl) "" ""
    "_.insert" "5m 125-175" "_none" (vlax-curve-getEndPoint pl) "" ""
  ); command
  (repeat (1- (vlax-curve-getEndParam pl)); [assumes NOT CLOSED]
    (setq
      v1 (vlax-curve-getPointAtParam pl (1- n)) ; previous
      v2 (vlax-curve-getPointAtParam pl n) ; current
      v3 (vlax-curve-getPointAtParam pl (1+ n)) ; next
      ang1 (angle v1 v2)
      ang2 (angle v2 v3)
    ); setq
    (command "_.insert"
      (if ; determine Block name
        (<=
          (if (> (abs (- ang1 ang2)) pi); if difference > 180 degrees
            (+ (min ang1 ang2) (- (* pi 2) (max ang1 ang2)))
              ; then -- compensate for change in direction crossing 0 degrees
            (abs (- ang1 ang2)); else -- size of difference
          ); if
          (/ pi 12); in radians [15 degrees]
        ); <=
        "5m 100-125" ; then [small pole]
        "5m 125-175" ; else [large pole]
      ); if
      "_none" v2 "" ""
    ); command
    (setq n (1+ n)); next vertex current
  ); repeat
  (princ)
); defun

 

  

Kent Cooper, AIA
0 Likes
Message 23 of 26

wian.meier
Enthusiast
Enthusiast

My apologies, here is a test dwg. with a real world scenario that we will be using it for.

0 Likes
Message 24 of 26

wian.meier
Enthusiast
Enthusiast

I rebooted my system this morning and gave it another go, it worked beautifully. It's going to take me sometime understand the code and learn from it, but it's motivated me even more.

 

Thank you for this

Message 25 of 26

dlanorh
Advisor
Advisor

No problem. 👍

 

The secret is in the (defun @Anonymous). This calculates the external deflection angle of the new segment from the previous one, and is always between 0 and +/- 180 degrees  (0 and +/- pi radians). A very important angle in alignment design etc.

 

If you need any code explanations don't be afraid to ask.

I am not one of the robots you're looking for

0 Likes
Message 26 of 26

john.uhden
Mentor
Mentor

Offhand, I think the absolute value of the deflection will do.

John F. Uhden

0 Likes