Author Topic: How to get the angle of the Picked vertex on multi-vertex polyline or Mline  (Read 8034 times)

0 Members and 1 Guest are viewing this topic.

jaydee

  • Guest
Hi.
I couldn't find anything about returning the vertex angle of a multi-vertices polyline/mline
What i could think of is to compare the picked point with a set vertex points

What i would like to know which 2 points in the list "Lst" is my picked point "PP1" sit in between, then work out the angle from here?

Code: [Select]
(setq a (entsel))
(setq PP1 (car (cdr  a)))
==>(4255.76 23382.0 0.0)

(setq c (entget (car a)))

(setq lst (massoc 10 c))    ;;;for lwpolyline
==>((-1389.12 21356.8) (1946.27 24398.4) (3218.53 21477.1) (4972.19 24484.3)
(7447.94 21374.0) (9682.99 24312.5))

(setq lst (massoc 11 c))    ;;;for Mline

(defun massoc (key alist / x nlist)          ; Jaysen Long
  (foreach x alist
    (if
      (eq key (car x))
      (setq nlist (cons (cdr x) nlist))
      )
    )
  (reverse nlist)
  )

What i have been using to get the angle is via the osnap option. I could be wrong about the osnap option is, if the selected polyline sitting on top of a very crowded background(xref) with lots of lines underneath, then I believe the result could be inconsistent.

Code: [Select]
(setvar "osmode" 512)  ;;;NEArest
(setq a (getpoint))
(setq midpt (osnap a "mid"))
(setq endpt (osnap a "end"))
(setq plang (angle midpt endpt))

Thankyou
« Last Edit: August 23, 2011, 08:03:38 AM by jaydee »

Jeff_M

  • King Gator
  • Posts: 4099
  • C3D user & customizer
Look into the (vlax-curve-*) functions. (vlax-curve-paramatpoint will give you the segment the point is on (4.23 would mean the point is 23% along the 5th segment). SO from this you can get the PointAtParam for Params 3.0 (the 4th vertex) and 4.0 (the 5th vertex) and 5.0 (the 6th vertex). From those 3 points you can get the angle. The Params are 0 based with 0.0 usually being the startparam (Usually = almost always...Owen Wengard pointed out specific circumstances whereby programmers could alter this, but in my 20+ years working in Autocad I have yet to see it in my everyday use).

kruuger

  • Swamp Rat
  • Posts: 637
Code: [Select]
(defun c:TEST ( / OB EN PT SEG PRE_SEG POST_SEG)
  (setq OB (entsel "\nSelect polyline segment: "))
  (setq EN (car OB))
  (setq PT (cadr OB))
  (setq PT (vlax-Curve-GetClosestPointTo EN PT))
  (princ
    (strcat
      "\n-> Point on line: ("
      (vl-String-Trim "()" (vl-Princ-To-String PT))
      ")"
    )
  )
  (princ
    (strcat
      "\n-> Segment:       "
      (itoa (fix (setq SEG (vlax-curve-getParamAtPoint EN PT))))
    )
  )
  (princ
    (strcat
      "\n-> Start vertex:  "
      (itoa (setq PRE_SEG (fix SEG))) " | Coord.: ("
      (vl-String-Trim "()" (vl-Princ-To-String (vlax-Curve-GetPointAtParam EN PRE_SEG)))
      ")"
    )
  )
  (princ
    (strcat
      "\n-> End vertex:    "
      (itoa (setq POST_SEG (1+ PRE_SEG))) " | Coord.: ("
      (vl-String-Trim "()" (vl-Princ-To-String (vlax-Curve-GetPointAtParam EN POST_SEG)))
      ")"
    )
  )
  (textscr)
  (princ)
)
it will be useful ?
kruuger

jaydee

  • Guest
Thankyou Jeff and kruuger for the code and advice. and CAB for links, will read into it
Time to rework and finetune some of my codes.
Cheers
« Last Edit: August 23, 2011, 08:18:44 AM by jaydee »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
For a polyline, I would agree to use the vlax-curve-* functions, however, since an MLine is not a Curve Object, one cannot use the vlax-curve-* functions with it.

Below is an example to return the interior & exterior angles of the selected segment of an MLine, the returned angles are formatted using the angtos function so that you can see which angles are being calculated, but in practice, radians would be returned.

Code: [Select]
(defun c:test ( / e l p )
    (if
        (and
            (setq e (entsel "\nSelect MLine: "))
            (setq p (trans (cadr e) 1 0))
            (eq "MLINE" (cdr (assoc 0 (setq e (entget (car e))))))
        )
        (progn
            (setq l (LM:mAssoc 11 e))
            (setq p
                (car
                    (vl-sort-i
                        (mapcar
                            (function
                                (lambda ( a b )
                                    (distance p (LM:ProjectPointToLine p a b))
                                )
                            )
                            l (append (cdr l) (list (car l)))
                        )
                        '<
                    )
                )
            )
            (
                (lambda ( a ) (mapcar 'angtos (list a (- (+ pi pi) a))))
                (cond
                    (   (zerop p)
                        (LM:GetLeftAngle (last l) (car l) (cadr l))
                    )
                    (   (= p (1- (length l)))
                        (LM:GetLeftAngle (nth (1- p) l) (last l) (car l))
                    )
                    (   t
                        (LM:GetLeftAngle (nth (1- p) l) (nth p l) (nth (1+ p) l))
                    )
                )
            )
        )
    )
)

(defun LM:mAssoc ( key lst / pair )
    (if (setq pair (assoc key lst))
        (cons (cdr pair) (LM:mAssoc key (cdr (member pair lst))))
    )
)

(defun LM:ProjectPointToLine ( pt p1 p2 / nm )
    (setq nm (mapcar '- p2 p1)
          p1 (trans p1 0 nm)
          pt (trans pt 0 nm)
    )
    (trans (list (car p1) (cadr p1) (caddr pt)) nm 0)
)

(defun LM:GetLeftAngle ( p1 p2 p3 )
    (rem (+ pi pi (- (angle p2 p1) (angle p2 p3))) (+ pi pi))
)

(vl-load-com) (princ)

jaydee

  • Guest
Hi Lee. Thankyou for the code.
Just tested on multi segment MLINE drawn zigzag @ 45deg.
The FIRST segment seems to return incorrect angles ("316.45198912" "43.54801088")
The others OK ("270.00000000" "90.00000000").

What i need is the angle of the straight segment, NOT the angles between 2 segments

Cheers

Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
The FIRST segment seems to return incorrect angles ("316.45198912" "43.54801088")

The first segment will return the interior/exterior angle between the start vertex and end vertex (undefined for open MLines, defined for closed MLines).

What i need is the angle of the straight segment, NOT the angles between 2 segments

It seems that I misunderstood the task - I saw CAB's links and thought that was what you were looking for  :oops:

« Last Edit: August 23, 2011, 07:51:38 PM by Lee Mac »

Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
Try this instead:

Code: [Select]
(defun c:test ( / e l p )
    (if
        (and
            (setq e (entsel "\nSelect MLine: "))
            (setq p (trans (cadr e) 1 0))
            (eq "MLINE" (cdr (assoc 0 (setq e (entget (car e))))))
        )
        (progn
            (setq l (LM:mAssoc 11 e))
            (setq p
                (car
                    (vl-sort-i
                        (mapcar
                            (function
                                (lambda ( a b )
                                    (distance p (LM:ProjectPointToLine p a b))
                                )
                            )
                            l (append (cdr l) (list (car l)))
                        )
                        '<
                    )
                )
            )
            (angtos
                (cond
                    (  (= p (1- (length l)))
                       (angle (last l) (car l))
                    )
                    (  t
                       (angle (nth p l) (nth (1+ p) l))
                    )
                )
            )
        )
    )
)

(defun LM:mAssoc ( key lst / pair )
    (if (setq pair (assoc key lst))
        (cons (cdr pair) (LM:mAssoc key (cdr (member pair lst))))
    )
)

(defun LM:ProjectPointToLine ( pt p1 p2 / nm )
    (setq nm (mapcar '- p2 p1)
          p1 (trans p1 0 nm)
          pt (trans pt 0 nm)
    )
    (trans (list (car p1) (cadr p1) (caddr pt)) nm 0)
)

(vl-load-com) (princ)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
I was just opening doors, not serving the meal. 8-)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12926
  • London, England
I was just opening doors, not serving the meal. 8-)

Oh I wasn't blaming you, I should have read the thread a little more thoroughly  :ugly:

LE3

  • Guest
I was just opening doors, not serving the meal. 8-)

Wonder what the OP it is doing.... well just eating  :roll:

jaydee

  • Guest
Lee. What amaze me is how do you manage to write a code so quickly. :blank: :blank:

I unserstand what CAB trying to say. I admit im a slow leaner and at the moment Im only capable of modding an existing code and scouge bits and pieces of scatter codes and trying to make it into a functional lisp.

Ta

LE3

  • Guest
Lee. What amaze me is how do you manage to write a code so quickly. :blank: :blank:

I unserstand what CAB trying to say. I admit im a slow leaner and at the moment Im only capable of modding an existing code and scouge bits and pieces of scatter codes and trying to make it into a functional lisp.

Ta

Let me say this:

All here at theSwamp know about Lee's skills - He it is a master and apart likes to help without asking anything - no questions about it - Great guy indeed.

Now, me/and guess we, would like to see others putting more efforts, to show what the have done so far or what they can do, code skeletons, pseudo-code, ideas on how to solve things, etc...

TheSwamp have already a bunch of open-source code available to search and to put together - from simple routines to gems and why not to some day match Lee's code.

My 0.2 cts.