Visual LISP, AutoLISP and General Customization

Visual LISP, AutoLISP and General Customization

Reply
Distinguished Contributor
ozitag
Posts: 288
Registered: ‎05-09-2008
Message 1 of 11 (7,031 Views)
Accepted Solution

New tlen.lsp for polylines

7031 Views, 10 Replies
10-12-2010 06:27 AM

Hi guys,

 

I don't use AutoCad so much, in fact I have been hopeless for a while with the new interface, but steadily I'm getting there.

 

It seems with 2010 onwards the area command doesn't work on plines. So that means the famous tlen.lsp doesn't work anymore. I have tried to play around with it myself, but just can't get it to work. (Don't have any experience with lisp). I've tried using the lengthen command instead, but I can't get it to work either.

 

The current lsp is:

 

(defun C:TLENG (/ ss tl n ent itm obj l)
  (setq ss (ssget)
        tl 0
        n (1- (sslength ss)))
  (while (>= n 0)
    (setq ent (entget (setq itm (ssname ss n)))
          obj (cdr (assoc 0 ent))
          l (cond
              ((= obj "LINE")
                (distance (cdr (assoc 10 ent))(cdr (assoc 11 ent))))
              ((= obj "ARC")
                (* (cdr (assoc 40 ent))
                   (if (minusp (setq l (- (cdr (assoc 51 ent))
                                          (cdr (assoc 50 ent)))))
                     (+ pi pi l) l)))
              ((or (= obj "CIRCLE")(= obj "SPLINE")(= obj "POLYLINE")
                   (= obj "LWPOLYLINE")(= obj "ELLIPSE"))
                (command "_.area" "_o" itm)
                (getvar "perimeter"))
              (T 0))
          tl (+ tl l)
          n (1- n)))
  (alert (strcat "Total length of selected objects is " (rtos tl)))
  (princ)
)

 

Can someone guide me please.

Thanks.

Ozitag

IV 2010
Distinguished Mentor
lpseifert
Posts: 889
Registered: ‎08-08-2006
Message 2 of 11 (7,026 Views)

Re: New tlen.lsp for polylines

10-12-2010 07:03 AM in reply to: ozitag

you may want to look into using Vlisp functions to return the length of objects instead...

 

Examples...

 

(vla-get-length obj)

(vlax-get-property obj 'Circumference)

(vlax-curve-getDistAtPoint obj (vlax-curve-getEndPoint obj))

 

 

~~~Civil 3D 2008~~~
Mentor
stevor
Posts: 848
Registered: ‎12-26-2005
Message 3 of 11 (7,018 Views)

Re: New tlen.lsp for polylines

10-12-2010 08:13 AM in reply to: ozitag
For elapsed distance, try: (- (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj ) (vlax-curve-getDistAtParam obj (vlax-curve-getStartParam obj ) )
S
*Expert Elite*
Kent1Cooper
Posts: 5,388
Registered: ‎09-13-2004
Message 4 of 11 (6,991 Views)

Re: New tlen.lsp for polylines

10-12-2010 07:34 PM in reply to: lpseifert

lpseifert wrote:

....

(vlax-curve-getDistAtPoint  obj (vlax-curve-getEndPoint obj))


Be aware that the above returns zero for circles and for closed Polylines or Ellipses [but for some reason not closed Splines].  Using the shorter version of stevor's suggestion with parameters rather than points:

 

(vlax-curve-getDistAtParam  obj (vlax-curve-getEndParam obj))

 

gives you the length for any kind of finite object with linearity, open or closed.

Kent Cooper
Distinguished Contributor
ozitag
Posts: 288
Registered: ‎05-09-2008
Message 5 of 11 (6,986 Views)

Re: New tlen.lsp for polylines

10-12-2010 10:26 PM in reply to: Kent1Cooper

This is probably a really dumb question, but can I just use the Vlisp commands within a normal lisp file without trouble?

As I said, I've never done this stuff before.

Thanks for your responses.

Ozitag

IV 2010
*Expert Elite*
Kent1Cooper
Posts: 5,388
Registered: ‎09-13-2004
Message 6 of 11 (6,973 Views)

Re: New tlen.lsp for polylines

10-13-2010 06:23 AM in reply to: ozitag

Ozitag wrote:

....can I just use the Vlisp commands within a normal lisp file without trouble?

....


Yes.  You should be able to use this modification of your original [untested]:

 

(defun C:TLENG (/ ss tl n ent itm obj l)
  (setq

    ss (ssget)
    tl 0
    n (1- (sslength ss))

  ); end setq
  (while (>= n 0)
    (setq

      ent (ssname ss n)
      obj (cdr (assoc 0 (entget ent)))
      l

        (if (wcmatch obj "LINE,ARC,CIRCLE,*POLYLINE,SPLINE,ELLIPSE")

          (vlax-curve-getDistAtParam ent (vlax-curve-getEndParam ent))
          0

        ); end if
      tl (+ tl l)
      n (1- n)

    ); end setq

  ); end while
  (alert (strcat "Total length of selected objects is " (rtos tl)))
  (princ)
)

Kent Cooper
Distinguished Contributor
ozitag
Posts: 288
Registered: ‎05-09-2008
Message 7 of 11 (6,960 Views)

Re: New tlen.lsp for polylines

10-13-2010 10:33 PM in reply to: Kent1Cooper

Thanks for that.

I tried it and got an error that says:

 

; error: no function definition: VLAX-CURVE-GETENDPARAM

 

Do I need to somehow add the vlisp library?

Thanks,

Ozitag.

IV 2010
*Expert Elite*
Kent1Cooper
Posts: 5,388
Registered: ‎09-13-2004
Message 8 of 11 (6,946 Views)

Re: New tlen.lsp for polylines

10-14-2010 05:12 AM in reply to: ozitag

Ozitag wrote:

....I tried it and got an error that says:

; error: no function definition: VLAX-CURVE-GETENDPARAM

....


Add this line:

 

(vl-load-com)

 

to the beginning of the routine.  For me, some (vlax-...) functions [including, I believe, all the (vlax-curve-...) ones] work without doing that, and some don't, and I don't know what the difference is -- I think the ArchDeskTop overlay we have somehow takes care of some of them, but why not all, I couldn't say.  Anyway, apparently your setup doesn't include anything that takes care of any of them, so you need to load them.

Kent Cooper
Distinguished Contributor
ozitag
Posts: 288
Registered: ‎05-09-2008
Message 9 of 11 (6,935 Views)

Re: New tlen.lsp for polylines

10-14-2010 06:40 AM in reply to: Kent1Cooper

That worked really well.

Thanks for that.

Ozitag

IV 2010
*Expert Elite*
Kent1Cooper
Posts: 5,388
Registered: ‎09-13-2004
Message 10 of 11 (6,927 Views)

Re: New tlen.lsp for polylines

10-14-2010 08:14 AM in reply to: ozitag

Ozitag wrote:

That worked really well.

Thanks for that.

Ozitag


You're welcome.  If you don't mind, I have a suggestion to simplify the routine a little, as follows:

 

(defun C:TLENG (/ ss tl ent)
  (setq
    ss (ssget '((0 . "LINE,ARC,CIRCLE,*POLYLINE,SPLINE,ELLIPSE")))
    tl 0
  ); end setq
  (repeat (sslength ss)
    (setq
      ent (ssname ss 0)
      tl
        (+
          tl 
          (vlax-curve-getDistAtParam ent (vlax-curve-getEndParam ent))
        ); end + & tl
    ); end setq
    (ssdel ent ss)
  ); end repeat
  (alert (strcat "Total length of selected objects is " (rtos tl)))
  (princ)
); end defun

 

[If you don't ever have any "risk" of a selection containing XLINEs, you could reduce that filter list to:

'((0 . "*LINE,ARC,CIRCLE,ELLIPSE"))

The *LINE part will find Lines, all kinds of Polylines, and Splines.  But you wouldn't want to do it that way and let it also find Xlines, if you ever use them, because there will be a problem trying to determine their length.]

 

If you filter the selection set for the allowable entity types at the time of selection, then you know everything in the set will have a length that you want to add to the total.  That means you don't need to use a variable for the entity type or check that against a list, nor do you need to use a variable for the length, if present, to add to the total [you can just go ahead and add it directly], nor do you need the fallback position of adding 0 if it's not one of the right entity types.  So several variables and Lisp functions are eliminated.

 

The (repeat) and (ssdel) combination, in place of the (while) and increment-variable approach, is less of an "improvement" per se, but my personal preference.  Someone else has made the argument that (repeat (sslength ss).... is really a better "description" of what you want to do in a case like this.  But it also eliminates both the incrementing variable and the resetting of it, and the need for the routine to do any evaluation when it jumps back to the beginning of a (while) loop.  I couldn't say whether there's any time savings, comparing the work of (ssdel) against the combined work of the (while (>= n 0) evaluation and the (setq n (1- n)) incrementing.  But any such difference would never be noticeable unless you had a very large selection set.

 

SomeBuddy often uses an approach [worth taking a look at -- you can search the Discussion Group history], involving (ssnamex), that essentially converts the selection into a list of entity names, so it can use (foreach) on that list, instead of using either (while) or (repeat) on the selection set.  It can save a little code, but I've wondered whether the overhead of doing that conversion, and the needed screening of the resulting list for only certain kinds of information, outweigh any savings -- I wouldn't know how to test that.  But in any case, I find the (repeat) approach easier to grasp, looking at the code.

 

And of course, if you are going to need to use that selection set again for anything after you've added up the lengths, you wouldn't want to do it my way, because mine empties the selection set in the process of moving through it.

Kent Cooper
Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.