Skip to main content

Python implementation of Priority R-Tree

Project description

python_prtree

python_prtree is a python/c++ implementation of the Priority R-Tree (see references below). The supported futures are as follows:

  • Construct a Priority R-Tree (PRTree) from an array of rectangles
    • The array shape is (xmin, ymin, xmax, ymax) in 2D and (xmin, ymin, zmin, xmax, ymax, zmax) in 3D.
    • 3D PRTree is supported since >=0.4.0.
    • Changed the ordering of the array shape since >=0.5.0.
  • query and batch_query with rectangle(s)
    • Supports Point query with (x, y) in 2D and (x, y, z) in 3D since >=0.5.1
  • insert and erase (but not yet optimized)
    • Fixed a bug that one cannot insert to an empty PRTree at 0.5.0.
  • rebuild with already given data since >=0.5.0.
    • For better performance when too many insert/erase operations are called since.
  • The insert and query methods can now be passed pickable Python objects instead of int64 indexes since >=0.5.2.
    • See the example below for more details.

This package is mainly for mostly static situations where insertion and deletion events rarely occur (e.g. map matching).

Installation

You can install python_prtree with the pip command:

pip install python-prtree

If the pip installation does not work (e.g. on an M1 Mac), please git clone clone and install as follows:

pip install -U cmake pybind11
git clone --recursive https://github.com/atksh/python_prtree
cd python_prtree
python setup.py install

A Simple Example

import numpy as np
from python_prtree import PRTree2D

idxes = np.array([1, 2])  # must be unique because it uses idx as key for hash map
rects = np.array([[0.0, 0.0, 1.0, 0.5],
                  [1.0, 1.5, 1.2, 3.0]])  # (xmin, ymin, xmax, ymax)

prtree = PRTree2D(idxes, rects)  # initial construction

q = np.array([[0.5, 0.2, 0.6, 0.3],
              [0.8, 0.5, 1.5, 3.5]])
result = prtree.batch_query(q)
print(result)
# [[1], [1, 2]]

# You can insert an additional rectangle,
prtree.insert(3, np.array([1.0, 1.0, 2.0, 2.0]))
q = np.array([[0.5, 0.2, 0.6, 0.3],
              [0.8, 0.5, 1.5, 3.5]])
result = prtree.batch_query(q)
print(result)
# [[1], [1, 2, 3]]

# And erase by index.
prtree.erase(2)
result = prtree.batch_query(q)
print(result)
# [[1], [1, 3]]

# Point query
print(prtree.query(0.5, 0.5))
# [1]
print(prtree.query((0.5, 0.5)))
# [1]

New Features and Changes

python-prtree>=0.5.3

  • Add gzip compression for pickled objects.

python-prtree>=0.5.2

You can use pickable Python objects instead of int64 indexes for insert and query methods:

import numpy as np
from python_prtree import PRTree2D

objs = [{"name": "foo"}, (1, 2, 3)]  # must NOT be unique but pickable
rects = np.array([[0.0, 0.0, 1.0, 0.5],
                  [1.0, 1.5, 1.2, 3.0]])  # (xmin, ymin, xmax, ymax)

prtree = PRTree2D()
for obj, rect in zip(objs, rects):
    # keyword argments: bb(bounding box) and obj(object)
    prtree.insert(bb=rect, obj=obj)

# returns indexes genereted by incremental rule.
result = prtree.query((0, 0, 1, 1))
print(result)
# [1]

# returns objects when you specify the keyword argment return_obj=True
result = prtree.query((0, 0, 1, 1), return_obj=True)
print(result)
# [{'name': 'foo'}]

python-prtree>=0.5.0

  • [CRUTIAL] Changed the input order from (xmin, xmax, ymin, ymax, ...) to (xmin, ymin, xmax, ymax, ...).
  • [FEATURE] Added rebuild method to build the PRTree from scratch using the already given data.
  • [BUGFIX] Fixed a bug that prevented insertion into an empty PRTree.
  • [REMIND] Cross-version saving and loading compatibility is not guaranteed.

python-prtree>=0.4.0

You can use PRTree3D:

import numpy as np
from python_prtree import PRTree3D

idxes = np.array([1, 2])  # must be unique because it uses idx as key for hash map
rects = np.array([[0.0, 0.5, 0.0, 0.5, 1.0, 0.5],
                  [1.0, 1.5, 2.0, 1.2, 2.5, 3.0]])  # (xmin, ymin, zmin, xmax, ymax, zmax)

prtree = PRTree3D(idxes, rects)  # initial construction

q = np.array([[0.5, 0.2, 0.2, 0.6, 0.3, 0.3],
              [0.8, 0.5, 0.5, 1.5, 3.5, 3.5]])
result = prtree.batch_query(q)
print(result)
# [[], [2]]

python-prtree>=0.3.0

You can save and load a binary file as follows:

# save
prtree.save('tree.bin')


# load with binary file
prtree = PRTree('tree.bin')

# or defered load
prtree = PRTree()
prtree.load('tree.bin')

Cross-version compatibility is NOT guaranteed, so please reconstruct your tree when you update this package.

Note

The 1d-array batch query will be implicitly treated as a batch with size = 1. If you want 1d result, please use query method.

result = prtree.query(q[0])
print(result)
# [1]

result = prtree.batch_query(q[0])
print(result)
# [[1]]

You can also erase(delete) by index and insert a new one.

prtree.erase(1)  # delete the rectangle with idx=1 from the PRTree

prtree.insert(3, np.array([0.3, 0.5, 0.1, 0.2]))  # add a new rectangle to the PRTree

Performance

Construction

2d

2d_fig1

3d

3d_fig1

Query and batch query

2d

2d_fig2

3d

3d_fig2

Delete and insert

2d

2d_fig3

3d

3d_fig3

Requirement

  • numpy

NOTE

  • C++ implements this PRTree with Pybind11 and much faster than the numba implementation of PRTree.
  • If you can use C++, you should use boost::geometry (I did not know it and sadly made this package).
  • Please note that insert / erase operations are not optimized compared to ordinary r-tree. Plus, this implementation does not exactly follow that of the paper due to my technical skills.

Reference

The Priority R-Tree: A Practically Efficient and Worst-Case Optimal R-Tree Lars Arge, Mark de Berg, Herman Haverkort, and Ke Yi Proceedings of the 2004 ACM SIGMOD International Conference on Management of Data (SIGMOD '04), Paris, France, June 2004, 347-358. Journal version in ACM Transactions on Algorithms. author's page

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_prtree-0.5.5.tar.gz (2.2 MB view hashes)

Uploaded Source

Built Distributions

python_prtree-0.5.5-cp39-cp39-win_amd64.whl (130.1 kB view hashes)

Uploaded CPython 3.9 Windows x86-64

python_prtree-0.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (182.2 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

python_prtree-0.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (166.3 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

python_prtree-0.5.5-cp39-cp39-macosx_10_15_x86_64.whl (162.3 kB view hashes)

Uploaded CPython 3.9 macOS 10.15+ x86-64

python_prtree-0.5.5-cp38-cp38-win_amd64.whl (132.7 kB view hashes)

Uploaded CPython 3.8 Windows x86-64

python_prtree-0.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (182.2 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

python_prtree-0.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (166.2 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

python_prtree-0.5.5-cp38-cp38-macosx_10_15_x86_64.whl (162.2 kB view hashes)

Uploaded CPython 3.8 macOS 10.15+ x86-64

python_prtree-0.5.5-cp37-cp37m-win_amd64.whl (131.8 kB view hashes)

Uploaded CPython 3.7m Windows x86-64

python_prtree-0.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (183.4 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

python_prtree-0.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (167.4 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64

python_prtree-0.5.5-cp37-cp37m-macosx_10_15_x86_64.whl (161.0 kB view hashes)

Uploaded CPython 3.7m macOS 10.15+ x86-64

python_prtree-0.5.5-cp36-cp36m-win_amd64.whl (131.7 kB view hashes)

Uploaded CPython 3.6m Windows x86-64

python_prtree-0.5.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (183.0 kB view hashes)

Uploaded CPython 3.6m manylinux: glibc 2.17+ x86-64

python_prtree-0.5.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (167.3 kB view hashes)

Uploaded CPython 3.6m manylinux: glibc 2.17+ ARM64

python_prtree-0.5.5-cp36-cp36m-macosx_10_15_x86_64.whl (161.1 kB view hashes)

Uploaded CPython 3.6m macOS 10.15+ x86-64

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page