Author Topic: Challenge - Find interior angles of a closed polyline  (Read 13433 times)

0 Members and 1 Guest are viewing this topic.

T.Willey

  • Needs a day job
  • Posts: 5251
Challenge - Find interior angles of a closed polyline
« on: December 09, 2010, 04:49:32 PM »
Inspired by this post over at the Adesk Ng - http://forums.autodesk.com/t5/Visual-LISP-AutoLISP-and-General/Find-included-angles-of-Pline/td-p/2847672

I thought it would be a fun challenge, that wasn't too hard, but I got a little more than I thought I would.  I have a solution already, posted in that thread, but wondered how others would tackle it.  One of the issues was getting the angle value of 289 instead of 71, as shown in the pic attached.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

VovKa

  • Water Moccasin
  • Posts: 1626
  • Ukraine
Re: Challenge - Find interior angles of a closed polyline
« Reply #1 on: December 09, 2010, 05:16:35 PM »
Code: [Select]
(defun vk_GetLeftAngle (p1 p2 p3 / Ang)
  (if (minusp (setq Ang (rem (+ pi (angle p2 p1) (- (angle p3 p2))) (* pi 2.0))))
    (+ pi pi Ang)
    Ang
  )
)
(defun test (/ lst)
  (setq lst (mapcar 'cdr
   (vl-remove-if-not (function (lambda (e) (= (car e) 10)))
     (entget (car (entsel)))
   )
   )
  )
  (mapcar (function
   (lambda (p1 p2 p3 / Ang) (angtos (- (* 2 pi) (vk_GetLeftAngle p1 p2 p3))))
 )
 (cons (last lst) lst)
 lst
 (append (cdr lst) (list (car lst)))
  )
)
had vk_GetLeftAngle already in my libs

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Challenge - Find interior angles of a closed polyline
« Reply #2 on: December 09, 2010, 05:34:19 PM »
I guess you would just need to test which way the polyline goes then Vovka?

I like how you get the angle.  I didn't think of that one, and I tried a couple.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Challenge - Find interior angles of a closed polyline
« Reply #3 on: December 09, 2010, 07:30:14 PM »

yes, he's generally very frugal.

 :-)
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Lee Mac

  • Seagull
  • Posts: 12905
  • London, England
Re: Challenge - Find interior angles of a closed polyline
« Reply #4 on: December 09, 2010, 08:34:24 PM »
VovKa,

After studying your code, would this also work for the GetLeftAngle?

Code: [Select]
(defun LM:GetLeftAngle ( p1 p2 p3 )
  (rem (+ pi pi (- (angle p2 p1) (angle p2 p3))) (+ pi pi))
)

Lee Mac

  • Seagull
  • Posts: 12905
  • London, England
Re: Challenge - Find interior angles of a closed polyline
« Reply #5 on: December 09, 2010, 09:11:36 PM »
Not too imaginative, and using most of VovKa's code:

Code: [Select]
(defun LM:GetLeftAngle ( p1 p2 p3 )
  (rem (+ pi pi (- (angle p2 p1) (angle p2 p3))) (+ pi pi))
)
(defun c:test ( / l m )
  (setq l (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget (car (entsel))))))

  (setq l
    (mapcar '(lambda ( p1 p2 p3 ) (LM:GetLeftAngle p1 p2 p3))
      (cons (last l) l) l (append (cdr l) (list (car l)))
    )
  )
  (mapcar 'angtos (if (< (apply '+ l) (apply '+ (setq m (mapcar '(lambda ( x ) (- (* 2. pi) x)) l)))) l m))
)

VovKa

  • Water Moccasin
  • Posts: 1626
  • Ukraine
Re: Challenge - Find interior angles of a closed polyline
« Reply #6 on: December 10, 2010, 03:12:03 AM »
I guess you would just need to test which way the polyline goes then Vovka?
then i will need something like...
Code: [Select]
(defun vk_IsBoundaryClockwise (CoordsList)
  (minusp
    (apply '+
     (mapcar (function
(lambda (p1 p2)
 (* (+ (car p1) (car p2)) (- (cadr p1) (cadr p2)))
)
     )
     CoordsList
     (cons (last CoordsList) CoordsList)
     )
    )
  )
)
VovKa,

After studying your code, would this also work for the GetLeftAngle?

Code: [Select]
(defun LM:GetLeftAngle ( p1 p2 p3 )
  (rem (+ pi pi (- (angle p2 p1) (angle p2 p3))) (+ pi pi))
)
i think it perfectly will
« Last Edit: December 10, 2010, 03:25:24 AM by VovKa »

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Challenge - Find interior angles of a closed polyline
« Reply #7 on: December 10, 2010, 04:04:14 AM »
Not too imaginative, and using most of VovKa's code:

Code: [Select]
(defun LM:GetLeftAngle ( p1 p2 p3 )
  (rem (+ pi pi (- (angle p2 p1) (angle p2 p3))) (+ pi pi))
)
(defun c:test ( / l m )
  (setq l (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget (car (entsel))))))

  (setq l
    (mapcar '(lambda ( p1 p2 p3 ) (LM:GetLeftAngle p1 p2 p3))
      (cons (last l) l) l (append (cdr l) (list (car l)))
    )
  )
  (mapcar 'angtos (if (< (apply '+ l) (apply '+ (setq m (mapcar '(lambda ( x ) (- (* 2. pi) x)) l)))) l m))
)

I like your program, I want to shorten it a bit:
Code: [Select]
(defun LM:GetLeftAngle ( p1 p2 p3 )
  (rem (+ pi pi (- (angle p2 p1) (angle p2 p3))) (+ pi pi))
)
(defun c:test ( / l m )
  (setq l (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget (car (entsel))))))
  (setq l (mapcar 'LM:GetLeftAngle (cons (last l) l) l (append (cdr l) (list (car l)))))
  (mapcar 'angtos (if (< (apply '+ l) (apply '+ (setq m (mapcar '(lambda ( x ) (- (* 2. pi) x)) l)))) l m))
)

as an alternative, I propose a different approach:
Code: [Select]
(defun c:test (/ e)
 (if (setq e (car (entsel)))
  (reverse (f e (1- (cdr (assoc 90 (entget e)))) 0))
 )
)
(defun f (e i1 i2)
 (if (>= i1 0)
  (cons (angtos (rem (+ pi
                        pi
                        (- (angle (vlax-curve-getFirstDeriv e i1) '(0 0))
                           (angle '(0 0) (vlax-curve-getFirstDeriv e i2))
                        )
                     )
                     (+ pi pi)
                )
        )
        (f e (1- i1) i1)
  )
 )
)

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Challenge - Find interior angles of a closed polyline
« Reply #8 on: December 10, 2010, 07:42:18 AM »
Code: [Select]
(defun LM:GetLeftAngle ( p1 p2 p3 )
  (rem (+ pi pi (- (angle p2 p1) (angle p2 p3))) (+ pi pi))
)
(defun c:test ( / l m )
  (setq l (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget (car (entsel))))))

  (setq l
    (mapcar '(lambda ( p1 p2 p3 ) (LM:GetLeftAngle p1 p2 p3))
      (cons (last l) l) l (append (cdr l) (list (car l)))
    )
  )
  [color=red](mapcar 'angtos (if (< (apply '+ l) (apply '+ (setq m (mapcar '(lambda ( x ) (- (* 2. pi) x)) l)))) l m))[/color]
)
That's a clever line of code!

Lee Mac

  • Seagull
  • Posts: 12905
  • London, England
Re: Challenge - Find interior angles of a closed polyline
« Reply #9 on: December 10, 2010, 09:09:19 AM »
I like your program, I want to shorten it a bit:
Code: [Select]
(defun LM:GetLeftAngle ( p1 p2 p3 )
  (rem (+ pi pi (- (angle p2 p1) (angle p2 p3))) (+ pi pi))
)
(defun c:test ( / l m )
  (setq l (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget (car (entsel))))))
  (setq l (mapcar [color=red]'LM:GetLeftAngle[/color] (cons (last l) l) l (append (cdr l) (list (car l)))))
  (mapcar 'angtos (if (< (apply '+ l) (apply '+ (setq m (mapcar '(lambda ( x ) (- (* 2. pi) x)) l)))) l m))
)

Ah yes! Of course - no lambda needed  :oops:

Thanks Evgeniy!

as an alternative, I propose a different approach:

Time for more studying  :-)

Lee Mac

  • Seagull
  • Posts: 12905
  • London, England
Re: Challenge - Find interior angles of a closed polyline
« Reply #10 on: December 10, 2010, 09:09:51 AM »
That's a clever line of code!

Thanks Roy  :-)

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Challenge - Find interior angles of a closed polyline
« Reply #11 on: December 10, 2010, 10:16:22 AM »
I really liked the design
Code: [Select]
(Rem (+ pi pi (- (angle p2 p1) (angle p2 p3))) (+ pi pi))I will take it on his arms!
Previously, I always use multiple IF...

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Challenge - Find interior angles of a closed polyline
« Reply #12 on: December 10, 2010, 11:57:11 AM »
Man you guys are good!

Vovka - with the added function, yours shows the correct angles now.

Lee - yours shows the correct angles.

Evgeniy - yours shows the correct angles only half the time.  I think the issue is the same as Vovka's first post, where the polyline direction matters.  In the attached drawing, the bottom two polylines should only have one angle of 270, but you code shows the opposite.

I don't even want to show my code now, as the only way I could think of see which angle to get, was to test a point, and see if that was inside the polyline.  But I'll show, just don't laugh.

Code: [Select]
(defun c:Test ( / ActDoc CurSp Sel Data PlObj PtList cnt MaxCnt Ang tempAng Pt tempObj AngList Norm Pt2 tempAng2 )
   
    (setq ActDoc (vla-get-ActiveDocument (vlax-get-Acad-Object)))
    (setq CurSp
        (vlax-get
            ActDoc
            (if (equal (getvar 'CvPort) 1)
                'PaperSpace
                'ModelSpace
            )
        )
    )
    (if
        (and
            (setq Sel (entsel "\n Select closed polyline: "))
            (setq Data (entget (car Sel)))
            (= (cdr (assoc 0 Data)) "LWPOLYLINE")
            (equal (logand 1 (cdr (assoc 70 Data))) 1)
            (setq PlObj (vlax-ename->vla-object (car Sel)))
        )
        (progn
            (foreach i Data
                (if (equal (car i) 10)
                    (setq PtList (cons (cdr i) PtList))
                )
            )
            (setq PtList (reverse PtList))
            (setq cnt 0)
            (setq MaxCnt (1- (length PtList)))
            (while (<= cnt MaxCnt)
                (setq Ang
                    (abs
                        (-
                            (setq tempAng
                                    (angle
                                        (setq Pt (nth cnt PtList))
                                        (setq Pt2 (nth (if (zerop cnt) MaxCnt (1- cnt)) PtList))
                                    )
                            )
                            (setq tempAng2
                                (if
                                    (equal
                                        (setq tempAng2
                                                (angle
                                                    Pt
                                                    (nth (if (equal cnt MaxCnt) 0 (1+ cnt)) PtList)
                                                )
                                        )
                                        0.
                                    )
                                    (* pi 2.)
                                    tempAng2
                                )
                            )
                        )
                    )
                )
                (setq Pt (trans Pt (setq Norm (cdr (assoc 210 Data))) 0))
                (setq StPt (polar Pt tempAng 0.0001))
                (setq tempObj (vlax-invoke CurSp 'AddRay StPt (trans Pt2 Norm 0)))
                (vlax-invoke tempObj 'Rotate Pt (* (/ Ang 2.) (if (< tempAng tempAng2) 1. -1.)))
                (if
                    (equal
                        (rem
                            (/ (length (vlax-invoke PlObj 'IntersectWith tempObj acExtendNone)) 3)
                            2
                        )
                        1
                    )
                    (setq AngList (cons Ang AngList))
                    (setq AngList (cons (- (* pi 2.) Ang) AngList))
                )
                ;(print (car AngList))
                ;(getstring "\n Hit enter to continue: ")
                (if tempObj (vla-Delete tempObj))
                (setq tempObj nil)
                (setq cnt (1+ cnt))
            )
        )
    )
    (print (mapcar (function RTD) (reverse AngList)))
    (princ)
)

Off to study the code posted, so I can test somethings.  Thanks for posting guys!!
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

LE3

  • Guest
Re: Challenge - Find interior angles of a closed polyline
« Reply #13 on: December 10, 2010, 01:10:16 PM »
here are some outputs using some of my old stuff:

Lee Mac

  • Seagull
  • Posts: 12905
  • London, England
Re: Challenge - Find interior angles of a closed polyline
« Reply #14 on: December 10, 2010, 01:34:21 PM »
I really liked the design
Code: [Select]
(Rem (+ pi pi (- (angle p2 p1) (angle p2 p3))) (+ pi pi))I will take it on his arms!
Previously, I always use multiple IF...

Thanks Evgeniy - that's quite a compliment coming from you!  :-)