Find larger surface in a brep

Hi again,
my apologize in advance for the tons of quest that I will publish but I’m learning and I came from python and vb.net =D
I would need to find the largest surface of a brep, to define if the object is planar or not…
I though to pass through a dictionary to assign face index and it’s area, then pass areas to a list sort and retrieve the first or last element… but even if I add value to area to avoid value duplicate I still get an error of duplicated value…

public static int RetriveSurfaceID(Brep brep, string mode)
        {
            var aree = new Dictionary<double, int>();
            var faces = brep.Faces;
            foreach (var face in faces)
            {
                aree.Add(face.Brep.GetArea() + 0.000001, face.FaceIndex);
            }
            var areelist = aree.Keys.ToList();
            areelist.Sort();
            switch (mode)
            {
                case "MAX":
                    return aree[areelist[areelist.Count - 1]];
                case "MIN":
                    return aree[areelist[0]];
                default:
                    return -1;
            }
        }

immagine

If face is a BrepFace, then face.Brep retrieves the entire Brep that this face belongs to.
So, all your face.Breo.GetArea() retrieve the same value (the entre area of your Brep).

You need to use face.DuplicateFace(false).GetArea().

Even with that, the fact you are adding 0.000001 to the area does not prevent two values from being identical. If you have a box for instance, opposite faces always have the same area.

I gave a try to your code, returning a List instead, in case several faces have minimum or maximum value.

C#LargestBrepFace.gh (12.4 KB)

@magicteddy I still have to adapt to CSharp method, thank you so much, how do you suggest to do looking for min and max areas in a brep?
Consider that I will have have always objects that represent plates, so there’s no more than 2 “big” surfaces, others are thickness… I was using this trick with dict and areas in python and vb.net without problems, as well to target the external or internal face in case of bended plates… now I just looking for a way to know at the end is the solid is planar

Does it matter if you get two identical areas? Just use the first one in the list…

@Helvetosaur but I need the bigger or smaller, so to be sure I need at least to sort it by area… Is not ensured that the first one is the bigger or smaller

I assumed you only needed the biggest from the title, but if you need both ends, yes, then you would need to sort by area and then take the first and last elements in the sorted list…

@Helvetosaur Yep, but even if I need the biggest how can I be sure that will be in the first position? Am I missing something?

Well, something like this might work in python… (I don’t know C#)

import rhinoscriptsyntax as rs
import Rhino

def FindLargestSmallestFaces(brep):
    #returns the face index and area of the largest and smallest faces in a brep
    face_list=[]
    for i,face in enumerate(brep.Faces):
        face_area=face.DuplicateFace(False).GetArea()
        face_list.append((face_area,i))
    face_list.sort(reverse=True)
    return [face_list[0][1],face_list[0][0]],[face_list[-1][1],face_list[-1][0]]

obj_id=rs.GetObject("Select a brep",16,preselect=True)
if obj_id:
    brep=rs.coercebrep(obj_id)
    result=FindLargestSmallestFaces(brep)
    print result

The trick is you can sort a nested list and it sorts by the first numeric element in the nested lists. There are also other ways to do the sorting of course.

@Helvetosaur I did it in python with the dict trick and no problem, but I’m currently learnig c# xD

How about just looping through all faces, remembering min and max every time ?
There is also a .IsPlanar() method of BrepFace if this is your final goal.

C#LargestBrepFace.gh (11.9 KB)

Here’s a method using LINQ.

C#LargestBrepFace_221125_re.gh (15.5 KB)

-Kevin

1 Like

@kev.r thank you so much, at the end I solved with LINQ… here the code:

 public static int RetriveSurfaceID(RhinoDoc doc, Brep brep, string mode)
        {
           
            var indexed = brep.Faces.Select((item, index) => new { area = item.DuplicateFace(false).GetArea(), index });
            var results = indexed.OrderBy(item => Math.Round(item.area, 6)).Select(item => item.index).ToList();

            var idxList = results;          // < out
            var minIdx = results.First();   // < out
            var maxIdx = results.Last();    // < out
            switch (mode)
            {
                case "MAX":
                    return maxIdx;//aree[areelist[0]];
                case "MIN":
                    return minIdx;//aree[areelist[areelist.Count - 1]];
                default:
                    return -1;
            }
        }