Click or drag to resize

RTreeSearch Method (Sphere, EventHandlerRTreeEventArgs, Object)

Searches for items in a sphere.

Namespace:  Rhino.Geometry
Assembly:  RhinoCommon (in RhinoCommon.dll)
Since: 5.0
Syntax
public bool Search(
	Sphere sphere,
	EventHandler<RTreeEventArgs> callback,
	Object tag
)

Parameters

sphere
Type: Rhino.GeometrySphere
bounds used for searching.
callback
Type: SystemEventHandlerRTreeEventArgs
An event handler to be raised when items are found.
tag
Type: SystemObject
State to be passed inside the RTreeEventArgs Tag property.

Return Value

Type: Boolean
true if entire tree was searched. It is possible no results were found.
Remarks
Do not modify the tree while a Search() is in progress. Doing so can have unintended consequences, including corruption and crashes.If you need to modify the tree, collect the results during the search and modify the tree once the search is completed.
Examples
using Rhino;
using Rhino.Geometry;

namespace examples_cs
{
  [System.Runtime.InteropServices.Guid("0E82E6DA-5335-453A-AC94-2499BBBCBE55")]
  public class RTreeClosestPoint : Rhino.Commands.Command
  {
    public override string EnglishName { get { return "cs_RtreeClosestPoint"; } }

    void SearchCallback(object sender, RTreeEventArgs e)
    {
      SearchData data = e.Tag as SearchData;
      if (data == null)
        return;
      data.HitCount = data.HitCount + 1;
      Point3f vertex = data.Mesh.Vertices[e.Id];
      double distance = data.Point.DistanceTo(vertex);
      if (data.Index == -1 || data.Distance > distance)
      {
        // shrink the sphere to help improve the test
        e.SearchSphere = new Sphere(data.Point, distance);
        data.Index = e.Id;
        data.Distance = distance;
      }
    }

    class SearchData
    {
      public SearchData(Mesh mesh, Point3d point)
      {
        Point = point;
        Mesh = mesh;
        HitCount = 0;
        Index = -1;
        Distance = 0;
      }

      public int HitCount { get; set; }
      public Point3d Point { get; private set; }
      public Mesh Mesh { get; private set; }
      public int Index { get; set; }
      public double Distance { get; set; }
    }

    protected override Rhino.Commands.Result RunCommand(RhinoDoc doc, Rhino.Commands.RunMode mode)
    {
      Rhino.DocObjects.ObjRef objref;
      var rc = Rhino.Input.RhinoGet.GetOneObject("select mesh", false, Rhino.DocObjects.ObjectType.Mesh, out objref);
      if (rc != Rhino.Commands.Result.Success)
        return rc;

      Mesh mesh = objref.Mesh();
      objref.Object().Select(false);
      doc.Views.Redraw();

      using (RTree tree = new RTree())
      {
        for (int i = 0; i < mesh.Vertices.Count; i++)
        {
          // we can make a C++ function that just builds an rtree from the
          // vertices in one quick shot, but for now...
          tree.Insert(mesh.Vertices[i], i);
        }

        while (true)
        {
          Point3d point;
          rc = Rhino.Input.RhinoGet.GetPoint("test point", false, out point);
          if (rc != Rhino.Commands.Result.Success)
            break;

          SearchData data = new SearchData(mesh, point);
          // Use the first vertex in the mesh to define a start sphere
          double distance = point.DistanceTo(mesh.Vertices[0]);
          Sphere sphere = new Sphere(point, distance * 1.1);
          if (tree.Search(sphere, SearchCallback, data))
          {
            doc.Objects.AddPoint(mesh.Vertices[data.Index]);
            doc.Views.Redraw();
            RhinoApp.WriteLine("Found point in {0} tests", data.HitCount);
          }
        }
      }
      return Rhino.Commands.Result.Success;
    }
  }
}
Python
import Rhino
import rhinoscriptsyntax as rs

# data passed to the RTree's SearchCallback function that
# we can use for recording what is going on
class SearchData:
    def __init__(self, mesh, point):
        self.HitCount = 0
        self.Mesh = mesh
        self.Point = point
        self.Index = -1
        self.Distance = 0


def SearchCallback(sender, e):
    data = e.Tag
    data.HitCount += 1
    vertex = data.Mesh.Vertices[e.Id]
    distance = data.Point.DistanceTo(vertex)
    if data.Index == -1 or data.Distance > distance:
        # shrink the sphere to help improve the test
        e.SearchSphere = Rhino.Geometry.Sphere(data.Point, distance)
        data.Index = e.Id
        data.Distance = distance

def RunSearch():
    id = rs.GetObject("select mesh", rs.filter.mesh)
    mesh = rs.coercemesh(id)
    if mesh:
        rs.UnselectObject(id)
        tree = Rhino.Geometry.RTree()
        # I can add a RhinoCommon function that just builds an rtree from the
        # vertices in one quick shot, but for now...
        for i,vertex in enumerate(mesh.Vertices): tree.Insert(vertex, i)

        while(True):
            point = rs.GetPoint("test point")
            if not point: break

            data = SearchData(mesh, point)
            # Use the first vertex in the mesh to define a start sphere
            distance = point.DistanceTo(mesh.Vertices[0])
            sphere = Rhino.Geometry.Sphere(point, distance * 1.1)
            if tree.Search(sphere, SearchCallback, data):
                rs.AddPoint(mesh.Vertices[data.Index])
                print "Found point in {0} tests".format(data.HitCount)

if __name__=="__main__":
    RunSearch()
See Also