Skip to main content

rtree.c

An R-tree implementation in C.

Cities

Features

  • Supports any number of dimensions
  • Generic interface with support for variable sized items
  • ANSI C (C99)
  • Supports custom allocators
  • Robust, self-contained tests
  • Pretty darn good performance 🚀

Example

#include <stdio.h>
#include <string.h>
#include <math.h>
#include "rtree.h"

struct city {
    char *name;
    double lat;
    double lon;
};

struct city phx = { .name = "Phoenix", .lat = 33.448, .lon = -112.073 };
struct city enn = { .name = "Ennis", .lat = 52.843, .lon = -8.986 };
struct city pra = { .name = "Prague", .lat = 50.088, .lon = -14.420 };
struct city tai = { .name = "Taipei", .lat = 25.033, .lon = 121.565 };
struct city her = { .name = "Hermosillo", .lat = 29.102, .lon = -110.977 };
struct city him = { .name = "Himeji", .lat = 34.816, .lon = 134.700 };

bool city_iter(const double *rect, const void *item, void *udata) {
    const struct city *city = item;
    printf("%s\n", city->name);
    return true;
}

int main() {
    // create a new rtree where each item is a `struct city*`. 
    struct rtree *tr = rtree_new(sizeof(struct city*), 2);

    // load some cities into the rtree. Each set operation performs a copy of 
    // the data that is pointed to in the second and third arguments. 
    // The R-tree expects a rectangle, which is an array of doubles, that
    // has the first N values as the minimum corner of the rect, and the next
    // N values as the maximum corner of the rect, where N is the number of
    // dimensions provided to rtree_new(). For points the the min and max
    // values should match.
    rtree_insert(tr, (double[]){ phx.lon, phx.lat, phx.lon, phx.lat }, &phx);
    rtree_insert(tr, (double[]){ enn.lon, enn.lat, enn.lon, enn.lat }, &enn);
    rtree_insert(tr, (double[]){ pra.lon, pra.lat, pra.lon, pra.lat }, &pra);
    rtree_insert(tr, (double[]){ tai.lon, tai.lat, tai.lon, tai.lat }, &tai);
    rtree_insert(tr, (double[]){ her.lon, her.lat, her.lon, her.lat }, &her);
    rtree_insert(tr, (double[]){ him.lon, him.lat, him.lon, him.lat }, &him);
    
    printf("\n-- Northwestern cities --\n");
    rtree_search(tr, (double[]){ -180, 0, 0, 90 }, city_iter, NULL);

    printf("\n-- Northeastern cities --\n");
    rtree_search(tr, (double[]){ 0, 0, 180, 90 }, city_iter, NULL);

    // deleting an item is the same inserting
    rtree_delete(tr, (double[]){ phx.lon, phx.lat, phx.lon, phx.lat }, &phx);

    printf("\n-- Northwestern cities --\n");
    rtree_search(tr, (double[]){ -180, 0, 0, 90 }, city_iter, NULL);

    rtree_free(tr);

}
// output:
// -- northwest cities --
// Phoenix
// Ennis
// Prague
// Hermosillo
// 
// -- northeast cities --
// Taipei
// Himeji
// 
// -- northwest cities --
// Ennis
// Prague
// Hermosillo

Functions

rtree_new      # allocate a new rtree
rtree_free     # free the rtree
rtree_count    # return number of items
rtree_insert   # insert an item
rtree_delete   # delete an item
rtree_search   # search the rtree

Algorithms

This implementation is a variant of the original paper:
R-TREES. A DYNAMIC INDEX STRUCTURE FOR SPATIAL SEARCHING

Testing and benchmarks

The rtree.c file also contains robust testing and benchmark code.

$ cc -DRTREE_TEST rtree.c && ./a.out              # run tests
$ cc -DRTREE_TEST -O3 rtree.c && BENCH=1 ./a.out  # run benchmarks

The following benchmarks were run on my 2019 Macbook Pro (2.4 GHz 8-Core Intel Core i9) using gcc-9. One million random (evenly distributed) rectangles are inserted, searched, and deleted.

insert   1000000 ops in 0.406 secs, 406 ns/op, 2462496 op/sec
search   1000000 ops in 0.936 secs, 936 ns/op, 1068225 op/sec
delete   1000000 ops in 0.901 secs, 901 ns/op, 1109395 op/sec

License

rtree.c source code is available under the MIT License.

Metadata

Release files for rtreecpy 1.0.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rtreecpy 1.0.5
File Size Uploaded Provenance Actions
rtreecpy-1.0.5.tar.gz 16.3 kB Without provenance Details for rtreecpy-1.0.5.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for rtreecpy 1.0.5
File Interpreter ABI Platform Actions
rtreecpy-1.0.5-cp38-cp38-macosx_10_9_x86_64.whl CPython 3.8 CPython 3.8 macOS 10.9+ x86-64 Details for rtreecpy-1.0.5-cp38-cp38-macosx_10_9_x86_64.whl

Total release size: 35.5 kB

Release files / rtreecpy-1.0.5.tar.gz

Download URL rtreecpy-1.0.5.tar.gz
Size 16.3 kB
Tags Source
SHA-256 checksum
How to use checksums
238085f2147c302ea3e240ce9e0a1a095fa3e29b4e582375f83e20e38652dd08
BLAKE2b-256 checksum
How to use checksums
4309a7f7eb3ed0b81bbcb15afd155081794b8376aab2761b04a11ea0149d3968
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.8.0 pkginfo/1.8.2 readme-renderer/33.0 requests/2.26.0 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.8.1 keyring/23.5.0 rfc3986/1.5.0 colorama/0.4.4 CPython/3.8.10

Release files / rtreecpy-1.0.5-cp38-cp38-macosx_10_9_x86_64.whl

Download URL rtreecpy-1.0.5-cp38-cp38-macosx_10_9_x86_64.whl
Size 19.2 kB
Tags CPython 3.8 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
b2cc051f0e45548fee6ec540a477e97df4995de7f4d3d0db7f94112937b01c9b
BLAKE2b-256 checksum
How to use checksums
d14be9be10ada50918241ffb83c35b4c749962ddff2e7e11792de641001054a2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.8.0 pkginfo/1.8.2 readme-renderer/33.0 requests/2.26.0 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.8.1 keyring/23.5.0 rfc3986/1.5.0 colorama/0.4.4 CPython/3.8.10

Security for rtreecpy 1.0.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page