Author Topic: Draw pline  (Read 3852 times)

0 Members and 1 Guest are viewing this topic.

2cook2

  • Guest
Draw pline
« on: July 21, 2011, 03:45:55 PM »
I have a LISP routine that draws 3 separate lines.  I would like for it to draw a single pline instead.

CODE:

      (setq NewLine (vlax-invoke space 'addline Dway1 Dway3))            ;Draws Joint line
      (NLINE_chprop NewLine VLA_line1)

      (setq NewLine (vlax-invoke space 'addline Dway3 Dway4))            ;Draws tap side1
      (NLINE_chprop NewLine VLA_line1)

      (setq NewLine (vlax-invoke space 'addline Dway1 Dway2))            ;Draws tap side2
      (NLINE_chprop NewLine VLA_line1)

I am new to the visual thing.  I have tried using "Addlightweightpolyline" but keep getting errors.  A gentle push or a downright shove in the right direction would be appreciated.

Thanks


kruuger

  • Swamp Rat
  • Posts: 616
Re: Draw pline
« Reply #1 on: July 21, 2011, 03:52:06 PM »
Code: [Select]
; ============================================================ ;
; Add LWPoly                                                   ;
; ============================================================ ;
(defun jk:ACX_AddLWPoly (Space Pts Width Closed Props / arr Obj)
  (setq Pts (mapcar '(lambda (&) (list (car &)(cadr &))) Pts))
  (if
    (and
      (= Closed 1)
      (equal (car Pts)(last Pts) 0.01)
    )
    (setq Pts (reverse (cdr (reverse Pts))))
  )
  (setq Pts (apply 'append Pts)
        arr (vlax-make-safearray vlax-vbdouble (cons 1 (length Pts)))
        arr (vlax-make-variant (vlax-safearray-fill arr Pts))
        Obj (vla-addlightweightpolyline Space arr)
  )
  (if (numberp Width)(vla-put-constantwidth Obj (abs Width)))
  (if (member Closed '(0 1))(vla-put-closed Obj Closed))
  (mapcar
    '(lambda (%)
       (if
         (vlax-get-property Obj (car %))
         (vlax-put-property Obj (car %)(cdr %))
       )
    )
    Props
  )
  Obj
)
k.

Lee Mac

  • Seagull
  • Posts: 12265
  • London, England
Re: Draw pline
« Reply #2 on: July 21, 2011, 05:46:35 PM »
For the following examples, assume I have three points from which I wish to construct an LWPolyline:

Code: [Select]
(setq p1 '(1.2 3.4)
      p2 '(3.2 5.1)
      p3 '(6.2 8.4)
)

Since the vertices of an LWPolyline are 2D, (with the Z-coordinate constant, enumerated by the LWPolyline elevation), these points must be 2D.

For the construction of the LWPolyline, there are three routes you can take:

1) Command Call:

The slowest method, but perhaps most intuitive for a beginner, using existing AutoCAD command knowledge:

Code: [Select]
(command "_.pline" "_non" p1 "_non" p2 "_non" p3)
Note that the "_non" prefix is used to avoid interference with any active Object Snaps.

2) Entmake

The fastest method, but maybe a little obscure if you aren't familiar with the various DXF group codes:

Code: [Select]
(entmakex
  (list
    (cons 0 "LWPOLYLINE")
    (cons 100 "AcDbEntity")
    (cons 100 "AcDbPolyline")
    (cons 90 3)
    (cons 70 0)
    (cons 10 p1)
    (cons 10 p2)
    (cons 10 p3)
  )
)

A full reference for the DXF group codes utilised by the above code can be found here.

3) Visual LISP AddLightWeightPolyline method

Let us first grab modelspace, just for this example:

Code: [Select]
(setq mspace
  (vla-get-modelspace
    (vla-get-activedocument (vlax-get-acad-object))
  )
)

Now, there are three ways you can invoke the AddLightWeightPolyline method:

The undocumented vlax-invoke function:

Code: [Select]
(vlax-invoke mspace 'addlightweightpolyline (append p1 p2 p3))
This avoids the need to use Variants and Safearrays, but, you must ensure that all the coordinate values are Reals (Doubles), otherwise this method will fail. This subtlety can sometimes be overlooked and is a difficult bug to spot.

The vlax-invoke-method function, or the vla-addlightweightpolyline function:

These perform in much the same way, accepting the same parameter data types. The subtle difference is that vla-addlightweightpolyline is an expression that is resolved at compilation, whereas vlax-invoke-method function is an expression that is resolved at runtime. This difference would imply that, if you have mispelled a method called by vlax-invoke-method, the error will arise at runtime, whereas a mispelling using the vla-* function will be caught at compilation. Furthermore, the vla-* functions are derived from the ActiveX type library, (which, for the AutoCAD object model, is registered automatically); when working with functions derived from other object models (such as Excel), you would have to import the relevant type library to obtain a set of functions analogous to the vla-* functions (but with a different (specified) prefix).

vlax-invoke-method
Code: [Select]
(vlax-invoke-method mspace 'addlightweightpolyline
  (vlax-make-variant
    (vlax-safearray-fill
      (vlax-make-safearray vlax-vbdouble '(0 . 5)) (append p1 p2 p3)
    )
  )
)

vla-addlightweightpolyline
Code: [Select]
(vla-addlightweightpolyline mspace
  (vlax-make-variant
    (vlax-safearray-fill
      (vlax-make-safearray vlax-vbdouble '(0 . 5)) (append p1 p2 p3)
    )
  )
)



Note that none of the above demonstrated methods allow for changes in UCS, or indeed express whether the original point set is defined in UCS or WCS.

All of the above methods could be altered to accept a list of points, but I shall leave this as an exercise for you to think about since I am merely providing an outline.

Finally, none of the posted code has been tested and all of the information has been plucked out of my head, having been gathered over the years mostly from these forums; so there may well be some mistakes - don't hesitate to correct me.

I hope this helps!

Lee
« Last Edit: July 21, 2011, 05:53:11 PM by Lee Mac »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10365
Re: Draw pline
« Reply #3 on: July 21, 2011, 05:50:56 PM »
Wow Lee a tutorial.  Nice  8-)

Some code I snatched out of my collection.

Code: [Select]
  ;;  by CAB 03/22/2009
  ;;  Expects pts to be a list of 2D or 3D points
  ;;  Returns new pline object, not closed
  (defun makePline (spc pts / norm elv pline)
    (setq norm  (trans '(0 0 1) 1 0 T)
          elv   (caddr (trans (car pts) 1 norm))
    )
    (setq pline
      (vlax-invoke Spc 'addLightWeightPolyline
        (apply 'append
          (mapcar  '(lambda (pt)
             (setq pt (trans pt 1 norm))
             (list (car pt) (cadr pt)))       
            pts)))
    )
    (vla-put-Elevation pline elv)
    (vla-put-Normal pline (vlax-3d-point norm))
    pline
  )


  (setq Space
(if (= 1 (getvar "CVPORT"))
   (vla-get-PaperSpace (vla-get-activedocument (vlax-get-acad-object)))
   (vla-get-ModelSpace (vla-get-activedocument (vlax-get-acad-object)))
)
  )

  (makePline Space (list Dway1 Dway2 Dway3 Dway4))
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: 12265
  • London, England
Re: Draw pline
« Reply #4 on: July 21, 2011, 06:00:17 PM »
Wow Lee a tutorial.  Nice  8-)

Thanks Alan, I got a bit carried away  :-P

chlh_jd

  • Guest
Re: Draw pline
« Reply #5 on: July 22, 2011, 01:04:38 PM »
Nice LEE & Alan
here's I used
Code: [Select]
;;;lst must be ptlst and dxf-list , forexample (list (list pt1 pt2 pt3)  (cons 70 1) (cons 62 1) ...)
(defun draw-pl (lst)
  (entmake
    (append
      (list (cons 0 "LWPOLYLINE")
(cons 100 "AcDbEntity")
(cons 100 "AcDbPolyline")
(cons 90 (length (car lst)))
       )     
      (mapcar (function (lambda (x) (cons 10 x))) (car lst));_points of pline.
      (list (cons 70 1)) ;closed
      (cdr lst)
    )
  )
)
e.g
Code: [Select]
(draw-pl (list (list pt1 pt2 pt3) (cons 8 "TEST")(cons 62 1)))
another  way
Code: [Select]
;;;--------------------------------------------------------------------------------------;;;
;;;drwa-pline                                                                            ;;;
;;;--------------------------------------------------------------------------------------;;;
;;;
;;;function: to make a polyline by code and return ename
;;;
;;;Variants:
;;;pl_list: the points list offered by order
;;;width : 0.0 or num, or a list like ((0.0 0.0) (0.0 20) (20 0.0)...),if nil it will getvar "plinewid" ,
;;;        if it's length noteq d90 then wid41 and wid42 equal to 0.0 .   
;;;d42_lst: 0.0 or num, or nil, if nil or it's length noteq d90 then d42 equal to 0.0 .
;;;
;;;lay_pl: layername, if nil it will getvar "CLAYER"
;;;
;;;color : color number, if it's -1 then getvar "COLOR" ellse set it by the given color number
;;;
;;;Prompt:
;;;If width list or d42_lst list is Exist , it's order must be same to the pl_list,
;;;   otherwise it will take out a wrong polyline .
;;;
;;;Written By GSLS(SS),2010.06.30
;;;
(defun draw-pline
  (pl_list width   d42_lst lay_pl  color   d70
   /    d90    i    wid    d42    wid40
   wid41   en000   pb
  )
  (setq d90 (length pl_list)
pb  nil
i   0
  )
  (cond ((and (listp width)
      (listp d42_lst)
      (= (length width) (length d42_lst) d90)
)
(foreach pt pl_list
   (setq wid   (nth i width)
d42   (nth i d42_lst)
wid40 (car wid)
wid41 (cadr wid)
pb    (append pb
       (list (cons 10 pt)
     (cons 40 wid40)
     (cons 41 wid41)
     (cons 42 d42)
       )
       )
i     (1+ i)
   )
)
)
((and (or (numberp width) (null width))
      (listp d42_lst)
      (= (length d42_lst) d90)
)
(if (null width)
   (setq wid40 (getvar "plinewid")
wid41 (getvar "plinewid")
   )
   (setq wid40 width
wid41 width
   )
)
(foreach pt pl_list
   (setq d42 (nth i d42_lst)
pb  (append pb
     (list (cons 10 pt)
   (cons 40 wid40)
   (cons 41 wid41)
   (cons 42 d42)
     )
     )
i   (1+ i)
   )
)
)
((and (listp width)
      (= (length width) d90)
      (or (null d42_lst) (numberp d42_lst))
)
(if (null d42_lst)
   (setq d42 0.0)
   (setq d42 d42_lst)
)
(foreach pt pl_list
   (setq wid   (nth i width)
wid40 (car wid)
wid41 (cadr wid)
pb    (append pb
       (list (cons 10 pt)
     (cons 40 wid40)
     (cons 41 wid41)
     (cons 42 d42)
       )
       )
i     (1+ i)
   )
)
)
(t
(if (numberp width)
   (setq wid40 width
wid41 width
   )
   (setq wid40 0.0
wid41 0.0
   )
)
(foreach pt pl_list
   (setq pb (append pb
    (list (cons 10 pt)
  (cons 40 wid40)
  (cons 41 wid41)
  (cons 42 0.0)
    )
    )
   )
)
)
  )
  (setq en000 (append (list
(cons 0 "LWPOLYLINE")
(cons 100 "AcDbEntity")
(cons 8
      (if (and lay_pl (/= lay_pl ""))
lay_pl
(getvar "CLAYER")
      )
)
(cons 100 "AcDbPolyline")
(cons 90 d90)
(cons 70 d70)
      )
      pb
      )
  )
  (if (and color (/= -1 color))
    (setq en000 (append en000 (list (cons 62 color))))
  )
  (if (= nil (entmake en000))
    (*error*  "Failure to make LwPolyLine,Please check intput")
  (entlast))
)

ferry

  • Guest
Re: Draw pline
« Reply #6 on: August 22, 2011, 09:22:14 PM »
For the following examples, assume I have three points from which I wish to construct an LWPolyline:

Code: [Select]
(setq p1 '(1.2 3.4)
      p2 '(3.2 5.1)
      p3 '(6.2 8.4)
)

How can I draw square as an example?
When I add an extra point p4 it will not work!

Ferry.
« Last Edit: August 22, 2011, 09:29:09 PM by ferry »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10365
Re: Draw pline
« Reply #7 on: August 22, 2011, 11:34:59 PM »
Welcome to The Swamp.  8-)

Which method are you using to make your pline?

For a square, not closed use this.
Code: [Select]
(command "_.pline" "_non" p1 "_non" p2 "_non" p3 "_non" p4 "_non" p1)
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.

HofCAD

  • Guest
Re: Draw pline
« Reply #8 on: August 23, 2011, 09:27:26 AM »
Ferry,

Look in the Attachments.
Draw Square Lisp.LSP for plane AutoLisp solutions
Draw Square Vlisp.LSP for Visual LISP solutions
SquareDia.lsp for AutoLisp solutions with dialogbox

Regards, HofCAD CSI.

cmwade77

  • Swamp Rat
  • Posts: 1206
Re: Draw pline
« Reply #9 on: August 24, 2011, 04:43:27 PM »
Wow Lee a tutorial.  Nice  8-)

Some code I snatched out of my collection.

Code: [Select]
  ;;  by CAB 03/22/2009
  ;;  Expects pts to be a list of 2D or 3D points
  ;;  Returns new pline object, not closed
  (defun makePline (spc pts / norm elv pline)
    (setq norm  (trans '(0 0 1) 1 0 T)
          elv   (caddr (trans (car pts) 1 norm))
    )
    (setq pline
      (vlax-invoke Spc 'addLightWeightPolyline
        (apply 'append
          (mapcar  '(lambda (pt)
             (setq pt (trans pt 1 norm))
             (list (car pt) (cadr pt)))       
            pts)))
    )
    (vla-put-Elevation pline elv)
    (vla-put-Normal pline (vlax-3d-point norm))
    pline
  )


  (setq Space
(if (= 1 (getvar "CVPORT"))
   (vla-get-PaperSpace (vla-get-activedocument (vlax-get-acad-object)))
   (vla-get-ModelSpace (vla-get-activedocument (vlax-get-acad-object)))
)
  )

  (makePline Space (list Dway1 Dway2 Dway3 Dway4))

I actually use this in several of my routines that we use here, it is fast and works very well. Just a heads up.

ferry

  • Guest
Re: Draw pline
« Reply #10 on: August 25, 2011, 06:00:56 AM »
Welcome to The Swamp.  8-)

Which method are you using to make your pline?

I was looking to the tutorial of Lee Mac with the methods 'Entmake'
and 'Visual LISP AddLightWeightPolyline method'.
I saw the solution in the attachments of HofCAD.

Lee Mac

  • Seagull
  • Posts: 12265
  • London, England
Re: Draw pline
« Reply #11 on: August 25, 2011, 08:08:59 AM »
If you add 'p4' to the entmakex list, you will need to change the DXF 90 code to 4 since there are now 4 vertices.

Similarly, for the Visual LISP methods involving variants, you would need to increase the size of the safearray from '(0 . 5) to '(0 . 7)

Lee

CAB

  • Global Moderator
  • Seagull
  • Posts: 10365
Re: Draw pline
« Reply #12 on: August 25, 2011, 08:32:17 AM »
I actually use this in several of my routines that we use here, it is fast and works very well. Just a heads up.

Glad you found some use for the code.  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.