Skip to main content

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!(
33//!     range_of_index
34//!         .iter()
35//!         .any(|r| r.lower() <= indexed_point && r.upper() >= indexed_point)
36//! );
37//! ```
38//! Z3 curve is used for two dimensional point and time indexing and can be accessed
39//! through the `SpaceTimeFillingCurves` factory.
40//! ```
41//! use space_time::SpaceTimeFillingCurves;
42//!
43//! let curve = SpaceTimeFillingCurves::get_point_curve(1024, -180.0, -90.0, 180.0, 90.0, 159753997829.0);
44//! let indexed_point_in_time = curve.index(2.3522, 48.8566, 1587583997829.0); // Paris, France. April 22, 2020 as milliseconds since Unix Epoch.
45//! let range_of_index = curve.ranges(2.3522, 48.85, 2.354, 48.857, 1587583997828.0, 1587583997828.0, &[]);
46//!
47//! assert!(range_of_index.iter().any(|r| r.lower() <= indexed_point_in_time && r.upper() >= indexed_point_in_time));
48//! ```
49//!
50//! Extended Z-order curves are used for non-points.
51//! `XZ2SFC` for spatial indexing of non-points.
52//! ```
53//! use space_time::SpaceFillingCurves;
54//!
55//! let curve = SpaceFillingCurves::get_non_point_curve(12, -180.0, -90.0, 180.0, 90.0);
56//! let indexed_polygon = curve.index(2.3522, 48.8466, 2.39, 49.9325);
57//! let range_of_index = curve.ranges(2.0, 48.0, 3.0, 50.0, None);
58//!
59//! assert!(
60//!     range_of_index
61//!         .iter()
62//!         .any(|r| r.lower() <= indexed_polygon && r.upper() >= indexed_polygon)
63//! );
64//! ```
65//! `XZ3SFC` for spatial-temporal indexing of non-points.
66//!
67//! ```
68//! use space_time::SpaceTimeFillingCurves;
69//!
70//! let curve = SpaceTimeFillingCurves::get_non_point_curve(
71//!     12,
72//!     -180.0,
73//!     -90.0,
74//!     0.0,
75//!     180.0,
76//!     90.0,
77//!     1_893_456_000.0,
78//! );
79//!
80//! let indexed_polygon = curve.index(
81//!     2.3522,
82//!     48.8466,
83//!     1_556_496_000.0,
84//!     2.39,
85//!     49.9325,
86//!     1_556_496_000.0,
87//! );
88//!
89//! 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);
90//!
91//! assert!(
92//!     range_of_index
93//!         .iter()
94//!         .any(|r| r.lower() <= indexed_polygon && r.upper() >= indexed_polygon)
95//! );
96//! ```
97
98pub mod index_range;
99pub mod xzorder;
100pub mod zorder;
101
102#[cfg(test)]
103extern crate quickcheck;
104
105#[cfg(test)]
106#[macro_use]
107extern crate quickcheck_macros;
108
109extern crate alloc;
110
111use xzorder::{xz2_sfc::XZ2SFC, xz3_sfc::XZ3SFC};
112use zorder::{z_3::ZCurve3D, z_curve_2d::ZCurve2D};
113
114/// Factory providing space filling curves
115pub struct SpaceFillingCurves;
116
117impl SpaceFillingCurves {
118    /// Return point indexing curve with a resolution.
119    #[must_use]
120    pub fn get_point_curve(
121        resolution: u32,
122        x_min: f64,
123        y_min: f64,
124        x_max: f64,
125        y_max: f64,
126    ) -> ZCurve2D {
127        ZCurve2D::new(resolution, x_min, y_min, x_max, y_max)
128    }
129
130    /// Return a non-point indexing curve with a resolution.
131    #[must_use]
132    pub fn get_non_point_curve(
133        resolution: u32,
134        x_min: f64,
135        y_min: f64,
136        x_max: f64,
137        y_max: f64,
138    ) -> XZ2SFC {
139        XZ2SFC::new(resolution, x_min, y_min, x_max, y_max)
140    }
141}
142
143/// Factory providing space-time filling curves
144pub struct SpaceTimeFillingCurves;
145
146impl SpaceTimeFillingCurves {
147    /// Return point-time indexing curve.
148    #[must_use]
149    pub fn get_point_curve(
150        resolution: u32,
151        x_min: f64,
152        y_min: f64,
153        x_max: f64,
154        y_max: f64,
155        t_max: f64,
156    ) -> ZCurve3D {
157        ZCurve3D::new(resolution, x_min, y_min, x_max, y_max, t_max)
158    }
159
160    /// Return a nonpoint space-time indexing curve.
161    #[must_use]
162    pub fn get_non_point_curve(
163        resolution: u32,
164        x_min: f64,
165        y_min: f64,
166        z_min: f64,
167        x_max: f64,
168        y_max: f64,
169        z_max: f64,
170    ) -> XZ3SFC {
171        XZ3SFC::new(resolution, x_min, y_min, z_min, x_max, y_max, z_max)
172    }
173}
174
175/// Hints to the `range` function implementation for `SpacefillingCurve2D`s.
176pub enum RangeComputeHints {
177    /// Number of times to recurse.
178    MaxRecurse(usize),
179}