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?
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.
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
)
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()
@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
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)
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.
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…
SetCPlaneToPlanarSrf-2.py (1.8 KB)
beautiful! much thanks!