Draw poiyline using a list containing X, Y coordinate

Draw poiyline using a list containing X, Y coordinate

Anonymous
Not applicable
3,011 Views
14 Replies
Message 1 of 15

Draw poiyline using a list containing X, Y coordinate

Anonymous
Not applicable

Hello, all. I am a beginner of AutoCAD lisp.

 

I have two simple questions

 

 

1. I generate a list which containing X Y coordinate such as:

 

Coor = (100 10 101 12 103 32)

which means X1 = 100, Y1 = 10, X2 = 101, Y2 = 12, X3 = 103, Y3 = 32.

Here, how can I make lisp code to work as like:

(COMMAND "PLINE" "100,10" "101,12" "103,32" "")

 

2. Through the web search, I understand there are several methods to draw pline from the list as like:

Coor_1 = ((100 10) (101 12) (103 32))

Here, how can I change the list format from Coor (original one in above #1) to Coor_1?

 

Thank you. Cheers,

0 Likes
3,012 Views
14 Replies
Replies (14)
Message 2 of 15

Anonymous
Not applicable

I've find the solution by myself. Thanks.

0 Likes
Message 3 of 15

Discussion_Admin
Alumni
Alumni

Can you post the solution to share with other searching ???

 

Thanks
Discussion_Admin

0 Likes
Message 4 of 15

john.uhden
Mentor
Mentor

Just to perhaps confirm what you found, Coor is called a flat list (x1 y1 x2 y2 xn yn) whereas Coor_1 is a 2D list (a list of 2D points).

The flat list is what you need if you want to use (vla-addlightweighrpolyline ...).

The 2D list is handy if you want to use (command ".pline" (mapcar Coor_1) "")

The 2D list can be converted into a flat list by (apply 'append Coor_1).

The flat list can be converted into a 2D list by grouping the list in pairs...

 

  (defun @group (old n / item new)
    (while old
      (while (< (length item) n)
        (setq item (cons (car old) item) old (cdr old))
      )
      (setq new (cons (reverse item) new) item nil)
    )
    (reverse new)
  )

Such as (@group Coor 2)
which can also be used for 3D flat lists, as in
(@group flatlist 3)

John F. Uhden

0 Likes
Message 5 of 15

Kent1Cooper
Consultant
Consultant

This can actually be a lot simpler than you might think.  The 'Coordinates VLA Property of a LWPolyline is just such a "flat list," and can be imposed on a Polyline, even one without the same number of vertices.  The coordinates do need to be real numbers, though, not integers.  The following makes that conversion, and draws a temporary minimal Polyline, then imposes those coordinates on it.  The PLINETYPE System Variable needs to be other than 0, because a "heavy" Polyline needs XYZ coordinates, not just XY.

 

(vl-load-com); if not already loaded

(setvar 'plinetype 2); in case it happens to be 0

(setq Coor (mapcar 'float Coor))
(command "_.pline" (getvar 'viewctr) "@1,0" "")
(vlax-put (vlax-ename->vla-object (entlast)) 'Coordinates Coor)

 

This has an additional benefit over any approach that breaks up the list into point lists and uses them in a PLINE command, that this doesn't require any accounting for whether any Object Snap modes are running.

Kent Cooper, AIA
0 Likes
Message 6 of 15

john.uhden
Mentor
Mentor

Excellent!  That's actually the way I usually do it, though sometimes I will use entmake because I can include the desired layer name without any additional code, plus plinewid and closed.  Actually, entmake followed by putting the coordinates is probably the best and easiest.  The last step is to setbulge.

John F. Uhden

0 Likes
Message 7 of 15

martti.halminen
Collaborator
Collaborator

 

Another way to make a 2D list:

 

(defun pairify (l)
  ;; (a b c d...) -> ((a b)(c d) ...)
  (cond ((null l) nil)
        (T (cons (list (car l) (cadr l)) (pairify (cddr l))))))

-- 

 

0 Likes
Message 8 of 15

john.uhden
Mentor
Mentor

But then you need a tripify function, or maybe trioify for heavies or 3Ds.

John F. Uhden

0 Likes
Message 9 of 15

Ranjit_Singh
Advisor
Advisor

arz6oiof wrote:...........

Coor = (100 10 101 12 103 32)

....

Here, how can I make lisp code to work as like:

(COMMAND "PLINE" "100,10" "101,12" "103,32" "")

...........


There can be many possible ways as suggested above by other members. Here is one example

Command: (setq Coor '(100 10 101 12 103 32))
(100 10 101 12 103 32)
Command: (mapcar '(lambda (x y) (list x y)) Coor (cdr Coor))
((100 10) (10 101) (101 12) (12 103) (103 32))

To make a pline from this list,

(apply 'command (append '("._pline") (mapcar '(lambda (x y) (list x y)) Coor (cdr Coor)) '("")))

2d_point_list.gif

 

Message 10 of 15

phanaem
Collaborator
Collaborator

@Ranjit_Singh wrote:


There can be many possible ways as suggested above by other members. Here is one example

Command: (setq Coor '(100 10 101 12 103 32))
(100 10 101 12 103 32)
Command: (mapcar '(lambda (x y) (list x y)) Coor (cdr Coor))
((100 10) (10 101) (101 12) (12 103) (103 32))

 


Ranjit, your list has 5 vertexes, not 3, like it should be (= list_length / 2), so it is not the same polyline.

 

0 Likes
Message 11 of 15

Ranjit_Singh
Advisor
Advisor

phanaem wrote:...
Ranjit, your list has 5 vertexes, not 3, like it should be (= list_length / 2), so it is not the same polyline... 

Thanks for the correction. I have adjusted my code

(setq Coor '(100 10 101 12 103 32) ctr 1)
(apply 'command
       (append '("._pline")
               (vl-remove nil
                          (mapcar '(lambda (x y)
                                    (if (minusp (setq ctr (- ctr)))
                                     (list x y)))
                                  coor
                                  (cdr coor)))
               '("")))

2d_point_list_correct.gif 

0 Likes
Message 12 of 15

DannyNL
Advisor
Advisor

Just for fun and info.

Lee Mac has written two nice short solutions to convert number lists to 2D or 3D point lists.

 

(defun LM:lst->3DPoint ( l ) ;; © Lee Mac 2010
   (if
      l
      (cons (list (car l) (cadr l) (caddr l)) (LM:lst->3DPoint (cdddr l)))
   )
)

(defun LM:lst->2DPoint ( l ) ;; © Lee Mac 2010
   (if
      l
      (cons (list (car l) (cadr l)) (LM:lst->2DPoint (cddr l)))
   )
)
0 Likes
Message 13 of 15

phanaem
Collaborator
Collaborator

@DannyNL wrote:

Just for fun and info.

Lee Mac has written two nice short solutions to convert number lists to 2D or 3D point lists.

 

Not sure if Lee Mac should be credited for these functions. Even in this topic there is a similar one.

He could write them from scratch, I know I did, but I guess so did many others, way before us.

 

If the speed matters, here is an alternative, 5 times faster (tested on 2000 points polyline)

 

(defun list->2Dpoints (l / a b r)
  (foreach b l
    (cond
      (a (setq r (cons (list a b) r) a nil))
      (T (setq a b))
    )
  )
  (reverse r)
)


(defun list->3Dpoints (l / a b c r)
  (foreach c l
    (cond
      (b (setq r (cons (list a b c) r) a nil b nil))
      (a (setq b c))
      (T (setq a c))
    )
  )
  (reverse r)
)
0 Likes
Message 14 of 15

DannyNL
Advisor
Advisor

Yep, that would be another way. There are multiple way to achieve the same.

 

Although these functions are pretty straightforward and could be written by anyone with average LISP knowledge, the code examples I posted were written by Lee Mac. I just copied and pasted, so I think it is more than fair to mention credit him since I didn't write them myself.

 

And since I do not work very often with lists that contain over 100 points, they are more than sufficient for my needs. In my case I'm not interested in faster if that means a difference of a couple of milliseconds Smiley Happy

0 Likes
Message 15 of 15

phanaem
Collaborator
Collaborator

@DannyNL wrote:

Yep, that would be another way. There are multiple way to achieve the same.

 

Although these functions are pretty straightforward and could be written by anyone with average LISP knowledge, the code examples I posted were written by Lee Mac. I just copied and pasted, so I think it is more than fair to mention credit him since I didn't write them myself.

 

And since I do not work very often with lists that contain over 100 points, they are more than sufficient for my needs. In my case I'm not interested in faster if that means a difference of a couple of milliseconds Smiley Happy


Fair enough.

For the sake of truth, the posted lisp is not 5 times faster, it's less than 2. The test I did wasn't accurate.

 

0 Likes