AfraLISP - Learn AutoLISP for AutoCAD productivity

Visual LISP & Polylines - Part 1

by Kenny Ramage

Dealing with polylines using straight forward AutoLISP can be quite a pain. But, believe it or not, using Visual LISP they are a breeze to modify and manipulate. Let's have a look shall we?

Manipulating Polylines

First of all, fire up AutoCAD and draw a polyline but do not close it :

Polyline state 1

Now, type the following in the Visual LISP editor :

_$ (vl-load-com)

_$ (setq theobj (car (entsel "\nSelect a Polyline: ")))
<Entity name: 14e35f8>

_$ (setq theobj (vlax-ename->vla-object theobj))
#<VLA-OBJECT IAcadLWPolyline 01ea16d4>

_$ (vlax-dump-object theobj T)
; IAcadLWPolyline: AutoCAD Lightweight Polyline Interface

      ; Property values:
      ; Application (RO) = #<VLA-OBJECT IAcadApplication 00ac8928>
      ; Area (RO) = 16178.7
      ; Closed = 0
      ; Color = 256
      ; ConstantWidth = 0.0
      ; Coordinate = ...Indexed contents not shown...
      ; Coordinates = (540.98 557.623 640.815 449.587 453.624 403.879 ... )
      ; Document (RO) = #<VLA-OBJECT IAcadDocument 00ec89b4>
      ; Elevation = 0.0
      ; Handle (RO) = "957"
      ; HasExtensionDictionary (RO) = 0
      ; Hyperlinks (RO) = #<VLA-OBJECT IAcadHyperlinks 01ea1ec4>
      ; Layer = "7"
      ; Linetype = "BYLAYER"
      ; LinetypeGeneration = 0
      ; LinetypeScale = 1.0
      ; Lineweight = -1
      ; Normal = (0.0 0.0 1.0)
      ; ObjectID (RO) = 21902840
      ; ObjectName (RO) = "AcDbPolyline"
      ; OwnerID (RO) = 21901504
      ; PlotStyleName = "ByLayer"
      ; Thickness = 0.0
      ; Visible = -1
                    
      ; Methods supported:
      ; AddVertex (2)
      ; ArrayPolar (3)
      ; ArrayRectangular (6)
      ; Copy ()
      ; Delete ()
      ; Explode ()
      ; GetBoundingBox (2)
      ; GetBulge (1)
      ; GetExtensionDictionary ()
      ; GetWidth (3)
      ; GetXData (3)
      ; Highlight (1)
      ; IntersectWith (2)
      ; Mirror (2)
      ; Mirror3D (3)
      ; Move (2)
      ; Offset (1)
      ; Rotate (2)
      ; Rotate3D (3)
      ; ScaleEntity (2)
      ; SetBulge (2)
      ; SetWidth (3)
      ; SetXData (2)
      ; TransformBy (1)
      ; Update ()
      T

This is a listing of all the Properties and Methods belonging to our polyline object. Let's close the polyline:

_$ (vla-put-closed theobj :vlax-true)
nil

Polyline state 2

Now let's change the width of all the segments :

_$ (vla-put-ConstantWidth theobj 2.0)
nil

Polyline state 3

Let's "bulge" the third segment :

_$ (vla-setbulge theobj 2 0.5)
nil

Polyline state 4

Let's change the starting and ending width of the fourth segment :

_$ (vla-setwidth theobj 3 10.0 0.0)
nil

Polyline state 5

Let's get the area :

_$ (vla-get-area theobj)
14505.9

Now, we'll make it invisible :

_$ (vla-put-visible theobj :vlax-false)
nil

See it's gone. Let's bring it back :

_$ (vla-put-visible theobj :vlax-true)
nil

Now we'll explode it :

_$ (vla-explode theobj)
#<variant 8201 ...>

And delete the original :

_$ (vla-delete theobj)
nil

We are left with an exploded copy of our polyline :

Polyline state 6

A practical example

Right, let's have a look at extracting some information from a polyline. This program will extract the X and Y coordinates from any polyline.

(prompt "\nType \"VL-POLY\" to run........")

(defun c:vl-poly ( / theobj thelist n xval yval fname fn)
                            
;load the visual lisp extensions
(vl-load-com)
                            
;get the entity and entity name
(setq theobj (car (entsel "\nSelect a Polyline: ")))
                            
;convert to vl object
(setq theobj (vlax-ename->vla-object theobj))

;check if it's a polyline
(if (= (vlax-get-property theobj 'ObjectName) "AcDbPolyline")

;if it is, do the following
(progn

;retrieve the coordinates
(setq thelist (vlax-get-property theobj 'coordinates))

;convert to a list
(setq thelist (vlax-safearray->list  (variant-value thelist)))

;zero the counter
(setq n 0)

;create a text file
(setq fname "coord.txt")

;open it to write
(setq fn (open fname "w"))

;write the header
(write-line "PolyLine X and Y Coordinates" fn)

;underline the header
(write-line "*****************************************" fn)

;start the loop
(repeat (/ (length thelist) 2)

;get the x coordinate
(setq xval (rtos (nth n thelist)))

;increase the counter
(setq n (1+ n))

;get the y coordinate
(setq yval (rtos (nth n thelist)))

;write the x coordinate to the file
(write-line  (strcat "X-Value : " xval)  fn)

;write the x coordinate to the file
(write-line  (strcat "Y-Value : " yval)  fn)

;add a seperator
(write-line "-----------------------------" fn)

;increase the counter
(setq n (1+ n))

);repeat

;close the file
(close fn)

);progn

;it's not a polyline, inform the user
(alert "This is not a Polyline! - Please try again.")

);if

(princ)

);defun

;------------------------
;clean loading
(princ)
;---------------------------
;End of VL-POLY.LSP
;---------------------------

Save this as "VL-Poly.lsp" and then load and run it. Select any polyline.

The X and Y coordinates of each vertex will be output and written to a file named "Coord.txt" It should look something like this :

PolyLine X and Y Coordinates
*****************************************
X-Value : 478.6
Y-Value : 622
-----------------------------
X-Value : 815.5
Y-Value : 349.9
-----------------------------
X-Value : 636.7
Y-Value : 291.7
-----------------------------
X-Value : 586.7
Y-Value : 437.1
-----------------------------
X-Value : 516
Y-Value : 310.4
-----------------------------
X-Value : 349.6
Y-Value : 304.2
-----------------------------

In Part 2 we'll have a look at creating polylines and adding one or two "bulges".