LISP for length & diameter

LISP for length & diameter

anderson51
Advocate Advocate
3,931 Views
15 Replies
Message 1 of 16

LISP for length & diameter

anderson51
Advocate
Advocate

Hello,

Wondering if there is a LISP to calculate total extruded lengths based on diameter of selected objects?

 

For example:

Select All then have it break down as follows:

 

237' of 6" diameter

150' of 4" diameter

65'of 26" diameter

Accepted solutions (1)
3,932 Views
15 Replies
Replies (15)
Message 2 of 16

CodeDing
Advisor
Advisor

@anderson51 ,

 

Extruded lengths of what?

Based on diameter of what?

Select all of what?

 

Can you provide a sample drawing to help give us some context?

And please explain in more detail so that we, who do not work on the same things that you do each day, can understand better.

 

Having more of an idea of what you are referring to will give others a better understanding of how to help you.

 

Best,

~DD

0 Likes
Message 3 of 16

anderson51
Advocate
Advocate

Sorry for the sh!tty explanation in the first post....lemme try and do better.

 

I design dust control systems and diameter of pipe can vary anywhere between 4" up to 42". I have to go in and calculate total linear feet of pipe of the varying diameter. Currently, I do it all manually by measuring the diameter and viewing the extruded length in the properties, and calculating the totals by calculator...

 

I would be nice to be able to just select the 3D geometry and have a LISP routine do all that work for me.

 

See attached for an example drawing.

 

Thanks for the consideration.

 

Anderson

Message 4 of 16

CodeDing
Advisor
Advisor

@anderson51 ,

 

Can you make these cylinders instead of extrusions? Lol. that would help greatly...

 

I have found how to get the Length & radius for extruded items you have in your drawing, however you have some items which do not appear they were extruded? At least, I can't tell how they were made..

In this image, item 1 has a "Height" property, but item 2 does not. These appear to be created differently?

I cannot solve for an anomaly such as this with Lisp. I need the Height property.

image.png

Message 5 of 16

anderson51
Advocate
Advocate

Yes, Ive never tried with cylinders, but I don't see why they couldn't be.

Disregard the ones that don't have the properties, they need to be remade. I am not sure how those ended up in there to be honest.

 

It would be nice to get the diameters, but I don't see the info anywhere in the properties to even extract the data?

 

I really appreciate your help on this!

 

Anderson

0 Likes
Message 6 of 16

CodeDing
Advisor
Advisor

@anderson51 ,

 

Ok, well until further refinements can be made, this code gets the 'height' and the 'area' of the solid, then calculates for the radius (perhaps there are rounding errors somewhere because I saw some 2 unit radius pipes being calculated as 1.99999 units). Then your items are returned as a list of radius/length pairs.

 

For the items I mentioned above, about not having height property, if they are selected then the function will error out.

 

(defun c:PIPES ( / ss pipeData)
  ;Get pipes
  (prompt "\nSelect Cylindrical Pipes Only: ")
  (if (setq ss (ssget '((0 . "3DSOLID"))))
    (progn
      (setq pipeData (GetPipeData ss)) ;<-- returned format: ((rad length) (rad length) ...)
      (prompt "\nHere is your pipe data as a list:\n")
      (princ pipeData)
    );progn
  ;else
    (prompt "\nNo 3D Solids selected..")
  );if
  (princ)
);defun

(defun GetPipeData (ss / e height area radius dataList)
  ;loop through to get lengths ('height') and radius
  (repeat (setq cnt (sslength ss))
    (setq e (ssname ss (setq cnt (1- cnt))))
    (setq height (getpropertyvalue e "Height"))
    (setq area (getpropertyvalue e "Area"))
    ;using.. Cylinder Area = 2*pi*r*h + 2*pi*(r^2)
    ;..to find radius, we get.. r = (-h + (sqrt (h^2) + (2a / pi)) / 2
    (setq radius (/ (+ (- height) (sqrt (+ (expt height 2) (/ (* 2 area) pi)))) 2))
    (setq dataList (cons (list radius height) dataList))
  );repeat
);defun

 

 

Again, this process would be much easier if they were created as cylinders to begin with.

 

EDIT: Please take note that the Radii and Lengths will be in the same units!

 

Best,

~DD

0 Likes
Message 7 of 16

Kent1Cooper
Consultant
Consultant

The entity data and properties for 3D Solids are entirely inscrutable for purposes of getting dimensional information such as what you're after.  IF  they all ran in 3D-orthogonal directions, one might hope to figure that out from their bounding boxes, but they don't.  And IF  they were all of greater length than their diameter, one might hope to figure out from the bounding box dimensions which is which, but they're not [though the great majority of them are].

 

I think with some Searching you might find approaches to finding the extents of such things [that kind of question has come up before], even at non-orthogonal angles, though I don't recall how it can be done.  If you find such a routine, on the question of which extent is the length compared with the diameter:  if they're all circular in cross-section, two dimensions of such extents would have to both be diameters and therefore equal, so the one that doesn't match would be the length, whether longer than the diameter or not [and if all three are equal, it doesn't matter which].

Kent Cooper, AIA
0 Likes
Message 8 of 16

CodeDing
Advisor
Advisor

@anderson51 ,

 

Kent reminds me that my formula also makes 1 assumption.. The radius/diameter of the pipe is UNIFORM for its ENTIRE length..

 

Best,

~DD

Message 9 of 16

anderson51
Advocate
Advocate

Yessir, galvanized spiral ducting is always uniform.

 

Is it possible to set it up to read diameter instead of radius?

 

Thanks again!

0 Likes
Message 10 of 16

CodeDing
Advisor
Advisor

 

 

(defun GetPipeData (ss / e height area diameter dataList)
  ;loop through to get lengths ('height') and radii/diameters
  (repeat (setq cnt (sslength ss))
    (setq e (ssname ss (setq cnt (1- cnt))))
    (setq height (getpropertyvalue e "Height"))
    (setq area (getpropertyvalue e "Area"))
    ;using.. Cylinder Area = 2*pi*r*h + 2*pi*(r^2)
    ;..to find radius, we get.. r = (-h + (sqrt (h^2) + (2a / pi))) / 2
    (setq diameter (+ (- height) (sqrt (+ (expt height 2) (/ (* 2 area) pi)))))
    (setq dataList (cons (list diameter height) dataList))
  );repeat
);defun

 

 

UPDATE: There are no rounding errors in the function. It calculates correctly. The units in the example dwg provided were precise to only 4 decimal places and the 3D Solids mentioned as 2 units in radius are, in fact, less than 2 units in radius.

 

0 Likes
Message 11 of 16

anderson51
Advocate
Advocate

This is nice.

 

Is there a way to set it up to read in feet and inches instead of decimals?

 

Thanks again for the help.

0 Likes
Message 12 of 16

anderson51
Advocate
Advocate

Also, maybe I am asking for the moon here, but it would be really nice if it added up the running total for each diameter pipe instead of listing each individually.

 

 

0 Likes
Message 13 of 16

Kent1Cooper
Consultant
Consultant

@anderson51 wrote:

....

Is there a way to set it up to read in feet and inches instead of decimals?

.....


Change this:

 

(setq dataList (cons (list diameter height) dataList))

 

to this:

 

(setq dataList (cons (list (rtos diameter 4 3) (rtos height 4 3)) dataList))

 

Edit the 3's to suit the precision level you want [3 is to the nearest 1/8"].  And look into the DIMZIN System Variable about whether leading and/or trailing zeros should be suppressed.

Kent Cooper, AIA
Message 14 of 16

CodeDing
Advisor
Advisor
Accepted solution

@anderson51 ,

 


maybe I am asking for the moon here

I think we're out by Voyager 1 at this point, Lol.

 

Some notes:

- I rounded the diameters to 4 decimal places since your drawing was setup this way (but when they are printed to the command line you will only see 1 decimal place) (you should be able to tell where to update these)

- I used Kent's idea to print the total pipe length to nearest 1/8", but this could be updated also (the precise value is still maintained in pipeData)

 

** I had to round your pipe diameters because they are inconsistent in your drawing (to nearest 4 decimal). If your diameters will ALWAYS be to nearest 1" then this could be accounted for.. because as it stands currently, if you have a pipe with a 4.0001 diameter in your drawing and a pipe with 4.000 diameter, then these will be counted as 2 different pipe diameters.

 

Give this a go:

 

(defun c:PIPES ( / ss pipeData cnt)
  ;Get pipes
  (prompt "\nSelect Cylindrical Pipes Only: ")
  (if (setq ss (ssget '((0 . "3DSOLID"))))
    (progn
      (setq pipeData (GetPipeData ss)) ;<-- returned format: ((dia length) (dia length) ...)
      (setq pipeData (SortPipeData pipeData))
      (setq cnt 0)
      (prompt "\n----- Pipe Data -----")
      (foreach pipe pipeData
        (prompt (strcat "\nPipe #" (itoa (setq cnt (1+ cnt)))
                        "\n - Diameter:  " (rtos (car pipe) 2 1)
                        "\n - Total Count: " (itoa (cadr pipe))
                        "\n - Total Length: " (rtos (caddr pipe) 4 3)))
      );foreach
      (prompt "\n---------------------")
    );progn
  ;else
    (prompt "\nNo 3D Solids selected..")
  );if
  (princ)
);defun

(defun LM:roundm ( n m )
  ;; Round Multiple  -  Lee Mac
  ;; Rounds 'n' to the nearest multiple of 'm'
  (* m (fix ((if (minusp n) - +) (/ n (float m)) 0.5)))
)

(defun LM:roundto ( n p )
  ;; Round To  -  Lee Mac
  ;; Rounds 'n' to 'p' decimal places
  (LM:roundm n (expt 10.0 (- p)))
)

(defun GetPipeData (ss / e cnt height area diameter dataList)
  ;loop through to get lengths ('height') and radii/diameters
  (repeat (setq cnt (sslength ss))
    (setq e (ssname ss (setq cnt (1- cnt))))
    (setq height (getpropertyvalue e "Height"))
    (setq area (getpropertyvalue e "Area"))
    ;using.. Cylinder Area = 2*pi*r*h + 2*pi*(r^2)
    ;..to find radius, we get.. r = (-h + (sqrt (h^2) + (2a / pi))) / 2
    (setq diameter (+ (- height) (sqrt (+ (expt height 2) (/ (* 2 area) pi)))))
    (setq dataList (cons (list (LM:roundto diameter 4) height) dataList))
  );repeat
);defun

(defun SortPipeData (pipeData / pipe tmp dataList)
  ;returns pipe data like... ((diameter pipeCount totalLegth) ...)
  (foreach pipe pipeData
    (cond
      ((setq tmp (assoc (car pipe) dataList))
        (setq dataList (subst (list (car tmp) (1+ (cadr tmp)) (+ (caddr tmp) (cadr pipe))) tmp dataList)))
      (t
        (setq dataList (cons (list (car pipe) 1 (cadr pipe)) dataList)))
    );cond
  );foreach
  dataList
);defun

 

Best,

~DD

Message 15 of 16

anderson51
Advocate
Advocate

Wow, I'm blown away!

Amazing work gentlemen.

 

Can't thank @CodeDing @Kent1Cooper  enough for the support over the years.

Message 16 of 16

ashishYJMDV
Explorer
Explorer
Can we get the total length of a tubing (Straight pipes and Bends ) in plant 3d.
0 Likes