├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches ├── rstar.rs └── rtree.rs ├── src ├── geometry.rs ├── lib.rs ├── tree │ ├── mbr │ │ ├── index │ │ │ ├── mod.rs │ │ │ ├── r.rs │ │ │ └── rstar.rs │ │ ├── leaf.rs │ │ ├── leafgeometry.rs │ │ ├── map.rs │ │ ├── mod.rs │ │ ├── node.rs │ │ └── query.rs │ ├── mod.rs │ └── xmbr │ │ ├── index │ │ └── mod.rs │ │ ├── mod.rs │ │ └── node.rs └── vecext.rs └── tests ├── rstar.rs └── rtree.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.o 3 | *.so 4 | *.rlib 5 | *.dll 6 | 7 | # Executables 8 | *.exe 9 | 10 | # Generated by Cargo 11 | /target/ 12 | 13 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 14 | # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock 15 | Cargo.lock 16 | // rust fmt backup files 17 | *.bk 18 | 19 | .vscode/ 20 | .DS_Store -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spatial" 3 | version = "1.0.1" 4 | authors = ["Adam Baxter"] 5 | description = "An N-Dimensional R-tree family spatial tree implementations" 6 | repository = "https://github.com/ambaxter/spatial-rs.git" 7 | homepage = "https://github.com/ambaxter/spatial-rs" 8 | license = "MIT/Apache-2.0" 9 | readme = "README.md" 10 | keywords = ["spatial","geometry","tree","r-tree","rstar"] 11 | edition = '2021' 12 | rust-version = "1.61" 13 | 14 | 15 | [dependencies] 16 | itertools = "0.12" 17 | ordered-float = "4" 18 | num = "0.4" 19 | 20 | [dev-dependencies] 21 | approx = "0.5" 22 | rand = "0.8" -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Adam Baxter 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spatial-rs 2 | N-Dimensional Spatial Tree implementations library for Rust 3 | 4 | Currently only implements R* Tree, but I'm trying to keep it generic enough where most spatial trees can be supported in a single interface. 5 | 6 | ## License 7 | 8 | Licensed under either of 9 | 10 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 11 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 12 | 13 | at your option. 14 | 15 | ### Contribution 16 | 17 | Unless you explicitly state otherwise, any contribution intentionally submitted 18 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any 19 | additional terms or conditions. 20 | -------------------------------------------------------------------------------- /benches/rstar.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate rand; 4 | extern crate spatial; 5 | extern crate test; 6 | 7 | use rand::{random}; 8 | use spatial::geometry::{Point, Rect}; 9 | use spatial::tree::mbr::MbrRectQuery; 10 | use spatial::{RStar, RStarTree}; 11 | use test::Bencher; 12 | 13 | fn generate_tree_with_size(count: usize) -> RStarTree, usize> { 14 | let mut tree_map = RStar::new_with_max(32); 15 | for i in 0..count { 16 | tree_map.insert( 17 | Point::new([random::(), random::(), random::()]), 18 | i, 19 | ); 20 | } 21 | tree_map 22 | } 23 | 24 | #[bench] 25 | fn insert_rng_bench_3d_10(b: &mut Bencher) { 26 | b.iter(|| { 27 | generate_tree_with_size(10); 28 | }); 29 | } 30 | 31 | #[bench] 32 | fn insert_rng_bench_3d_100(b: &mut Bencher) { 33 | b.iter(|| { 34 | generate_tree_with_size(100); 35 | }); 36 | } 37 | 38 | #[bench] 39 | fn insert_rng_bench_3d_1000(b: &mut Bencher) { 40 | b.iter(|| { 41 | generate_tree_with_size(1000); 42 | }); 43 | } 44 | 45 | #[bench] 46 | fn insert_rng_bench_3d_10000(b: &mut Bencher) { 47 | b.iter(|| { 48 | generate_tree_with_size(10000); 49 | }); 50 | } 51 | 52 | fn search_rng_bench_3d(b: &mut Bencher, size: usize) { 53 | let tree_map = generate_tree_with_size(size); 54 | b.iter(|| { 55 | let x_array = [random::(), random::(), random::()]; 56 | let y_array = [random::(), random::(), random::()]; 57 | tree_map 58 | .iter_query(MbrRectQuery::Overlaps(Rect::from_corners(x_array, y_array))) 59 | .count(); 60 | }); 61 | } 62 | 63 | fn remove_rng_bench_3d(b: &mut Bencher, size: usize) { 64 | let mut tree_map = generate_tree_with_size(size); 65 | b.iter(|| { 66 | let x_array = [random::(), random::(), random::()]; 67 | let y_array = [random::(), random::(), random::()]; 68 | let removed = tree_map.remove(MbrRectQuery::Overlaps(Rect::from_corners(x_array, y_array))); 69 | for (lshape, item) in removed { 70 | tree_map.insert(lshape, item); 71 | } 72 | }); 73 | } 74 | 75 | #[bench] 76 | fn search_rng_bench_3d_10(b: &mut Bencher) { 77 | search_rng_bench_3d(b, 10); 78 | } 79 | 80 | #[bench] 81 | fn search_rng_bench_3d_100(b: &mut Bencher) { 82 | search_rng_bench_3d(b, 100); 83 | } 84 | 85 | #[bench] 86 | fn search_rng_bench_3d_1000(b: &mut Bencher) { 87 | search_rng_bench_3d(b, 1000); 88 | } 89 | 90 | #[bench] 91 | fn search_rng_bench_3d_10000(b: &mut Bencher) { 92 | search_rng_bench_3d(b, 10000); 93 | } 94 | 95 | #[bench] 96 | fn remove_rng_bench_3d_10(b: &mut Bencher) { 97 | remove_rng_bench_3d(b, 10); 98 | } 99 | 100 | #[bench] 101 | fn remove_rng_bench_3d_100(b: &mut Bencher) { 102 | remove_rng_bench_3d(b, 100); 103 | } 104 | 105 | #[bench] 106 | fn remove_rng_bench_3d_1000(b: &mut Bencher) { 107 | remove_rng_bench_3d(b, 1000); 108 | } 109 | 110 | #[bench] 111 | fn remove_rng_bench_3d_10000(b: &mut Bencher) { 112 | remove_rng_bench_3d(b, 10000); 113 | } 114 | -------------------------------------------------------------------------------- /benches/rtree.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate rand; 4 | extern crate spatial; 5 | extern crate test; 6 | 7 | use rand::Rng; 8 | use spatial::geometry::{Point, Rect}; 9 | use spatial::tree::mbr::MbrRectQuery; 10 | use spatial::{RLinearTree, RQuadraticTree, RTree}; 11 | use test::Bencher; 12 | use rand::random; 13 | 14 | fn generate_linear_tree_with_size(count: usize) -> RLinearTree, usize> { 15 | let mut tree_map = RTree::new_linear_with_max(32); 16 | for i in 0..count { 17 | tree_map.insert( 18 | Point::new([random::(), random::(), random::()]), 19 | i, 20 | ); 21 | } 22 | tree_map 23 | } 24 | 25 | fn generate_quadratic_tree_with_size(count: usize) -> RQuadraticTree, usize> { 26 | let mut tree_map = RTree::new_quadratic_with_max(32); 27 | for i in 0..count { 28 | tree_map.insert( 29 | Point::new([random::(), random::(), random::()]), 30 | i, 31 | ); 32 | } 33 | tree_map 34 | } 35 | 36 | // Linear benches 37 | #[bench] 38 | fn insert_linear_rng_bench_3d_10(b: &mut Bencher) { 39 | b.iter(|| { 40 | generate_linear_tree_with_size(10); 41 | }); 42 | } 43 | 44 | #[bench] 45 | fn insert_linear_rng_bench_3d_100(b: &mut Bencher) { 46 | b.iter(|| { 47 | generate_linear_tree_with_size(100); 48 | }); 49 | } 50 | 51 | #[bench] 52 | fn insert_linear_rng_bench_3d_1000(b: &mut Bencher) { 53 | b.iter(|| { 54 | generate_linear_tree_with_size(1000); 55 | }); 56 | } 57 | 58 | #[bench] 59 | fn insert_linear_rng_bench_3d_10000(b: &mut Bencher) { 60 | b.iter(|| { 61 | generate_linear_tree_with_size(10000); 62 | }); 63 | } 64 | 65 | fn search_linear_rng_bench_3d(b: &mut Bencher, size: usize) { 66 | let tree_map = generate_linear_tree_with_size(size); 67 | b.iter(|| { 68 | let x_array = [random::(), random::(), random::()]; 69 | let y_array = [random::(), random::(), random::()]; 70 | tree_map 71 | .iter_query(MbrRectQuery::Overlaps(Rect::from_corners(x_array, y_array))) 72 | .count(); 73 | }); 74 | } 75 | 76 | fn remove_linear_rng_bench_3d(b: &mut Bencher, size: usize) { 77 | let mut tree_map = generate_linear_tree_with_size(size); 78 | b.iter(|| { 79 | let x_array = [random::(), random::(), random::()]; 80 | let y_array = [random::(), random::(), random::()]; 81 | let removed = tree_map.remove(MbrRectQuery::Overlaps(Rect::from_corners(x_array, y_array))); 82 | for (lshape, item) in removed { 83 | tree_map.insert(lshape, item); 84 | } 85 | }); 86 | } 87 | 88 | #[bench] 89 | fn search_linear_rng_bench_3d_10(b: &mut Bencher) { 90 | search_linear_rng_bench_3d(b, 10); 91 | } 92 | 93 | #[bench] 94 | fn search_linear_rng_bench_3d_100(b: &mut Bencher) { 95 | search_linear_rng_bench_3d(b, 100); 96 | } 97 | 98 | #[bench] 99 | fn search_linear_rng_bench_3d_1000(b: &mut Bencher) { 100 | search_linear_rng_bench_3d(b, 1000); 101 | } 102 | 103 | #[bench] 104 | fn search_linear_rng_bench_3d_10000(b: &mut Bencher) { 105 | search_linear_rng_bench_3d(b, 10000); 106 | } 107 | 108 | #[bench] 109 | fn remove_linear_rng_bench_3d_10(b: &mut Bencher) { 110 | remove_linear_rng_bench_3d(b, 10); 111 | } 112 | 113 | #[bench] 114 | fn remove_linear_rng_bench_3d_100(b: &mut Bencher) { 115 | remove_linear_rng_bench_3d(b, 100); 116 | } 117 | 118 | #[bench] 119 | fn remove_linear_rng_bench_3d_1000(b: &mut Bencher) { 120 | remove_linear_rng_bench_3d(b, 1000); 121 | } 122 | 123 | #[bench] 124 | fn remove_linear_rng_bench_3d_10000(b: &mut Bencher) { 125 | remove_linear_rng_bench_3d(b, 10000); 126 | } 127 | 128 | // Quadratic benches 129 | #[bench] 130 | fn insert_quadratic_rng_bench_3d_10(b: &mut Bencher) { 131 | b.iter(|| { 132 | generate_quadratic_tree_with_size(10); 133 | }); 134 | } 135 | 136 | #[bench] 137 | fn insert_quadratic_rng_bench_3d_100(b: &mut Bencher) { 138 | b.iter(|| { 139 | generate_quadratic_tree_with_size(100); 140 | }); 141 | } 142 | 143 | #[bench] 144 | fn insert_quadratic_rng_bench_3d_1000(b: &mut Bencher) { 145 | b.iter(|| { 146 | generate_quadratic_tree_with_size(1000); 147 | }); 148 | } 149 | 150 | #[bench] 151 | fn insert_quadratic_rng_bench_3d_10000(b: &mut Bencher) { 152 | b.iter(|| { 153 | generate_quadratic_tree_with_size(10000); 154 | }); 155 | } 156 | 157 | fn search_quadratic_rng_bench_3d(b: &mut Bencher, size: usize) { 158 | let tree_map = generate_quadratic_tree_with_size(size); 159 | b.iter(|| { 160 | let x_array = [random::(), random::(), random::()]; 161 | let y_array = [random::(), random::(), random::()]; 162 | tree_map 163 | .iter_query(MbrRectQuery::Overlaps(Rect::from_corners(x_array, y_array))) 164 | .count(); 165 | }); 166 | } 167 | 168 | fn remove_quadratic_rng_bench_3d(b: &mut Bencher, size: usize) { 169 | let mut tree_map = generate_quadratic_tree_with_size(size); 170 | b.iter(|| { 171 | let x_array = [random::(), random::(), random::()]; 172 | let y_array = [random::(), random::(), random::()]; 173 | let removed = tree_map.remove(MbrRectQuery::Overlaps(Rect::from_corners(x_array, y_array))); 174 | for (lshape, item) in removed { 175 | tree_map.insert(lshape, item); 176 | } 177 | }); 178 | } 179 | 180 | #[bench] 181 | fn search_quadratic_rng_bench_3d_10(b: &mut Bencher) { 182 | search_quadratic_rng_bench_3d(b, 10); 183 | } 184 | 185 | #[bench] 186 | fn search_quadratic_rng_bench_3d_100(b: &mut Bencher) { 187 | search_quadratic_rng_bench_3d(b, 100); 188 | } 189 | 190 | #[bench] 191 | fn search_quadratic_rng_bench_3d_1000(b: &mut Bencher) { 192 | search_quadratic_rng_bench_3d(b, 1000); 193 | } 194 | 195 | #[bench] 196 | fn search_quadratic_rng_bench_3d_10000(b: &mut Bencher) { 197 | search_quadratic_rng_bench_3d(b, 10000); 198 | } 199 | 200 | #[bench] 201 | fn remove_quadratic_rng_bench_3d_10(b: &mut Bencher) { 202 | remove_quadratic_rng_bench_3d(b, 10); 203 | } 204 | 205 | #[bench] 206 | fn remove_quadratic_rng_bench_3d_100(b: &mut Bencher) { 207 | remove_quadratic_rng_bench_3d(b, 100); 208 | } 209 | 210 | #[bench] 211 | fn remove_quadratic_rng_bench_3d_1000(b: &mut Bencher) { 212 | remove_quadratic_rng_bench_3d(b, 1000); 213 | } 214 | 215 | #[bench] 216 | fn remove_quadratic_rng_bench_3d_10000(b: &mut Bencher) { 217 | remove_quadratic_rng_bench_3d(b, 10000); 218 | } 219 | -------------------------------------------------------------------------------- /src/geometry.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! Various geometric shapes to insert into spatial trees 9 | 10 | use num::{Bounded, Float}; 11 | use std::convert::{AsMut, AsRef, TryInto}; 12 | use std::fmt::Debug; 13 | use std::ops::{Deref, DerefMut}; 14 | use crate::FP; 15 | 16 | /// An n-dimensional point 17 | #[derive(Debug, Clone)] 18 | pub struct Point { 19 | pub coords: [P; DIM], 20 | } 21 | 22 | impl Point { 23 | /// New Point from a `GenericArray` 24 | pub fn new(coords: [P; DIM]) -> Point { 25 | for coord in &coords { 26 | assert!(Float::is_finite(*coord), "{:?} should be finite", coord); 27 | } 28 | Point { coords } 29 | } 30 | /// New Point from a slice 31 | pub fn from_slice(slice: &[P]) -> Point { 32 | Point::new(slice.try_into().unwrap()) 33 | } 34 | } 35 | 36 | impl Deref for Point { 37 | type Target = [P]; 38 | 39 | fn deref(&self) -> &[P] { 40 | &self.coords 41 | } 42 | } 43 | 44 | impl DerefMut for Point { 45 | fn deref_mut(&mut self) -> &mut [P] { 46 | &mut self.coords 47 | } 48 | } 49 | 50 | impl AsRef<[P]> for Point { 51 | fn as_ref(&self) -> &[P] { 52 | &self.coords 53 | } 54 | } 55 | 56 | impl AsMut<[P]> for Point { 57 | fn as_mut(&mut self) -> &mut [P] { 58 | &mut self.coords 59 | } 60 | } 61 | 62 | /// An n-dimensional line segment 63 | #[derive(Debug, Clone)] 64 | pub struct LineSegment { 65 | // TODO: Would this be better as [(P,P)]? 66 | pub x: Point, 67 | pub y: Point, 68 | } 69 | 70 | impl LineSegment { 71 | /// New LineSegment from two GenericArrays representing either end 72 | pub fn new(x: [P; DIM], y: [P; DIM]) -> LineSegment { 73 | LineSegment { 74 | x: Point::new(x), 75 | y: Point::new(y), 76 | } 77 | } 78 | /// New LineSegment from two slices representing either end 79 | pub fn from_slices(x: &[P], y: &[P]) -> LineSegment { 80 | LineSegment { 81 | x: Point::from_slice(x), 82 | y: Point::from_slice(y), 83 | } 84 | } 85 | } 86 | 87 | /// An n-dimensional rectangle 88 | #[derive(Debug, Clone)] 89 | pub struct Rect { 90 | pub edges: [(P, P); DIM], 91 | } 92 | 93 | impl Rect { 94 | /// New Rect from a `GenericArray` 95 | pub fn new(mut edges: [(P, P); DIM]) -> Rect { 96 | // ensure that the edge coordinates are valid and ordered correctly 97 | for &mut (ref mut x, ref mut y) in &mut edges { 98 | assert!(Float::is_finite(*x), "{:?} should be finite", x); 99 | assert!(Float::is_finite(*y), "{:?} should be finite", y); 100 | *x = Float::min(*x, *y); 101 | *y = Float::max(*x, *y); 102 | } 103 | Rect { edges } 104 | } 105 | 106 | /// New Rect from corners 107 | pub fn from_corners(x: [P; DIM], y: [P; DIM]) -> Rect { 108 | use crate::tree::mbr::MbrLeafGeometry; 109 | let mut edges = Rect::max_inverted(); 110 | Point::new(x).expand_mbr_to_fit(&mut edges); 111 | Point::new(y).expand_mbr_to_fit(&mut edges); 112 | edges 113 | } 114 | 115 | /// An inverted Rect where ever dimension's (x, y) coordinates are (MAX, MIN). Simplifies finding boundaries. 116 | pub fn max_inverted() -> Rect { 117 | let edges = [(Bounded::max_value(), Bounded::min_value()); DIM]; 118 | Rect { edges } 119 | } 120 | 121 | /// The largest possible rect 122 | pub fn max() -> Rect { 123 | let edges = [(Bounded::min_value(), Bounded::max_value()); DIM]; 124 | Rect { edges } 125 | } 126 | } 127 | 128 | impl Deref for Rect { 129 | type Target = [(P, P)]; 130 | 131 | fn deref(&self) -> &[(P, P)] { 132 | &self.edges 133 | } 134 | } 135 | 136 | impl DerefMut for Rect { 137 | fn deref_mut(&mut self) -> &mut [(P, P)] { 138 | &mut self.edges 139 | } 140 | } 141 | 142 | impl AsRef<[(P, P)]> for Rect { 143 | fn as_ref(&self) -> &[(P, P)] { 144 | self.deref() 145 | } 146 | } 147 | 148 | impl AsMut<[(P, P)]> for Rect { 149 | fn as_mut(&mut self) -> &mut [(P, P)] { 150 | self.deref_mut() 151 | } 152 | } 153 | 154 | // When trying to use Other(Box>) 155 | // the trait bound `shapes::Shape

: std::marker::Sized` is not satisfied [E0277] 156 | // the trait bound `shapes::Shape

: std::clone::Clone` is not satisfied [E0277] 157 | // the trait bound `shapes::Shape

+ 'static: std::fmt::Debug` is not satisfied [E0277] 158 | // 159 | /// A convenience enum that contains `Point`, `LineSegment`, and `Rect` 160 | #[derive(Debug, Clone)] 161 | pub enum Shapes { 162 | Point(Point), 163 | LineSegment(LineSegment), 164 | Rect(Rect), // Other(Box>) 165 | } 166 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! Spatial Trees 9 | 10 | #[macro_use] 11 | extern crate itertools; 12 | 13 | extern crate num; 14 | extern crate ordered_float; 15 | 16 | #[cfg(test)] 17 | #[macro_use] 18 | extern crate approx; 19 | 20 | pub trait FP: 21 | Float 22 | + Signed 23 | + Bounded 24 | + MulAssign 25 | + AddAssign 26 | + ToPrimitive 27 | + FromPrimitive 28 | + Copy 29 | + Debug 30 | + Default 31 | + FloatCore 32 | + TryInto> 33 | { 34 | } 35 | 36 | impl FP for f32 {} 37 | impl FP for f64 {} 38 | 39 | pub mod geometry; 40 | pub mod tree; 41 | mod vecext; 42 | 43 | use num::{Bounded, Float, FromPrimitive, Signed, ToPrimitive}; 44 | use ordered_float::{FloatCore, NotNan}; 45 | use std::convert::TryInto; 46 | use std::fmt::Debug; 47 | use std::ops::{AddAssign, MulAssign}; 48 | pub use tree::mbr::{RLinearTree, RQuadraticTree, RStar, RStarTree, RTree}; 49 | -------------------------------------------------------------------------------- /src/tree/mbr/index/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! Specific implementations for inserting and removing leaves 9 | 10 | use crate::geometry::Rect; 11 | use crate::tree::mbr::{MbrLeaf, MbrLeafGeometry, MbrNode, MbrQuery}; 12 | use crate::FP; 13 | pub mod r; 14 | pub mod rstar; 15 | 16 | pub const D_MAX: usize = 64; 17 | const AT_ROOT: bool = true; 18 | const NOT_AT_ROOT: bool = false; 19 | const FORCE_SPLIT: bool = true; 20 | const DONT_FORCE_SPLIT: bool = false; 21 | 22 | /// Insert the leaf into the root 23 | pub trait IndexInsert 24 | where 25 | NODE: MbrNode, 26 | { 27 | fn insert_into_root(&self, root: NODE, leaf: MbrLeaf) -> NODE; 28 | 29 | fn preferred_min(&self) -> usize; 30 | 31 | fn new_leaves(&self) -> NODE; 32 | 33 | fn new_no_alloc_leaves(&self) -> NODE; 34 | } 35 | 36 | pub type RemoveReturn = (NODE, Vec>); 37 | 38 | /// Remove entries from the tree that match the query, but not the retain function f. 39 | pub trait IndexRemove 40 | where 41 | NODE: MbrNode, 42 | I: IndexInsert, 43 | { 44 | fn remove_from_root, F: FnMut(&T) -> bool>( 45 | &self, 46 | root: NODE, 47 | insert_index: &I, 48 | query: Q, 49 | f: F, 50 | ) -> RemoveReturn; 51 | } 52 | 53 | /// Generic trait for splitting an MbrNode 54 | pub trait MbrNodeSplit { 55 | fn split>( 56 | &self, 57 | min: usize, 58 | mbr: &mut Rect, 59 | children: &mut Vec, 60 | ) -> (Rect, Vec); 61 | } 62 | -------------------------------------------------------------------------------- /src/tree/mbr/index/r.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use std::fmt::Debug; 9 | use std::marker::PhantomData; 10 | use std::mem; 11 | use std::ops::Deref; 12 | 13 | use itertools::Itertools; 14 | use num::{Bounded, One, Zero}; 15 | use ordered_float::NotNan; 16 | 17 | use crate::geometry::Rect; 18 | use crate::tree::mbr::index::{ 19 | IndexInsert, IndexRemove, MbrNodeSplit, RemoveReturn, AT_ROOT, D_MAX, NOT_AT_ROOT, 20 | }; 21 | use crate::tree::mbr::{MbrLeaf, MbrLeafGeometry, MbrNode, MbrQuery, RTreeNode}; 22 | use crate::vecext::RetainAndAppend; 23 | use crate::FP; 24 | 25 | #[derive(Debug)] 26 | #[must_use] 27 | enum InsertResult { 28 | Ok, 29 | Split(RTreeNode), 30 | } 31 | 32 | pub trait PickSeed { 33 | fn pick_seed>( 34 | &self, 35 | mbr: &Rect, 36 | children: &Vec, 37 | ) -> (usize, usize); 38 | } 39 | 40 | pub struct Quadratic; 41 | 42 | impl PickSeed for Quadratic 43 | where 44 | LG: MbrLeafGeometry, 45 | { 46 | fn pick_seed>( 47 | &self, 48 | _mbr: &Rect, 49 | children: &Vec, 50 | ) -> (usize, usize) { 51 | let (_, k, l) = children 52 | .iter() 53 | .enumerate() 54 | .tuple_combinations() 55 | // PS1 56 | .map(|((k, k_child), (l, l_child))| { 57 | let mut mbr = Rect::max_inverted(); 58 | k_child.expand_mbr_to_fit(&mut mbr); 59 | l_child.expand_mbr_to_fit(&mut mbr); 60 | (mbr.area() - k_child.area() - l_child.area(), k, l) 61 | }) 62 | // PS2 63 | .max_by_key(|&(j, _, _)| j.try_into().ok().unwrap()) 64 | .unwrap(); 65 | (k, l) 66 | } 67 | } 68 | 69 | pub struct Linear; 70 | 71 | impl PickSeed for Linear 72 | where 73 | LG: MbrLeafGeometry, 74 | { 75 | fn pick_seed>( 76 | &self, 77 | mbr: &Rect, 78 | children: &Vec, 79 | ) -> (usize, usize) { 80 | let mut widths = [P::default(); DIM]; 81 | izip!(widths.iter_mut(), mbr.deref()).for_each(|(width, &(min, max))| { 82 | *width = max - min; 83 | if *width <= Zero::zero() { 84 | *width = One::one(); 85 | } 86 | }); 87 | let mut greatest_lower = [(Bounded::max_value(), 0); DIM]; 88 | let mut least_upper = [(Bounded::min_value(), 0); DIM]; 89 | 90 | // LPS1 91 | children.iter().enumerate().for_each(|(i, child)| { 92 | izip!(least_upper.iter_mut(), greatest_lower.iter_mut()) 93 | .enumerate() 94 | .for_each( 95 | |(dim, (&mut (ref mut lmax, ref mut li), &mut (ref mut gmin, ref mut gi)))| { 96 | let min_for_axis = child.min_for_axis(dim); 97 | let max_for_axis = child.max_for_axis(dim); 98 | if min_for_axis > *lmax { 99 | *lmax = min_for_axis; 100 | *li = i; 101 | } 102 | if max_for_axis < *gmin { 103 | *gmin = min_for_axis; 104 | *gi = i; 105 | } 106 | }, 107 | ); 108 | }); 109 | 110 | let (_, mut k, mut l) = izip!(widths.iter(), least_upper.iter(), greatest_lower.iter()) 111 | // LPS2 112 | .map(|(width, &(lmax, li), &(gmin, gi))| (((gmin - lmax) / *width), li, gi)) 113 | // LPS3 114 | .max_by_key(|&(separation, _, _)| separation.try_into().ok().unwrap()) 115 | .unwrap(); 116 | 117 | if k > l { 118 | mem::swap(&mut k, &mut l); 119 | } 120 | (k, l) 121 | } 122 | } 123 | 124 | pub struct SeedSplit { 125 | pick_seed: PS, 126 | _p: PhantomData

, 127 | _lg: PhantomData, 128 | _t: PhantomData, 129 | } 130 | 131 | impl SeedSplit 132 | where 133 | LG: MbrLeafGeometry, 134 | { 135 | pub fn linear() -> SeedSplit { 136 | SeedSplit { 137 | pick_seed: Linear, 138 | _p: PhantomData, 139 | _lg: PhantomData, 140 | _t: PhantomData, 141 | } 142 | } 143 | 144 | pub fn quadratic() -> SeedSplit { 145 | SeedSplit { 146 | pick_seed: Quadratic, 147 | _p: PhantomData, 148 | _lg: PhantomData, 149 | _t: PhantomData, 150 | } 151 | } 152 | } 153 | 154 | impl MbrNodeSplit for SeedSplit 155 | where 156 | LG: MbrLeafGeometry, 157 | PS: PickSeed, 158 | { 159 | fn split>( 160 | &self, 161 | min: usize, 162 | mbr: &mut Rect, 163 | children: &mut Vec, 164 | ) -> (Rect, Vec) { 165 | assert!(!children.is_empty(), "Empty children should not be split."); 166 | // QS1 167 | let (mut k, mut l) = self.pick_seed.pick_seed(mbr, children); 168 | 169 | // in the unlikely scenario of a tie, just pick something 170 | if k == l { 171 | if k < children.len() - 1 { 172 | l += 1; 173 | } else { 174 | k -= 1; 175 | } 176 | } 177 | 178 | assert!(k < l, "k {:?} must be less than l {:?}", k, l); 179 | 180 | let mut k_mbr = Rect::max_inverted(); 181 | let k_child = children.remove(k); 182 | k_child.expand_mbr_to_fit(&mut k_mbr); 183 | let mut k_children = Vec::new(); 184 | k_children.push(k_child); 185 | 186 | let mut l_mbr = Rect::max_inverted(); 187 | // -1 because we removed k 188 | let l_child = children.remove(l - 1); 189 | l_child.expand_mbr_to_fit(&mut l_mbr); 190 | let mut l_children = Vec::new(); 191 | l_children.push(l_child); 192 | 193 | loop { 194 | // QS2 195 | if children.is_empty() { 196 | break; 197 | } 198 | if k_children.len() + children.len() == min { 199 | for child in children.iter() { 200 | child.expand_mbr_to_fit(&mut k_mbr); 201 | } 202 | k_children.append(children); 203 | break; 204 | } 205 | if l_children.len() + children.len() == min { 206 | for child in children.iter() { 207 | child.expand_mbr_to_fit(&mut l_mbr); 208 | } 209 | l_children.append(children); 210 | break; 211 | } 212 | // QS3 213 | if let Some(child) = children.pop() { 214 | let mut k_expanded = k_mbr.clone(); 215 | child.expand_mbr_to_fit(&mut k_expanded); 216 | let mut l_expanded = l_mbr.clone(); 217 | child.expand_mbr_to_fit(&mut l_expanded); 218 | let k_area = k_mbr.area(); 219 | let l_area = l_mbr.area(); 220 | if (k_expanded.area() - k_area, k_area, k_children.len()) 221 | < (l_expanded.area() - l_area, l_area, l_children.len()) 222 | { 223 | k_mbr = k_expanded; 224 | k_children.push(child); 225 | } else { 226 | l_mbr = l_expanded; 227 | l_children.push(child); 228 | } 229 | } 230 | } 231 | *mbr = k_mbr; 232 | children.append(&mut k_children); 233 | (l_mbr, l_children) 234 | } 235 | } 236 | 237 | pub struct RInsert { 238 | preferred_min: usize, 239 | max: usize, 240 | splitter: NS, 241 | _p: PhantomData

, 242 | _lg: PhantomData, 243 | _t: PhantomData, 244 | } 245 | 246 | impl RInsert 247 | where 248 | LG: MbrLeafGeometry, 249 | NS: MbrNodeSplit, 250 | { 251 | pub fn new(splitter: NS) -> RInsert { 252 | // TODO: This type specification shouldn't be needed? 253 | RInsert::new_with_max(splitter, D_MAX) 254 | } 255 | 256 | pub fn new_with_max(splitter: NS, max: usize) -> RInsert { 257 | let min = (max as f32 * 0.3f32) as usize; 258 | RInsert { 259 | preferred_min: min, 260 | max, 261 | splitter, 262 | _p: PhantomData, 263 | _lg: PhantomData, 264 | _t: PhantomData, 265 | } 266 | } 267 | 268 | fn area_cost( 269 | &self, 270 | mbr: &Rect, 271 | leaf: &MbrLeaf, 272 | ) -> (NotNan

, NotNan

) { 273 | let mut expanded = mbr.clone(); 274 | leaf.expand_mbr_to_fit(&mut expanded); 275 | let mbr_area = mbr.area(); 276 | let expanded_area = expanded.area(); 277 | let area_cost = expanded_area - mbr_area; 278 | ( 279 | area_cost.try_into().ok().unwrap(), 280 | expanded_area.try_into().ok().unwrap(), 281 | ) 282 | } 283 | 284 | fn choose_subnode<'tree>( 285 | &self, 286 | level: &'tree mut Vec>, 287 | leaf: &MbrLeaf, 288 | ) -> &'tree mut RTreeNode { 289 | assert!(!level.is_empty(), "Level should not be empty!"); 290 | level 291 | .iter_mut() 292 | .min_by_key(|a| self.area_cost(a.mbr(), leaf)) 293 | .unwrap() 294 | } 295 | 296 | //OT1 297 | fn handle_overflow(&self, level: &mut RTreeNode) -> InsertResult { 298 | match *level { 299 | RTreeNode::Leaves { 300 | ref mut mbr, 301 | ref mut children, 302 | } => { 303 | let (split_mbr, split_children) = 304 | self.splitter.split(self.preferred_min, mbr, children); 305 | InsertResult::Split(RTreeNode::Leaves { 306 | mbr: split_mbr, 307 | children: split_children, 308 | }) 309 | } 310 | RTreeNode::Level { 311 | ref mut mbr, 312 | ref mut children, 313 | } => { 314 | let (split_mbr, split_children) = 315 | self.splitter.split(self.preferred_min, mbr, children); 316 | InsertResult::Split(RTreeNode::Level { 317 | mbr: split_mbr, 318 | children: split_children, 319 | }) 320 | } 321 | } 322 | } 323 | 324 | fn insert_into_level( 325 | &self, 326 | level: &mut RTreeNode, 327 | leaf: MbrLeaf, 328 | ) -> InsertResult { 329 | //I4 330 | leaf.geometry.expand_mbr_to_fit(level.mbr_mut()); 331 | match *level { 332 | //I2 333 | RTreeNode::Leaves { 334 | ref mut children, .. 335 | } => { 336 | children.push(leaf); 337 | } 338 | //I1 339 | RTreeNode::Level { 340 | ref mut children, .. 341 | } => { 342 | //CS3 343 | let insert_result = 344 | self.insert_into_level(self.choose_subnode(children, &leaf), leaf); 345 | //I3 346 | if let InsertResult::Split(child) = insert_result { 347 | children.push(child); 348 | } 349 | } 350 | } 351 | //I2 & I3 352 | if level.len() > self.max { 353 | return self.handle_overflow(level); 354 | } 355 | InsertResult::Ok 356 | } 357 | } 358 | 359 | impl IndexInsert> 360 | for RInsert 361 | where 362 | NS: MbrNodeSplit, 363 | LG: MbrLeafGeometry, 364 | { 365 | fn insert_into_root( 366 | &self, 367 | mut root: RTreeNode, 368 | leaf: MbrLeaf, 369 | ) -> RTreeNode { 370 | let result = self.insert_into_level(&mut root, leaf); 371 | if let InsertResult::Split(split) = result { 372 | let mut mbr = root.mbr().clone(); 373 | split.expand_mbr_to_fit(&mut mbr); 374 | let children = vec![root, split]; 375 | root = RTreeNode::Level { mbr, children }; 376 | } 377 | root 378 | } 379 | 380 | fn preferred_min(&self) -> usize { 381 | self.preferred_min 382 | } 383 | 384 | fn new_leaves(&self) -> RTreeNode { 385 | RTreeNode::new_leaves() 386 | } 387 | 388 | fn new_no_alloc_leaves(&self) -> RTreeNode { 389 | RTreeNode::new_no_alloc() 390 | } 391 | } 392 | 393 | pub struct RRemove { 394 | min: usize, 395 | _p: PhantomData

, 396 | _lg: PhantomData, 397 | _t: PhantomData, 398 | } 399 | 400 | impl RRemove 401 | where 402 | LG: MbrLeafGeometry, 403 | { 404 | pub fn with_min(min: usize) -> RRemove { 405 | assert!(min > 0, "min({:?}) must be at least 0.", min); 406 | RRemove { 407 | min, 408 | _p: PhantomData, 409 | _lg: PhantomData, 410 | _t: PhantomData, 411 | } 412 | } 413 | 414 | /// Removes matching leaves from a leaf level. Return true if the level should be retained 415 | fn remove_matching_leaves< 416 | Q: MbrQuery>, 417 | F: FnMut(&T) -> bool, 418 | >( 419 | &self, 420 | query: &Q, 421 | mbr: &mut Rect, 422 | children: &mut Vec>, 423 | removed: &mut Vec>, 424 | to_reinsert: &mut Vec>, 425 | f: &mut F, 426 | at_root: bool, 427 | ) -> bool { 428 | let orig_len = children.len(); 429 | // D2 430 | children.retain_and_append(removed, |leaf| !query.accept_leaf(leaf) || f(&leaf.item)); 431 | let children_removed = orig_len != children.len(); 432 | // CT3 433 | if children.len() < self.min && !at_root { 434 | to_reinsert.append(children); 435 | return false; 436 | } 437 | // CT4 438 | if children_removed { 439 | *mbr = Rect::max_inverted(); 440 | for child in children { 441 | child.expand_mbr_to_fit(mbr); 442 | } 443 | } 444 | true 445 | } 446 | 447 | /// Consume all child leaves and queue them for reinsert 448 | fn consume_leaves_for_reinsert( 449 | &self, 450 | nodes: &mut Vec>, 451 | to_reinsert: &mut Vec>, 452 | ) { 453 | for node in nodes { 454 | match *node { 455 | RTreeNode::Leaves { 456 | ref mut children, .. 457 | } => to_reinsert.append(&mut mem::replace(children, Vec::with_capacity(0))), 458 | RTreeNode::Level { 459 | ref mut children, .. 460 | } => self.consume_leaves_for_reinsert(children, to_reinsert), 461 | } 462 | } 463 | } 464 | 465 | /// Recursively remove leaves from a level. Return true if the level should be retianed 466 | fn remove_leaves_from_level< 467 | Q: MbrQuery>, 468 | F: FnMut(&T) -> bool, 469 | >( 470 | &self, 471 | query: &Q, 472 | level: &mut RTreeNode, 473 | removed: &mut Vec>, 474 | to_reinsert: &mut Vec>, 475 | f: &mut F, 476 | at_root: bool, 477 | ) -> bool { 478 | // FL1 479 | if !query.accept_level(level) { 480 | return true; 481 | } 482 | match *level { 483 | // FL2 484 | RTreeNode::Leaves { 485 | ref mut mbr, 486 | ref mut children, 487 | .. 488 | } => { 489 | return self.remove_matching_leaves( 490 | query, 491 | mbr, 492 | children, 493 | removed, 494 | to_reinsert, 495 | f, 496 | at_root, 497 | ) 498 | } 499 | RTreeNode::Level { 500 | ref mut mbr, 501 | ref mut children, 502 | .. 503 | } => { 504 | let orig_len = children.len(); 505 | children.retain_mut(|child| { 506 | self.remove_leaves_from_level( 507 | query, 508 | child, 509 | removed, 510 | to_reinsert, 511 | f, 512 | NOT_AT_ROOT, 513 | ) 514 | }); 515 | let children_removed = orig_len != children.len(); 516 | // CT5 517 | // This technically goes against the original R-Tree paper, 518 | // but it's a bit simpler given the height-naive data structures and algorithms I've written 519 | if children.len() < self.min && !at_root { 520 | self.consume_leaves_for_reinsert(children, to_reinsert); 521 | return false; 522 | } 523 | if children_removed { 524 | *mbr = Rect::max_inverted(); 525 | for child in &*children { 526 | child.expand_mbr_to_fit(mbr); 527 | } 528 | } 529 | } 530 | } 531 | true 532 | } 533 | } 534 | 535 | impl IndexRemove, I> 536 | for RRemove 537 | where 538 | LG: MbrLeafGeometry, 539 | I: IndexInsert>, 540 | { 541 | fn remove_from_root< 542 | Q: MbrQuery>, 543 | F: FnMut(&T) -> bool, 544 | >( 545 | &self, 546 | mut root: RTreeNode, 547 | insert_index: &I, 548 | query: Q, 549 | mut f: F, 550 | ) -> RemoveReturn> { 551 | if root.is_empty() { 552 | (root, Vec::with_capacity(0)) 553 | } else { 554 | // CT1 555 | let mut to_reinsert = Vec::new(); 556 | let mut removed = Vec::new(); 557 | // D1 && CT2 558 | self.remove_leaves_from_level( 559 | &query, 560 | &mut root, 561 | &mut removed, 562 | &mut to_reinsert, 563 | &mut f, 564 | AT_ROOT, 565 | ); 566 | // Insert algorithms require an empty root to be for leaves 567 | if root.is_empty() && root.has_levels() { 568 | root = insert_index.new_leaves(); 569 | } 570 | // CT6 571 | for leaf in to_reinsert { 572 | root = insert_index.insert_into_root(root, leaf); 573 | } 574 | (root, removed) 575 | } 576 | } 577 | } 578 | -------------------------------------------------------------------------------- /src/tree/mbr/index/rstar.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use crate::geometry::Rect; 9 | use num::{Float, Zero}; 10 | use ordered_float::NotNan; 11 | use std::cmp; 12 | use std::fmt::Debug; 13 | use std::marker::PhantomData; 14 | use std::ops::Range; 15 | use crate::tree::mbr::index::{IndexInsert, AT_ROOT, DONT_FORCE_SPLIT, D_MAX, FORCE_SPLIT, NOT_AT_ROOT}; 16 | use crate::tree::mbr::{MbrLeaf, MbrLeafGeometry, MbrNode, RTreeNode}; 17 | use crate::FP; 18 | 19 | const D_REINSERT_P: f32 = 0.30f32; 20 | const D_SPLIT_P: f32 = 0.40f32; 21 | const D_CHOOSE_SUBTREE_P: usize = 32; 22 | 23 | /// The sum of all of the Shapes's edges. Used in the R* algorithm 24 | pub trait Margin

{ 25 | fn margin(&self) -> P; 26 | } 27 | 28 | impl Margin

for Rect { 29 | fn margin(&self) -> P { 30 | self.edges 31 | .iter() 32 | .fold(Zero::zero(), |margin, &(x, y)| margin + y - x) 33 | } 34 | } 35 | 36 | #[derive(Debug)] 37 | #[must_use] 38 | enum InsertResult { 39 | Ok, 40 | Reinsert(Vec>), 41 | Split(RTreeNode), 42 | } 43 | 44 | impl InsertResult { 45 | fn is_reinsert(&self) -> bool { 46 | match *self { 47 | InsertResult::Reinsert(_) => true, 48 | _ => false, 49 | } 50 | } 51 | } 52 | 53 | #[derive(Debug)] 54 | pub struct RStarInsert { 55 | max: usize, 56 | preferred_min: usize, 57 | reinsert_m: usize, 58 | choose_subtree_p: usize, 59 | min_k: usize, 60 | max_k: usize, 61 | _p: PhantomData

, 62 | _lg: PhantomData, 63 | _t: PhantomData, 64 | } 65 | 66 | impl RStarInsert 67 | where 68 | LG: MbrLeafGeometry, 69 | { 70 | pub fn new() -> RStarInsert { 71 | RStarInsert::new_with_options(D_MAX, D_REINSERT_P, D_SPLIT_P, D_CHOOSE_SUBTREE_P) 72 | } 73 | 74 | pub fn new_with_max(max: usize) -> RStarInsert { 75 | RStarInsert::new_with_options(max, D_REINSERT_P, D_SPLIT_P, D_CHOOSE_SUBTREE_P) 76 | } 77 | 78 | pub fn new_with_options( 79 | max: usize, 80 | reinsert_p: f32, 81 | split_p: f32, 82 | choose_subtree_p: usize, 83 | ) -> RStarInsert { 84 | let preferred_min = cmp::max((max as f32 * reinsert_p.min(split_p)) as usize, 1); 85 | let reinsert_size = cmp::max((max as f32 * reinsert_p) as usize, 1); 86 | let reinsert_m = max - reinsert_size; 87 | 88 | let min_k = cmp::max((max as f32 * split_p) as usize, 1); 89 | let max_k = cmp::max(max - (2 * min_k) + 1, min_k + 1); 90 | // On max_k==min_k, the iterator in split is a no-op and vec splits occur at index 0. Happens with M - 2m + 1 and M - 2m + 2 for various small Ms. 91 | // The above line should prevent this, but assert in case code changes 92 | assert!( 93 | max_k > min_k, 94 | "max_k({:?}) must be greater than min_k({:?})", 95 | max_k, 96 | min_k 97 | ); 98 | assert!( 99 | max > max_k, 100 | "max({:?}) must be greater than max_k({:?})", 101 | max, 102 | max_k 103 | ); 104 | RStarInsert { 105 | max, 106 | preferred_min, 107 | reinsert_m, 108 | choose_subtree_p, 109 | min_k, 110 | max_k, 111 | _p: PhantomData, 112 | _lg: PhantomData, 113 | _t: PhantomData, 114 | } 115 | } 116 | 117 | fn area_cost( 118 | &self, 119 | mbr: &Rect, 120 | leaf: &MbrLeaf, 121 | ) -> (NotNan

, NotNan

) { 122 | let mut expanded = mbr.clone(); 123 | leaf.expand_mbr_to_fit(&mut expanded); 124 | let mbr_area = mbr.area(); 125 | let area_cost = expanded.area() - mbr_area; 126 | ( 127 | area_cost.try_into().ok().unwrap(), 128 | mbr_area.try_into().ok().unwrap(), 129 | ) 130 | } 131 | 132 | fn overlap_cost(&self, mbr: &Rect, leaf: &MbrLeaf) -> NotNan

{ 133 | let overlap = leaf.area_overlapped_with_mbr(mbr); 134 | let overlap_cost = leaf.area() - overlap; 135 | overlap_cost.try_into().ok().unwrap() 136 | } 137 | 138 | fn overlap_area_cost( 139 | &self, 140 | mbr: &Rect, 141 | leaf: &MbrLeaf, 142 | ) -> (NotNan

, NotNan

, NotNan

) { 143 | let (area_cost, mbr_area) = self.area_cost(mbr, leaf); 144 | let overlap_cost = self.overlap_cost(mbr, leaf); 145 | (overlap_cost, area_cost, mbr_area) 146 | } 147 | 148 | // CS2 + optimizations 149 | fn choose_subnode<'tree>( 150 | &self, 151 | level: &'tree mut Vec>, 152 | leaf: &MbrLeaf, 153 | ) -> &'tree mut RTreeNode { 154 | assert!(!level.is_empty(), "Level should not be empty!"); 155 | if level.first().unwrap().has_leaves() { 156 | if level.len() > self.choose_subtree_p { 157 | level.sort_by_key(|a| self.area_cost(a.mbr(), leaf)); 158 | let (left, _) = level.split_at_mut(self.choose_subtree_p); 159 | return left 160 | .iter_mut() 161 | .min_by_key(|a| self.overlap_cost(a.mbr(), leaf)) 162 | .unwrap(); 163 | } else { 164 | return level 165 | .iter_mut() 166 | .min_by_key(|a| self.overlap_area_cost(a.mbr(), leaf)) 167 | .unwrap(); 168 | } 169 | } 170 | level 171 | .iter_mut() 172 | .min_by_key(|a| self.area_cost(a.mbr(), leaf)) 173 | .unwrap() 174 | } 175 | 176 | fn split_for_reinsert( 177 | &self, 178 | mbr: &mut Rect, 179 | children: &mut Vec>, 180 | ) -> Vec> { 181 | // RI1 & RI2 182 | children.sort_by_key(|a| a.distance_from_mbr_center(mbr).try_into().ok().unwrap()); 183 | //RI3 184 | let split = children.split_off(self.reinsert_m); 185 | *mbr = Rect::max_inverted(); 186 | for child in children { 187 | child.expand_mbr_to_fit(mbr); 188 | } 189 | split 190 | } 191 | 192 | fn insert_into_level( 193 | &self, 194 | level: &mut RTreeNode, 195 | leaf: MbrLeaf, 196 | at_root: bool, 197 | force_split: bool, 198 | ) -> InsertResult { 199 | //I4 200 | leaf.geometry.expand_mbr_to_fit(level.mbr_mut()); 201 | match *level { 202 | //I2 203 | RTreeNode::Leaves { 204 | ref mut children, .. 205 | } => { 206 | children.push(leaf); 207 | } 208 | //I1 209 | RTreeNode::Level { 210 | ref mut mbr, 211 | ref mut children, 212 | } => { 213 | //CS3 214 | let insert_result = self.insert_into_level( 215 | self.choose_subnode(children, &leaf), 216 | leaf, 217 | NOT_AT_ROOT, 218 | force_split, 219 | ); 220 | //I3 221 | if let InsertResult::Split(child) = insert_result { 222 | children.push(child); 223 | } else { 224 | //I4 225 | if insert_result.is_reinsert() { 226 | *mbr = Rect::max_inverted(); 227 | for child in children { 228 | child.mbr().expand_mbr_to_fit(mbr); 229 | } 230 | } 231 | return insert_result; 232 | } 233 | } 234 | } 235 | //I2 & I3 236 | if level.len() > self.max { 237 | return self.handle_overflow(level, at_root, force_split); 238 | } 239 | InsertResult::Ok 240 | } 241 | 242 | // fn best_position_for_axis -> (margin, (axis, edge, index)) 243 | fn best_split_position_for_axis>( 244 | &self, 245 | axis: usize, 246 | children: &mut Vec, 247 | ) -> (P, (usize, usize, usize)) { 248 | let mut margin: P = Zero::zero(); 249 | let mut d_area: P = Float::max_value(); 250 | let mut d_overlap: P = Float::max_value(); 251 | let mut d_edge: usize = 0; 252 | let mut d_index: usize = 0; 253 | 254 | for edge in 0..2 { 255 | if edge == 0 { 256 | children.sort_by_key(|child| child.min_for_axis(axis).try_into().ok().unwrap()); 257 | } else { 258 | children.sort_by_key(|child| child.max_for_axis(axis).try_into().ok().unwrap()); 259 | } 260 | 261 | for k in self.min_k..self.max_k { 262 | let mut r1 = Rect::max_inverted(); 263 | let mut r2 = Rect::max_inverted(); 264 | 265 | let (left, right) = children.split_at(k); 266 | for child in left { 267 | child.expand_mbr_to_fit(&mut r1); 268 | } 269 | for child in right { 270 | child.expand_mbr_to_fit(&mut r2); 271 | } 272 | 273 | // (I) 274 | let area = r1.area() + r2.area(); 275 | // (II) 276 | margin += r1.margin() + r2.margin(); 277 | // (III) 278 | let overlap = r1.area_overlapped_with_mbr(&r2); 279 | 280 | // CSI1 281 | if (overlap, area) < (d_overlap, d_area) { 282 | d_overlap = overlap; 283 | d_area = area; 284 | d_edge = edge; 285 | d_index = k; 286 | } 287 | } 288 | } 289 | (margin, (axis, d_edge, d_index)) 290 | } 291 | 292 | fn split>( 293 | &self, 294 | mbr: &mut Rect, 295 | children: &mut Vec, 296 | ) -> (Rect, Vec) { 297 | // S1 & S2 298 | let (s_axis, s_edge, s_index) = Range { start: 0, end: DIM } 299 | // CSA1 300 | .map(|axis| self.best_split_position_for_axis(axis, children)) 301 | // CSA2 302 | .min_by_key(|&(margin, _)| margin.try_into().ok().unwrap()) 303 | .unwrap() 304 | .1; 305 | 306 | if s_edge == 0 { 307 | children.sort_by_key(|child| child.min_for_axis(s_axis).try_into().ok().unwrap()); 308 | } else { 309 | children.sort_by_key(|child| child.max_for_axis(s_axis).try_into().ok().unwrap()); 310 | } 311 | // S3 312 | let split_children = children.split_off(s_index); 313 | *mbr = Rect::max_inverted(); 314 | let mut split_mbr = Rect::max_inverted(); 315 | for child in &*children { 316 | child.expand_mbr_to_fit(mbr); 317 | } 318 | for split_child in &split_children { 319 | split_child.expand_mbr_to_fit(&mut split_mbr); 320 | } 321 | (split_mbr, split_children) 322 | } 323 | 324 | //OT1 325 | fn handle_overflow( 326 | &self, 327 | level: &mut RTreeNode, 328 | at_root: bool, 329 | force_split: bool, 330 | ) -> InsertResult { 331 | if !at_root && !force_split { 332 | match *level { 333 | RTreeNode::Leaves { 334 | ref mut mbr, 335 | ref mut children, 336 | } => return InsertResult::Reinsert(self.split_for_reinsert(mbr, children)), 337 | _ => unreachable!(), 338 | } 339 | } 340 | match *level { 341 | RTreeNode::Leaves { 342 | ref mut mbr, 343 | ref mut children, 344 | } => { 345 | let (split_mbr, split_children) = self.split(mbr, children); 346 | InsertResult::Split(RTreeNode::Leaves { 347 | mbr: split_mbr, 348 | children: split_children, 349 | }) 350 | } 351 | RTreeNode::Level { 352 | ref mut mbr, 353 | ref mut children, 354 | } => { 355 | let (split_mbr, split_children) = self.split(mbr, children); 356 | InsertResult::Split(RTreeNode::Level { 357 | mbr: split_mbr, 358 | children: split_children, 359 | }) 360 | } 361 | } 362 | } 363 | 364 | fn handle_split_root( 365 | &self, 366 | root: RTreeNode, 367 | split: RTreeNode, 368 | ) -> RTreeNode { 369 | let mut mbr = root.mbr().clone(); 370 | split.expand_mbr_to_fit(&mut mbr); 371 | RTreeNode::Level { 372 | mbr: mbr, 373 | children: vec![root, split], 374 | } 375 | } 376 | } 377 | 378 | impl IndexInsert> 379 | for RStarInsert 380 | where 381 | LG: MbrLeafGeometry, 382 | { 383 | fn insert_into_root( 384 | &self, 385 | mut root: RTreeNode, 386 | leaf: MbrLeaf, 387 | ) -> RTreeNode { 388 | let insert_results = self.insert_into_level(&mut root, leaf, FORCE_SPLIT, DONT_FORCE_SPLIT); 389 | match insert_results { 390 | InsertResult::Split(child) => self.handle_split_root(root, child), 391 | // RI4 392 | InsertResult::Reinsert(leaves) => { 393 | for leaf in leaves { 394 | match self.insert_into_level(&mut root, leaf, AT_ROOT, FORCE_SPLIT) { 395 | InsertResult::Split(child) => { 396 | root = self.handle_split_root(root, child); 397 | } 398 | InsertResult::Reinsert(_) => unreachable!(), 399 | InsertResult::Ok => continue, 400 | } 401 | } 402 | root 403 | } 404 | _ => root, 405 | } 406 | } 407 | 408 | fn preferred_min(&self) -> usize { 409 | self.preferred_min 410 | } 411 | 412 | fn new_leaves(&self) -> RTreeNode { 413 | RTreeNode::new_leaves() 414 | } 415 | 416 | fn new_no_alloc_leaves(&self) -> RTreeNode { 417 | RTreeNode::new_no_alloc() 418 | } 419 | } 420 | 421 | #[cfg(test)] 422 | mod tests { 423 | use super::*; 424 | use crate::geometry::Rect; 425 | 426 | #[test] 427 | fn margin() { 428 | let g_one = [1.0f64, 1.0f64, 1.0f64]; 429 | let g_zero = [0.0f64, 0.0f64, 0.0f64]; 430 | 431 | // contained 432 | let zero_one = Rect::from_corners(g_zero.clone(), g_one.clone()); 433 | // margin 434 | assert_relative_eq!(3.0f64, zero_one.margin()); 435 | } 436 | } 437 | -------------------------------------------------------------------------------- /src/tree/mbr/leaf.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use crate::geometry::Rect; 9 | use std::fmt::Debug; 10 | use std::marker::PhantomData; 11 | use crate::tree::mbr::MbrLeafGeometry; 12 | use crate::FP; 13 | 14 | /// A tree leaf 15 | #[derive(Debug, Clone)] 16 | pub struct MbrLeaf { 17 | pub geometry: LG, 18 | pub item: T, 19 | _p: PhantomData

, 20 | } 21 | 22 | impl MbrLeaf 23 | where 24 | LG: MbrLeafGeometry, 25 | { 26 | /// New leaf from geometry and item 27 | pub fn new(geometry: LG, item: T) -> MbrLeaf { 28 | MbrLeaf { 29 | geometry, 30 | item, 31 | _p: PhantomData, 32 | } 33 | } 34 | 35 | /// Consumes self, returning the geometry and item 36 | pub fn extract(self) -> (LG, T) { 37 | (self.geometry, self.item) 38 | } 39 | 40 | pub fn as_tuple(&self) -> (&LG, &T) { 41 | (&self.geometry, &self.item) 42 | } 43 | 44 | pub fn as_mut_tuple(&mut self) -> (&LG, &mut T) { 45 | (&self.geometry, &mut self.item) 46 | } 47 | } 48 | 49 | impl MbrLeafGeometry for MbrLeaf 50 | where 51 | LG: MbrLeafGeometry, 52 | { 53 | fn dim(&self) -> usize { 54 | self.geometry.dim() 55 | } 56 | 57 | fn area(&self) -> P { 58 | self.geometry.area() 59 | } 60 | 61 | fn min_for_axis(&self, dim: usize) -> P { 62 | self.geometry.min_for_axis(dim) 63 | } 64 | 65 | fn max_for_axis(&self, dim: usize) -> P { 66 | self.geometry.max_for_axis(dim) 67 | } 68 | 69 | fn expand_mbr_to_fit(&self, edges: &mut Rect) { 70 | self.geometry.expand_mbr_to_fit(edges) 71 | } 72 | 73 | fn distance_from_mbr_center(&self, edges: &Rect) -> P { 74 | self.geometry.distance_from_mbr_center(edges) 75 | } 76 | 77 | fn contained_by_mbr(&self, edges: &Rect) -> bool { 78 | self.geometry.contained_by_mbr(edges) 79 | } 80 | 81 | fn overlapped_by_mbr(&self, edges: &Rect) -> bool { 82 | self.geometry.overlapped_by_mbr(edges) 83 | } 84 | 85 | fn area_overlapped_with_mbr(&self, edges: &Rect) -> P { 86 | self.geometry.area_overlapped_with_mbr(edges) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/tree/mbr/leafgeometry.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use crate::geometry::{LineSegment, Point, Rect, Shapes}; 9 | use num::{pow, Float, FromPrimitive, One, Zero}; 10 | use std::ops::{Deref, DerefMut}; 11 | use crate::FP; 12 | 13 | /// The minimum functionality required to insert leaf geometry into `MbrMap` 14 | /// Until the rust compiler allows compile-time generic integers, we'll be using generic_array's `ArrayLength` to specify 15 | /// geometry dimensions at compile time. 16 | /// 17 | /// The parameter `mbr` represents a minimum bounding rectangle. 18 | /// An mbr whose corners are at (x1, y1), (x2, y2) will have the corresponding edges: (x1, x2), (y1, y2) 19 | pub trait MbrLeafGeometry { 20 | /// The geometry's dimension count 21 | fn dim(&self) -> usize; 22 | 23 | /// Determine the area of the geometry 24 | fn area(&self) -> P; 25 | 26 | /// the minimum extent for a given axis 27 | fn min_for_axis(&self, dim: usize) -> P; 28 | 29 | /// the maximum extent for a given axis 30 | fn max_for_axis(&self, dim: usize) -> P; 31 | 32 | /// Expand the mbr to minimally fit the leaf 33 | fn expand_mbr_to_fit(&self, mbr: &mut Rect); 34 | 35 | /// Determine the distance from the mbr's center 36 | fn distance_from_mbr_center(&self, mbr: &Rect) -> P; 37 | 38 | /// Determine if the leaf is completely contained in the mbr 39 | fn contained_by_mbr(&self, mbr: &Rect) -> bool; 40 | 41 | /// Determine if the leaf overlaps the mbr 42 | fn overlapped_by_mbr(&self, mbr: &Rect) -> bool; 43 | 44 | /// Determines the leaf area shared with the rectangle. 45 | /// In cases where the leaf and mbr overlap, but the leaf has no area (point or a line, for example), return 0 46 | fn area_overlapped_with_mbr(&self, mbr: &Rect) -> P; 47 | } 48 | 49 | impl MbrLeafGeometry for Point { 50 | fn dim(&self) -> usize { 51 | self.coords.len() 52 | } 53 | 54 | fn area(&self) -> P { 55 | Zero::zero() 56 | } 57 | 58 | fn min_for_axis(&self, dim: usize) -> P { 59 | *self.coords.get(dim).unwrap() 60 | } 61 | 62 | fn max_for_axis(&self, dim: usize) -> P { 63 | *self.coords.get(dim).unwrap() 64 | } 65 | 66 | fn expand_mbr_to_fit(&self, mbr: &mut Rect) { 67 | for (&mut (ref mut x, ref mut y), &z) in izip!(mbr.deref_mut(), self.deref()) { 68 | *x = Float::min(*x, z); 69 | *y = Float::max(*y, z); 70 | } 71 | } 72 | 73 | fn distance_from_mbr_center(&self, mbr: &Rect) -> P { 74 | let two = FromPrimitive::from_usize(2).unwrap(); 75 | let dist: P = izip!(mbr.deref(), self.deref()) 76 | .fold(Zero::zero(), |distance, (&(x, y), &z)| { 77 | distance + pow(((x + y) / two) - z, 2) 78 | }); 79 | dist.sqrt() 80 | } 81 | 82 | fn contained_by_mbr(&self, mbr: &Rect) -> bool { 83 | self.overlapped_by_mbr(mbr) 84 | } 85 | 86 | fn overlapped_by_mbr(&self, mbr: &Rect) -> bool { 87 | for (&(x, y), &z) in izip!(mbr.deref(), self.deref()) { 88 | if z < x || y < z { 89 | return false; 90 | } 91 | } 92 | true 93 | } 94 | 95 | #[allow(unused_variables)] 96 | fn area_overlapped_with_mbr(&self, mbr: &Rect) -> P { 97 | Zero::zero() 98 | } 99 | } 100 | 101 | impl MbrLeafGeometry for LineSegment { 102 | fn dim(&self) -> usize { 103 | self.x.dim() 104 | } 105 | fn area(&self) -> P { 106 | Zero::zero() 107 | } 108 | 109 | fn min_for_axis(&self, dim: usize) -> P { 110 | Float::min( 111 | *self.x.coords.get(dim).unwrap(), 112 | *self.y.coords.get(dim).unwrap(), 113 | ) 114 | } 115 | 116 | fn max_for_axis(&self, dim: usize) -> P { 117 | Float::max( 118 | *self.x.coords.get(dim).unwrap(), 119 | *self.y.coords.get(dim).unwrap(), 120 | ) 121 | } 122 | 123 | fn expand_mbr_to_fit(&self, mbr: &mut Rect) { 124 | self.x.expand_mbr_to_fit(mbr); 125 | self.y.expand_mbr_to_fit(mbr); 126 | } 127 | 128 | fn distance_from_mbr_center(&self, mbr: &Rect) -> P { 129 | let two = FromPrimitive::from_usize(2).unwrap(); 130 | let dist: P = izip!(mbr.deref(), self.x.deref(), self.y.deref()) 131 | .fold(Zero::zero(), |distance, (&(x1, y1), &x2, &y2)| { 132 | distance + pow((x1 + y1) / two - (x2 + y2) / two, 2) 133 | }); 134 | dist.sqrt() 135 | } 136 | 137 | fn contained_by_mbr(&self, mbr: &Rect) -> bool { 138 | self.x.contained_by_mbr(mbr) && self.y.contained_by_mbr(mbr) 139 | } 140 | 141 | fn overlapped_by_mbr(&self, mbr: &Rect) -> bool { 142 | self.x.overlapped_by_mbr(mbr) || self.y.overlapped_by_mbr(mbr) 143 | } 144 | 145 | #[allow(unused_variables)] 146 | fn area_overlapped_with_mbr(&self, mbr: &Rect) -> P { 147 | Zero::zero() 148 | } 149 | } 150 | 151 | impl MbrLeafGeometry for Rect { 152 | fn dim(&self) -> usize { 153 | self.edges.len() 154 | } 155 | 156 | fn area(&self) -> P { 157 | self.deref() 158 | .iter() 159 | .fold(One::one(), |area, &(x, y)| area * (y - x)) 160 | } 161 | 162 | fn min_for_axis(&self, dim: usize) -> P { 163 | self.edges.get(dim).unwrap().0 164 | } 165 | 166 | fn max_for_axis(&self, dim: usize) -> P { 167 | self.edges.get(dim).unwrap().1 168 | } 169 | 170 | fn expand_mbr_to_fit(&self, mbr: &mut Rect) { 171 | for (&mut (ref mut x1, ref mut y1), &(x2, y2)) in izip!(mbr.deref_mut(), self.deref()) { 172 | *x1 = Float::min(*x1, x2); 173 | *y1 = Float::max(*y1, y2); 174 | } 175 | } 176 | 177 | fn distance_from_mbr_center(&self, mbr: &Rect) -> P { 178 | let two = FromPrimitive::from_usize(2).unwrap(); 179 | let dist: P = izip!(mbr.deref(), self.deref()) 180 | .fold(Zero::zero(), |distance, (&(x1, y1), &(x2, y2))| { 181 | distance + pow((x1 + y1) / two - (x2 + y2) / two, 2) 182 | }); 183 | dist.sqrt() 184 | } 185 | 186 | fn contained_by_mbr(&self, mbr: &Rect) -> bool { 187 | for (&(x1, y1), &(x2, y2)) in izip!(mbr.deref(), self.deref()) { 188 | if x2 < x1 || y1 < y2 { 189 | return false; 190 | } 191 | } 192 | true 193 | } 194 | 195 | fn overlapped_by_mbr(&self, mbr: &Rect) -> bool { 196 | for (&(x1, y1), &(x2, y2)) in izip!(mbr.deref(), self.deref()) { 197 | if !(x1 < y2) || !(x2 < y1) { 198 | return false; 199 | } 200 | } 201 | true 202 | } 203 | 204 | fn area_overlapped_with_mbr(&self, mbr: &Rect) -> P { 205 | izip!(mbr.deref(), self.deref()).fold(One::one(), |area, (&(x1, y1), &(x2, y2))| { 206 | area * Float::max(Float::min(y1, y2) - Float::max(x1, x2), Zero::zero()) 207 | }) 208 | } 209 | } 210 | 211 | impl MbrLeafGeometry for Shapes { 212 | fn dim(&self) -> usize { 213 | match *self { 214 | Shapes::Point(ref point) => point.dim(), 215 | Shapes::LineSegment(ref linesegment) => linesegment.dim(), 216 | Shapes::Rect(ref rect) => rect.dim(), 217 | } 218 | } 219 | 220 | fn area(&self) -> P { 221 | match *self { 222 | Shapes::Point(ref point) => point.area(), 223 | Shapes::LineSegment(ref linesegment) => linesegment.area(), 224 | Shapes::Rect(ref rect) => rect.area(), 225 | } 226 | } 227 | 228 | fn min_for_axis(&self, dim: usize) -> P { 229 | match *self { 230 | Shapes::Point(ref point) => point.min_for_axis(dim), 231 | Shapes::LineSegment(ref linesegment) => linesegment.min_for_axis(dim), 232 | Shapes::Rect(ref rect) => rect.min_for_axis(dim), 233 | } 234 | } 235 | 236 | fn max_for_axis(&self, dim: usize) -> P { 237 | match *self { 238 | Shapes::Point(ref point) => point.max_for_axis(dim), 239 | Shapes::LineSegment(ref linesegment) => linesegment.max_for_axis(dim), 240 | Shapes::Rect(ref rect) => rect.max_for_axis(dim), 241 | } 242 | } 243 | 244 | fn expand_mbr_to_fit(&self, mbr: &mut Rect) { 245 | match *self { 246 | Shapes::Point(ref point) => point.expand_mbr_to_fit(mbr), 247 | Shapes::LineSegment(ref linesegment) => linesegment.expand_mbr_to_fit(mbr), 248 | Shapes::Rect(ref rect) => rect.expand_mbr_to_fit(mbr), 249 | } 250 | } 251 | 252 | fn distance_from_mbr_center(&self, mbr: &Rect) -> P { 253 | match *self { 254 | Shapes::Point(ref point) => point.distance_from_mbr_center(mbr), 255 | Shapes::LineSegment(ref linesegment) => linesegment.distance_from_mbr_center(mbr), 256 | Shapes::Rect(ref rect) => rect.distance_from_mbr_center(mbr), 257 | } 258 | } 259 | 260 | fn contained_by_mbr(&self, mbr: &Rect) -> bool { 261 | match *self { 262 | Shapes::Point(ref point) => point.contained_by_mbr(mbr), 263 | Shapes::LineSegment(ref linesegment) => linesegment.contained_by_mbr(mbr), 264 | Shapes::Rect(ref rect) => rect.contained_by_mbr(mbr), 265 | } 266 | } 267 | 268 | fn overlapped_by_mbr(&self, mbr: &Rect) -> bool { 269 | match *self { 270 | Shapes::Point(ref point) => point.overlapped_by_mbr(mbr), 271 | Shapes::LineSegment(ref linesegment) => linesegment.overlapped_by_mbr(mbr), 272 | Shapes::Rect(ref rect) => rect.overlapped_by_mbr(mbr), 273 | } 274 | } 275 | 276 | fn area_overlapped_with_mbr(&self, mbr: &Rect) -> P { 277 | match *self { 278 | Shapes::Point(ref point) => point.area_overlapped_with_mbr(mbr), 279 | Shapes::LineSegment(ref linesegment) => linesegment.area_overlapped_with_mbr(mbr), 280 | Shapes::Rect(ref rect) => rect.area_overlapped_with_mbr(mbr), 281 | } 282 | } 283 | } 284 | 285 | #[cfg(test)] 286 | mod tests { 287 | use super::*; 288 | use crate::geometry::{LineSegment, Point, Rect, Shapes}; 289 | use std::ops::Deref; 290 | 291 | const ONE: [f64; 3] = [1.0f64, 1.0f64, 1.0f64]; 292 | const ZERO: [f64; 3] = [0.0f64, 0.0f64, 0.0f64]; 293 | const NEG_ONE: [f64; 3] = [-1.0f64, -1.0f64, -1.0f64]; 294 | const NEG_TWO: [f64; 3] = [-2.0f64, -2.0f64, -2.0f64]; 295 | 296 | // distance of [0.5, 0.5, 0.5] 297 | const EXPECTED_DISTANCE: f64 = 0.86602540378f64; 298 | 299 | #[test] 300 | fn point() { 301 | let point: Point = Point::new([0.0; 3]); 302 | for i in point.deref() { 303 | assert_relative_eq!(0.0f64, i); 304 | } 305 | 306 | let zero: Shapes = Shapes::Point(Point::from_slice(&ZERO)); 307 | let one: Shapes = Shapes::Point(Point::from_slice(&ONE)); 308 | let neg_one: Shapes = Shapes::Point(Point::from_slice(&NEG_ONE)); 309 | 310 | // Shape tests 311 | // dim 312 | assert_eq!(ZERO.len(), zero.dim()); 313 | // area 314 | assert_relative_eq!(0.0f64, zero.area()); 315 | // min/max for axis 316 | for (i, item) in ZERO.iter().enumerate() { 317 | assert_relative_eq!(*item, zero.min_for_axis(i)); 318 | assert_relative_eq!(*item, zero.max_for_axis(i)); 319 | } 320 | let mut bounding_mbr = Rect::max_inverted(); 321 | // expand_mbr_to_fit 322 | zero.expand_mbr_to_fit(&mut bounding_mbr); 323 | one.expand_mbr_to_fit(&mut bounding_mbr); 324 | for (i, (x, y)) in izip!(&ZERO, &ONE).enumerate() { 325 | assert_relative_eq!(*x, bounding_mbr.min_for_axis(i)); 326 | assert_relative_eq!(*y, bounding_mbr.max_for_axis(i)); 327 | } 328 | 329 | // distance_from_mbr_center 330 | assert_relative_eq!( 331 | EXPECTED_DISTANCE, 332 | zero.distance_from_mbr_center(&bounding_mbr), 333 | max_relative = 0.00000001 334 | ); 335 | 336 | // contained_by_mbr 337 | assert!(zero.contained_by_mbr(&bounding_mbr)); 338 | assert!(one.contained_by_mbr(&bounding_mbr)); 339 | assert!(!neg_one.contained_by_mbr(&bounding_mbr)); 340 | 341 | // overlapped_by_mbr 342 | assert!(zero.overlapped_by_mbr(&bounding_mbr)); 343 | assert!(one.overlapped_by_mbr(&bounding_mbr)); 344 | assert!(!neg_one.overlapped_by_mbr(&bounding_mbr)); 345 | 346 | // area_overlapped_with_mbr 347 | assert_relative_eq!(0.0f64, zero.area_overlapped_with_mbr(&bounding_mbr)); 348 | } 349 | 350 | #[test] 351 | fn line_segment() { 352 | // contained 353 | let zero_one: Shapes = Shapes::LineSegment(LineSegment::from_slices(&ZERO, &ONE)); 354 | // overlap 355 | let neg_one_one: Shapes = 356 | Shapes::LineSegment(LineSegment::from_slices(&NEG_ONE, &ONE)); 357 | // outside 358 | let neg_two_neg_one: Shapes = 359 | Shapes::LineSegment(LineSegment::from_slices(&NEG_TWO, &NEG_ONE)); 360 | 361 | // Shape tests 362 | // dim 363 | assert_eq!(ZERO.len(), zero_one.dim()); 364 | 365 | // area 366 | assert_relative_eq!(0.0f64, zero_one.area()); 367 | 368 | // min/max for axis 369 | for (i, (x, y)) in izip!(&ZERO, &ONE).enumerate() { 370 | assert_relative_eq!(*x, zero_one.min_for_axis(i)); 371 | assert_relative_eq!(*y, zero_one.max_for_axis(i)); 372 | } 373 | 374 | let mut bounding_mbr = Rect::max_inverted(); 375 | 376 | // expand_mbr_to_fit 377 | zero_one.expand_mbr_to_fit(&mut bounding_mbr); 378 | for (i, (x, y)) in izip!(&ZERO, &ONE).enumerate() { 379 | assert_relative_eq!(*x, bounding_mbr.min_for_axis(i)); 380 | assert_relative_eq!(*y, bounding_mbr.max_for_axis(i)); 381 | } 382 | 383 | // distance_from_mbr_center 384 | assert_relative_eq!( 385 | EXPECTED_DISTANCE, 386 | neg_one_one.distance_from_mbr_center(&bounding_mbr), 387 | max_relative = 0.00000001 388 | ); 389 | 390 | // contained_by_mbr 391 | assert!(zero_one.contained_by_mbr(&bounding_mbr)); 392 | assert!(!neg_one_one.contained_by_mbr(&bounding_mbr)); 393 | assert!(!neg_two_neg_one.contained_by_mbr(&bounding_mbr)); 394 | 395 | // overlapped_by_mbr 396 | assert!(zero_one.overlapped_by_mbr(&bounding_mbr)); 397 | assert!(neg_one_one.overlapped_by_mbr(&bounding_mbr)); 398 | assert!(!neg_two_neg_one.overlapped_by_mbr(&bounding_mbr)); 399 | 400 | // area_overlapped_with_mbr 401 | assert_relative_eq!(0.0f64, zero_one.area_overlapped_with_mbr(&bounding_mbr)); 402 | } 403 | 404 | #[test] 405 | fn rect() { 406 | let g_one = [1.0f64, 1.0f64, 1.0f64]; 407 | let g_zero = [0.0f64, 0.0f64, 0.0f64]; 408 | let g_neg_one = [-1.0f64, -1.0f64, -1.0f64]; 409 | let g_neg_two = [-2.0f64, -2.0f64, -2.0f64]; 410 | 411 | // contained 412 | let zero_one = Rect::from_corners(g_zero.clone(), g_one.clone()); 413 | // overlapped 414 | let neg_one_one = Rect::from_corners(g_neg_one.clone(), g_one.clone()); 415 | // outside 416 | let neg_two_neg_one = Rect::from_corners(g_neg_two.clone(), g_neg_one.clone()); 417 | 418 | // Shape tests 419 | // dim 420 | assert_eq!(zero_one.len(), zero_one.dim()); 421 | 422 | // area 423 | assert_relative_eq!(1.0f64, zero_one.area()); 424 | 425 | // min/max for axis 426 | for (i, (x, y)) in izip!(&ZERO, &ONE).enumerate() { 427 | assert_relative_eq!(*x, zero_one.min_for_axis(i)); 428 | assert_relative_eq!(*y, zero_one.max_for_axis(i)); 429 | } 430 | 431 | let mut bounding_mbr = Rect::max_inverted(); 432 | // expand_mbr_to_fit 433 | zero_one.expand_mbr_to_fit(&mut bounding_mbr); 434 | for (i, (x, y)) in izip!(&ZERO, &ONE).enumerate() { 435 | assert_relative_eq!(*x, bounding_mbr.min_for_axis(i)); 436 | assert_relative_eq!(*y, bounding_mbr.max_for_axis(i)); 437 | } 438 | 439 | // distance_from_mbr_center 440 | assert_relative_eq!( 441 | EXPECTED_DISTANCE, 442 | neg_one_one.distance_from_mbr_center(&bounding_mbr), 443 | max_relative = 0.00000001 444 | ); 445 | 446 | // contained_by_mbr 447 | assert!(zero_one.contained_by_mbr(&bounding_mbr)); 448 | assert!(!neg_one_one.contained_by_mbr(&bounding_mbr)); 449 | assert!(!neg_two_neg_one.contained_by_mbr(&bounding_mbr)); 450 | 451 | // overlapped_by_mbr 452 | assert!(zero_one.overlapped_by_mbr(&bounding_mbr)); 453 | assert!(neg_one_one.overlapped_by_mbr(&bounding_mbr)); 454 | assert!(!neg_two_neg_one.overlapped_by_mbr(&bounding_mbr)); 455 | 456 | // area_overlapped_with_mbr 457 | assert_relative_eq!(1.0f64, zero_one.area_overlapped_with_mbr(&bounding_mbr)); 458 | assert_relative_eq!(1.0f64, neg_one_one.area_overlapped_with_mbr(&bounding_mbr)); 459 | } 460 | } 461 | -------------------------------------------------------------------------------- /src/tree/mbr/map.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use std::mem; 9 | use std::ops::Deref; 10 | use std::rc::Rc; 11 | use std::slice::{Iter as SliceIter, IterMut as SliceIterMut}; 12 | 13 | use crate::geometry::Rect; 14 | use crate::tree::mbr::index::{IndexInsert, IndexRemove}; 15 | use crate::tree::mbr::{MbrLeaf, MbrLeafGeometry, MbrNode, MbrQuery, MbrRectQuery, RTreeNode}; 16 | use crate::FP; 17 | 18 | /// The generic container interface for spatial maps. Will, at the very least, be able to support R, R+, R*, and X trees 19 | pub struct MbrMap { 20 | insert_index: I, 21 | remove_index: R, 22 | root: NODE, 23 | len: usize, 24 | } 25 | 26 | impl MbrMap, I, R> 27 | where 28 | LG: MbrLeafGeometry, 29 | I: IndexInsert>, 30 | R: IndexRemove, I>, 31 | { 32 | /// Create a new MbrMap with the given insert and remove indexes 33 | pub fn new(insert_index: I, remove_index: R) -> MbrMap, I, R> { 34 | let new_root = insert_index.new_leaves(); 35 | MbrMap { 36 | insert_index: insert_index, 37 | remove_index: remove_index, 38 | root: new_root, 39 | len: 0, 40 | } 41 | } 42 | 43 | /// Insert an item 44 | pub fn insert(&mut self, geometry: LG, item: T) { 45 | self.root = self.insert_index.insert_into_root( 46 | mem::replace(&mut self.root, self.insert_index.new_no_alloc_leaves()), 47 | MbrLeaf::new(geometry, item), 48 | ); 49 | self.len += 1; 50 | } 51 | 52 | /// Remove all items whose shapes are accepted by the query. Returns removed entries. 53 | pub fn remove>>( 54 | &mut self, 55 | query: Q, 56 | ) -> Vec<(LG, T)> { 57 | self.retain(query, |_| false) 58 | } 59 | 60 | /// Remove all items whose shapes are accepted by the query and where f(&T) returns false. Returns removed entries 61 | pub fn retain>, F: FnMut(&T) -> bool>( 62 | &mut self, 63 | query: Q, 64 | f: F, 65 | ) -> Vec<(LG, T)> { 66 | let (new_root, removed) = self.remove_index.remove_from_root( 67 | mem::replace(&mut self.root, self.insert_index.new_no_alloc_leaves()), 68 | &self.insert_index, 69 | query, 70 | f, 71 | ); 72 | self.len -= removed.len(); 73 | self.root = new_root; 74 | let mut removed_extract = Vec::with_capacity(removed.len()); 75 | for leaf in removed { 76 | removed_extract.push(leaf.extract()); 77 | } 78 | removed_extract 79 | } 80 | 81 | /// Whether the map is empty 82 | pub fn is_empty(&self) -> bool { 83 | self.len == 0 84 | } 85 | 86 | /// Length of the map 87 | pub fn len(&self) -> usize { 88 | self.len 89 | } 90 | 91 | /// Clear the map 92 | pub fn clear(&mut self) { 93 | self.root = self.insert_index.new_leaves(); 94 | self.len = 0; 95 | } 96 | 97 | /// Iter for the map 98 | pub fn iter(&self) -> Iter> { 99 | Iter::new(MbrRectQuery::Overlaps(Rect::max()), &self.root) 100 | } 101 | 102 | /// IterMut for the map 103 | pub fn iter_mut(&mut self) -> IterMut> { 104 | IterMut::new(MbrRectQuery::Overlaps(Rect::max()), &mut self.root) 105 | } 106 | 107 | /// Iter for the map with a given query 108 | pub fn iter_query>>( 109 | &self, 110 | query: Q, 111 | ) -> Iter { 112 | Iter::new(query, &self.root) 113 | } 114 | 115 | /// IterMut for the map with a given query 116 | pub fn iter_query_mut>>( 117 | &mut self, 118 | query: Q, 119 | ) -> IterMut { 120 | IterMut::new(query, &mut self.root) 121 | } 122 | } 123 | 124 | type LeafIter<'tree, P, const DIM: usize, LG, T> = SliceIter<'tree, MbrLeaf>; 125 | 126 | /// Iterate through all `MbrNode::Leaves` matching a query 127 | struct LevelIter<'tree, P: FP, const DIM: usize, LG, T, Q> 128 | where 129 | LG: 'tree, 130 | T: 'tree, 131 | Q: MbrQuery>, 132 | { 133 | query: Rc, 134 | root: &'tree RTreeNode, 135 | level_stack: Vec>>, 136 | finished: bool, 137 | } 138 | 139 | impl<'tree, P: FP, const DIM: usize, LG, T, Q> LevelIter<'tree, P, DIM, LG, T, Q> 140 | where 141 | LG: MbrLeafGeometry + 'tree, 142 | T: 'tree, 143 | Q: MbrQuery>, 144 | { 145 | /// Constructor 146 | fn new( 147 | query: Rc, 148 | root: &'tree RTreeNode, 149 | ) -> LevelIter<'tree, P, DIM, LG, T, Q> { 150 | if root.is_empty() || !query.accept_level(root) { 151 | return LevelIter { 152 | query: query, 153 | root: root, 154 | level_stack: Vec::with_capacity(0), 155 | finished: true, 156 | }; 157 | } 158 | LevelIter { 159 | query: query, 160 | root: root, 161 | level_stack: Vec::new(), 162 | finished: false, 163 | } 164 | } 165 | 166 | /// Select the next matching leaves level 167 | fn next_leaves( 168 | &mut self, 169 | mut m_iter: SliceIter<'tree, RTreeNode>, 170 | ) -> Option> { 171 | let mut iter_node = m_iter.next(); 172 | while let Some(node) = iter_node { 173 | if !self.query.accept_level(node) { 174 | iter_node = m_iter.next(); 175 | continue; 176 | } 177 | self.level_stack.push(m_iter); 178 | match *node { 179 | RTreeNode::Leaves { ref children, .. } => return Some(children.iter()), 180 | RTreeNode::Level { ref children, .. } => { 181 | let next = self.next_leaves(children.iter()); 182 | if next.is_none() { 183 | m_iter = self.level_stack.pop().unwrap(); 184 | iter_node = m_iter.next(); 185 | continue; 186 | } 187 | return next; 188 | } 189 | } 190 | } 191 | None 192 | } 193 | } 194 | 195 | impl<'tree, P: FP, const DIM: usize, LG, T, Q> Iterator for LevelIter<'tree, P, DIM, LG, T, Q> 196 | where 197 | LG: MbrLeafGeometry + 'tree, 198 | T: 'tree, 199 | Q: MbrQuery>, 200 | { 201 | type Item = LeafIter<'tree, P, DIM, LG, T>; 202 | 203 | fn next(&mut self) -> Option> { 204 | if self.finished { 205 | return None; 206 | } 207 | if self.level_stack.is_empty() { 208 | match *self.root { 209 | RTreeNode::Leaves { ref children, .. } => { 210 | self.finished = true; 211 | return Some(children.iter()); 212 | } 213 | RTreeNode::Level { ref children, .. } => { 214 | self.level_stack.push(children.iter()); 215 | } 216 | } 217 | } 218 | let mut m_iter = self.level_stack.pop().unwrap(); 219 | let mut next = self.next_leaves(m_iter); 220 | while let None = next { 221 | if !self.level_stack.is_empty() { 222 | m_iter = self.level_stack.pop().unwrap(); 223 | next = self.next_leaves(m_iter); 224 | } else { 225 | self.finished = true; 226 | break; 227 | } 228 | } 229 | next 230 | } 231 | } 232 | 233 | type LeafIterMut<'tree, P, const DIM: usize, LG, T> = SliceIterMut<'tree, MbrLeaf>; 234 | 235 | /// Iterate mutably through all `MbrNode::Leaves` matching a query 236 | struct LevelIterMut<'tree, P: FP, const DIM: usize, LG, T, Q> 237 | where 238 | LG: 'tree, 239 | T: 'tree, 240 | Q: MbrQuery>, 241 | { 242 | query: Rc, 243 | root: &'tree mut RTreeNode, 244 | level_stack: Vec>>, 245 | finished: bool, 246 | } 247 | 248 | impl<'tree, P: FP, const DIM: usize, LG, T, Q> LevelIterMut<'tree, P, DIM, LG, T, Q> 249 | where 250 | LG: MbrLeafGeometry + 'tree, 251 | T: 'tree, 252 | Q: MbrQuery>, 253 | { 254 | /// Constructor 255 | fn new( 256 | query: Rc, 257 | root: &'tree mut RTreeNode, 258 | ) -> LevelIterMut<'tree, P, DIM, LG, T, Q> { 259 | if root.is_empty() || !query.accept_level(root) { 260 | return LevelIterMut { 261 | query: query, 262 | root: root, 263 | level_stack: Vec::with_capacity(0), 264 | finished: true, 265 | }; 266 | } 267 | LevelIterMut { 268 | query: query, 269 | root: root, 270 | level_stack: Vec::new(), 271 | finished: false, 272 | } 273 | } 274 | 275 | unsafe fn unpack_root_lifetime(&mut self) -> &'tree mut RTreeNode { 276 | let root: *mut RTreeNode = self.root; 277 | &mut *root 278 | } 279 | 280 | /// Select the next matching leaves level 281 | fn next_leaves( 282 | &mut self, 283 | mut m_iter: SliceIterMut<'tree, RTreeNode>, 284 | ) -> Option> { 285 | let mut iter_node = m_iter.next(); 286 | while let Some(node) = iter_node { 287 | if !self.query.accept_level(node) { 288 | iter_node = m_iter.next(); 289 | continue; 290 | } 291 | self.level_stack.push(m_iter); 292 | match *node { 293 | RTreeNode::Leaves { 294 | ref mut children, .. 295 | } => return Some(children.iter_mut()), 296 | RTreeNode::Level { 297 | ref mut children, .. 298 | } => { 299 | let next = self.next_leaves(children.iter_mut()); 300 | if next.is_none() { 301 | m_iter = self.level_stack.pop().unwrap(); 302 | iter_node = m_iter.next(); 303 | continue; 304 | } 305 | return next; 306 | } 307 | } 308 | } 309 | None 310 | } 311 | } 312 | 313 | impl<'tree, P: FP, const DIM: usize, LG, T, Q> Iterator for LevelIterMut<'tree, P, DIM, LG, T, Q> 314 | where 315 | LG: MbrLeafGeometry + 'tree, 316 | T: 'tree, 317 | Q: MbrQuery>, 318 | { 319 | type Item = LeafIterMut<'tree, P, DIM, LG, T>; 320 | 321 | fn next(&mut self) -> Option> { 322 | if self.finished { 323 | return None; 324 | } 325 | if self.level_stack.is_empty() { 326 | match unsafe { self.unpack_root_lifetime() } { 327 | &mut RTreeNode::Leaves { 328 | ref mut children, .. 329 | } => { 330 | self.finished = true; 331 | return Some(children.iter_mut()); 332 | } 333 | &mut RTreeNode::Level { 334 | ref mut children, .. 335 | } => { 336 | self.level_stack.push(children.iter_mut()); 337 | } 338 | } 339 | } 340 | let mut m_iter = self.level_stack.pop().unwrap(); 341 | let mut next = self.next_leaves(m_iter); 342 | while let None = next { 343 | if !self.level_stack.is_empty() { 344 | m_iter = self.level_stack.pop().unwrap(); 345 | next = self.next_leaves(m_iter); 346 | } else { 347 | self.finished = true; 348 | break; 349 | } 350 | } 351 | next 352 | } 353 | } 354 | 355 | /// Iter all `Leaf` items matching a query 356 | pub struct Iter<'tree, P: FP, const DIM: usize, LG, T, Q> 357 | where 358 | LG: 'tree, 359 | T: 'tree, 360 | Q: MbrQuery>, 361 | { 362 | query: Rc, 363 | level_iter: LevelIter<'tree, P, DIM, LG, T, Q>, 364 | leaf_iter: Option>, 365 | finished: bool, 366 | } 367 | 368 | impl<'tree, P: FP, const DIM: usize, LG, T, Q> Iter<'tree, P, DIM, LG, T, Q> 369 | where 370 | LG: MbrLeafGeometry + 'tree, 371 | T: 'tree, 372 | Q: MbrQuery>, 373 | { 374 | /// Constructor 375 | fn new(query: Q, root: &'tree RTreeNode) -> Iter<'tree, P, DIM, LG, T, Q> { 376 | let rc_query = Rc::new(query); 377 | let level_iter = LevelIter::new(rc_query.clone(), root); 378 | Iter { 379 | query: rc_query, 380 | level_iter: level_iter, 381 | leaf_iter: None, 382 | finished: false, 383 | } 384 | } 385 | 386 | /// Select the next matching leaf 387 | fn next_leaf( 388 | &mut self, 389 | mut iter: SliceIter<'tree, MbrLeaf>, 390 | ) -> Option<(&'tree LG, &'tree T)> { 391 | while let Some(ref mut leaf) = iter.next() { 392 | if !self.query.accept_leaf(leaf) { 393 | continue; 394 | } 395 | self.leaf_iter = Some(iter); 396 | return Some(leaf.as_tuple()); 397 | } 398 | None 399 | } 400 | } 401 | 402 | impl<'tree, P: FP, const DIM: usize, LG, T, Q> Iterator for Iter<'tree, P, DIM, LG, T, Q> 403 | where 404 | LG: MbrLeafGeometry + 'tree, 405 | T: 'tree, 406 | Q: MbrQuery>, 407 | { 408 | type Item = (&'tree LG, &'tree T); 409 | 410 | fn next(&mut self) -> Option<(&'tree LG, &'tree T)> { 411 | if self.finished { 412 | return None; 413 | } 414 | if self.leaf_iter.is_none() { 415 | self.leaf_iter = self.level_iter.next(); 416 | } 417 | if self.leaf_iter.is_none() { 418 | self.finished = true; 419 | return None; 420 | } 421 | let iter = self.leaf_iter.take().unwrap(); 422 | let mut next = self.next_leaf(iter); 423 | while let None = next { 424 | let leaf_iter = self.level_iter.next(); 425 | if !leaf_iter.is_none() { 426 | next = self.next_leaf(leaf_iter.unwrap()); 427 | } else { 428 | self.finished = true; 429 | break; 430 | } 431 | } 432 | next 433 | } 434 | } 435 | 436 | /// Mutably iterate all `Leaf` entries matching a query 437 | pub struct IterMut<'tree, P: FP, const DIM: usize, LG, T, Q> 438 | where 439 | LG: 'tree, 440 | T: 'tree, 441 | Q: MbrQuery>, 442 | { 443 | query: Rc, 444 | level_iter: LevelIterMut<'tree, P, DIM, LG, T, Q>, 445 | leaf_iter: Option>, 446 | finished: bool, 447 | } 448 | 449 | impl<'tree, P: FP, const DIM: usize, LG, T, Q> IterMut<'tree, P, DIM, LG, T, Q> 450 | where 451 | LG: MbrLeafGeometry + 'tree, 452 | T: 'tree, 453 | Q: MbrQuery>, 454 | { 455 | /// Constructor 456 | fn new( 457 | query: Q, 458 | root: &'tree mut RTreeNode, 459 | ) -> IterMut<'tree, P, DIM, LG, T, Q> { 460 | let rc_query = Rc::new(query); 461 | let level_iter = LevelIterMut::new(rc_query.clone(), root); 462 | IterMut { 463 | query: rc_query, 464 | level_iter: level_iter, 465 | leaf_iter: None, 466 | finished: false, 467 | } 468 | } 469 | 470 | /// Select the next matching leaf 471 | fn next_leaf( 472 | &mut self, 473 | mut iter: SliceIterMut<'tree, MbrLeaf>, 474 | ) -> Option<(&'tree LG, &'tree mut T)> { 475 | while let Some(ref mut leaf) = iter.next() { 476 | if !self.query.deref().accept_leaf(leaf) { 477 | continue; 478 | } 479 | self.leaf_iter = Some(iter); 480 | let unsafe_leaf = unsafe { 481 | let unsafe_leaf: *mut MbrLeaf = *leaf; 482 | &mut *unsafe_leaf 483 | }; 484 | return Some(unsafe_leaf.as_mut_tuple()); 485 | } 486 | None 487 | } 488 | } 489 | 490 | impl<'tree, P: FP, const DIM: usize, LG, T, Q> Iterator for IterMut<'tree, P, DIM, LG, T, Q> 491 | where 492 | LG: MbrLeafGeometry, 493 | T: 'tree, 494 | Q: MbrQuery>, 495 | { 496 | type Item = (&'tree LG, &'tree mut T); 497 | 498 | fn next(&mut self) -> Option<(&'tree LG, &'tree mut T)> { 499 | if self.finished { 500 | return None; 501 | } 502 | if self.leaf_iter.is_none() { 503 | self.leaf_iter = self.level_iter.next(); 504 | } 505 | if self.leaf_iter.is_none() { 506 | self.finished = true; 507 | return None; 508 | } 509 | let iter = self.leaf_iter.take().unwrap(); 510 | let mut next = self.next_leaf(iter); 511 | while let None = next { 512 | let leaf_iter = self.level_iter.next(); 513 | if !leaf_iter.is_none() { 514 | next = self.next_leaf(leaf_iter.unwrap()); 515 | } else { 516 | self.finished = true; 517 | break; 518 | } 519 | } 520 | next 521 | } 522 | } 523 | -------------------------------------------------------------------------------- /src/tree/mbr/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! Collection of minimum bounding rectangle spatial trees 9 | 10 | mod index; 11 | mod leaf; 12 | mod leafgeometry; 13 | mod map; 14 | mod node; 15 | mod query; 16 | 17 | use std::marker::PhantomData; 18 | use crate::tree::mbr::index::r::{Linear, Quadratic, RInsert, RRemove, SeedSplit}; 19 | use crate::tree::mbr::index::rstar::RStarInsert; 20 | use crate::tree::mbr::index::{IndexInsert, MbrNodeSplit}; 21 | pub use crate::tree::mbr::leaf::MbrLeaf; 22 | pub use crate::tree::mbr::leafgeometry::MbrLeafGeometry; 23 | pub use crate::tree::mbr::map::{Iter, IterMut, MbrMap}; 24 | pub use crate::tree::mbr::node::{MbrNode, RTreeNode}; 25 | pub use crate::tree::mbr::query::{MbrQuery, MbrRectQuery}; 26 | use crate::FP; 27 | 28 | /// Convenience struct for creating a new R Tree 29 | /// 30 | /// Agorithms described by Guttman, A. (1984). "R-Trees: A Dynamic Index Structure for Spatial Searching" 31 | pub struct RTree { 32 | _p: PhantomData

, 33 | _lg: PhantomData, 34 | _t: PhantomData, 35 | } 36 | 37 | /// R Quadratic Tree Type 38 | pub type RQuadraticTree = MbrMap< 39 | RTreeNode, 40 | RInsert>, 41 | RRemove, 42 | >; 43 | /// R Quadratic Tree Type 44 | pub type RLinearTree = MbrMap< 45 | RTreeNode, 46 | RInsert>, 47 | RRemove, 48 | >; 49 | 50 | impl RTree 51 | where 52 | LG: MbrLeafGeometry, 53 | { 54 | /// Create a new R Tree using the Linear splitting algorithm with min and max children lengths set to 19 and 64, respectively 55 | pub fn new_linear() -> RLinearTree { 56 | // TODO: This type specification shouldn't be needed? Compliation error without them :/ 57 | RTree::map_from_insert(RInsert::new(SeedSplit::::linear())) 58 | } 59 | 60 | /// Create a new R Tree using the Linear splitting algorithm with max children lengths as provided. min length will be set to 0.3 * max 61 | pub fn new_linear_with_max(max: usize) -> RLinearTree { 62 | RTree::map_from_insert(RInsert::new_with_max( 63 | SeedSplit::::linear(), 64 | max, 65 | )) 66 | } 67 | 68 | /// Create a new R Tree using the Quadratic splitting algorithm with min and max children lengths set to 19 and 64, respectively 69 | pub fn new_quadratic() -> RQuadraticTree { 70 | RTree::map_from_insert(RInsert::new( 71 | SeedSplit::::quadratic(), 72 | )) 73 | } 74 | 75 | /// Create a new R Tree using the Quadratic splitting algorithm with max children lengths as provided. min length will be set to 0.3 * max 76 | pub fn new_quadratic_with_max(max: usize) -> RQuadraticTree { 77 | RTree::map_from_insert(RInsert::new_with_max( 78 | SeedSplit::::quadratic(), 79 | max, 80 | )) 81 | } 82 | 83 | fn map_from_insert>( 84 | insert: RInsert, 85 | ) -> MbrMap, RInsert, RRemove> { 86 | let min = insert.preferred_min(); 87 | MbrMap::new(insert, RRemove::with_min(min)) 88 | } 89 | } 90 | 91 | /// R* Tree Type 92 | pub type RStarTree = 93 | MbrMap, RStarInsert, RRemove>; 94 | 95 | /// Convenience struct for creating a new R* Tree 96 | /// 97 | /// Algorithms descibed by Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990). "The R*-tree: an efficient and robust access method for points and rectangles". 98 | pub struct RStar { 99 | _p: PhantomData

, 100 | _lg: PhantomData, 101 | _t: PhantomData, 102 | } 103 | 104 | impl RStar 105 | where 106 | LG: MbrLeafGeometry, 107 | { 108 | /// Create a new R* tree with min and max children lengths set to 19 and 64, respectively 109 | pub fn new() -> RStarTree { 110 | RStar::map_from_insert(RStarInsert::new()) 111 | } 112 | 113 | /// Create a new R* tree with max children lengths as provided. min length will be set to 0.3 * max 114 | pub fn new_with_max(max: usize) -> RStarTree { 115 | RStar::map_from_insert(RStarInsert::new_with_max(max)) 116 | } 117 | 118 | /// Creates a mew R* tree with options as provided. min children will be set to reinsert_p.min(split_p) * max 119 | pub fn new_with_options( 120 | max: usize, 121 | reinsert_p: f32, 122 | split_p: f32, 123 | choose_subtree_p: usize, 124 | ) -> RStarTree { 125 | RStar::map_from_insert(RStarInsert::new_with_options( 126 | max, 127 | reinsert_p, 128 | split_p, 129 | choose_subtree_p, 130 | )) 131 | } 132 | 133 | fn map_from_insert(rstar_insert: RStarInsert) -> RStarTree { 134 | let min = rstar_insert.preferred_min(); 135 | MbrMap::new(rstar_insert, RRemove::with_min(min)) 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/tree/mbr/node.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use crate::geometry::Rect; 9 | use std::fmt::Debug; 10 | use crate::tree::mbr::{MbrLeaf, MbrLeafGeometry}; 11 | use crate::FP; 12 | 13 | /// A node in an MbrMap 14 | pub trait MbrNode: MbrLeafGeometry { 15 | /// Create an empty leaf level 16 | fn new_leaves() -> Self; 17 | 18 | /// Create an empty leaf level with no capacity for leaves. 19 | /// Only used for passing ownership of root into the index functions 20 | fn new_no_alloc() -> Self; 21 | 22 | /// Does the level point to leaves? 23 | fn has_leaves(&self) -> bool; 24 | 25 | /// Does the level point to other levels? 26 | fn has_levels(&self) -> bool; 27 | 28 | /// Borrow the level's minimum bounding rectangle 29 | fn mbr(&self) -> &Rect; 30 | 31 | /// Mutably borrow the level's minimum bounding rectangle 32 | fn mbr_mut(&mut self) -> &mut Rect; 33 | 34 | /// Number of level's children 35 | fn len(&self) -> usize; 36 | 37 | /// Does the level have children? 38 | fn is_empty(&self) -> bool; 39 | } 40 | 41 | /// Level node of a tree. Either contains other levels or leaves 42 | #[derive(Debug)] 43 | pub enum RTreeNode { 44 | /// Contains only other levels 45 | Level { 46 | mbr: Rect, 47 | children: Vec>, 48 | }, 49 | /// Contains only leaves 50 | Leaves { 51 | mbr: Rect, 52 | children: Vec>, 53 | }, 54 | } 55 | 56 | impl MbrNode for RTreeNode 57 | where 58 | LG: MbrLeafGeometry, 59 | { 60 | fn new_leaves() -> RTreeNode { 61 | RTreeNode::Leaves { 62 | mbr: Rect::max_inverted(), 63 | children: Vec::new(), 64 | } 65 | } 66 | 67 | fn new_no_alloc() -> RTreeNode { 68 | RTreeNode::Leaves { 69 | mbr: Rect::max_inverted(), 70 | children: Vec::with_capacity(0), 71 | } 72 | } 73 | 74 | fn has_leaves(&self) -> bool { 75 | match *self { 76 | RTreeNode::Level { .. } => false, 77 | RTreeNode::Leaves { .. } => true, 78 | } 79 | } 80 | 81 | fn has_levels(&self) -> bool { 82 | !self.has_leaves() 83 | } 84 | 85 | fn mbr(&self) -> &Rect { 86 | match *self { 87 | RTreeNode::Level { ref mbr, .. } => mbr, 88 | RTreeNode::Leaves { ref mbr, .. } => mbr, 89 | } 90 | } 91 | 92 | fn mbr_mut(&mut self) -> &mut Rect { 93 | match *self { 94 | RTreeNode::Level { ref mut mbr, .. } => mbr, 95 | RTreeNode::Leaves { ref mut mbr, .. } => mbr, 96 | } 97 | } 98 | 99 | fn len(&self) -> usize { 100 | match *self { 101 | RTreeNode::Level { ref children, .. } => children.len(), 102 | RTreeNode::Leaves { ref children, .. } => children.len(), 103 | } 104 | } 105 | 106 | fn is_empty(&self) -> bool { 107 | match *self { 108 | RTreeNode::Level { ref children, .. } => children.is_empty(), 109 | RTreeNode::Leaves { ref children, .. } => children.is_empty(), 110 | } 111 | } 112 | } 113 | 114 | impl MbrLeafGeometry for RTreeNode 115 | where 116 | LG: MbrLeafGeometry, 117 | { 118 | fn dim(&self) -> usize { 119 | self.mbr().dim() 120 | } 121 | 122 | fn expand_mbr_to_fit(&self, mbr: &mut Rect) { 123 | self.mbr().expand_mbr_to_fit(mbr) 124 | } 125 | 126 | fn distance_from_mbr_center(&self, mbr: &Rect) -> P { 127 | self.mbr().distance_from_mbr_center(mbr) 128 | } 129 | 130 | fn contained_by_mbr(&self, mbr: &Rect) -> bool { 131 | self.mbr().contained_by_mbr(mbr) 132 | } 133 | 134 | fn overlapped_by_mbr(&self, mbr: &Rect) -> bool { 135 | self.mbr().overlapped_by_mbr(mbr) 136 | } 137 | 138 | fn area_overlapped_with_mbr(&self, mbr: &Rect) -> P { 139 | self.mbr().area_overlapped_with_mbr(mbr) 140 | } 141 | 142 | fn area(&self) -> P { 143 | self.mbr().area() 144 | } 145 | 146 | fn min_for_axis(&self, dim: usize) -> P { 147 | self.mbr().min_for_axis(dim) 148 | } 149 | 150 | fn max_for_axis(&self, dim: usize) -> P { 151 | self.mbr().max_for_axis(dim) 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/tree/mbr/query.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use crate::geometry::Rect; 9 | use std::fmt::Debug; 10 | use crate::tree::mbr::{MbrLeaf, MbrLeafGeometry, MbrNode}; 11 | use crate::FP; 12 | 13 | /// Query trait for navigating the tree 14 | pub trait MbrQuery { 15 | /// Returns true if the leaf matches the query 16 | fn accept_leaf(&self, leaf: &MbrLeaf) -> bool; 17 | /// Returns true if the level matches the query 18 | fn accept_level(&self, level: &NODE) -> bool; 19 | } 20 | 21 | /// Rect based query 22 | #[derive(Debug, Clone)] 23 | pub enum MbrRectQuery { 24 | /// Matching leaves are ones that are completely contained by this rect 25 | ContainedBy(Rect), 26 | /// Matching leaves are ones that overlap this rect 27 | Overlaps(Rect), 28 | } 29 | 30 | impl MbrQuery for MbrRectQuery 31 | where 32 | LG: MbrLeafGeometry, 33 | NODE: MbrNode, 34 | { 35 | // Does this query accept the given leaf? 36 | fn accept_leaf(&self, leaf: &MbrLeaf) -> bool { 37 | match *self { 38 | MbrRectQuery::ContainedBy(ref query) => leaf.geometry.contained_by_mbr(query), 39 | MbrRectQuery::Overlaps(ref query) => leaf.geometry.overlapped_by_mbr(query), 40 | } 41 | } 42 | 43 | // Does this query accept the given level? 44 | fn accept_level(&self, level: &NODE) -> bool { 45 | match *self { 46 | MbrRectQuery::ContainedBy(ref query) => level.overlapped_by_mbr(query), 47 | MbrRectQuery::Overlaps(ref query) => level.overlapped_by_mbr(query), 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/tree/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! A collection of spatial trees 9 | 10 | pub mod mbr; 11 | mod xmbr; 12 | 13 | //pub mod xmbr; 14 | 15 | // TODO: Figure this out later :/ 16 | // pub trait SpatialMap<'tree, P, DIM, LG, LEVEL, T> 17 | // where DIM: ArrayLength

+ ArrayLength<(P, P)>, 18 | // LG: 'tree, 19 | // T: 'tree 20 | // { 21 | // Insert an item 22 | // fn insert(&mut self, geometry: LG, item: T); 23 | // 24 | // Remove all items whose shapes are accepted by the query 25 | // fn remove>(&mut self, query: Q) -> Vec<(LG, T)>; 26 | // 27 | // Remove all items whose shapes are accepted by the query and where f(&T) returns false 28 | // fn retain(&mut self, query: Q, f: F) -> Vec<(LG, T)> 29 | // where Q: SpatialQuery, 30 | // F: FnMut(&T) -> bool; 31 | // 32 | // Whether the map is empty 33 | // fn is_empty(&self) -> bool; 34 | // 35 | // Length of the map 36 | // fn len(&self) -> usize; 37 | // 38 | // Clear the map 39 | // fn clear(&mut self); 40 | // 41 | // Iter for the map 42 | // fn iter>(&'tree self) -> ITER; 43 | // 44 | // IterMut for the map 45 | // fn iter_mut>(&'tree mut self) -> ITERM; 46 | // 47 | // Iter for the map with a given query 48 | // fn iter_query(&'tree self, query: Q) -> ITER 49 | // where Q: SpatialQuery, 50 | // ITER: Iterator; 51 | // 52 | // IterMut for the map with a given query 53 | // fn iter_query_mut(&'tree mut self, query: Q) -> ITERM 54 | // where Q: SpatialQuery, 55 | // ITERM: Iterator; 56 | // } 57 | // 58 | -------------------------------------------------------------------------------- /src/tree/xmbr/index/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | -------------------------------------------------------------------------------- /src/tree/xmbr/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | mod index; 9 | mod node; 10 | 11 | pub use crate::tree::xmbr::node::XTreeNode; 12 | -------------------------------------------------------------------------------- /src/tree/xmbr/node.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use crate::geometry::Rect; 9 | use std::fmt::Debug; 10 | use crate::tree::mbr::{MbrLeaf, MbrLeafGeometry, MbrNode}; 11 | use crate::FP; 12 | 13 | /// Level node of a tree. Either contains other levels or leaves 14 | #[derive(Debug)] 15 | pub enum XTreeNode { 16 | /// Contains only other levels 17 | Level { 18 | mbr: Rect, 19 | // TODO: Replace with bitset 20 | split_dim: usize, 21 | super_node_size: Option, 22 | children: Vec>, 23 | }, 24 | /// Contains only leaves 25 | Leaves { 26 | mbr: Rect, 27 | super_node_size: Option, 28 | children: Vec>, 29 | }, 30 | } 31 | 32 | impl XTreeNode 33 | where 34 | LG: MbrLeafGeometry, 35 | { 36 | pub fn is_super(&self) -> bool { 37 | match *self { 38 | XTreeNode::Level { 39 | super_node_size, .. 40 | } => super_node_size.is_some(), 41 | XTreeNode::Leaves { 42 | super_node_size, .. 43 | } => super_node_size.is_some(), 44 | } 45 | } 46 | } 47 | 48 | impl MbrNode for XTreeNode 49 | where 50 | LG: MbrLeafGeometry, 51 | { 52 | fn new_leaves() -> XTreeNode { 53 | XTreeNode::Leaves { 54 | mbr: Rect::max_inverted(), 55 | super_node_size: None, 56 | children: Vec::new(), 57 | } 58 | } 59 | 60 | fn new_no_alloc() -> XTreeNode { 61 | XTreeNode::Leaves { 62 | mbr: Rect::max_inverted(), 63 | super_node_size: None, 64 | children: Vec::with_capacity(0), 65 | } 66 | } 67 | 68 | fn has_leaves(&self) -> bool { 69 | match *self { 70 | XTreeNode::Level { .. } => false, 71 | XTreeNode::Leaves { .. } => true, 72 | } 73 | } 74 | 75 | fn has_levels(&self) -> bool { 76 | !self.has_leaves() 77 | } 78 | 79 | fn mbr(&self) -> &Rect { 80 | match *self { 81 | XTreeNode::Level { ref mbr, .. } => mbr, 82 | XTreeNode::Leaves { ref mbr, .. } => mbr, 83 | } 84 | } 85 | 86 | fn mbr_mut(&mut self) -> &mut Rect { 87 | match *self { 88 | XTreeNode::Level { ref mut mbr, .. } => mbr, 89 | XTreeNode::Leaves { ref mut mbr, .. } => mbr, 90 | } 91 | } 92 | 93 | fn len(&self) -> usize { 94 | match *self { 95 | XTreeNode::Level { ref children, .. } => children.len(), 96 | XTreeNode::Leaves { ref children, .. } => children.len(), 97 | } 98 | } 99 | 100 | fn is_empty(&self) -> bool { 101 | match *self { 102 | XTreeNode::Level { ref children, .. } => children.is_empty(), 103 | XTreeNode::Leaves { ref children, .. } => children.is_empty(), 104 | } 105 | } 106 | } 107 | 108 | impl MbrLeafGeometry for XTreeNode 109 | where 110 | LG: MbrLeafGeometry, 111 | { 112 | fn dim(&self) -> usize { 113 | self.mbr().dim() 114 | } 115 | 116 | fn expand_mbr_to_fit(&self, mbr: &mut Rect) { 117 | self.mbr().expand_mbr_to_fit(mbr) 118 | } 119 | 120 | fn distance_from_mbr_center(&self, mbr: &Rect) -> P { 121 | self.mbr().distance_from_mbr_center(mbr) 122 | } 123 | 124 | fn contained_by_mbr(&self, mbr: &Rect) -> bool { 125 | self.mbr().contained_by_mbr(mbr) 126 | } 127 | 128 | fn overlapped_by_mbr(&self, mbr: &Rect) -> bool { 129 | self.mbr().overlapped_by_mbr(mbr) 130 | } 131 | 132 | fn area_overlapped_with_mbr(&self, mbr: &Rect) -> P { 133 | self.mbr().area_overlapped_with_mbr(mbr) 134 | } 135 | 136 | fn area(&self) -> P { 137 | self.mbr().area() 138 | } 139 | 140 | fn min_for_axis(&self, dim: usize) -> P { 141 | self.mbr().min_for_axis(dim) 142 | } 143 | 144 | fn max_for_axis(&self, dim: usize) -> P { 145 | self.mbr().max_for_axis(dim) 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/vecext.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 spatial-rs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! Various Vec Extensions 9 | 10 | trait RetainPart 11 | where 12 | F: FnMut(&T) -> bool, 13 | { 14 | fn retain_part(&mut self, f: F) -> usize; 15 | } 16 | 17 | pub trait RetainAndAppend 18 | where 19 | F: FnMut(&T) -> bool, 20 | { 21 | fn retain_and_append(&mut self, m: &mut Vec, f: F); 22 | } 23 | 24 | impl RetainPart for Vec 25 | where 26 | F: FnMut(&T) -> bool, 27 | { 28 | fn retain_part(&mut self, mut f: F) -> usize { 29 | let len = self.len(); 30 | let mut del = 0; 31 | { 32 | let v = &mut **self; 33 | 34 | for i in 0..len { 35 | if !f(&v[i]) { 36 | del += 1; 37 | } else if del > 0 { 38 | v.swap(i - del, i); 39 | } 40 | } 41 | } 42 | del 43 | } 44 | } 45 | 46 | #[allow(unused_mut)] 47 | impl RetainAndAppend for Vec 48 | where 49 | F: FnMut(&T) -> bool, 50 | { 51 | fn retain_and_append(&mut self, m: &mut Vec, mut f: F) { 52 | let del = self.retain_part(f); 53 | if del > 0 { 54 | for _ in 0..del { 55 | m.push(self.pop().unwrap()); 56 | } 57 | } 58 | } 59 | } 60 | 61 | #[cfg(test)] 62 | mod tests { 63 | use super::*; 64 | use std::cmp::PartialEq; 65 | 66 | trait ContainsAll 67 | where 68 | T: PartialEq, 69 | { 70 | fn contains_all(&self, that: &Vec) -> bool; 71 | } 72 | 73 | impl ContainsAll for Vec 74 | where 75 | T: PartialEq, 76 | { 77 | fn contains_all(&self, items: &Vec) -> bool { 78 | for item in items { 79 | if !self.contains(item) { 80 | return false; 81 | } 82 | } 83 | true 84 | } 85 | } 86 | 87 | #[test] 88 | fn retain_and_append() { 89 | let mut v = vec![1, 2, 3, 4, 5, 6]; 90 | let left = vec![1, 2, 3]; 91 | let right = vec![4, 5, 6, 7]; 92 | 93 | let mut appender = vec![7]; 94 | 95 | v.retain_and_append(&mut appender, |x| *x < 4); 96 | assert!(v.len() == 3); 97 | assert!(left.contains_all(&v)); 98 | assert!(appender.len() == 4); 99 | assert!(right.contains_all(&appender)); 100 | } 101 | 102 | #[test] 103 | fn retain_mut() { 104 | let mut v = vec![1, 2, 3, 4, 5, 6]; 105 | let left = vec![0, 1, 2]; 106 | 107 | v.retain_mut(|x| { 108 | *x -= 1; 109 | *x < 3 110 | }); 111 | assert!(v.len() == 3); 112 | assert!(left.contains_all(&v)); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /tests/rstar.rs: -------------------------------------------------------------------------------- 1 | extern crate spatial; 2 | 3 | use spatial::geometry::{Point, Rect}; 4 | use spatial::tree::mbr::MbrRectQuery; 5 | use spatial::RStar; 6 | 7 | #[test] 8 | fn rstar_integration() { 9 | let mut tree_map = RStar::new_with_max(16); 10 | for i in 0..32 { 11 | let i_f32 = i as f32; 12 | tree_map.insert(Point::new([i_f32; 3]), i); 13 | println!("i: {:?}", i); 14 | } 15 | assert_eq!(32, tree_map.len()); 16 | assert_eq!(tree_map.len(), tree_map.iter().count()); 17 | assert_eq!(tree_map.len(), tree_map.iter_mut().count()); 18 | 19 | println!("Remove query"); 20 | let removed = tree_map.remove(MbrRectQuery::ContainedBy(Rect::from_corners( 21 | [0.0f32, 0.0f32, 0.0f32], 22 | [9.0f32, 9.0f32, 9.0f32], 23 | ))); 24 | assert_eq!(10, removed.len()); 25 | assert_eq!(22, tree_map.len()); 26 | assert_eq!(tree_map.len(), tree_map.iter().count()); 27 | 28 | println!("Retain query"); 29 | let removed_retain = tree_map.retain(MbrRectQuery::ContainedBy(Rect::max()), |x| *x >= 20); 30 | assert_eq!(10, removed_retain.len()); 31 | assert_eq!(12, tree_map.len()); 32 | assert_eq!(tree_map.len(), tree_map.iter().count()); 33 | 34 | println!("Remove all"); 35 | let retain_none = tree_map.remove(MbrRectQuery::ContainedBy(Rect::max())); 36 | assert_eq!(12, retain_none.len()); 37 | assert_eq!(0, tree_map.len()); 38 | assert_eq!(tree_map.len(), tree_map.iter().count()); 39 | 40 | for i in 0..32 { 41 | let i_f32 = i as f32; 42 | tree_map.insert(Point::new([i_f32; 3]), i); 43 | println!("i: {:?}", i); 44 | } 45 | assert_eq!(32, tree_map.len()); 46 | assert_eq!(tree_map.len(), tree_map.iter().count()); 47 | } 48 | -------------------------------------------------------------------------------- /tests/rtree.rs: -------------------------------------------------------------------------------- 1 | extern crate spatial; 2 | 3 | use spatial::geometry::{Point, Rect}; 4 | use spatial::tree::mbr::MbrRectQuery; 5 | use spatial::RTree; 6 | 7 | #[test] 8 | fn rlinear_integration() { 9 | let mut tree_map = RTree::new_linear_with_max(16); 10 | for i in 0..32 { 11 | let i_f32 = i as f32; 12 | tree_map.insert(Point::new([i_f32; 3]), i); 13 | println!("i: {:?}", i); 14 | } 15 | assert_eq!(32, tree_map.len()); 16 | assert_eq!(tree_map.len(), tree_map.iter().count()); 17 | assert_eq!(tree_map.len(), tree_map.iter_mut().count()); 18 | 19 | println!("Remove query"); 20 | let removed = tree_map.remove(MbrRectQuery::ContainedBy(Rect::from_corners( 21 | [0.0f32, 0.0f32, 0.0f32], 22 | [9.0f32, 9.0f32, 9.0f32], 23 | ))); 24 | assert_eq!(10, removed.len()); 25 | assert_eq!(22, tree_map.len()); 26 | assert_eq!(tree_map.len(), tree_map.iter().count()); 27 | 28 | println!("Retain query"); 29 | let removed_retain = tree_map.retain(MbrRectQuery::ContainedBy(Rect::max()), |x| *x >= 20); 30 | assert_eq!(10, removed_retain.len()); 31 | assert_eq!(12, tree_map.len()); 32 | assert_eq!(tree_map.len(), tree_map.iter().count()); 33 | 34 | println!("Remove all"); 35 | let retain_none = tree_map.remove(MbrRectQuery::ContainedBy(Rect::max())); 36 | assert_eq!(12, retain_none.len()); 37 | assert_eq!(0, tree_map.len()); 38 | assert_eq!(tree_map.len(), tree_map.iter().count()); 39 | 40 | for i in 0..32 { 41 | let i_f32 = i as f32; 42 | tree_map.insert(Point::new([i_f32; 3]), i); 43 | println!("i: {:?}", i); 44 | } 45 | assert_eq!(32, tree_map.len()); 46 | assert_eq!(tree_map.len(), tree_map.iter().count()); 47 | } 48 | 49 | #[test] 50 | fn rquadratic_integration() { 51 | let mut tree_map = RTree::new_quadratic_with_max(16); 52 | for i in 0..32 { 53 | let i_f32 = i as f32; 54 | tree_map.insert(Point::new([i_f32; 3]), i); 55 | println!("i: {:?}", i); 56 | } 57 | assert_eq!(32, tree_map.len()); 58 | assert_eq!(tree_map.len(), tree_map.iter().count()); 59 | assert_eq!(tree_map.len(), tree_map.iter_mut().count()); 60 | 61 | println!("Remove query"); 62 | let removed = tree_map.remove(MbrRectQuery::ContainedBy(Rect::from_corners( 63 | [0.0f32, 0.0f32, 0.0f32], 64 | [9.0f32, 9.0f32, 9.0f32], 65 | ))); 66 | assert_eq!(10, removed.len()); 67 | assert_eq!(22, tree_map.len()); 68 | assert_eq!(tree_map.len(), tree_map.iter().count()); 69 | 70 | println!("Retain query"); 71 | let removed_retain = tree_map.retain(MbrRectQuery::ContainedBy(Rect::max()), |x| *x >= 20); 72 | assert_eq!(10, removed_retain.len()); 73 | assert_eq!(12, tree_map.len()); 74 | assert_eq!(tree_map.len(), tree_map.iter().count()); 75 | 76 | println!("Remove all"); 77 | let retain_none = tree_map.remove(MbrRectQuery::ContainedBy(Rect::max())); 78 | assert_eq!(12, retain_none.len()); 79 | assert_eq!(0, tree_map.len()); 80 | assert_eq!(tree_map.len(), tree_map.iter().count()); 81 | 82 | for i in 0..32 { 83 | let i_f32 = i as f32; 84 | tree_map.insert(Point::new([i_f32; 3]), i); 85 | println!("i: {:?}", i); 86 | } 87 | assert_eq!(32, tree_map.len()); 88 | assert_eq!(tree_map.len(), tree_map.iter().count()); 89 | } 90 | --------------------------------------------------------------------------------