package rtree
All checked builds passInstall
dune-project
Dependency
Authors
Maintainers
Sources
sha256=1cf52e63601cfeaaae8b37ce8afaa6ef41dcadd575fc2bff15be14414bb4622c
sha512=57e1695156518793b705411e91648e7f2524f7bb5415c661ae47af59ef376b9d057bb612c3d1409fcc73d64b50d5df3030d7d0b533ec18c4d04bc63a35d0eb7e
Description
This implements a simple, functional R-Tree library in pure OCaml with support for efficient bulk loading of values.
README
ocaml-rtree
This repository used to live at mariusae/ocaml-rtree where most of the core implementation was done.
This implements a simple rtree library according to Guttman's original paper. Currently node splitting is done through the quadratic algorithm in that paper.
Some benchmarks are available too.
Usage
There are two key elements to an rtree. The type of envelopes used and the type of the values being store in the tree. These values must come with a function to calculate an envelope.
The core library comes with an implementation of envelopes as two-dimensional rectangles.
# #show_module Rtree.Rectangle;;
module Rectangle :
sig
type t
val dimensions : int
val compare_dim : int -> t -> t -> int
val empty : t
val intersects : t -> t -> bool
val merge : t -> t -> t
val merge_many : t list -> t
val area : t -> float
val contains : t -> t -> bool
val pp : Format.formatter -> t -> unit
val coords : t -> float * float * float * float
val v : x0:float -> y0:float -> x1:float -> y1:float -> t
endIf you wanted to store lines in your rtree, one possible implementation might be the following.
module Line = struct
type t = { p0 : float * float; p1 : float * float }
(* You could write a more performant [equal] function. *)
let equal = Stdlib.( = )
let pp ppf t =
Format.fprintf ppf "{ p1: (%.2f, %.2f), p2: (%.2f, %.2f) }" (fst t.p0)
(snd t.p0) (fst t.p1) (snd t.p1)
type envelope = Rtree.Rectangle.t
let envelope { p0 = (x1, y1); p1 = (x2, y2) } =
let x0 = Float.min x1 x2 in
let x1 = Float.max x1 x2 in
let y0 = Float.min y1 y2 in
let y1 = Float.max y1 y2 in
Rtree.Rectangle.v ~x0 ~y0 ~x1 ~y1
end
module R = Rtree.Make(Rtree.Rectangle)(Line)And now we will install the pretty printer.
# #install_printer R.pp;;Insertion
To insert into an rtree, you simply pass a value into a pre-existing rtree. You can create an empty rtree where you control the maximum node load size. This is essentially the branching factor in the tree. The correct value is hard to guess.
# let index = R.empty 8;;
val index : R.t = []
# let index = R.insert index Line.{ p0 = (1., 2.); p1 = (3., 3.) };;
val index : R.t =
[(((1., 3.), (2., 3.)), { p1: (1.00, 2.00), p2: (3.00, 3.00) })]
# let index = R.insert index Line.{ p0 = (4., 4.); p1 = (5., 5.) };;
val index : R.t =
[(((4., 5.), (4., 5.)), { p1: (4.00, 4.00), p2: (5.00, 5.00) })
(((1., 3.), (2., 3.)), { p1: (1.00, 2.00), p2: (3.00, 3.00) })]Loading
If you have a list of values to put into an rtree, then you are better off using the load function instead of folding and inserting. This uses the OMT algorithm and should give you a more optimised rtree layout.
# let lines =
Line.[
{ p0 = (0., 0.); p1 = (1., 1.) };
{ p0 = (1., 1.); p1 = (2., 2.) };
{ p0 = (2., 2.); p1 = (3., 3.) };
{ p0 = (3., 3.); p1 = (4., 4.) };
]
in
R.load ~max_node_load:2 lines
- : R.t =
[|(((0., 2.), (0., 2.)),
[(((0., 1.), (0., 1.)), { p1: (0.00, 0.00), p2: (1.00, 1.00) })
(((1., 2.), (1., 2.)), { p1: (1.00, 1.00), p2: (2.00, 2.00) })])
(((2., 4.), (2., 4.)),
[(((2., 3.), (2., 3.)), { p1: (2.00, 2.00), p2: (3.00, 3.00) })
(((3., 4.), (3., 4.)), { p1: (3.00, 3.00), p2: (4.00, 4.00) })])|]Also see image.ml for rendering an rtree with vg.
Find
Finding values requires you to pass in a search envelope. A list of result, perhaps empty, will be returned.
# R.find index (Rtree.Rectangle.v ~x0:0. ~y0:0. ~x1:3. ~y1:3.);;
- : Line.t list = [{Line.p0 = (1., 2.); p1 = (3., 3.)}]
# R.find index (Rtree.Rectangle.v ~x0:0. ~y0:0. ~x1:5. ~y1:5.);;
- : Line.t list =
[{Line.p0 = (4., 4.); p1 = (5., 5.)}; {Line.p0 = (1., 2.); p1 = (3., 3.)}]
Dependencies (1)
-
dune
>= "3.6"
Dev Dependencies (5)
Optional Dependencies
None
Used by
None
Conflicts
None
Build status
Results of building rtree with each compiler on check.ci.ocaml.org, run of against opam-repository 8a77e58. All results for this package.
Each result links to its build log. To keep crawlers from overloading the site, build logs require a GitHub sign-in (see ocurrent/opam-health-check). On your first log, GitHub asks you to “Authorize opam-health-check”, the OCurrent app that runs these checks; it sees only your public profile, not your repositories. The sign-in lasts 30 days.
| Version | OCaml 4.11 | OCaml 4.14 | OCaml 5.2 | OCaml 5.4 | OCaml 5.5 |
|---|---|---|---|---|---|
| 0.3.0 (this version) | good | good | good | good | good |
- good Package successfully built
- partial One of the dependencies failed to build
- bad Package failed to build
- n/a Package is not available in this environment
- internal Internal failure