Lisp to calculate total length By Layer fix

Lisp to calculate total length By Layer fix

kylei7449
Enthusiast Enthusiast
10,826 Views
28 Replies
Message 1 of 29

Lisp to calculate total length By Layer fix

kylei7449
Enthusiast
Enthusiast

I'd like to get this code modified so it will 1) return length by default (doesn't ask for user input), and 2) returns the total length in feet & inches. Here is the code I found that will work for what I need...essentially the same as TLEN, but this selects By Layer, which for my application is much more useful (as you only need to select one entity).

 

Thanks

 

; Length/Area of Polyline by Layer
; David Bethel May 2004 from an original idea by David Watson
; This command will give a total area or length for all polylines on a specified layer.
;
(defun c:zone ( / ss la rv i tv op en)

(while (not ss)
(princ "\nPick any object on the required layer")
(setq ss (ssget)))

(initget "Length Area")
(setq rv (getkword "\nWould you like to measure Length/<Area> : "))
(and (not rv)
(setq rv "Area"))

(setq la (cdr (assoc 8 (entget (ssname ss 0))))
ss (ssget "X" (list (cons 0 "*POLYLINE")
(cons 8 la)))
i (sslength ss)
tv 0
op 0)
(while (not (minusp (setq i (1- i))))
(setq en (ssname ss i))
(command "_.AREA" "_E" en)
(cond ((= rv "Length")
(setq tv (+ tv (getvar "PERIMETER"))))
(T
(setq tv (+ tv (getvar "AREA")))
(if (/= (logand (cdr (assoc 70 (entget en))) 1) 1)
(setq op (1+ op))))))

(princ (strcat "\nTotal " rv
" for layer " la
" = " (rtos tv 2 2)
" in " (itoa (sslength ss)) " polylines\n"
(if (/= rv "Length")
(strcat (itoa op) " with open polylines") "")))
(prin1))

0 Likes
Accepted solutions (2)
10,827 Views
28 Replies
Replies (28)
Message 21 of 29

Kent1Cooper
Consultant
Consultant

@kylei7449 wrote:

.... 

The line:  tl (+ tl (vlax-curve-getDistAtParam....) that's adding each of the multiples correct??

.... Can you suggest a good resource for learning Lisp? .... But trying to find for example formatting of numbers can be a challenge (ex. decimal, engineering, architectural, etc.) ....


Yes, that's what it's doing.  The 'tl' is the 'total length' [so far] value, and it's recalculating  that for each object by adding the length of the object to the same variable [the result of the addition replaces the previous value that is used within  the addition].

 

A Search here will find lots of people asking for resources for learning AutoLisp, with lots of suggestions, links, etc.

 

As for number formats, AutoLisp does all its work with only integers, decimal numbers or scientific notation [which I suppose are really just a variant form of decimal].  But it can convert numbers in other formats to forms it can use, with certain functions like (distof) and (angtof) -- see the Conversion Functions Reference.

Kent Cooper, AIA
0 Likes
Message 22 of 29

kylei7449
Enthusiast
Enthusiast

Yes, very nice. A lot more condensed than the code I started out with. Works great. (I like the screen cap, very nice)

 

Am I right to assume this does the aggregate of the lines? 

(rtos (apply '+ (cdr x)) 2 2)

Thanks for your help, much appreciated Ranjit.

0 Likes
Message 23 of 29

Ranjit_Singh
Advisor
Advisor

Yes. You are correct. 

0 Likes
Message 24 of 29

john.uhden
Mentor
Mentor

Kent seemed to be concerned about linetypes.  What about color, width, thickness, elevation, xdata, and space?  So sorry, I must have forgotten something.  Oh yeah, closed or open, plot or noplot.  Spline curved? Hyperlinks?  Things attached by reactors?  :]

John F. Uhden

0 Likes
Message 25 of 29

kylei7449
Enthusiast
Enthusiast

hey Ranit

I was wondering if you can look at this code to see where it's breaking down? (If you have the time of course) It's your previous code I used for the linetypes but I've modified it to search for hatches (by layer) and return the square footages. It does  technically run but doesn't produce the correct results (and in the right format).

 

Where it's getting hung up on is multiple hatch areas (meaning separate entities) on the same layer. For example, if I have 4 separate hatches (meaning each area has its own hatch entity) on layer "test," it is returning the test layer 4 times and listing each area found as 4X the actual. So, it's multiplying the actual individual areas by however many separate hatches it finds. If it finds 6 hatches, it's multiplied by 6; if it finds 3, it's three times, etc. However, if I create one complete hatch (one entity) out of those 4 separate areas the program works. The output should only be a listing of each layer it finds a hatch on and return the grand total area. 

 

It also needs a way to trap the error if there is a hatch that doesn't have an 'area' property. (self-intersecting) The program will error out and not return anything. If possible, it would need to return 'no area found' for that layer. 

 

;| Ranjit Singh
7/25/17
|;


(defun c:TLENH (/ du lst lst2)
     (setq lst (vl-sort (mapcar '(lambda (x) (cons (getpropertyvalue x "Area") (cdr (assoc 8 (entget x)))))
         (mapcar 'cadr (ssnamex (ssget "_x" '((0 . "*HATCH") (8 . "test,test2,test3,test4,test5,test6"))))))
               '(lambda (x y) (< (cdr x) (cdr y)))))
            (mapcar '(lambda (x)
               (if (null (member x lst2))
                    (setq lst2 (cons x lst2))))
                       (mapcar '(lambda (x)
                         (cons (cdr x)
                           (apply '+
                           (vl-remove nil
               (mapcar '(lambda (y)
                  (if (= (cdr y) (cdr x))
                      (car x)))
                       lst)))))
                      lst))

          (mapcar '(lambda (x) (princ (strcat (car x) " - " (rtos (/ (cdr x) 12.0) 4 0) "\n"))) lst2)
           (princ (strcat "Total sq footage of selected objects is " (rtos (apply '+ (mapcar 'cdr lst2)) 4 0)))

 

(princ)

)

 

Here's an example of what it's returning...

 

TLENH_screen shot.png

 

From the image above....

Test is reporting the total area (of three separate areas) created as one hatch entity. It returns the total sq ft correctly. (although you can see the format isn't correct -- the sq ft number is correct though)

Test2 is reporting a single hatch correctly.

Test3 is reporting a single hatch correctly.

Now here's the issue...

Test4 is reporting five separate hatch entities and it's returning results that are 5 times the actual for each one. It should also only return the aggregate for layer Test4, not list out each separate area. 

Ditto for Test6 (although its results are 4 times the actual)

 

Take a look if you can, thanks.

 

 

 

0 Likes
Message 26 of 29

Ranjit_Singh
Advisor
Advisor

I adjusted my code in post 19.

;;Ranjit Singh
;;8/9/17
(defun c:somefunc (/ lst lst2) (setq lst (mapcar '(lambda (x) (cons (getpropertyvalue x "Area") (cdr (assoc 8 (entget x))))) (vl-remove-if 'listp (mapcar 'cadr (ssnamex (ssget "_x" '((0 . "hatch") (8 . "test,test[2-6]")))))))) (vl-remove nil (mapcar '(lambda (x) (setq lst2 (cons (if (null (member x lst2)) x) lst2))) (mapcar 'cdr lst))) (mapcar '(lambda (x) (princ (strcat "\n=======\n" (car x))) (mapcar 'print (cdr x)) (princ (strcat "\nTotal: " (rtos (apply '+ (cdr x)) 2 2) "\n=======\n"))) (setq lst (vl-sort (mapcar '(lambda (x) (cons (cdar x) (mapcar 'car x))) (mapcar '(lambda (y) (vl-remove-if-not '(lambda (x) (= y (cdr x))) lst)) (vl-remove nil lst2))) '(lambda (x y) (< (car x) (car y)))))) (princ (strcat "\nGrand Total: " (rtos (apply '+ (apply 'append (mapcar 'cdr lst))) 2 2))) (princ))

You can easily adjust as needed. Let me know if you run in any issues. Good luck.Hatch_Cumulative.gif

 

0 Likes
Message 27 of 29

kylei7449
Enthusiast
Enthusiast

Hey Ranjjit,

No matter what I do to modify this line, I can't get it to format. 

(mapcar 'print (cdr x))

Here's what I tried...

(mapcar 'print (rtos (/ (cdr x) 144.0) 4 0))

 

But this gives me a bad argument type. 

0 Likes
Message 28 of 29

Ranjit_Singh
Advisor
Advisor

Try something like this

(mapcar 'print (mapcar '(lambda (x) (rtos x 4 0)) (cdr x)))

EDIT: princ may produce a cleaner output, since you are displaying architectural formating

(mapcar 'princ (mapcar '(lambda (x) (strcat "\n" (rtos x 4 0))) (cdr x)))

 

 

0 Likes
Message 29 of 29

symoin
Enthusiast
Enthusiast

Is there any way we can use layers instead of linetypes. I tried changing the code 6 to code 8.

My idea is I should run the code and I should get the total length of all the objects on each layer into an excel.

either by selection or all by using "X" in the code.

 

Your help in this issue with be always appreciated.

Thanks

0 Likes