2
$\begingroup$

I need to find the top surface area (in one plane) and total surface area (by summing all the faces) of a complicated mesh. For that I need to know how to fit a plane to the top of a mesh to find the top surface area. The mesh can be .obj or .stl or .ply

$\endgroup$
4
  • $\begingroup$ Can you elaborate on what you mean by top surface area? for example a square bottomed pyramid, would it be the area of the base (the shape seen from the top) or the tip, or the faces visible from the top view? Or you could sum the faces whose face normal is within some tolerance of (0, 0, 1) $\endgroup$
    – batFINGER
    Commented Apr 5, 2016 at 5:58
  • $\begingroup$ So If it is a squarebase pyramid , faces visible from top will be top surface area. That will be the area of square if square is facing the camera. Whereas all the faces of pyramid will come under total surface area. I know to sum up the areas of faces and get total surface area. But since top surface area is in one plane.. I need to find a solution.please help $\endgroup$
    – kpdkps
    Commented Apr 5, 2016 at 17:44
  • $\begingroup$ In the last comment in blender.stackexchange.com/questions/47675/… I showed the code for summing the area of selected faces. area = sum(f.calc_area() for f in bm.faces if f.select) Edit mode, Go to top view, box select visible, Object mode, then run code. Is that what you are after? $\endgroup$
    – batFINGER
    Commented Apr 6, 2016 at 1:48
  • $\begingroup$ Can you help me with what you said. .summing up the faces whose normal is within some tolerance. . How to try that @batFINGER $\endgroup$
    – kpdkps
    Commented Apr 7, 2016 at 3:37

1 Answer 1

3
$\begingroup$

Here as requested is faces whose normal vector has angle from up vector of less than 80 degrees.

import bpy
import bmesh
from math import radians
from mathutils import Vector

obj = bpy.context.active_object
mw = obj.matrix_world
bm = bmesh.new()
bm.from_mesh(obj.data)

up = Vector((0, 0, 1))
# local space    
area = sum(f.calc_area() for f in bm.faces if up.angle(f.normal) < radians(80))
print("local", area)
# global space
area = sum(f.calc_area() for f in bm.faces if up.angle(mw * f.normal) < radians(80))
print("global", area)
# or avoid a lot of matrix mult by converting "up" to local space.
up = mw.inverted() * up
area = sum(f.calc_area() for f in bm.faces if up.angle(f.normal) < radians(80))
print("global", area)

bm.free()
$\endgroup$
1
  • $\begingroup$ That works great. How would that look for the ground or floor plane? I do have mesh with boxes representing buildings and would like to calculate the roof and ground surface. $\endgroup$
    – Philipp R
    Commented Nov 1, 2023 at 15:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .