AfraLISP - Learn AutoLISP for AutoCAD productivity

Visual LISP & Polylines - Part 2

by Kenny Ramage

This is the VBA method to create a lightweight polyline from a list of vertices.

RetVal = object.AddLightweightPolyline(VerticesList)
  • Object : ModelSpace Collection, PaperSpace Collection, Block. The object or objects this method applies to.
  • VerticesList : Variant (array of doubles). The array of 2D OCS coordinates specifying the vertices of the polyline. At least two points (four elements) are required for constructing a lightweight polyline. The array size must be a multiple of 2.
  • RetVal : LightweightPolyline object. The newly created LightweightPolyline object.

In Visual Lisp, the syntax would be as follows :

(vla-addLightweightPolyline Object VerticesList)

and would return RetVal.

The Process

Let's try this out. First we need a reference to Model Space :

_$ (setq mspace (vla-get-modelSpace (vla-get-activeDocument
#<VLA-OBJECT IAcadModelSpace 01ea5064>

Get the first point :

_$ (setq pt1 (getpoint))
(424.505 252.213 0.0)

Extract the X and Y coordinates

_$ (setq pt1 (list (car pt1) (cadr pt1)))
(424.505 252.213)

And now the second point :

_$ (setq pt2 (getpoint))
(767.689 518.148 0.0)

Extract the X and Y coordinates :

_$ (setq pt2 (list (car pt2) (cadr pt2)))
(767.689 518.148)

Join the the two lists together :

_$ (setq pt1 (append pt1 pt2))
(424.505 252.213 767.689 518.148)

Construct a 4 element safearray :

_$ (setq anarray (vlax-make-safearray vlax-vbDouble '(0 . 3)))

Fill it with our point X and Y values :

_$ (vlax-safearray-fill anarray pt1)

Draw the polyline :

_$ (setq myobj (vla-addLightweightPolyline mspace anarray))
#<VLA-OBJECT IAcadLWPolyline 01ea5914>

A Practical Example

Let's now have a look how we could apply this to a practical example :

(prompt "\nType \"VL-Steel\" to run......")
;set up default rotation angle
(if (= rot nil) (setq rot 0))
;define the function and declare all local variables
(defun C:VL-Steel ( / ptlist oldsnap oldecho oldblip acaddoc util mspace names sizes
dcl_id siza userclick dlist H B T1 T2 R1 IP IPA P1 ptlisp tmp myobj fname fn pts)
;load VL functions
;obtain reference to the Active Document
(setq acaddoc (vla-get-activeDocument (vlax-get-acad-object)))
;obtain reference to Utilities
(setq util (vla-get-utility acaddoc))
;obtain reference to Model Space
(setq mspace (vla-get-modelSpace acaddoc))
;store system variables
(setq oldsnap (vla-getvariable acaddoc "OSMODE")
       oldecho  (vla-getvariable acaddoc "CMDECHO")
         oldblip  (vla-getvariable acaddoc "BLIPMODE")
;switch off system variables
(vla-setvariable acaddoc "CMDECHO" 0)
(vla-setvariable acaddoc "BLIPMODE" 0)
;create list of steel sections for the list box
(setq names '("100x55x8" "120x64x10" "140x73x13" "160x82x16"
"180x91x19" "200x100x22" "203x133x25" "203x133x30" "254x146x31"
"254x146x37" "254x146x43" ) )
;create list of steel section values
(setq sizes '((100.0 55.0 4.1 5.7 7.0) 
(120.0 64.0 4.4 6.3 7.0) (140.0 73.0 4.7 6.9 7.0) 
(160.0 82.0 5.0 7.4 9.0) (180.0 91.0 5.3 8.0 9.0)
(200.0 100.0 5.6 8.5 12.0) (203.2 133.4 5.8 7.8 7.6) 
(206.8 133.8 6.3 9.6 7.6) (251.5 146.1 6.1 8.6 7.6) 
(256.0 146.4 6.4 10.9 7.6) (259.6 147.3 7.3 12.7 7.6)))
;construct the dialog
;load the dialog
(setq dcl_id (load_dialog fname))
(if (not (new_dialog "ubeam" dcl_id))
;setup the list box
(start_list "selections")
(mapcar 'add_list names)
;default rotation angle
(set_tile "rot" (rtos rot))
;setup the Cancel button
  "(done_dialog) (setq userclick nil)"
;setup the OK button
     "(progn (setq siza (atof (get_tile \"selections\")))
                   (setq rot (atof (get_tile \"rot\")))"
     "(done_dialog) (setq userclick T))" )
;display the dialog
;unload the dialog
(unload_dialog dcl_id)
;delete the temp DCL file
(vl-file-delete fname)
  ;if the OK button was selected
  (if userclick
    ;do the following
      ;retrieve the steel section values
      (setq dlist (nth (fix siza) sizes))
      ;place them into variables
      (mapcar 'set '(H B T1 T2 R1) dlist)
      ;switch on the intersection snap
      (vla-setvariable acaddoc "OSMODE" 32)
      ;get the insertion point
      (setq IP (vla-getpoint util nil "\nInsertion Point : "))
      ;switch off the snaps   
      (vla-setvariable acaddoc "OSMODE" 0)   
      ;calculate the points and store them in a list
      (setq pts (list 
        (setq P1 (vla-polarpoint util IP 0 (/ T1 2)))
	(setq P1 (vla-polarpoint util P1 (DTR 90.0) 
		 (/ (- H (+ T2 T2 R1 R1)) 2)))
	(setq P1 (vla-polarpoint util P1 (DTR 45.0) 
		(sqrt (* R1 R1 2.0))))
	(setq P1 (vla-polarpoint util P1 0 
		 (/ (- B (+ T1 R1 R1)) 2)))
	(setq P1 (vla-polarpoint util P1 (DTR 90.0) T2))
	(setq P1 (vla-polarpoint util P1 (DTR 180.0) B))
	(setq P1 (vla-polarpoint util P1 (DTR 270.0) T2))
	(setq P1 (vla-polarpoint util P1 0 
		 (/ (- B (+ T1 R1 R1)) 2)))
	(setq P1 (vla-polarpoint util P1 (DTR 315.0) 
		(sqrt (* R1 R1 2.0))))
	(setq P1 (vla-polarpoint util P1 (DTR 270.0) 
		 (- H (+ T2 T2 R1 R1))))
	(setq P1 (vla-polarpoint util P1 (DTR 225.0) 
		(sqrt (* R1 R1 2.0))))
	(setq P1 (vla-polarpoint util P1 (DTR 180.0) 
		 (/ (- B (+ T1 R1 R1)) 2)))
	(setq P1 (vla-polarpoint util P1 (DTR 270.0) T2))
	(setq P1 (vla-polarpoint util P1 0 B))
	(setq P1 (vla-polarpoint util P1 (DTR 90.0) T2))
	(setq P1 (vla-polarpoint util P1 (DTR 180.0) 
		 (/ (- B (+ T1 R1 R1)) 2)))
	(setq P1 (vla-polarpoint util P1 (DTR 135.0) 
		 (sqrt (* R1 R1 2.0))))
	(setq P1 (vla-polarpoint util IP 0 (/ T1 2)))
        ;extract only the X and Y values of each point list
          '(lambda  (pt)
                ;convert to lists
		(setq pt (vlax-safearray->list (variant-value pt)))
                ;X and Y values only
		(setq ptlist (cons (list (car pt) (cadr pt)) ptlist))
        ;break the point list up into elements
	(setq ptlist (apply 'append ptlist))
        ;create a safearray to store the elements
	(setq tmp (vlax-make-safearray vlax-vbDouble 
		  (cons 0 (- (vl-list-length ptlist) 1))))
        ;fill the safearray
      	(vlax-safearray-fill tmp ptlist)
        ;draw the steel section
      	(setq myobj (vla-addLightweightPolyline mspace tmp))
        ;radius the corners
	(vla-setbulge myobj 1 0.4142)
	(vla-setbulge myobj 7 0.4142)
	(vla-setbulge myobj 9 0.4142)
	(vla-setbulge myobj 15 0.4142)
        ;rotate the object
        (vla-rotate myobj ip (dtr rot))
         ;reset system variables
     	 (vla-setvariable acaddoc "OSMODE" oldsnap)
    	 (vla-setvariable acaddoc "CMDECHO" oldecho)
     	 (vla-setvariable acaddoc "BLIPMODE" oldblip)
         ;release all objects
    	 (vlax-release-object mspace)
     	 (vlax-release-object util)
     	 (vlax-release-object acaddoc)
  ;finish clean
(defun create_dialog ()
;create a temp DCL file
(setq fname (vl-filename-mktemp "dcl.dcl"))
;open it to write
(setq fn (open fname "w"))
;write the dialog coding
"ubeam : dialog { 
     label = \"VL-Steel\";
     : list_box {
        label = \"Choose Section :\";
        key = \"selections\";
        allow_accept = true;
        height = 8;
     : edit_box {
       label = \"Rotation Angle :\";
       key = \"rot\";
       edit_limit = 4;
       edit_width = 4;
     ok_cancel ;
     :text_part {
         label = \"Designed and Created\";
     :text_part {
         label = \"by Kenny Ramage\";
     }" fn)
;close the temp DCL file
(close fn)
;convert degrees to radians
(defun DTR (a)
 (* pi (/ a 180))
;load clean

Save this as VL-Steel.lsp and then load and run it. A dialog like this will appear :

dialog box

Choose the section size you would like, choose a rotation angle, select an insertion point, and voila, your steel section is drawn using a polyline.

"OK Kenny, now we give in. HOW do you calculate a bulge?"

Bulge = TAN ( / Included Angle 4)

In our case Bulge = TAN ( / 90 4) = 0.4142

Thanks to Stig Madsen for the insight into some of this coding.

Click here to download the sample coding from this tutorial.

If you would like to have a look at a similar application, but written in VBA, just click here.