The code to use an R-Tree is below. The idea is that you have your point cloud, and you create a transformed R-tree that transforms the plane youâ€™re interested in into the world-XY plane.

Then you can use a BoundingBox query on the R-Tree that is the world-XY plane + tolerance.

The performance on 1.2 million points is as follows. As you can see, the most time is spent in creating the R-tree and the subsequent spatial query is very low.

```
Created a pointcloud with 1200000 points in 138 ms
Created an R-tree spatial search structure with 1200000 points in 2830 ms
Queried 1200000 and found 13495 points on the plane in 6 ms
```

Having said that, it is probably not faster than your implementation, because that scales linearly with the number of points, not quadratically as I assumed when I first read your post.

```
protected override Result RunCommand([NotNull] RhinoDoc doc, RunMode mode)
{
int nPoints = 10000;
var res = RhinoGet.GetInteger("Give number of points", true, ref nPoints, 1, Int32.MaxValue);
if (res != Result.Success)
return res;
// get a random plane with origin in the center of the unit cube
Random r = new Random();
var n = new Vector3d(r.NextDouble(), r.NextDouble(), r.NextDouble());
n.Unitize();
Plane p = new Plane(new Point3d(.5, .5, .5), n);
// get the transform to XY-plane
Transform p2p = Transform.PlaneToPlane(p, Plane.WorldXY);
// create the point cloud and an R-tree that
// has the same points but transformed such that the query
// plane is the XY plane.
var sw = Stopwatch.StartNew();
PointCloud pc = new PointCloud();
RTree rtree = new RTree();
BoundingBox pcBB = BoundingBox.Empty;
for (int i = 0; i < nPoints; ++i)
{
var pt = new Point3d(r.NextDouble(), r.NextDouble(), r.NextDouble());
pc.Add(pt);
}
sw.Stop();
RhinoApp.WriteLine($"Created a pointcloud with {nPoints} points in {sw.ElapsedMilliseconds} ms");
sw = Stopwatch.StartNew();
for (int i = 0; i < nPoints; ++i)
{
var pt = pc.PointAt(i);
pt.Transform(p2p);
rtree.Insert(pt, i);
pcBB.Union(pt);
}
sw.Stop();
RhinoApp.WriteLine($"Created an R-tree spatial search structure with {nPoints} points in {sw.ElapsedMilliseconds} ms");
// reduce the height of the transformed bounding box
// to the search tolerance
const double tolerance = 1e-2;
Point3d min = pcBB.Min;
min.Z = -tolerance / 2;
Point3d max = pcBB.Max;
max.Z = +tolerance / 2;
pcBB.Min = min;
pcBB.Max = max;
sw = Stopwatch.StartNew();
// query the RTree and store the results
Point3dList found = new Point3dList();
rtree.Search(pcBB, (o, a) =>
{
found.Add(pc.PointAt(a.Id));
});
sw.Stop();
RhinoApp.WriteLine($"Queried {nPoints} and found {found.Count} points on the plane in {sw.ElapsedMilliseconds} ms.");
// add the pointcloud and the points on the plane
// to the document
doc.Objects.AddPointCloud(pc);
doc.Objects.AddPoints(found);
return Result.Success;
}
```