Jump to content

Lisp to calculate total area of all 3D faces parallel to a plane


PCaires

Recommended Posts

Hello everyone.

I have several projects where I need to calculate the total area of all 3D selected objects visible faces, parallel to a plane, for example the XZ plane.

 

If I do a MERGE comand, I get a single 3D solid and with the command AREA > OBJECT, I can only get overall area, which is not intended.

 

I've been looking at the forum but have not found the solution yet.

 

Is there any LISP code that can get rid of this arduous task or can anyone get it for me please?

 

example.dwg

Link to comment
Share on other sites

Hello again everyone.

No replys yet..

Maybe I not express myself well or maybe actually asked an impossible thing to do in Autocad...

 

I'lll put the question another way.

Imagine that have a home modeled in CAD, that is, have several walls and a ceiling.

Now we want to paint all the walls of one color and the other roof.

We need to know what the total area of the walls and the ceiling.

 

So my question is:

How can calculate these 3D areas in Autocad?

First the area of the walls, then the area of the ceiling.

Link to comment
Share on other sites

I think you have to do it manually... Look into your example-after.dwg... I've unioned all 3d solids, then I used solidedit command face option and copy to copy top region to helper location, then I did the same with part that wasn't connected and I copied second region next to first and unioned finally those 2 regions into single region... Now I only looked for area with area command... For walls - I mean inside areas it's difficult task, but I think that first step is to union all 3dsolid geometry and then proceed to extract regions required... I am afraid that this is the only way as there is no quick select of bounding regions in 3d space around inner picked point... What you could also try to do in this situation is to make section of walls somewhere at the middle of height of walls - see what is perimeter of walls and multiply that number with height of walls if and only if the height is constant... Also an here you have to consider outside and inside boundaries and calculate only for those that are your subject of the task...

 

example-after.dwg

Link to comment
Share on other sites

marko_ribar, thanks for the time you spent studying my request.

Still I do not know if I could understand very well what is proposed but it seems equally time consuming.

 

David Bethel, your observation reminded me that for my projects I also have to calculate the volumes of the elements so I think your suggestion would not serve me but thanks anyway.

 

 

At this time, for the calculation of areas manually I follow this way:

1- 2D drawing of polylines each element and place each polyline in each layer depending on the height of the element

2- With all drawn polylines I use the lisp of the following post http://www.cadtutor.net/forum/showthread.php?28604-lisp-to-calculate-total-areas&p=183993&viewfull=1#post183993

to calculate the total area of ​​each layer

3- After I MERGE to unite all solids in a solid only

4 AREA> OBJECT give me the total area of ​​all faces of this solid

5- subtract point 2 point 4 twice and get the non-planar faces to the XY plane

Link to comment
Share on other sites

Have you looked into thickness and plines then area is lengthxheight for irregular vertical face use pface or pline area is available then.

 

BIGAL, what a pleasant surprise. From what I've been watching in the forum you are a true master Cad.

Thanks for replying my post.

For now, the project I'm working just have vertical walls and horizontal ceilings.

I do not see how to use your thick suggestion.

Of course I can measure the length of each element and knowing its thickness I can manually calculate its area. Then multiplying that area by the height have the volume but I will have to do so element by element which is time consuming. Right?

 

I'm looking for something more productive.

Something with the project modeled in 3D I could take the areas of visible faces, just like if you were to paint them.

Volumes already I can do with MASSPROP.

 

I'm not familiar with PFACE and I can't well understand its functionality in my case...

Edited by PCaires
Link to comment
Share on other sites

I think you have to do it manually... Look into your example-after.dwg... I've unioned all 3d solids, then I used solidedit command face option and copy to copy top region to helper location, then I did the same with part that wasn't connected and I copied second region next to first and unioned finally those 2 regions into single region... Now I only looked for area with area command... For walls - I mean inside areas it's difficult task, but I think that first step is to union all 3dsolid geometry and then proceed to extract regions required... I am afraid that this is the only way as there is no quick select of bounding regions in 3d space around inner picked point... What you could also try to do in this situation is to make section of walls somewhere at the middle of height of walls - see what is perimeter of walls and multiply that number with height of walls if and only if the height is constant... Also an here you have to consider outside and inside boundaries and calculate only for those that are your subject of the task...

 

[ATTACH]55902[/ATTACH]

 

Excellent your post marko_ribar here http://www.cadtutor.net/forum/showthread.php?94332-Solidedit-task&p=645733&viewfull=1#post645733

I thought coloring faces and then lisp calculating those areas will work so I tried to SOLIDEDIT>BODY>SHELL but it occurs the following error: "Modeling Operation Error: Non-manifold edge detected."

 

Also occurs me if I shell it with small thickness I'll obtain almost the same surface. Then divide it by 2 to obtain the surface area. It's not accurate but vs saving time...

But I'm stuck :oops:

Any more ideas?

Link to comment
Share on other sites

I was about to propose to you that link - you were just faster...

Here I wrote this lisp for you - if you need only data and you operate with such 3DSOLIDS like in your example.dwg - I am afraid that for more complex geometry it may fail (exploded unioned 3dsolid produce body(ies) entity(ies) or surface(s)), but who knows it just may even work I just haven't tested it on such examples)...

 

(defun c:calc-base-diff-areas-3dentities ( / *error* unit *adoc* ss 3dsollst reglst surflst bodylst 3dsolss entlst totar basear el )

 (vl-load-com)

 (defun *error* ( m )
   (if *adoc* (vla-endundomark *adoc*))
   (if m (prompt m))
   (princ)
 )

 (defun unit ( v )
   (mapcar '(lambda ( x ) (/ x (distance '(0.0 0.0 0.0) v))) v)
 )

 (setq *adoc* (vla-get-activedocument (vlax-get-acad-object)))

 (prompt "\nSelect 3DSOLID(S),REGION(S),SURFACE(S),BODY(IES) you want to calculate only vertical areas from...")
 (setq ss (ssget "_:L" '((0 . "3DSOLID,REGION,*SURFACE,BODY"))))
 (while (not ss)
   (prompt "\nEmpty sel.set... Please select at least 1 3D entity or make correct selection of 3D entities on unlocked layer(s) you want to process again...")
   (setq ss (ssget "_:L" '((0 . "3DSOLID,REGION,*SURFACE,BODY"))))
 )
 (vla-startundomark *adoc*)
 (setq 3dsollst (vl-remove nil (mapcar '(lambda ( x ) (if (eq (cdr (assoc 0 (entget x))) "3DSOLID") x)) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))))
 (setq reglst (vl-remove nil (mapcar '(lambda ( x ) (if (eq (cdr (assoc 0 (entget x))) "REGION") x)) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))))
 (setq surflst (vl-remove nil (mapcar '(lambda ( x ) (if (wcmatch (cdr (assoc 0 (entget x))) "*SURFACE") x)) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))))
 (setq bodylst (vl-remove nil (mapcar '(lambda ( x ) (if (eq (cdr (assoc 0 (entget x))) "BODY") x)) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))))
 (if 3dsollst
   (progn
     (setq 3dsolss (ssadd))
     (foreach 3dsol 3dsollst
       (ssadd 3dsol 3dsolss)
     )
     (command "_.UNION" 3dsolss)
     (while (< 0 (getvar 'cmdactive)) (command ""))
     (command "_.EXPLODE" (entlast))
     (while (< 0 (getvar 'cmdactive)) (command ""))
     (setq entlst (vl-remove-if 'listp (mapcar 'cadr (ssnamex (ssget "_P")))))
   )
 )
 (setq totar 0.0)
 (foreach ent entlst
   (command "_.AREA" "_O" ent)
   (while (< 0 (getvar 'cmdactive)) (command ""))
   (setq totar (+ totar (getvar 'area)))
 )
 (foreach reg reglst
   (setq totar (+ totar (vla-get-area (vlax-ename->vla-object reg))))
 )
 (foreach surf surflst
   (command "_.AREA" "_O" surf)
   (while (< 0 (getvar 'cmdactive)) (command ""))
   (setq totar (+ totar (getvar 'area)))
 )
 (foreach body bodylst
   (command "_.AREA" "_O" body)
   (while (< 0 (getvar 'cmdactive)) (command ""))
   (setq totar (+ totar (getvar 'area)))
 )
 (setq basear 0.0)
 (foreach reg reglst
   (if (or (equal (unit (vlax-safearray->list (vlax-variant-value (vla-get-normal (vlax-ename->vla-object reg))))) '(0.0 0.0 1.0) 1e-6) (equal (unit (vlax-safearray->list (vlax-variant-value (vla-get-normal (vlax-ename->vla-object reg))))) '(0.0 0.0 -1.0) 1e-6))
     (setq basear (+ basear (vla-get-area (vlax-ename->vla-object reg))))
   )
 )
 (foreach ent entlst
   (cond
     ( (eq (cdr (assoc 0 (entget ent))) "REGION")
       (if (or (equal (unit (vlax-safearray->list (vlax-variant-value (vla-get-normal (vlax-ename->vla-object ent))))) '(0.0 0.0 1.0) 1e-6) (equal (unit (vlax-safearray->list (vlax-variant-value (vla-get-normal (vlax-ename->vla-object ent))))) '(0.0 0.0 -1.0) 1e-6))
         (setq basear (+ basear (vla-get-area (vlax-ename->vla-object ent))))
       )
     )
     ( (wcmatch (cdr (assoc 0 (entget ent))) "*SURFACE")
       (setq el (entlast))
       (command "_.EXPLODE" ent)
       (while (< 0 (getvar 'cmdactive)) (command ""))
       (if (and (not (equal el (entlast))) (eq (cdr (assoc 0 (entget (entlast)))) "REGION"))
         (progn
           (if (or (equal (unit (vlax-safearray->list (vlax-variant-value (vla-get-normal (vlax-ename->vla-object (entlast)))))) '(0.0 0.0 1.0) 1e-6) (equal (unit (vlax-safearray->list (vlax-variant-value (vla-get-normal (vlax-ename->vla-object (entlast)))))) '(0.0 0.0 -1.0) 1e-6))
             (setq basear (+ basear (vla-get-area (vlax-ename->vla-object (entlast)))))
           )
           (command "_.UNDO" "_B")
         )
       )
     )
   )
 )
 (foreach surf surflst
   (setq el (entlast))
   (command "_.EXPLODE" surf)
   (while (< 0 (getvar 'cmdactive)) (command ""))
   (if (and (not (equal el (entlast))) (eq (cdr (assoc 0 (entget (entlast)))) "REGION"))
     (progn
       (if (or (equal (unit (vlax-safearray->list (vlax-variant-value (vla-get-normal (vlax-ename->vla-object (entlast)))))) '(0.0 0.0 1.0) 1e-6) (equal (unit (vlax-safearray->list (vlax-variant-value (vla-get-normal (vlax-ename->vla-object (entlast)))))) '(0.0 0.0 -1.0) 1e-6))
         (setq basear (+ basear (vla-get-area (vlax-ename->vla-object (entlast)))))
       )
       (command "_.UNDO" "_B")
     )
   )
 )
 (if 3dsollst (command "_.UNDO" "_B"))
 (prompt "\nTotal area : ") (princ (rtos totar 2 50))
 (prompt "\nTotal base area : ") (princ (rtos basear 2 50))
 (prompt "\nTotal difference area (vertical + non-planar elements) : ") (princ (rtos (- totar basear) 2 50))
 (*error* nil)
)

HTH, M.R.

 

[EDIT : Have updated code and tested it with complex 3D SOLID geometry - should work now]

Edited by marko_ribar
code changed - to accept complex 3d geometry
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...