# nanoflann: a header-only KD-tree library for C++11 nearest neighbour search

> nanoflann is a C++11 header-only fork of FLANN that builds KD-trees over R2, R3, SO(2) and SO(3) data. It installs by copying one header, and it deliberately does not do approximate search.

**jlblancoc/nanoflann** — nanoflann: a C++11 header-only library for Nearest Neighbor (NN) search with KD-trees

- Repository: https://github.com/jlblancoc/nanoflann
- Stars: 2,689 · Forks: 527
- Language: C++
- License: NOASSERTION
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/jlblancoc-nanoflann

## What nanoflann solves, and who ends up using it

The problem is mundane and recurring: you have a set of points and you need the nearest ones to a query point, fast, without pulling in a build system. nanoflann answers that with a KD-tree. The README describes it as a C++11 header-only library for building KD-Trees of datasets with different topologies: R2, R3 (point clouds), SO(2) and SO(3) (2D and 3D rotation groups). That last pair is the part most KD-tree code does not cover. If your data is rotations rather than coordinates, the tree still works, and the repository ships SO2_adaptor_example.cpp and SO3_adaptor_example.cpp under examples/ to show the adaptor shape.

The audience is narrower than "anyone doing geometry". This is for C++ developers who already have a point container and do not want a dependency graph. Robotics is the obvious home: the README notes the project was born as a child project of MRPT, and the badge table lists nanoflann_vendor packages built for ROS 2 Humble, Jazzy, Kilted, Lyrical and Rolling. If you are outside that world and only need a few hundred lookups, a linear scan is simpler and this library earns nothing.

## The mechanism: one header, an adaptor, and a tree you own

nanoflann is a fork of the flann library by Marius Muja and David G. Lowe. The fork keeps the KD-tree idea and drops the parts that required linking. The README is blunt about the trade: "No support for approximate NN is provided." Every query is exact. That is a design commitment, not an oversight, and it shapes when the library is the right pick.

The integration point is an adaptor. You do not hand nanoflann a std::vector and hope. You expose your data through the interface the tree expects, then construct the tree over that adaptor. The examples directory shows the variations the maintainers support: pointcloud_adaptor_example.cpp for a point cloud, vector_of_vectors_example.cpp for nested vectors, matrix_example.cpp for matrix-backed storage, and KDTreeVectorOfVectorsAdaptor.h as a ready-made adaptor. Two further examples, pointcloud_custom_metric.cpp and pointcloud_custom_resultset.cpp, cover supplying your own distance metric and your own result set, so the search does not have to return into a std::vector if that allocation pattern bothers you.

Because the tree is a template instantiated in your translation unit, there is no shared object and no ABI to match. The cost is compile time and code size, and the README does not discuss either. dynamic_pointcloud_example.cpp exists for the case where points change after the tree is built, which is worth reading before you assume you can rebuild cheaply on every frame.

## Installing nanoflann and running a first radius search

The README gives the fastest route first: clone the repository and take the include/nanoflann.hpp file for use where you need it. On Debian or Ubuntu 21.04 and newer, the packaged route is a single command.

```bash
sudo apt install libnanoflann-dev
```

After that, the header is on the include path and you add one line to your source. The README states that nanoflann does not require compiling or installing, and that you just need to include it.

```cpp
#include <nanoflann.hpp>
```

macOS users have two package managers to choose from. The README lists Homebrew and MacPorts.

```bash
brew install brewsci/science/nanoflann
```

```bash
brew tap brewsci/science
brew install nanoflann
```

```bash
sudo port install nanoflann
```

For a first real use, the repository's examples are the reference. examples/pointcloud_kdd_radius.cpp is the radius-search example, and examples/example_with_cmake/ shows how to build an example against the header with CMake. Build that directory first and read the output before writing your own adaptor.

## Where nanoflann is the wrong tool

The README states that no support for approximate NN is provided. If your dataset is large enough that exact search is too slow, this library has nothing to offer, and the original flann is the place to look. There is no knob to trade recall for speed.

The second constraint is dimensionality. KD-trees degrade as dimensions grow, and nothing in the README claims otherwise. The documented topologies are R2, R3, SO(2) and SO(3). If you are matching high-dimensional descriptors, the tree structure works against you and a different index type is the honest answer.

Third, there is no GPU path. The related searches include "nanoflann gpu", and the material contains no GPU support at all. Anyone arriving with that expectation should stop here.

Finally, there is no Python binding. "nanoflann python" is a common search, but this repository is C++ with a header you include. A Python user needs a separate binding project, not this one.

## nanoflann compared with the flann it forked from

The comparison that matters is the one the README makes itself. nanoflann is a fork of flann, and the split is about scope. flann is a library you build and link, with multiple index types and approximate search. nanoflann is a single header with KD-trees and exact search.

That difference decides the choice. If you need approximate nearest neighbours, multiple index families, or a prebuilt library with a stable ABI, use flann. If you need to drop a header into an existing CMake target and get exact lookups over points or rotations without adding a link dependency, nanoflann is the smaller commitment. The examples/example_with_cmake/ and examples/example_with_pkgconfig/ directories show both consumption styles, so you can see what each costs before committing.

The ROS 2 packaging is a second, quieter signal. nanoflann_vendor packages are built and released for five ROS 2 distributions, which means a robotics team can depend on nanoflann through the package manager rather than vendoring the header by hand.

## Maintenance, licence and the cost of upgrading

The repository is not archived. The last push was on 2026-09-18, ten days before this writing, and the most recent release, 1.13.0, was tagged on 2026-09-17. The two before it, 1.12.1 and 1.12.0, landed on 2026-08-08 and 2026-08-06. That is a steady cadence across recent months, and the CI badges cover Linux, clang-format checks, CircleCI, Windows via AppVeyor and code coverage.

Upgrade cost is low by construction. There is no library to relink and no soname to track, so adopting a new release means replacing one header. The real work is reading CHANGELOG.rst, which the README points to for the list of project changes, and recompiling. Template code surfaces breakage at compile time rather than at runtime, which is the better failure mode here.

On licensing, the README says nanoflann follows the original license terms and is distributed under the BSD license. The repository's licence file is named COPYING, and the GitHub licence field reports NOASSERTION, meaning the automated classifier did not match it to a standard identifier. That mismatch is worth resolving yourself before you ship binaries. This is not legal advice; read COPYING and decide.

## Conclusion

Adopt nanoflann when you need exact nearest neighbour or radius search over points or rotations in C++11 and want no build step beyond one include. Skip it if you need approximate search, GPU execution, or a Python API, because the README states none of those exist here. Before wiring it into a product, open include/nanoflann.hpp and confirm the BSD terms in COPYING match how you redistribute binaries, then check CHANGELOG.rst for the 1.13.0 changes that landed on 2026-09-17.

## FAQ

### What is a k-d tree?

It is the spatial index nanoflann builds over your data. The README describes nanoflann as a library for building KD-Trees of datasets with different topologies, including R2, R3, SO(2) and SO(3).

### How do I install nanoflann on Ubuntu?

On Debian or Ubuntu 21.04 and newer the README gives sudo apt install libnanoflann-dev. The alternative it lists first is cloning the repository and taking include/nanoflann.hpp directly.

### Does nanoflann support approximate nearest neighbour search?

No. The README states plainly that no support for approximate NN is provided, so every query is exact. If you need approximate search, the flann library it forked from is the relevant project.

### What licence is nanoflann released under?

The README says nanoflann follows the original license terms and is distributed under the BSD license. The repository's licence file is named COPYING, and the GitHub licence field reports NOASSERTION rather than a standard identifier.

### Does nanoflann have a GPU or Python version?

The material describes only a C++11 header-only library, with no GPU support and no Python binding mentioned. The documented topologies are R2, R3, SO(2) and SO(3).

## Sources

- [Issues](https://github.com/jlblancoc/nanoflann/issues)
- [jlblancoc/nanoflann on GitHub](https://github.com/jlblancoc/nanoflann)
- [README](https://github.com/jlblancoc/nanoflann/blob/master/README.md)
- [Releases](https://github.com/jlblancoc/nanoflann/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jlblancoc-nanoflann
