Jump to content

Calculate mass of Solids including ones in blocks.


CADkitt

Recommended Posts

I frankenbuild 2 autolisp scripts to output the mass of a solid (in mm density is from steel 0.00782 g/mm^3/7820 kg/m^3 )

It also explodes all blocks and then undo that, so your blocks are unharmed, but this way it also uses the solids in those blocks.

 

 

The volume code is from lee mac:

http://www.cadtutor.net/forum/showthread.php?37358-how-to-Pick-the-Value-of-Volume

The explode code is also from lee mac:

http://www.cadtutor.net/forum/showthread.php?53107-Xplode-All-Blocks

 

This is my franken build code: (remember output is from a part in mm)

(defun c:vol (/ ss vol bset |cmdecho|)
 (vl-load-com)
 (SETQ |cmdecho| (GETVAR "cmdecho"))
 (SETVAR "cmdecho" 1)
 (COMMAND "undo" "begin")
 (c:ExplodeAllBlocks)
 (COMMAND "undo" "end")
 (if (setq ss (ssget '((0 . "3DSOLID"))))
   (progn
     (setq vol
       (apply '+
         (vl-remove-if
           'vl-catch-all-error-p
             (mapcar
               (function
                 (lambda (x)
                   (vl-catch-all-apply
                     'vla-get-volume (list x))))
               (mapcar 'vlax-ename->vla-object
                 (vl-remove-if 'listp
                   (mapcar 'cadr (ssnamex ss))))))))
     (command "undo" "")(princ (strcat "\n<< Total Volume = " (rtos vol 2 2) " >>"))
     (setq volume (rtos vol 2 2)) ))
    (setq massa (* 0.00782 vol)))
  (PRINC (strcat "\n<<mass:" (rtos (/ massa 1000) 2 2) " kg >>"))
 (princ)
 (SETVAR "cmdecho" |cmdecho|)
 )

Explode block lisp from lee mac

(defun c:ExplodeAllBlocks ( / *error* _StartUndo _EndUndo doc locked ss )
 (vl-load-com)
 ;; © Lee Mac 2010

 ;; Error Handler

 (defun *error* ( msg )
   (if locked
     (mapcar
       (function
         (lambda ( l )
           (vl-catch-all-apply 'vla-put-lock (list l :vlax-true))
         )
       )
       locked
     )
   )
   (if doc (_EndUndo doc))
   (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
       (princ (strcat "\n** Error: " msg " **")))
   (princ)
 )

 (defun _StartUndo ( doc ) (_EndUndo doc)
   (vla-StartUndoMark doc)
 )

 (defun _EndUndo ( doc )
   (if (= 8 (logand 8 (getvar 'UNDOCTL)))
     (vla-EndUndoMark doc)
   )
 )

 ;; Start an Undo Mark

 (_StartUndo
   (setq doc
     (vla-get-ActiveDocument
       (vlax-get-acad-object)
     )
   )
 )

 ;; Unlock all Layers

 (vlax-for l (vla-get-layers doc)
   (if (eq :vlax-true (vla-get-lock l))
     (progn
       (vla-put-lock l :vlax-false)
       (setq locked (cons l locked))
     )
   )
 )

 ;; Now lets explode 'em

 (if (ssget "_X" '((0 . "INSERT")))
   (progn
     (vlax-for obj (setq ss (vla-get-ActiveSelectionSet doc))
       (if (vl-catch-all-error-p
             (vl-catch-all-apply 'vla-Explode (list obj))
           )
         (princ (strcat "\n** Unable to Explode Block: " (vla-get-name obj) " **"))
         (vla-delete obj)
       )
     )
     (vla-delete ss)
   )
 )  

 ;; ReLock the Layers

 (mapcar
   (function
     (lambda ( l ) (vla-put-lock l :vlax-true))
   )
   locked
 )

 ;; End the Undo mark

 (_EndUndo doc)
 
 ;; Exit Cleanly

 (princ)
)

Edited by CADkitt
Link to comment
Share on other sites

I am seeing that I am doing something stupid going from a intreger to a string and back again :P

But at least I understand it a bit better now :)

Edit fixed it :)

Link to comment
Share on other sites

You don't need to explode the blocks, you can step through the objects contained within without exploding. But you'll need to alter your a bit. Did some fiddling of my own:

(vl-load-com)

(setq *mass-fact* 0.00782)

;; Command to calculate the volume of selected objects
(defun c:vol (/ vol:calc vol:calc-block blst sum ss item)
 ;; Helper function to calculate a single entity's volume
 (defun vol:calc (eo / val)
   (cond
     ((eq (vla-get-ObjectName eo) "AcDbBlockReference")
      (vol:calc-block (vla-get-EffectiveName eo))
     )
     ((not (vl-catch-all-error-p (setq val (vl-catch-all-apply 'vla-get-Volume (list eo))))) val)
     (t 0.0)
   )
 )

 ;; Helper function to calculate the volume contained within a block definition
 (defun vol:calc-block (name / blk item sum)
   (setq sum 0.0)
   (if (setq blk (assoc name blst))
     (setq sum (cdr blk))
     (if (not (vl-catch-all-error-p (setq blk (vl-catch-all-apply 'vla-Item (list *BlocksCollection* name))))
         )
       (progn
         (vlax-for item blk
           (setq sum (+ sum (vol:calc item)))
         )
         (setq blst (cons (cons name sum) blst))
       )
     )
   )
   sum
 )

 ;; Initialize variables
 (setq sum 0.0)
 (or *ActiveDocument* (setq *ActiveDocument* (vla-get-ActiveDocument (vlax-get-acad-object))))
 (or *BlocksCollection* (setq *BlocksCollection* (vla-get-Blocks *ActiveDocument*)))

 ;; Step through a selection set, adding the volume of each item to a sum
 (princ "\nSelect entities to calculate volume from: ")
 (if (and (setq ss (ssget '((0 . "3DSOLID,INSERT"))))
          (not (vl-catch-all-error-p
                 (setq ss (vl-catch-all-apply 'vla-get-ActiveSelectionSet (list *ActiveDocument*)))
               )
          )
     )
   (vlax-for item ss
     (setq sum (+ sum (vol:calc item)))
   )
 )

 (princ (strcat "\n<< Total Volume = " (rtos (/ sum (expt 1000.0 3)) 2 3) " m³ >>"))
 (princ
   (strcat "\n<< Mass @" (rtos *mass-fact*) " = " (rtos (/ (* *mass-fact* sum) 1000.0) 2 2) " kg >>")
 )

 (princ)
)

Link to comment
Share on other sites

I had read of such an autolisp magic :shock: very nice!

I can find all the vl commands in help but what is or does: (t 0.0)

 

I updated mine a bit with Irneb output calculations, just to learn it.

(defun c:vol (/ ss vol bset |cmdecho|)
 (setq density 0.00782)
 (vl-load-com)
 (SETQ |cmdecho| (GETVAR "cmdecho"))
 (SETVAR "cmdecho" 0)
 (COMMAND "undo" "begin")
 (c:ExplodeAllBlocks)
 (COMMAND "undo" "end")
 (if (setq ss (ssget '((0 . "3DSOLID"))))
   (progn
     (setq vol
       (apply '+
         (vl-remove-if
           'vl-catch-all-error-p
             (mapcar
               (function
                 (lambda (x)
                   (vl-catch-all-apply
                     'vla-get-volume (list x))))
               (mapcar 'vlax-ename->vla-object
                 (vl-remove-if 'listp
                   (mapcar 'cadr (ssnamex ss))))))))
     (command "undo" "")
     (setq volume (rtos vol 2 2)) ))
    (setq massa (* density vol))

 (princ (strcat "\n<< Total Volume = " (rtos (/ vol (expt 1000.0 3)) 2 4) " m³ >>"))
 (PRINC (strcat "\n<< Mass @" (rtos (* density 1000000) 2 2) " kg/m^3 = " (rtos (/ massa 1000) 2 2) " kg >>"))
 (princ)
 (SETVAR "cmdecho" |cmdecho|)
 )

Edited by CADkitt
Link to comment
Share on other sites

That's a portion of the cond. It can be seen as cond's else portion (as opposed to if's). E.g.:

(cond
 ((<Test case 1>)
   <Perform actions when Test1 is true>
 )
 ((<Test case 2>)
   <Perform actions when Test2 is true>
 )
 (t
   <Perform actions when neither Test1 nor Test2 is true>
 )
)

And then the 0.0 is simply passing a zero as the result of the function.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...