Pick a point on a mesh by click

Code

I have this code to pick a point on a specific mesh object:


        public static Point3d? GetPointOnMesh(RhinoObject obj, String message = "Select a point on mesh")
        {
            // Validate input
            if (obj == null || obj.ObjectType != ObjectType.Mesh)
            {
                RhinoApp.WriteLine("Invalid mesh object.");
                return null;
            }

            Mesh mesh = obj.Geometry as Mesh;
            if (mesh == null)
            {
                RhinoApp.WriteLine("Invalid mesh object.");
                return null;
            }

            GetObject go = new GetObject();
            go.SetCommandPrompt(message);
            go.GeometryFilter = ObjectType.MeshVertex;
            go.AcceptNothing(true);
            go.Get();

            if (go.CommandResult() != Result.Success)
                return null;

            if (go.ObjectCount == 1)
            {
                var objClicked = go.Object(0).Object();
                if (objClicked.Id != obj.Id)
                {
                    RhinoApp.WriteLine("Clicked mesh is not the same mesh you clicked before.");
                    return null;
                }

                var pickedPoint = go.Point();
                if (pickedPoint != null)
                {
                    RhinoApp.WriteLine("Picked point: {0}", pickedPoint);
                    return pickedPoint;
                }
                else
                {
                    RhinoApp.WriteLine("Failed to get a point on the mesh.");
                    return null;
                }
            }
            else
            {
                RhinoApp.WriteLine("Failed to get a point on the mesh.");
                return null;
            }
        }

I’m calling the method like this:


            Point3d? point = Helper.GetPointOnMesh(inObj);
            if (point.HasValue)
            {
                RhinoApp.WriteLine("Selected point: {0}", point.Value);
            }

Question

The code works fine bu the picked point is too large:

Picked point: -1.23432101234321E+308,-1.23432101234321E+308,-1.23432101234321E+308

Selected point: -1.23432101234321E+308,-1.23432101234321E+308,-1.23432101234321E+308

I cannot figure out what I’m missing :roll_eyes:

Too far from origin?

I double-checked. The object is close to the origin:

Setting go.AcceptNothing(true); to false didn’t help.

this is a unset value

public const double UnsetValue = -1.23432101234321e+308

see
https://developer.rhino3d.com/api/rhinocommon/rhino.rhinomath/unsetvalue

check the result you get from
GetResult result = go.Get();
it should be
GetResult.Point
You can also / additionally check for Point3d.Unset, instead of checking for null

1 Like

I logged the result by:

GetResult getResult = go.Get();
RhinoApp.WriteLine("Get result: {0}", getResult);
RhinoApp.WriteLine("Get result type: {0}", getResult.GetType());
RhinoApp.WriteLine("Picked point: {0}", pickedPoint);

The logs are:

Get result: Object
Get result type: Rhino.Input.GetResult
Picked point: -1.23432101234321E+308,-1.23432101234321E+308,-1.23432101234321E+308

2023-08-26 23_17_46-

as a starting Point to get your script running

then it should be quite straight forward to implement

Boolean Constrain(
    Mesh mesh, 
    Boolean allowPickingPointOffObject
)

see documentation here

hope this helps - kind regards - tom

1 Like

You were right. The implementation is now done:


        public static Point3d? GetPointOnMesh(RhinoObject obj, String message = "Select a point on mesh")
        {
            // Validate input
            if (obj == null || obj.ObjectType != ObjectType.Mesh)
            {
                RhinoApp.WriteLine("Invalid mesh object.");
                return null;
            }

            Mesh mesh = obj.Geometry as Mesh;
            if (mesh == null)
            {
                RhinoApp.WriteLine("Invalid mesh object.");
                return null;
            }

            GetPoint gp = new GetPoint();
            gp.SetCommandPrompt(message);
            gp.Constrain(mesh, false);
            gp.Get();

            if (gp.CommandResult() != Result.Success)
                return null;

            var pickedPoint = gp.Point();
            if (pickedPoint == null || pickedPoint == Point3d.Unset)
            {
                RhinoApp.WriteLine("Couldn't get a point on mesh.");
                return null;
            }

            RhinoApp.WriteLine("Picked point: {0}", pickedPoint);
            return pickedPoint;
        }

Test

It works fine:

Pick multiple points on mesh

Here is the code to pick multiple points on a mesh:


        public static List<Point3d> GetPointOnMesh(RhinoObject obj, String message = "Select points on mesh (Esc to cancel)")
        {
            // Validate input
            if (obj == null || obj.ObjectType != ObjectType.Mesh)
            {
                RhinoApp.WriteLine("Invalid mesh object.");
                return null;
            }

            Mesh mesh = obj.Geometry as Mesh;
            if (mesh == null)
            {
                RhinoApp.WriteLine("Invalid mesh object.");
                return null;
            }

            List<Point3d> points = new List<Point3d>();

            while (true)
            {
                GetPoint gp = new GetPoint();
                gp.SetCommandPrompt(message);
                gp.Constrain(mesh, false);
                gp.Get();

                if (gp.CommandResult() != Result.Success)
                    break; // User cancelled.

                var pickedPoint = gp.Point();
                if (pickedPoint == null || pickedPoint == Point3d.Unset)
                {
                    RhinoApp.WriteLine("Couldn't get a point on mesh.");
                    continue;
                }

                RhinoApp.WriteLine("Picked point: {0}", pickedPoint);
                points.Add(pickedPoint);
            }

            return points;
        }

It can be called like this:


            List<Point3d> points = Helper.GetPointOnMesh(inObj);
            if (points == null || points.Count < 1)
            {
                RhinoApp.WriteLine("No points are selected");
                return Result.Failure;
            }

            RhinoApp.WriteLine("Selected points count: {0}", points.Count);

Test

It works just fine: