Wish, set cplane to surface, report if surface is planar

when setting cplane to surface, it would be nice if it reported if the surface is planar so you know if the cplane if really “on” the surface.

if not is it something that could be scripted?

You can use old gumball trick to find out whether the surface is planar: turn the gumball on and select the surface. If the gumball displays two scale handles only (X and Y, but no Z), it means that the surface is planar.

1 Like

HI @kleerkoat,
If your using Windows you can try these scripts
one surface and one for curve

-RunScript (
Sub surfacePlanarTest
Dim strObject

strObject = Rhino.GetObject("Select a surface", 8, True)
If Not IsNull(strObject) Then
	If Rhino.IsSurfacePlanar(strObject) Then
		Rhino.Print "The surface is planar."
	Else
		Rhino.Print "The surface is not planar."
	End If
End If
	End Sub 
surfacePlanarTest

)

-RunScript (
Sub curvePlanarTest
Dim strObject

strObject = Rhino.GetObject(“Select a curve”, 4, True)
If Not IsNull(strObject) Then
If Rhino.IsCurvePlanar(strObject) Then
Rhino.Print “The curve is planar.”
Else
Rhino.Print “The curve is not planar.”
End If
End If
End Sub
curvePlanarTest
)

1 Like

thank you!

There is also SelPlanarSrf.

-Pascal

i hacked this together from a script @Helvetosaur had posted in another thread about getting a subsurface. i have a feeling it is such a terrible hack that 95% of it is unnecessary. what do you think. lol

  def setCPlaneToPlanarSrf():
    sel = rs.GetObjectEx("Pick a polysurface object", 16, False)
    if not sel: return
    objID = sel[0]
    pick_pt = sel[3]
    tol = sc.doc.ModelAbsoluteTolerance

    rhobj = rs.coercerhinoobject(objID)
    brep = rhobj.Geometry
    for face in brep.Faces:
        rc, u, v = face.ClosestPoint(pick_pt)
        if rc:
            face_pt = face.PointAt(u, v)
            if face_pt.DistanceTo(pick_pt) < tol:
                if face.IsPointOnFace(
                        u, v) == Rhino.Geometry.PointFaceRelation.Interior:
                    rhobj.SelectSubObject(face.ComponentIndex(), True, True,
                                          True)


#    rs.AddPoint(pick_pt)
    if rs.IsSurfacePlanar(face):
        print "THE SURFACE IS PLANAR."
        rs.Command("_noecho _cplane _surface")
    else:
        rs.MessageBox("The surface is not planar.")
setCPlaneToPlanarSrf()
1 Like

@kleerkoat dunno if this is even slightly more useful or better in any way but at least it is different code:


import Rhino
import rhinoscriptsyntax as rs

def CPlaneToSurface():
    
    rc, oRef = Rhino.Input.RhinoGet.GetOneObject("Select a surface, or a polysurface face.", False, filter =Rhino.DocObjects.ObjectType.Surface)
    if rc != Rhino.Commands.Result.Success: return
    id = oRef.ObjectId
    pt = oRef.SelectionPoint()

        
    idx = oRef.GeometryComponentIndex.Index
    if  idx == -1:
        geo= rs.coercesurface(id)
    else:
        geo = oRef.Brep().Faces[idx]
        pass
    rc, myPlane = geo.TryGetPlane()
    
    u = None
    v = None
    
    if pt == Rhino.Geometry.Point3d.Unset:
        u  = geo.Domain(0).Mid
        v = geo.Domain(1).Mid
        pt = geo.PointAt(u,v)
        
    if rc:
        myPlane.Origin = pt
        print  "The surface is planar. CPlane set"
        
    else:
        if u == None and v == None:
            rc, u, v = geo.ClosestPoint(pt)
        srf = geo.UnderlyingSurface()
        get_rc, myPlane = srf.FrameAt(u,v)
        
        print "The surface is not planar. CPlane set to a tangent plane."
        
    rs.ViewCPlane(plane=myPlane)
    
if __name__ == '__main__': CPlaneToSurface()
    

    

-Pascal

1 Like

that’s interesting, took me a second to realize that it uses the pick point for 0. nice touch. i have an issue with polysurfaces for some reason.

Does something like this work for reporting if a face is planar?

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

def CheckFacePlanarity():    
    msg="Select a surface or polysurface face to check planarity"
    srf_filter=Rhino.DocObjects.ObjectType.Surface 
    rc,objref=Rhino.Input.RhinoGet.GetOneObject(msg,False,srf_filter)
    if rc!=Rhino.Commands.Result.Success: return
    
    msg="Surface or polysurface face IS {}planar"
    if not objref.Face().IsPlanar(sc.doc.ModelAbsoluteTolerance):
        print msg.format("NOT ")
    else:
        print msg.format("")
CheckFacePlanarity()

it’s reporting correctly here.

what is that other part of your script doing?

for face in brep.Faces:
    rc, u, v = face.ClosestPoint(pick_pt)
    if rc:
        face_pt = face.PointAt(u, v)
        if face_pt.DistanceTo(pick_pt) < tol:
            if face.IsPointOnFace(
                    u, v) == Rhino.Geometry.PointFaceRelation.Interior:
                rhobj.SelectSubObject(face.ComponentIndex(), True, True,
                                      True)

I think that was just a different way of getting a face out of a polysurface via where the pick point was. But looks like it is not necessary to do it that way.

Hm - is that mine? I do not see that offset here - can you send me your file? You’ve probably had the request answered in 6 different ways so it may not matter but I’m curious as to why the plane is being offset…

-Pascal

yeah, it was yours. here’s the file. i colored just some of the faces that it’s bugging out on. btw, i like how yours places the cplane at the pick point and it also maybe keeps the Z axis out on solids?

side note, i did an Export Selected on this geometry to a new file. i reopened the file and i noticed that the snapshots from the original file are still there even though none of the geometry or layers are still in the file. i don’t know if that’s a bug or by design.bug.3dm (280.3 KB)

Hm Hm… working here as expected… try:

CPlaneToSurface.py (1.2 KB)

-Pascal

still doing it. why would it work there and not here? any settings i may have wrong?

Here’s another one you can try - this one sets the CPlane to the chosen face/surface in the active view. If the face/surface is not planar, nothing is done.

SetCPlaneToPlanarSrf.py (998 Bytes)

nice! is there possibly a way to have the z axis always out when you subselect a surface that part of a solid? hate to be picky, you’ve been so generous. :wink:

Hmm, didn’t consider that, think it might be possible, need to see if the little gray cells are up to the task…

OK, give this one a shot… let me know if it bombs anywhere… :bomb:

SetCPlaneToPlanarSrf-2.py (1.8 KB)

1 Like

beautiful! much thanks!