Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Get a point of a polilyne

26 REPLIES 26
SOLVED
Reply
Message 1 of 27
Anonymous
1799 Views, 26 Replies

Get a point of a polilyne

Hi masters!

 

I am working in a new LISP, to change the dimensions of a drawing for an aligned dimension. Dimensions you can see in the drawing are made of simple lines.

 

So, first of all i tried to identify the point nº3 of the triangles. After that i will make a dimensions between those 2.

I am stuck in this point and dont know how to get it. I imagine i need to identify the coordinates of those point. If anyone knows any other way to make it easier i will apreciate it.

 

How i will run the lisp? I will select only the items i need to change, and will run the lisp. I will do the same action again and again until all the dimensions are changed.

 

There is no need to create the dimstyle and layer, because both will be already created in the drawing.

 

 

Thanks in advance!

26 REPLIES 26
Message 2 of 27
devitg
in reply to: Anonymous

@Anonymous 

Would you  ? 

do the same action again and again until all the dimensions are changed.

 

 by picking each 2 triangle at the time??

 

 

Message 3 of 27
Anonymous
in reply to: devitg

Yes, i will repeat the same action again and again until all are done. Making it automatic will be hard (as sometimes the dimensions are inclined, and with my knowledge i dont know if that will be possible)

 

Anyways i just need to identify the 3rd point of those triangles, which are a polilyne

Message 4 of 27
devitg
in reply to: Anonymous

It will be better to use GETPOINT, as such triangles have 6 vertex 

;;;((16.1137 10.0344 0.0)
;;;  (16.0824 10.0344 0.0)
;;;  (16.1137 10.1182 0.0)
;;;  (16.1449 10.0344 0.0)
;;;  (16.1137 10.0344 0.0)
;;;  (16.1137 10.0344 0.0))

so you can use 

;IDENTIFY THE POINTS
  (setq p1 (getpoint "\nPick the point " ))
  (setq p2 (getpoint p1 "\nThe other point."))

             
;;;  (setq pt1 (list (car p1) (cadr p1))
;;;  (setq pt2 (list (car p2) (cadr p2))
  )

 

Message 5 of 27
Anonymous
in reply to: devitg

I want to make it automatic. With getpoint you must select the points in the window.

 

Searching i found this function: 

(setq e (nth 0 d))

Where 0 is the poisition of the list, and d is the list. Despite of this still dont know how to identify onlye the triangle 

Message 6 of 27
devitg
in reply to: Anonymous

try nth 2

Message 7 of 27
Sea-Haven
in reply to: devitg

2 triangles 3 points each, do a furtherest distance apart will give the 2 outermost  points angle does not matter.

Message 8 of 27
Moshe-A
in reply to: Anonymous

@Anonymous ,

 

What's the point in getting the triangle head vertex with (getpoint) when you can achieve the same result by directly running DIMALIGNED?

 

When you can accomplish a task with standard command no lisp is needed - right?!

 

Moshe 

Message 9 of 27
devitg
in reply to: Sea-Haven

@Sea-Haven , despite the triangle have 6 vertices, the OP also  want to erase both triangles and the POLYLINES between them after doing the ALIGNED DIM 

 

Message 10 of 27
Anonymous
in reply to: Moshe-A

This is a part of a more complex lisp i am working on. I need to select  and remove those lines. Thats why i want to make it automatic.

 

This is the lisp i have updates. I am still stuck in the part where i get the points of the polilyne.

 

(defun c:co (/ ss s1 s2 p1 p2 pt1 pt2)

  (setq ss (ssget ()))
  (setq s1 (acet-ss-ssget-filter ss '((8 . "*_linea"))) ; I will delete this items later
	s2 (acet-ss-ssget-filter ss '((8 . "*_dist"))) ; I will delete this items later
	s3 (acet-ss-ssget-filter ss '((8 . "*_linea")(0 . "LWPOLYLINE,POLYLINE")(-4 . "&")(70 . 1))) ;Select only the triangles. Polilynes which are closed
  )
                      
;IDENTIFY THE POINTS
  (setq p1 ()
	p2 ()
  )
  (setq pt1 (nth 2 p1)
	pt2 (nth 2 p2)
  )
  
;DRAW DIMENSION
 (setvar "clayer" "_EST-ARM-REP")
 (setvar "dimstyle" "05-DCE-50-ARM")
 (command "_dimaligned" pt1 pt2 "")
  
;ERASE SELECTION 1 AND 2
 (command "_erase" s1 s2 "")
 (princ)
)


 

 

Message 11 of 27
Moshe-A
in reply to: Anonymous

@Anonymous ,

 

What's the story of this drawing, from where it came? is it an option to ask the sender to fix this?

 

 Moshe

 

Message 12 of 27
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

....

So, first of all i tried to identify the point nº3 of the triangles. ....


For that, it's a matter of (vlax-curve) Parameters, which start at 0 for the first vertex, just as (nth) uses 0 for the first item in a list and (ssname) uses 0 for the first object in the selection.

 

If pl is the entity name of the Polyline [gotten from something like, in your Message 10 code, (ssname s3 somenumber)], this will give you the 3rd vertex at the point of the arrow:

 

(vlax-curve-getPointAtParam pl 2)

 

But that depends on the arrow always being a 5-vertex construction like that, with the point at the 3rd vertex.

 

Make sure you have running Osnap off, or build in "none" Osnap calls when you use those points in a dimensioning command.  And include the line

(vl-load-com) 

in the command definition if that isn't done for you elsewhere.

Kent Cooper, AIA
Message 13 of 27
devitg
in reply to: Kent1Cooper

@Anonymous 

 you post about the same topic before : at ‎04-01-2020 04:16 PM 

 

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/place-a-dimension-between-2-point/m-p/9231129 

 

and never give a like or  comment 

 

 

Message 14 of 27
Anonymous
in reply to: Kent1Cooper

Thanks for your help @Kent1Cooper, but it didnt work at all.

The triangles i wanna select are always a 2D polilyne and always have 5 vertices.

First of all i converted the selection (which are 2 triangles) into a Vla-object, then i tried to get the points as you described. What did i do wrong? Osnap is off.

 

"error: wrong argument type: lentityp <Selection set: 3732"

 

 

 

(defun c:co (/ ss s1 s2 s3 s4 p1 p2 pt1 pt2)
(vl-load-com)
  (setq ss (ssget ()))
  (setq s1 (acet-ss-ssget-filter ss '((8 . "*_linea"))) 
	s2 (acet-ss-ssget-filter ss '((8 . "*_dist"))) 
	s3 (acet-ss-ssget-filter ss '((8 . "*_linea")(0 . "LWPOLYLINE,POLYLINE")(-4 . "&")(70 . 1))) 
	s4 (vlax-ename->vla-object s3)
  )                      
;IDENTIFY THE POINTS
  (setq p1 (car s4)
	p2 (cdr s4)
  )
  (setq pt1 (vlax-curve-getPointAtParam p1 2)
	pt2 (vlax-curve-getPointAtParam p2 2)
  )
  
;DRAW DIMENSION
 (setvar "clayer" "_EST-ARM-REP")
 (command "_dimaligned" pt1 pt2 "")
  
;ERASE SELECTION 1 AND 2
 (command "_erase" s1 s2 "")
 (princ)
)

 

 

 

Thanks for your help!

 

Message 15 of 27
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

Thanks for your help @Kent1Cooper, but it didnt work at all.

The triangles i wanna select are always a 2D polilyne and always have 5 vertices.

First of all i converted the selection (which are 2 triangles) into a Vla-object, then i tried to get the points as you described. What did i do wrong? Osnap is off.

 

....
	s3 (acet-ss-ssget-filter ss '((8 . "*_linea")(0 . "LWPOLYLINE,POLYLINE")(-4 . "&")(70 . 1))) 
	s4 (vlax-ename->vla-object s3)
  )                      
;IDENTIFY THE POINTS
  (setq p1 (car s4)
	p2 (cadr s4)
  )
  (setq pt1 (vlax-curve-getPointAtParam p1 2)
	pt2 (vlax-curve-getPointAtParam p2 2)
  )
....

....


If s3 is a selection set, you can't make a VLA object out of that -- it needs to be an entity name.  So your s4 setting is incorrect.  I think you could omit s4 altogether, and say:

(setq p1 (ssname s3 0) p2 (ssname s3 1))

and go from there.

 

The (vlax-curve-...) functions can take an entity name -- they don't require a VLA object.

Kent Cooper, AIA
Message 16 of 27
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:

....

....
	s3 (acet-ss-ssget-filter ss '((8 . "*_linea")(0 . "LWPOLYLINE,POLYLINE")(-4 . "&")(70 . 1))) 
	s4 (vlax-ename->vla-object s3)
  )                      
;IDENTIFY THE POINTS
  (setq p1 (car s4)
	p2 (cadr s4)
  )
....

....


If s3 is a selection set, you can't make a VLA object out of that -- it needs to be an entity name.  So your s4 setting is incorrect.  ....


In addition, if your idea was that s4 would be a selection set  containing VLA objects  [which it can't be -- selection sets contain entity names], then using (car s4) and (cadr s4) to get the two arrowheads out of it is also incorrect.  Those functions are for getting the 1st and 2nd things from a list, not from a selection set.

Kent Cooper, AIA
Message 17 of 27
Anonymous
in reply to: Kent1Cooper

Thank you so much @Kent1Cooper  for your help!! that worked!

I also found another mistake in the list: to put a dimension i needed 3 point, so i get the 3rd point in the middle of the pt1 and pt2

 

I will leave the lisp here just i case anyone needs it in the future:

 

 

(defun c:co (/ ss s1 s2 s3 p1 p2 pt1 pt2 pt3 x y)
(vl-load-com)
  (setq ss (ssget ()))
  (setq s1 (acet-ss-ssget-filter ss '((8 . "*_linea"))) 
	s2 (acet-ss-ssget-filter ss '((8 . "*_dist"))) 
	s3 (acet-ss-ssget-filter ss '((8 . "*_linea")(0 . "LWPOLYLINE,POLYLINE")(-4 . "&")(70 . 1))) 
  )                      
;IDENTIFY THE POINTS
  (setq p1 (ssname s3 0)
	p2 (ssname s3 1)
  )
  (setq pt1 (vlax-curve-getPointAtParam p1 2)
	pt2 (vlax-curve-getPointAtParam p2 2)
  )
;GET MIDDLE POINT (PT3)
  (setq x (/ (+ (car pt1) (car pt2)) 2)
	y (/ (+ (cadr pt1) (cadr pt2)) 2)
	z (/ (+ (caddr pt1) (caddr pt2)) 2)
        pt3 (list x y z)
  )
;DRAW DIMENSION
 (setvar "clayer" "_EST-ARM-REP")
 (command "_dimaligned" pt1 pt2 pt3)
  
;ERASE SELECTION 1 AND 2
 (command "_erase" s1 s2 "")
 (princ)
)

 

Message 18 of 27
john.uhden
in reply to: Anonymous

I think that the point of a polyline is to be able to join lines and arcs together into one continuous entity that can even be closed and offset as a whole.  They are great for contours and property boundaries. 😁

John F. Uhden

Message 19 of 27
Moshe-A
in reply to: Anonymous

@Anonymous  hi,

 

Even though you closed this,  here is the ultimate solution you can get  😀

command called CUSDIM (custom dimension) and it validates the triangles for it's vertices\edges and been an isosceles triangle, eliminating redundant vertices and if something been wrong, you will be alerted.

with CUSDIM you won't be worried about the head vertex been the 3rd point. it will be found no matter how the polyline was drawn 😀

 

the program start by declaring 2 constants:

 

(setq  LINEAR_FUZZ 1e-3)
(setq ANGULAR_FUZZ 1e-5)

 

the (equal) function is used a lot to verifies points and angles been equals in limit. if the accuracy level is not enough for you, increase (or decrease) these constants. LINEAR_FUZZ is for points and ANGULAR_FUZZ is for angles.

 

another constant you would like to set is the dimension line offset distance (how far the dimension line is placed from the triangles):

 

(setq DL_OSET_DIST (* (getvar "dimtxt") (getvar "dimscale") 4))

 

as you can see it is 4 times DIMTXT under the current dimstyle. if it is too close\far change it as needed. the program does not handles the dimension style (which is very important) or layer, these are left for you.

 

if the triangles lays for horizontal\vertical dimension they will be drawn with DIMLINEAR otherwise it will be DIMALIGNED.

 

enjoy

Moshe

 

 

 

;;; cusdim.lsp
;;; Custom Dimension command
;;; by Moshe.A
;;; APR 28, 2020

(vl-load-com) ; load activex support

(defun c:cusdim (/ get_vertices elim_zero_seg elim_cont_seg get_head_vertex pos_dimlin ; local funcrions
                   LINEAR_FUZZ ANGULAR_FUZZ DL_OSET_DIST ss lst0 lst1 p0 p1 ;| local variables |;)
 
 (defun get_vertices (ename / l lst)
  (setq l (fix (vlax-curve-getEndParam ename))) 
  (repeat l
   (setq lst (cons (vlax-curve-getPointAtParam ename (setq l (1- l))) lst))
  ); repeat

  lst  
 ); get_vertices
 
 ; eliminate zero distance segments 
 (defun elim_zero_seg (lst / points)
  (while (not
            (vl-every
              '(lambda (t0 t1)
                 (if (not (equal (distance t0 t1) 0.0 LINEAR_FUZZ))
                  (setq points (cons t0 points))
                 ); if 
               )
               lst
               (cdr (append lst (list (car lst))))
            ); vl-every
         ); not
   (setq lst points points nil)
  ); while

  points
 ); elim_zero_seg
  
 ; eliminate continuing segments
 (defun elim_cont_seg (lst / points)
  (while (not
           (vl-every
            '(lambda (t0 t1 t2)
              (if (not (equal (angle t0 t1) (angle t1 t2) ANGULAR_FUZZ))
               (setq points (cons t1 points))
              ); if
             ); lambda
             lst
             (cdr  (append lst (list (car lst))))
             (cddr (append lst (list (car lst)) (list (cadr lst))))
           ); vl-every
         ); not
   (setq lst points points nil)
  ); while

  (if (= (vl-list-length lst) 3)
   points 
   (progn
    (vlr-beep-reaction) 
    (alert "error: invalid triangle selected.")
   ); progn
  ); if
 ); elim_cont_seg
  
 (defun get_head_vertex (lst / angleAtVertices angle_sum ; local functions
                               dataL)

  (defun angleAtVertices (/ qang) ; local function

   (defun qang (a0 a1 / a2)
    (if (> a0 a1) 
     (setq a2 (- a0 a1))
     (setq a2 (- a1 a0))
    )

    (if (> a2 pi)
     (- (* pi 2) a2)
     a2 
    )  
   ); qang
    
   (mapcar
    '(lambda (t0 t1 t2)
      (cons (qang (angle t1 t0) (angle t1 t2)) (list t1))
     )
     lst
     (cdr  (append lst (list (car lst))))
     (cddr (append lst (list (car lst)) (list (cadr lst))))
    ); mapcar
  ); angleAtVertices
   
  (defun angle_sum () 
   (apply
     '+
     (mapcar
      '(lambda (d)
        (car d) 
       )
      dataL
     ); mapcar
   ); apply
  ); angle_sum
    
  ; here start (get_head_vertex)
  (setq dataL (angleAtVertices))
   
  (cond
   ((not (equal (angle_sum) pi ANGULAR_FUZZ))
    (vlr-beep-reaction)
    (alert "error: invalid triangle selected.")
   ); case
   ((equal (car (nth 0 dataL)) (car (nth 1 dataL)) ANGULAR_FUZZ)
    (cadr (nth 2 dataL))
   )
   ((equal (car (nth 0 dataL)) (car (nth 2 dataL)) ANGULAR_FUZZ)
    (cadr (nth 1 dataL))
   )
   ((equal (car (nth 1 dataL)) (car (nth 2 dataL)) ANGULAR_FUZZ)
    (cadr (nth 0 dataL))
   )
   ( t ; not isosceles triangle
    (vlr-beep-reaction)
    (alert "error: invalid triangle selected.")
   )
  ); cond
 ); get_head_vertex

 ; position dimension line 
 (defun pos_dimlin (t0 t1 / ax cx ang0 ang1)
  (setq ang0 (angle t0 t1)) 
  (setq ax (/ (distance t0 t1) 2))
  (setq cx (sqrt (+ (expt ax 2) (expt DL_OSET_DIST 2))))
  (setq ang1 (atan (/ DL_OSET_DIST ax)))
   
  (if (and
        (> ang0 (* pi 0.5))
        (< ang0 (* pi 1.5))
      )
   (polar t0 (+ ang0 ang1) cx)
   (polar t0 (- ang0 ang1) cx)
  ); if
 ); pos_dimlin

 ; here start (c:cusdim)
 (setvar "cmdecho" 0)

 ; declare some constants 
 (setq  LINEAR_FUZZ 1e-3)
 (setq ANGULAR_FUZZ 1e-5)
 ; dimension line offset distance 
 (setq DL_OSET_DIST (* (getvar "dimtxt") (getvar "dimscale") 4))
  
 (if  (and
       (setq ss (ssget '((0 . "*polyline") (70 . 1)))) ; filter closed AcDb2dPolyline and\or AcDbPolyline
       (= (sslength ss) 2)			       ; only 2 objects allowed
      )
   (if (and
        (setq lst0 (elim_zero_seg (get_vertices (ssname ss 0))))
        (setq lst1 (elim_cont_seg lst0))
        (setq p0 (get_head_vertex lst1))
        (setq lst0 (elim_zero_seg (get_vertices (ssname ss 1))))
        (setq lst1 (elim_cont_seg lst0))
        (setq p1 (get_head_vertex lst1))
      )
    (cond
     ((or
        (equal (car  p0) (car  p1) LINEAR_FUZZ)
        (equal (cadr p0) (cadr p1) LINEAR_FUZZ)
      )
      (command "._dimlinear" "_None" p0 "_None" p1 "_None" (pos_dimlin p0 p1))
     ); case
     ( t
      (command "._dimaligned" "_None" p0 "_None" p1 "_None" pos_dimlin p0 p1))
     )
    ); cond
   ); if
 ); if

 (setvar "cmdecho" 1)
  (princ) 
); c:cusdim
  

 

 

 

 

 

 

 

 

 

 

 

Message 20 of 27
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

... to put a dimension i needed 3 point, so i get the 3rd point in the middle of the pt1 and pt2

….

....
;GET MIDDLE POINT (PT3)
  (setq x (/ (+ (car pt1) (car pt2)) 2)
	y (/ (+ (cadr pt1) (cadr pt2)) 2)
	z (/ (+ (caddr pt1) (caddr pt2)) 2)
        pt3 (list x y z)
  )
....

For that part, here's a more concise way to do it, without separate variables for each coordinate:

 

(setq pt3 (mapcar '/ (mapcar '+ pt1 pt2) '(2 2 2)))

 

The inner [second] (mapcar) function adds the coordinates in each direction of the two points together all in one operation, and the outer [first] one divides the values of those sums by 2 each.

Kent Cooper, AIA

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report