Point-On-BRep selection

Hi Everyone -
Trying to write a plugin (C#) which performs analysis on a point on a surface selected by the user. I’d like to use all possible surface types - surface (untrimmed=surface, trimmed=brep), polysurface (brep with multiple faces), extrusion (converted to brep with multiple faces), and so on (coming later since they’re so different: mesh (mesh faces), groups, blocks, etc…). Anyways starting with surface and brep.

Here’s where I start: (with a little editing, hopefully nothing is missing)

                 ObjRef initSrf = null;
                 doc.Objects.UnselectAll();
                 GetObject selectObjs = new GetObject();
                 selectObjs.SetCommandPrompt("Select Surface");
             ObjectType geoFilter = ObjectType.Surface | 
                 //ObjectType.PolysrfFilter |
                 ObjectType.Mesh |
                 ObjectType.Brep |
                 ObjectType.Extrusion |
                 ObjectType.SubD;
                 selectObjs.GeometryFilter = geoFilter;
                 selectObjs.Get();
                 if (selectObjs.CommandResult() != Result.Success) return selectObjs.CommandResult();
                 RhinoApp.WriteLine("G " + selectObjs.Object(0).Object().ToString());
                 initSrf = selectObjs.Object(0);
             GetPoint bouncePoint = new GetPoint();
             bouncePoint.SetCommandPrompt("Pick the point on the surface");
             switch (initSrf.Object().ObjectType)
             {
                 case ObjectType.Brep:
                 case ObjectType.Surface:
                     RhinoApp.WriteLine("# of faces: {0}",initSrf.Brep().Faces.Count);
                     bouncePoint.Constrain(initSrf.Brep(), -1, -1, false);
                     break;
                 case ObjectType.Extrusion:
                     Extrusion extru = initSrf.Object().Geometry as Extrusion;
                     newbrep = extru.ToBrep();
                     RhinoApp.WriteLine("# of extrusion faces: {0}", newbrep.Faces.Count);
                     bouncePoint.Constrain(newbrep, -1, -1, false);
                     break;
             }
             bouncePoint.Get();
             if (bouncePoint.CommandResult() != Result.Success) return bouncePoint.CommandResult();
             Point3d srfPoint = bouncePoint.Point();
             double[] firstPoint = new double[2];
             Vector3d firstNormal = new Vector3d();
             switch (initSrf.Object().ObjectType)
             {
                 case ObjectType.Brep:
                     BrepFace face = bouncePoint.PointOnBrep(out firstPoint[0], out firstPoint[1]);
 
                     if (face == null)
                     {
                         RhinoApp.WriteLine("face is null?");
                     }
                     RhinoApp.WriteLine("U = {0}, V = {1}", firstPoint[0], firstPoint[1]);
                     RhinoApp.WriteLine("brep face " + face.ToString());
                     firstNormal = face.NormalAt(firstPoint[0], firstPoint[1]);
                     if (face.OrientationIsReversed) firstNormal.Reverse();
                     firstRotate = Transform.Rotation(Math.PI, firstNormal, srfPoint);
                     doc.Objects.Transform(firstRay, firstRotate, false);
                     doc.Views.Redraw();
                     break;
                 case ObjectType.Mesh:
                     Dialogs.ShowMessage("Mesh not working yet", "no mesh");
                     return Result.Failure;
             }
 
             return Result.Success;
         }
     }

The problem seems to be that bouncePoint.PointOnBrep(out u, out v); always returns null. I get the u and v parameters of the surface I just don’t know which brep face’s parameters are being returned.

I can start the switch another way, which is successful for a single, untrimmed (i.e. pure) surface (which is still shown as a brep, not a surface in the RhinoApp.WriteLine ("G " + selectObjs.Object(0).Object().ToString()); output):

            switch (initSrf.Object().ObjectType)
            {
                case ObjectType.Brep:
                    BrepFace face = initSrf.Face();
                    bouncePoint.PointOnBrep(out firstPoint[0], out firstPoint[1]);

I might be able to boil this down to one item: under what condition does GetPoint.PointOnBrep return the BrepFace? (searching for “PointOnBrep” has precious few returns, maybe no-one is using it?)

If there’s other, better ways to work with polysurface component pieces (and later, meshes), I’m open to suggestions. Thanks.

Hi @Daniel_Beckmann,

From the documentation for PointOnBrep() it looks there is no way to get out which face the point was on.

Maybe try using Brep.ClosestPoint() instead, see: https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Brep_ClosestPoint_1.htm

For the overhead of one additional method call, you get back a ComponentIndex which you can query for the *Face Index, see https://developer.rhino3d.com/api/RhinoCommon/html/P_Rhino_Geometry_ComponentIndex_Index.htm

Thanks, @lando.schumpich.

I thought the documentation for PointOnBrep said that the face was returned, were you looking at a different document?

Parameters

u

Type: System.Double
If the point was on a Brep face, then the u parameter.

v

Type: System.Double
If the point was on a Brep face, then the v parameter.

Return Value

Type: BrepFace
The Brep face or null if the point was not on a Brep face.

I’ve been thinking about ClosestPoint() too, fortunately it returns the normal as you pointed out, saving a couple of method calls; maybe I won’t need the ComponentIndex.

Hi @Daniel_Beckmann,

You are right, i misread the documentation.

I did some small tests and see the same behaviour with PointOnBrep() always returning None for the FaceIndex.

@dale, can you take a look? here is my minimal example, maybe we are both missing something obvious here…:

import Rhino
import scriptcontext as sc

def testGetPointOnBrep():
    
    result, objRef = Rhino.Input.RhinoGet.GetOneObject("Pick polysurface", False, Rhino.DocObjects.ObjectType.Brep)
    if result != Rhino.Commands.Result.Success:
        return result
        
    picked = objRef.Brep()
    if not picked: return
    
    gp = Rhino.Input.Custom.GetPoint()
    gp.SetCommandPrompt("Pick Point")
    gp.Constrain(picked, -1, -1, False)
    
    gp.Get()
    
    if gp.CommandResult() != Rhino.Commands.Result.Success:
        return gp.CommandResult()
        
    print gp.PointOnBrep()
    
if __name__ == "__main__":
    testGetPointOnBrep()

Hi @lando.schumpich,

Yes, I see this. I’ve logged the issue:

https://mcneel.myjetbrains.com/youtrack/issue/RH-57874

As a work around, use the point returned by GetPoint as the argument to Brep.ClosestPoint.

Thanks,

– Dale

2 Likes

Hi @dale - thanks for looking into it
Dan

Hi.
Four years have passed, and this issue still seems to persist. GetPoint.PointOnSurface, OnBrep, OnCurve, and OnObject are still returning null.
Are there any alternative solutions?

I’ve mentioned an alternative above.

As some point, the methods in question will be deprecated and replaced with something better suited for .NET.

– Dale

Hi,dale.
I see it, and that’s what I’m doing now. I just want to understand in what circumstances the PointOnBrep method will be effective, or if these methods will not be fixed, can they be marked as obsolete ?