Similar objects

I want to check if two breps are the same, so what do you think the best way is?

Hi @arc.feizbahr
https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.geometrybase/geometryequals
It doesn’t check for custom user data. So two identical objects with different user text will return as identical.

bool AreBRepsSame(Brep brep1, Brep brep2)
{
    // Simpler checks less computationally expensive
    if (brep1.GetBoundingBox(false) != brep2.GetBoundingBox(false) ||
        brep1.Faces.Count != brep2.Faces.Count ||
        brep1.Edges.Count != brep2.Edges.Count ||
        brep1.Vertices.Count != brep2.Vertices.Count)
        return false;

    // Detailed comparison if gets flagged as potential equal
    return brep1.GeometryEquals(brep2);
}

Farouk

4 Likes

Have you benchmarked this to see if it’s actually worth doing (a performance win)?

My assumption had been that the McNeel folks were also smart enough to do the easy checks first (inside GeometryEquals) :slight_smile:

Hi @Nathan_Bossett ,
I hope all is well. They do integrate some basic checks based on my benchmarks, but running the basic checks yourself is faster according to my benchmarks

Comparing BRep 0 with BRep 1:
  All Checks: 0.000222 seconds, Result: False
  Detailed Only: 0.003564 seconds, Result: False

Depending on the geometry complexity It is computationally less expensive to run the most basic checks yourself based on my benchmarks.
Great observation anyway I did not actually check it but turns out that It is faster in some cases, in other cases It was faster to run only the detailed check.

Farouk

thanks for your answer @farouk.serragedine , but i actually need it with a lot more precision,
as you see, in this code, complex form’s faces and edges etc. might be the same, and it might get them as look alike breps, but i want to see if they are the same even in deferent rotations, positions and with same exact form in details, not just count of faces and edges, so i was wondering if there is any way to compare geometries (i don’t know if it works or not…)

I agree with you

@arc.feizbahr what you’re aiming for is quite tricky. But not impossible.

Do you want to compare two objects, or compare many objects? And always breps?

– cs

thanks for reply @csykes ,
It’s always breps, and it is actually a comparison between one and many breps, but a comparison between two breps would work too.

Hi @arc.feizbahr,
Could you please upload a 3d model with a brep that fails the similarity checks so that we can help you work something out?
We could compute edge lengths and relative angles or maybe perform a volumetric control based on pointcloud rellative distances. If you upload a model I am sure we can work something out.
Farouk

actually I haven’t tried anything but equality of geometries yet, I was thinking of checking every edge length and face area but it’s not 100% reliable and I also thought there might be a simpler way for that,
what I want to check is if two MDF sheets with holes or cuts are the same? or not.
I will put an example here for you in rhino7.
test.3dm (197.3 KB)
thanks

Good morning @arc.feizbahr ,

The compare_breps function takes two Brep objects and checks if their largest faces have the same distances from their centroids to the start/end point of the edges, this will also map the hole location relative to the area centroid. That way we get a reliable and relative rappresentation of the geometry. It returns True if the distances are the same and False otherwise.

Seems to work quite well for your use case, that’s the easiest relative comparison we could implement.

def compare_breps(brep1, brep2):
    def get_largest_face(brep):
        
        largest_face = max(brep.Faces, key=lambda face: rg.AreaMassProperties.Compute(face).Area)
        return largest_face

    def get_distances_to_centroid(face):
        
        centroid = rg.AreaMassProperties.Compute(face).Centroid
        
        distances = [round(trim.Edge.EdgeCurve.PointAtStart.DistanceTo(centroid))
                     for loop in face.Loops for trim in loop.Trims]
        distances += [round(trim.Edge.EdgeCurve.PointAtEnd.DistanceTo(centroid))
                      for loop in face.Loops for trim in loop.Trims]
        return sorted(distances)


    return get_distances_to_centroid(get_largest_face(brep1)) == get_distances_to_centroid(get_largest_face(brep2))

Hope this helps,
Farouk

thanks @farouk.serragedine ,
I tested it, It works fine in my case.
appreciate that.