How to obtain the area of a single face of a mesh?
Hello - Ctrl-Shift select the face and DupBorder
. If the face is planar, Area
on that curve should report it. If not, Patch
the border curve and ask for Area
on the resulting surface.
-Pascal
I need in Python
Hello - here is an example that may help - you need to pass in the correct mash face index - I just used [0] here.
import rhinoscriptsyntax as rs
import Rhino
def test():
id = rs.GetObject(filter = 32, preselect=True)
if not id: return
mesh = rs.coercemesh(id)
mesh2 = mesh.Faces.ExtractFaces([0])
info = Rhino.Geometry.AreaMassProperties.Compute(mesh2, True, False, False, False)
print info.Area
pass
test()
-Pascal
So I need to extract the face first and then request the area.
Why does a face within the mesh have no identity?
Hello - the Area finder works on a mesh, not a mesh face in a larger mesh, so by extracting that as its own mesh, you can feed it to the area finding function. Note the mesh here is in memory, for the purposes of the area query only, you will not get it in the file unless you specifically add it.
-Pascal
Hello - what version of Rhino are you running? Please run SystemInfo
in Rhino and post the results.
-Pascal
Rhino 5 R14…
Hello - for V5, I guess you need to create your own mesh:
import rhinoscriptsyntax as rs
import Rhino
def test():
id = rs.GetObject(filter = 32, preselect=True)
if not id: return
mesh = rs.coercemesh(id)
face = mesh.Faces[0]
source_verts = [face.A, face.B, face.C, face.D]
verts = mesh.Vertices
mesh2 = Rhino.Geometry.Mesh()
for item in source_verts:
mesh2.Vertices.Add(verts[item])
mesh2.Faces.AddFace(0,1,2,3)
mesh2.Normals.ComputeNormals()
mesh2.Compact()
info = Rhino.Geometry.AreaMassProperties.Compute(mesh2)
print info.Area
test()
-Pascal
Hi Pascal,
thanks for the nice script. I am wondering if there is a trick to prevent error of multiple targets in Python?
Runtime error (ArgumentTypeException): Multiple targets could match: Compute(Surface), Compute(IEnumerable[GeometryBase]), Compute(Brep), Compute(Curve), Compute(Hatch), Compute(Mesh)
Traceback:
line 20, in script
I understand this is due to the method has different overload version which it is not a problem in C#. While in Python, do you have any suggestion?
Best,
Xingxin
P.S. Below is the script I want to use this method to compute the Barycentric Cell of such vertex
areas = [0] * mesh.Vertices.Count
for i in range(mesh.Faces.Count):
face = mesh.Faces.ExtractFaces([i])
area = Rhino.Geometry.AreaMassProperties.Compute(face, True, False, False, False).Area / 3
areas[mesh.Faces[i][0]] += area
areas[mesh.Faces[i][1]] += area
areas[mesh.Faces[i][2]] += area
a = areas
Hello - here is the example I keep as reference, from Dale Fugier -
import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs
#import a couple of things from System
import System.Collections.Generic.IEnumerable as IEnumerable
import System.Double as sd
tol = .001
targetId = rs.GetObject("Select surface or polyusurface to split", filter=8+16, preselect=True)
targetBrep = rs.coercebrep(targetId)
cuttingIds = rs.GetObjects("Select cutting surfaces or polysurfaces", filter=8+16)
cuttingBreps = [rs.coercebrep(id) for id in cuttingIds]
# When calling the splitter, you need to first tell Python what type of object you are going to
# give it for each parameter and then provide the actual parameter values:
# In this case the method needs a list of either breps or curves and a tolerance
#the code specifies the two types ahead of time - Rhino.Geometry.Brep and a number, System.Double, here as 'sd'
# imported at the top of the script.
splitList = targetBrep.Split.Overloads[IEnumerable[Rhino.Geometry.Brep], sd]( cuttingBreps, tol)
newIds = [ sc.doc.Objects.AddBrep(brep) for brep in splitList]
-Pascal
Doooope! Thank you so much!
In case other scripters would need it, here is the code:
import System.Boolean as bool
face = mesh.Faces.ExtractFaces([0])
info = Rhino.Geometry.AreaMassProperties.Compute.Overloads[Rhino.Geometry.Mesh, bool, bool, bool, bool](face, True, False, False, False)
If you want to compute face areas of a RhinoCommon mesh you could also implement e.g. Heron’s formula, like so:
import math
def triangleArea(ptA,ptB,ptC):
""" Compute area of triangle using Heron's Formula """
dA = ptB.DistanceTo(ptC)
dB = ptA.DistanceTo(ptC)
dC = ptA.DistanceTo(ptB)
p = (dA+dB+dC)/2
area = math.sqrt(p*(p-dA)*(p-dB)*(p-dC))
return area
def computeMeshFaceAreas(mesh):
""" Computes the face areas for a mesh using triangleArea """
faceAreas = []
vts = mesh.Vertices
for f in mesh.Faces:
if f.IsTriangle:
fA = triangleArea(vts[f.A],vts[f.B],vts[f.C])
elif f.IsQuad:
fA1 = triangleArea(vts[f.A],vts[f.B],vts[f.C])
fA2 = triangleArea(vts[f.A],vts[f.C],vts[f.D])
fA = fA1 + fA2
faceAreas.append(fA)
return faceAreas
Hi Anders,
thank you for the help! I know this formula. Similar to your code:
def triangleArea(pt_0,pt_1,pt_2):
e_01 = pt_1 - pt_0
e_12 = pt_2 - pt_1
norm = Rhino.Geometry.Vector3f.CrossProduct(e_01, e_12)
area = norm.Length / 2
return area
I was just a bit lazy and want to use API directly haha…
Anyway, thanks for dropping the advice! Hope you have fun with your skateboard!
Hi Pascal,
Just FYI, the ExtractedFaces() is not robust enough I supposed. Here attached is the manifold failed to extract faces.
[NOT ROBUST] Mesh.Faces.ExtractFaces().gh (173.5 KB)
Best,
Xingxin
What are you expecting it to do in your script? The method essentially pops (to use Python lingo) a sub-mesh from a mesh by a list of face indices:
210512_ExtractMeshFaces_GHPython_00.gh (171.1 KB)
If you’re looking to just delete faces you can use Mesh.Faces.DeleteFaces
.
Hi Anders,
I am just playing with @pascal 's method to get a list of MeshFaces area by looping over the mesh using Mesh.Faces.ExtractFaces
. And I found out that it may fail to extract…
That’s probably not a great logic: When you manipulate the input mesh at each iteration (i.e. pop a face), the indices in your for loop will eventually exceed the amount of faces in the mesh (i.e. the face count drops at each iteration):
Edit: You could use a while loop, but still it feels odd to implement ExtractFaces
for this (in that it is meant to operate on a list of face indices):
Hi Anders,
thanks for the reply! Yeah, I also found out the function literally extract rather than duplicate then extract… No worries, I was just playing with these function.
Thanks for the help!