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}