volume with calculation from multiple objects selected

volume with calculation from multiple objects selected

SinCity_XTRM
Explorer Explorer
2,393 Views
16 Replies
Message 1 of 17

volume with calculation from multiple objects selected

SinCity_XTRM
Explorer
Explorer

Hi everyone,

Im quite new at creating lisps, but my first one is already kicking my butt. Heres what I want the lisp to function, and hopefully someone can help me write this up. Thanks in advance. 

 

I would like to be able to select multiple 3DSolid objects and have it calculate the total Linear Footage. In my mind, this is how the workflow would go?

 

1. i have 3 objects i will be selecting

    1. 2 x 2 x 12

    2. 2 x 2 x 24

    3. 2 x 2 x 36

2. freeze all layers but the layer my solids are on.

3. enter lisp command to calculate

4. window select all the solids i wish to calculate

5. lisp grabs the volume result of 288

6. cmd line asks me for the "width 1" of tube - i would enter a value of 2

7. cmd line asks me for the "width 2" of tube - i would enter a value of 2

8. lisp has some formula like:   (288/(2*2))/12

9. an alert window pops up informing me the result is " 2in x 2in x 6LnFt "

10. I then become a happy camper..... 

 

attached is a pic of my thought. lsp total Lnft.jpg

0 Likes
Accepted solutions (1)
2,394 Views
16 Replies
Replies (16)
Message 2 of 17

ronjonp
Mentor
Mentor

Why do you need input if you're selecting a solid?

Here's a quick example 🙂

(defun c:foo (/ a b o r s v)
  ;; RJP » 2021-04-08
  (if (setq s (ssget '((0 . "3DSOLID"))))
    (progn (foreach e (vl-remove-if 'listp (mapcar 'cadr (ssnamex s)))
	     (vla-getboundingbox (setq o (vlax-ename->vla-object e)) 'a 'b)
	     (mapcar 'set '(a b) (mapcar 'vlax-safearray->list (list a b)))
	     (setq r (cons (vl-sort (mapcar 'abs (mapcar '- a b)) '>) r))
	     (setq v (cons (vla-get-volume o) v))
	   )
	   ;; Check that the tubes are all the same size
	   (if (and (apply '= (mapcar 'cadr r)) (apply '= (mapcar 'caddr r)))
	     (alert (strcat (vl-princ-to-string (cadr (setq b (car r))))
			    " x "
			    (vl-princ-to-string (caddr b))
			    " x "
			    (vl-princ-to-string (apply '+ (mapcar 'car r)))
			    "LnFt\nTotal Volume = "
			    (vl-princ-to-string (apply '+ v))
		    )
	     )
	     (alert "Tubes selected vary in size!!")
	   )
    )
  )
  (princ)
)
0 Likes
Message 3 of 17

Sea-Haven
Mentor
Mentor

Like  ronjonp a simple example

(defun c:test ( / obj x y z pointmin pointmax vol )
(setq obj (vlax-ename->vla-object (car (entsel "pick object "))))

(vla-GetBoundingBox obj 'minpoint 'maxpoint)
(setq pointmin (vlax-safearray->list minpoint))
(setq pointmax (vlax-safearray->list maxpoint))
;minpoint contains the minimum point of the bounding box
;maxpoint contains the maximum point of the bounding box

(setq x (abs (- (car pointmin)(car pointmax))))
(setq y (abs (- (cadr pointmin)(cadr pointmax))))
(setq Z (abs (- (caddr pointmin)(caddr pointmax))))

(setq vol (* x y z))

(if (< x y)
  (progn 
    (setq temp x)
    (setq x y)
    (setq y temp)
  )
)

(alert (strcat "Volume is " (rtos vol 2 2) "\nLength is " (rtos x 2 2) "\nWidth is " (rtos y 2 2) "\nHeight is " (rtos z 2 2)))
0 Likes
Message 4 of 17

3wood
Advisor
Advisor

If the length of the 3dSoild is not parallel to current UCS, the result is wrong.

Capture.PNG

0 Likes
Message 5 of 17

Sea-Haven
Mentor
Mentor

Maybe look at massprop rotated rectang.

Bounding Box:
Lower Bound: X= 234.772 Y= 143.5391 Z= 0
Upper Bound: X= 238.618 Y= 145.9988 Z= 10
Centroid: X= 236.695 Y= 144.769 Z= 5

 

Have to put the thinking cap on convert back to X Y Z 

0 Likes
Message 6 of 17

3wood
Advisor
Advisor

I guess for rotated 3dSolid, it may require "fit testing" for find out an angle which provides the largest distance between 2 bounding box points.

0 Likes
Message 7 of 17

Sea-Haven
Mentor
Mentor

If you dump the object

PrincipalDirections (RO) = (1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0) this is ortho

 

PrincipalDirections (RO) = (0.894427190999919 0.447213595499952 0.0 -0.447213595499952 0.894427190999919 0.0 0.0 0.0 1.0) this is rotated so if could rotate back to 0 0 1 then do bounding box. 

Message 8 of 17

Sea-Haven
Mentor
Mentor

Found it this is angle of solid if not 0. in radians.

 

(setq ang (- (/ pi 2) (atan (/ 0.894427190999919 0.447213595499952))))

 

Only issue is cw or ccw, realised the second value is positive or negative.

 

(setq ang (+ (* 1.5 pi)(abs (atan (/ 0.964763821237727 -0.263117405792126))))

 

Needs more testing.

 

 

Message 9 of 17

doaiena
Collaborator
Collaborator

Working with 3dSolids can be a bit tricky, especially if they get more complex.

 

If we are strictly talking about a solid of the type "BOX", the most straight forward approach would be to read its length/width/height properties.

 

If the solid type is unknown, a bounding box approach may do the job, but in order to work, the solid must be aligned to the WCS before we measure it. PrincipalDirections is not always a reliable source of information, on how to align the solid, depending on how the solid was created/edited. To be certain of the alignment, you could add vector information to the solid manually, which would correspond to its L/W/H dimensions and use that info to do the realignment.

 

Another approach, that would be harder to implement and will run slow is to extract the entity data and decode it. Then you could analyze the solid in place, without the need to align it to WCS.

 

And the last, but most powerful way to collect 3dSolid data is a few lines of code in .NET. That would open the door to analyze complex solids, irrespective of orientation.

0 Likes
Message 10 of 17

ronjonp
Mentor
Mentor

@3wood  Very true .. 

0 Likes
Message 11 of 17

SinCity_XTRM
Explorer
Explorer

this sounds like its a tricky request. 

 

@ronjonp came very close to what im thinking. though like @3wood noticed, it wont recognize solids that are not parallel to a UCS. or it doesnt recognize curved solids either. 

 

@Sea-Haven i couldnt seem to get your example to run.?? 

 

this is why in my original post, im thinking that the command line can prompt the user to ask for the width & height of the solids. that way a calculation can be done with that info with the volume info. this way, solids that are rotated and even curved can be  counted in the final result. 

and perhaps with some extra input from the user when prompted, with the volume info, we can have weight listed too in the alert..... just a thought. 

 

in my pic, is an example of the various types of solids that i would wish to select. lsp total Lnft2.jpg

0 Likes
Message 12 of 17

ronjonp
Mentor
Mentor
Accepted solution

@SinCity_XTRM 

Try this:

 

(defun c:foo (/ d1 d2 m s v)
  ;; RJP » 2021-04-12
  (if (and (setq d1 (getdist "\nEnter first width: "))
	   (setq d2 (getdist "\nEnter second width: "))
	   (setq s (ssget '((0 . "3DSOLID"))))
	   (setq v 0)
      )
    (progn (foreach e (vl-remove-if 'listp (mapcar 'cadr (ssnamex s)))
	     (setq v (+ v (vla-get-volume (vlax-ename->vla-object e))))
	   )
	   (alert (setq	m (strcat (vl-princ-to-string d1)
				  " x "
				  (vl-princ-to-string d2)
				  " x "
				  (vl-princ-to-string (/ v (* d1 d2)))
				  " LnFt\n\nVolume: "
				  (vl-princ-to-string v)
			  )
		  )
	   )
      (princ m)
    )
  )
  (princ)
)

 

0 Likes
Message 13 of 17

Kent1Cooper
Consultant
Consultant

@SinCity_XTRM wrote:

.... im thinking that the command line can prompt the user to ask for the width & height of the solids. that way a calculation can be done with that info with the volume info. this way, solids that are rotated and even curved can be  counted in the final result. 

.... 


So for the one with an end that is not perpendicular to the length:

Kent1Cooper_0-1618257538958.png

if a routine divides the Volume property by the height and width, the result will be the length to the mid-line of that slanted end, halfway between the lengths of the top and bottom surfaces.  Is that appropriate?  Or would you want the greatest-extent length [here, the length along the top surface]?  Or maybe the bottom surface?  Not that I have an idea of how to calculate those, but....

Kent Cooper, AIA
0 Likes
Message 14 of 17

SinCity_XTRM
Explorer
Explorer

this is it!!!!!

thank you so much! i did however modify the calculation slightly so the end value was in feet instead of inches. and, i was also able to use this similar lisp to use a different calculation to do round tubing...  I'm going to try and evaluate this whole thing and see if im able to remove one of the prompt questions for "width 2" as its no longer needed. 

 

thanks so much!!!!!!!!!!!!!!

 

square tube modification:

(vl-princ-to-string (/ (/ v (* d1 d2)) 12))

 

round tube modification:

(vl-princ-to-string (/ (/ v (* 3.14 (/ d1 2)(/ d1 2))) 12))

 

 

0 Likes
Message 15 of 17

ronjonp
Mentor
Mentor

Glad to help .. let me know if you need more help with the modifications. 🍻

Message 16 of 17

SinCity_XTRM
Explorer
Explorer

this would be appropiate. im going to use this lisp for material ordering. so i'll take that value and add a % to it anyways for the cutting etc. 

0 Likes
Message 17 of 17

devitg
Advisor
Advisor

@SinCity_XTRM 


@SinCity_XTRM wrote:

this is it!!!!!

thank you so much! i did however modify the calculation slightly so the end value was in feet instead of inches. and, i was also able to use this similar lisp to use a different calculation to do round tubing...  I'm going to try and evaluate this whole thing and see if im able to remove one of the prompt questions for "width 2" as its no longer needed. 

 

thanks so much!!!!!!!!!!!!!!

 

square tube modification:

(vl-princ-to-string (/ (/ v (* d1 d2)) 12))

 

round tube modification:

(vl-princ-to-string (/ (/ v (* 3.14 (/ d1 2)(/ d1 2))) 12))

 

 


(and (setq d1 (getdist "\nEnter first width: "))
	   (setq d2 d1 )); change to it 
	   (setq s (ssget '((0 . "3DSOLID"))))
	   (setq v 0)
      )
0 Likes