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
Solved! Go to Solution.
Solved by Kent1Cooper. Go to Solution.
Solved by Kent1Cooper. Go to Solution.
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))
@Anonymous 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.
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
@Anonymous 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)
)
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.
@Anonymous 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.
@Anonymous 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.
Thats even better and works a treat. I can even understand it. Sort of.
Thanks a lot for your time and effort.
Ozitag
hello, i need help with this one.
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.
@Anonymous 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.
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.
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.
@Anonymous 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.]
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))
)
)
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.