space_time/
lib.rs

1//
2// Copyright 2020, Gobsmacked Labs, LLC.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#![no_std]
17#![deny(missing_docs)]
18//! Partial port of the scala-based geomesa-z3 library from [geomesa](http://github.com/locationtech/geomesa)
19//! Partial port of [sfcurve](https://github.com/locationtech/sfcurve) scala space-filling curve library.
20//!
21//! Useful for representing and querying spatial objects
22//!
23//! Z2 curve is used for two dimensional point indexing and can be accessed through
24//! the `SpaceFillingCurves` factory.
25//! ```
26//! use space_time::SpaceFillingCurves;
27//!
28//! let curve = SpaceFillingCurves::get_point_curve(1024, -180.0, -90.0, 180.0, 90.0);
29//! let indexed_point = curve.index(2.3522, 48.8566);
30//! let range_of_index = curve.ranges(2.35, 48.85, 2.354, 48.857, &[]);
31//!
32//! assert!(range_of_index
33//!     .iter()
34//!     .any(|r| r.lower() <= indexed_point && r.upper() >= indexed_point));
35//! ```
36//! Z3 curve is used for two dimensional point and time indexing and can be accessed
37//! through the `SpaceTimeFillingCurves` factory.
38//! ```
39//! use space_time::SpaceTimeFillingCurves;
40//!
41//! let curve = SpaceTimeFillingCurves::get_point_curve(1024, -180.0, -90.0, 180.0, 90.0, 159753997829.0);
42//! let indexed_point_in_time = curve.index(2.3522, 48.8566, 1587583997829.0); // Paris, France. April 22, 2020 as milliseconds since Unix Epoch.
43//! let range_of_index = curve.ranges(2.3522, 48.85, 2.354, 48.857, 1587583997828.0, 1587583997828.0, &[]);
44//!
45//! assert!(range_of_index.iter().any(|r| r.lower() <= indexed_point_in_time && r.upper() >= indexed_point_in_time));
46//! ```
47//!
48//! Extended Z-order curves are used for non-points.
49//! `XZ2SFC` for spatial indexing of non-points.
50//! ```
51//! use space_time::SpaceFillingCurves;
52//!
53//! let curve = SpaceFillingCurves::get_non_point_curve(12, -180.0, -90.0, 180.0, 90.0);
54//! let indexed_polygon = curve.index(2.3522, 48.8466, 2.39, 49.9325);
55//! let range_of_index = curve.ranges(2.0, 48.0, 3.0, 50.0, None);
56//!
57//! assert!(range_of_index
58//!     .iter()
59//!     .any(|r| r.lower() <= indexed_polygon && r.upper() >= indexed_polygon));
60//! ```
61//! `XZ3SFC` for spatial-temporal indexing of non-points.
62//!
63//! ```
64//! use space_time::SpaceTimeFillingCurves;
65//!
66//! let curve = SpaceTimeFillingCurves::get_non_point_curve(
67//!     12,
68//!     -180.0,
69//!     -90.0,
70//!     0.0,
71//!     180.0,
72//!     90.0,
73//!     1_893_456_000.0,
74//! );
75//!
76//! let indexed_polygon = curve.index(
77//!     2.3522,
78//!     48.8466,
79//!     1_556_496_000.0,
80//!     2.39,
81//!     49.9325,
82//!     1_556_496_000.0,
83//! );
84//!
85//! let range_of_index = curve.ranges(2.0, 48.0, 1_556_300_000.0, 3.0, 50.0, 1_557_496_000.0, None);
86//!
87//! assert!(range_of_index
88//!     .iter()
89//!     .any(|r| r.lower() <= indexed_polygon && r.upper() >= indexed_polygon));
90//! ```
91
92pub mod index_range;
93pub mod xzorder;
94pub mod zorder;
95
96#[cfg(test)]
97extern crate quickcheck;
98
99#[cfg(test)]
100#[macro_use]
101extern crate quickcheck_macros;
102
103extern crate alloc;
104
105use xzorder::{xz2_sfc::XZ2SFC, xz3_sfc::XZ3SFC};
106use zorder::{z_3::ZCurve3D, z_curve_2d::ZCurve2D};
107
108/// Factory providing space filling curves
109pub struct SpaceFillingCurves;
110
111impl SpaceFillingCurves {
112    /// Return point indexing curve with a resolution.
113    #[must_use]
114    pub fn get_point_curve(
115        resolution: u32,
116        x_min: f64,
117        y_min: f64,
118        x_max: f64,
119        y_max: f64,
120    ) -> ZCurve2D {
121        ZCurve2D::new(resolution, x_min, y_min, x_max, y_max)
122    }
123
124    /// Return a non-point indexing curve with a resolution.
125    #[must_use]
126    pub fn get_non_point_curve(
127        resolution: u32,
128        x_min: f64,
129        y_min: f64,
130        x_max: f64,
131        y_max: f64,
132    ) -> XZ2SFC {
133        XZ2SFC::new(resolution, x_min, y_min, x_max, y_max)
134    }
135}
136
137/// Factory providing space-time filling curves
138pub struct SpaceTimeFillingCurves;
139
140impl SpaceTimeFillingCurves {
141    /// Return point-time indexing curve.
142    #[must_use]
143    pub fn get_point_curve(
144        resolution: u32,
145        x_min: f64,
146        y_min: f64,
147        x_max: f64,
148        y_max: f64,
149        t_max: f64,
150    ) -> ZCurve3D {
151        ZCurve3D::new(resolution, x_min, y_min, x_max, y_max, t_max)
152    }
153
154    /// Return a nonpoint space-time indexing curve.
155    #[must_use]
156    pub fn get_non_point_curve(
157        resolution: u32,
158        x_min: f64,
159        y_min: f64,
160        z_min: f64,
161        x_max: f64,
162        y_max: f64,
163        z_max: f64,
164    ) -> XZ3SFC {
165        XZ3SFC::new(resolution, x_min, y_min, z_min, x_max, y_max, z_max)
166    }
167}
168
169/// Hints to the `range` function implementation for `SpacefillingCurve2D`s.
170pub enum RangeComputeHints {
171    /// Number of times to recurse.
172    MaxRecurse(usize),
173}