Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

New tlen.lsp for polylines

20 REPLIES 20
SOLVED
Reply
Message 1 of 21
ozitag
69657 Views, 20 Replies

New tlen.lsp for polylines

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
20 REPLIES 20
Message 2 of 21
lpseifert
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~~~
Message 3 of 21
stevor
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
Message 4 of 21
Kent1Cooper
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, AIA
Message 5 of 21
ozitag
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
Message 6 of 21
Kent1Cooper
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, AIA
Message 7 of 21
ozitag
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
Message 8 of 21
Kent1Cooper
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, AIA
Message 9 of 21
ozitag
in reply to: Kent1Cooper

That worked really well.

Thanks for that.

Ozitag

IV 2010
Message 10 of 21
Kent1Cooper
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, AIA
Message 11 of 21
ozitag
in reply to: Kent1Cooper

Thats even better and works a treat. I can even understand it. Sort of.

Thanks a lot for your time and effort.

Ozitag

IV 2010
Message 12 of 21
ryanic18
in reply to: ozitag

hello, i need help with this one.1.jpg2.jpg

 

I always use the long way, get 22% of line then drawing xline offsetting it in 22% and mirror..
Do you have lisp that gives or calculate percentage of a line, polyline and arc.

Thank you.

Message 13 of 21
Kent1Cooper
in reply to: ryanic18


@ryanic18 wrote:

hello, i need help with this one.

....


Welcome to these Forums!  This seems un-related to the Subject of this thread, which means that if someone answers it here, others looking for the same thing may not be able to find it.  I suggest you [first Search for something that already does what you want, and if you don't find anything,] start a new thread.

Kent Cooper, AIA
Message 14 of 21
Kent1Cooper
in reply to: Kent1Cooper


Kent1Cooper wrote:

 

....  I suggest you ... start a new thread.


And when you do, describe more about what you want to do.  If you are drawing Xlines only for the purpose of [for example] TRIMming the object they're drawn across, a routine could be made to take 22% off both ends of any object, or leave 22% of it at each end and take out the middle, or some such thing.  If you actually need the Xlines themselves for some reason, it could be made to draw them, but if they are only an intermediate step on the way to what you really want to accomplish, it may not be necessary to actually draw them.  Also, a routine could be made to do whatever you're after with the 22% hard-coded into it, if you always need that specific ratio, or if the ratio isn't always the same, it could be made to ask the User what percentage inward they want to go.  Etc., etc.

Kent Cooper, AIA
Message 15 of 21
j_p_salvador
in reply to: Kent1Cooper

Hi Kent,

 

What if I want to divide that total length by 10? For example the total length is 900 then the autocad message should be "90". Can you do the code for me. Thanks in advance.

Message 16 of 21
Kent1Cooper
in reply to: j_p_salvador


@j_p_salvador wrote:

.... 

What if I want to divide that total length by 10? For example the total length is 900 then the autocad message should be "90". ....


Welcome to these Forums!

 

That would be a change of this line:

(alert (strcat "Total length of selected objects is " (rtos tl)))

 

to this:

 

(alert (strcat "Total length of selected objects is " (rtos (/ tl 10))))

 

That would return it in whatever your current numerical mode and precision settings are.  If you want it to always give you a whole number, even though the true distance usually will not  be one, you can have it round it off with the mode and precision [number of decimal places, or fraction denominator] options in the (rtos) function:

 

(alert (strcat "Total length of selected objects is " (rtos (/ tl 10) 2 0)))

 

[Consider changing the message to something about a tenth of the total length, if appropriate, or for example adding the word "decimeters" if your drawing units are millimeters.]

Kent Cooper, AIA
Message 17 of 21
j_p_salvador
in reply to: Kent1Cooper

Thanks Kent for that quick reply. Your answer is really what I need.

Message 18 of 21
dali.j
in reply to: Kent1Cooper

Hi All

So where should i add this line? in the beginning of the code?

Message 19 of 21
arpansark0544TCX
in reply to: ozitag

Use this 

LAYLENGTH -Sum Line Length and arrange in table by layer

 

 

(defun C:LAYLENGTH ( / *error* acdoc ss p i e a d l) (vl-load-com)
(setq acdoc (vla-get-activedocument (vlax-get-acad-object)))
(vla-startundomark acdoc)

(defun *error* (msg)
(and
msg
(not (wcmatch (strcase msg) "*CANCEL*,*QUIT*,*BREAK*,*EXIT*"))
(princ (strcat "\nError: " msg))
)
(if
(= 8 (logand (getvar 'undoctl) 8))
(vla-endundomark acdoc)
)
(princ)
)

(if
(and
(setq ss (ssget ":L" '((0 . "LINE,POLYLINE,LWPOLYLINE,ARC,CIRCLE,ELLIPSE,SPLINE"))))
(setq p (getpoint "\nTable scale depend on annotation scale.\nSpecify table insert point: "))
)
(progn
(repeat
(setq i (sslength ss))
(setq e (ssname ss (setq i (1- i)))
a (cdr (assoc 8 (entget e)))
d (vlax-curve-getdistatparam e (vlax-curve-getendparam e))
)
(if
(setq o (assoc a l))
(setq l (subst (list a (+ (cadr o) d)) o l))
(setq l (cons (list a d) l))
)
)
(setq l (vl-sort l '(lambda (a b) (< (car a) (car b)))))
(insert_table l p)
)
)
(*error* nil)
(princ)
)

(defun insert_table (lst pct / tab row col ht i n space)
(setq space (vlax-get acDoc (if (= 1 (getvar 'cvport)) 'PaperSpace 'ModelSpace))
ht (/ 2.5 (cond ((getvar 'cannoscalevalue)) (1.0)))
pct (trans pct 1 0)
n (trans '(1 0 0) 1 0 T)
tab (setq tab (vla-addtable space (vlax-3d-point pct) (+ 2 (length lst)) (length (car lst)) (* 2.5 ht) ht))
)
(vlax-put tab 'direction n)

(mapcar
(function
(lambda (rowType)
(vla-SetTextStyle tab rowType (getvar 'textstyle))
(vla-SetTextHeight tab rowType ht)
)
)
'(2 4 1)
)

(vla-put-HorzCellMargin tab (* 0.14 ht))
(vla-put-VertCellMargin tab (* 0.14 ht))

(setq lst (cons (mapcar '(lambda (a) (strcat "Col" (itoa (1+ (vl-position a (car lst)))))) (car lst)) lst))

(setq i 0)
(foreach col (apply 'mapcar (cons 'list lst))
(vla-SetColumnWidth tab i
(apply
'max
(mapcar
'(lambda (x)
((lambda (txb) (+ (abs (- (caadr txb) (caar txb))) (* 2.0 ht)))
(textbox (list (cons 1 (vl-princ-to-string x)) (cons 7 (getvar 'textstyle)) (cons 40 ht)))
)
)
col
)
)
)
(setq i (1+ i))
)

(setq lst (cons '("TITLE") lst))

(setq row 0)
(foreach r lst
(setq col 0)
(vla-SetRowHeight tab row (* 1.5 ht))
(foreach c r
(vla-SetText tab row col (if (numberp c) (rtos c) (vl-princ-to-string c)))
(setq col (1+ col))
)
(setq row (1+ row))
)
)

Message 20 of 21
dali.j
in reply to: ozitag

i clic commande LAYLENGHT -select all plyline-enter-and ask me to specify table insert point -i choose any point

but the same error: no function definition: VLAX-CURVE-GETENDPARAM

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost