How to choose Planarity test tolerance

Hi,

When testing .IsPlanar I can pass a tolerance.
However in what units is that tolerance interpreted?
I have a feeling that passing the document absolute tolerance is not relevant for testing of planarity or is it?

Thanks
-Willem

I’m not sure telling you “decimal units” is helpful.[quote=“Willem, post:1, topic:7185”]
I have a feeling that passing the document absolute tolerance is not relevant for testing of planarity or is it?
[/quote]

It really depends on what you are testing and why. In most cases, the document tolerance is rather loose and thus, non planar objects could be interpreted as planar. But perhaps this is what you want…

Hi Dale,

Thanks for your answer,
indeed “decimal units” is not that helpful for me. :smile:

Let me rephrase:
What I need to do is find the largest planar surface of a Brep. They are sheet metal parts to be made via CNC laser cutting. However without a tolerance some surfaces did not pass as being planar while for my purpose they are . So I need to allow for just a little tolerance, however I want to know what the number/value represents in order to make a useful decision on what tolerance value to use.

What I imagine is that a surface that is truly planar has a minimal boundingbox that has 0 thickness.
A surface that is slightly less planar will have a minimal boundingbox with some thickness.
I suspect that the tolerance used for planarity testing has a relation to that thickness (deviation from being absolute flat).
However, what I am wondering is if the tolerance is an absolute value regardless of the size of a surface, or that it is a relative value relating the absolute size of the surface to the thickness in some way.

Hope this gives enough insight in my issue to enlighten me enough.

Thanks
-Willem

I believe for surfaces, a plane is created from the surface’s normal direction at the “center” of the surface. Then, all control points are check for their distance from this plane. If the distance to any control falls outside of the “tolerance”, then the surface is deemed non-planar.

Yes it is.

Hi Dale,

Many thanks!
This seems just what I needed to know to setup a Planar checking for my type of geometry.
It never ceases to amaze me how great McNeel’s customer support is!

Thanks
-Willem

Here we go, I live in the land of workarounds so maybe this can to the job.
You should reprogram it to be sophisticated, but this is a proof of concept that works:


# This is a Holo hack...
# ugly and dirty, but it works.

# This will mess with the document tolerance,
# So add a good fail safe solution! 
# To make sure you don't get an error and continue
# modelling in Rhino with that!

import rhinoscriptsyntax as rs
# Get document tolerance
origTolerance=rs.UnitAbsoluteTolerance()
# Get surface
srf=rs.GetObject("get surface", filter=8+16, preselect=True, select=False)
# Get new tolerance of you choice, default is 1 unit
newTolerance=rs.RealBox (message="set tolerance for test", default_number=1, title="Tolerance", minimum=0.001, maximum=None)
# Set the new tolerance as document tolerance
rs.UnitAbsoluteTolerance(newTolerance)

# Duplicate the surface edges
edgecurves=rs.DuplicateEdgeCurves (srf)

# Check if a planar surface can be added to the curves
# This now uses the modified document tolerance
newSrfs=rs.AddPlanarSrf (edgecurves)
# This 'can' result in multiple surfaces
# so if the original surface has a hole in 
# a flat area then this can give a false positive

if newSrfs:
    # Since it can give a false positive I have added
    # a "show result" and a message box
    # (this can be swapped out with an analysis of the surface area, 
    # if they are pretty close you are ok to go
    rs.SelectObjects(newSrfs)
    rs.MessageBox ("The surface is flat within "+str(newTolerance)+" units.", buttons=0, title="Hurray!")
    rs.DeleteObjects(newSrfs)
else:
    rs.MessageBox("the surface is NOT flat enough", buttons=0, title="Argh!")

# Clean up the rest
rs.UnitAbsoluteTolerance(origTolerance)
rs.DeleteObjects(edgecurves)

Edit: PS I do this to learn, and the idea here was to work around a bounding box, so the surfaces can be analyzed quickly regardless of what orintation they have in space.

Edit 2: And I now realized that I wrongly read the initial post… I though it said you could NOT pass a tolerance… Oh, well, at least I learned a few new things :wink:

Edit3: In case anybody sees this and get confused:
I just learned that these four lines does the same job faster an better :blush:

import rhinoscriptsyntax as rs
obj=rs.GetObject("get")
val=rs.IsSurfacePlanar (obj, tolerance=5)
print val

Hi Jorgen,

Nice! Now I needed to find out for myself.
As Dale believed planarity is tested as the deviation from controlpoints from the plane through the “center” of the surface, I scripted this to test it. I ran out of time just now but it appears to be indeed to operate that way.
My initial surface that I testes was not setup right but a quick last test had better results.

-out for now back to deadlined work.

-Willem

import rhinoscriptsyntax as rs

def OrientBrepsFlat():
    #get polysurfaces and extrusions
    Obj = rs.GetObjects("Get Surface To Test:",8)
    
    # Get the RhinoObject
    Brep = rs.coercebrep(Obj)
    
    # assume a single face and get first Face in Brep Faclist
    Face = Brep.Faces[0]
    # Get the UV at the afce demain center
    a,b = Face.Domain(0)
    u = (a+b)/2
    a,b  = Face.Domain(1)
    v = (a+b)/2
    # get the surface frame(plane) at the domain center
    Frame = Face.FrameAt(u,v)
    # get the boundingbox alighned with the domain center frame
    BoundingBox = Brep.GetBoundingBox(Frame[1])
    # calculate the height of the boundingbox
    Height = BoundingBox.Max[2] - BoundingBox.Min[2]
    
    
    if Face.IsPlanar():
        print "Face is Planar (absolute)"
    else:
        print "Face is NOT Planar (absolute)"
    
    reportPlanarity(Height/2,"half the boundingbox height",Face)
    reportPlanarity((Height)-(Height/10) ,"the boundingbox height - 10% ",Face)
    reportPlanarity((Height)-(Height/20) ,"the boundingbox height - 5% ",Face)
    reportPlanarity((Height)-(Height/50) ,"the boundingbox height - 2% ",Face)
    reportPlanarity((Height)-(Height/100) ,"the boundingbox height - 1% ",Face)
    reportPlanarity(Height ,"the boundingbox height",Face)



def reportPlanarity(tol,msg,Face):
    
    if Face.IsPlanar(tol):
        print "Face is Planar with " + msg + " : " + str(tol)
    else:
        print "Face is NOT Planar with " + msg + " : " + str(tol)
        
        
        
OrientBrepsFlat()