From bf21bfd0f92d9e770421505c51f92ba7b94db58c Mon Sep 17 00:00:00 2001 From: BlockCat Date: Tue, 27 Dec 2022 13:44:56 +0100 Subject: [PATCH 01/17] remove fibonacci --- bevy_shapefile/src/road_map.rs | 5 ++--- src/lib.rs | 14 -------------- src/world.rs | 27 ++++++++++++--------------- 3 files changed, 14 insertions(+), 32 deletions(-) diff --git a/bevy_shapefile/src/road_map.rs b/bevy_shapefile/src/road_map.rs index f41da83..94f6a7c 100644 --- a/bevy_shapefile/src/road_map.rs +++ b/bevy_shapefile/src/road_map.rs @@ -135,7 +135,7 @@ fn load_junctions(roads: &Vec<(GenericPolyline, Record)>) -> HashMap, Record)>, ) -> HashMap { - let roads = roads + roads .into_par_iter() .enumerate() .map(|(id, (line, _))| { @@ -157,6 +157,5 @@ fn load_road_sections( (id, RoadSection { id, points, aabb }) }) - .collect::>(); - roads + .collect::>() } diff --git a/src/lib.rs b/src/lib.rs index 417e760..280c546 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,17 +46,3 @@ pub fn read_file>( Ok(d) } - -struct FibonacciIterator(usize, usize); - -impl Iterator for FibonacciIterator { - type Item = usize; - - fn next(&mut self) -> Option { - let (a, b) = (self.0, self.1); - self.0 = b; - self.1 = a + b; - - Some(self.1) - } -} diff --git a/src/world.rs b/src/world.rs index 0a93b7c..c43dce7 100644 --- a/src/world.rs +++ b/src/world.rs @@ -3,16 +3,12 @@ use crate::{ nwb::{self}, ui::{DirectedNetworkGraphContainer, PreProcess}, }; -use bevy::{prelude::*, tasks::AsyncComputeTaskPool}; -use bevy_polyline::{ - prelude::{Polyline, PolylineBundle, PolylineMaterial}, - PolylinePlugin, -}; +use bevy::prelude::*; +use bevy_polyline::prelude::{Polyline, PolylineBundle, PolylineMaterial}; use bevy_shapefile::{RoadId, RoadMap, RoadSection, AABB}; use network::DirectedNetworkGraph; use std::{ collections::{HashMap, HashSet}, - ops::Sub, path::Path, }; @@ -91,7 +87,7 @@ fn init_materials( mut polyline_materials: ResMut>, ) { let normal_material = polyline_materials.add(PolylineMaterial { - width: 1.0, + width: 0.2, color: config.normal_colour, perspective: true, ..Default::default() @@ -296,16 +292,17 @@ fn spawn_figure( polylines: &mut Assets, materials: &LoadedMaterials, ) -> Entity { + let polyline = polylines.add(Polyline { + vertices: section + .points + .iter() + .map(|c| Vec3::new(c.x, c.y, 0.0)) + .collect(), + ..Default::default() + }); commands .spawn(PolylineBundle { - polyline: polylines.add(Polyline { - vertices: section - .points - .iter() - .map(|c| Vec3::new(c.x, c.y, 0.0)) - .collect(), - ..Default::default() - }), + polyline, material: materials.normal_material.clone_weak(), ..Default::default() }) From 331233dc75fdd540bb337f266747c601c72b212e Mon Sep 17 00:00:00 2001 From: BlockCat Date: Tue, 27 Dec 2022 13:50:28 +0100 Subject: [PATCH 02/17] clippy --- Cargo.lock | 890 +++++++++--------- Cargo.toml | 5 +- bevy_shapefile/Cargo.toml | 5 +- bevy_shapefile/src/road_map.rs | 8 +- examples/layer.rs | 6 +- highway/Cargo.toml | 3 - highway/src/generation/core.rs | 2 +- highway/src/generation/dijkstra.rs | 12 +- .../src/generation/intermediate_network.rs | 2 +- highway/src/query/mod.rs | 2 +- network/Cargo.toml | 2 - network/src/directed_network/builder.rs | 6 +- network/src/directed_network/iterators.rs | 4 +- network/src/directed_network/mod.rs | 2 +- network/src/directed_network/node_data.rs | 2 +- src/main.rs | 1 - src/nwb.rs | 6 +- src/ui/layers.rs | 15 +- src/ui/mod.rs | 2 - src/ui/route.rs | 8 +- src/world.rs | 10 +- tools/dbf_to_sql/Cargo.toml | 3 - 22 files changed, 515 insertions(+), 481 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8888274..64d3a59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ab_glyph" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24606928a235e73cdef55a0c909719cadd72fce573e5713d58cb2952d8f5794c" +checksum = "4dcdbc68024b653943864d436fe8a24b028095bc1cf91a8926f8241e4aaffe59" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "ab_glyph_rasterizer" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" +checksum = "330223a1aecc308757b9926e9391c9b47f8ef2dbd8aea9df88312aea18c5e8d6" [[package]] name = "adler" @@ -54,9 +54,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -70,7 +70,7 @@ dependencies = [ "alsa-sys", "bitflags", "libc", - "nix 0.23.1", + "nix 0.23.2", ] [[package]] @@ -116,20 +116,11 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" [[package]] name = "approx" @@ -142,9 +133,9 @@ dependencies = [ [[package]] name = "arboard" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6045ca509e4abacde2b884ac4618a51d0c017b5d85a3ee84a7226eb33b3154a9" +checksum = "dc120354d1b5ec6d7aaf4876b602def75595937b5e15d356eb554ab5177e08bb" dependencies = [ "clipboard-win", "core-graphics", @@ -153,7 +144,6 @@ dependencies = [ "objc", "objc-foundation", "objc_id", - "once_cell", "parking_lot", "thiserror", "winapi", @@ -166,18 +156,6 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" -[[package]] -name = "as-slice" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" -dependencies = [ - "generic-array 0.12.4", - "generic-array 0.13.3", - "generic-array 0.14.5", - "stable_deref_trait", -] - [[package]] name = "ash" version = "0.37.1+1.3.235" @@ -189,34 +167,53 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" dependencies = [ - "concurrent-queue", + "concurrent-queue 2.0.0", "event-listener", "futures-core", ] [[package]] name = "async-executor" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ + "async-lock", "async-task", - "concurrent-queue", + "concurrent-queue 2.0.0", "fastrand", "futures-lite", - "once_cell", "slab", ] +[[package]] +name = "async-lock" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +dependencies = [ + "event-listener", + "futures-lite", +] + [[package]] name = "async-task" -version = "4.2.0" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "atomic-polyfill" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" +checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" +dependencies = [ + "critical-section", +] [[package]] name = "atomic_refcell" @@ -230,7 +227,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -243,15 +240,15 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base-x" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bevy" @@ -314,7 +311,7 @@ dependencies = [ "downcast-rs", "fastrand", "js-sys", - "ndk-glue 0.7.0", + "ndk-glue", "notify", "parking_lot", "serde", @@ -589,7 +586,7 @@ dependencies = [ "bevy_utils", "bevy_window", "bevy_winit", - "ndk-glue 0.7.0", + "ndk-glue", ] [[package]] @@ -833,7 +830,7 @@ dependencies = [ "async-channel", "async-executor", "async-task", - "concurrent-queue", + "concurrent-queue 1.2.4", "futures-lite", "once_cell", "wasm-bindgen-futures", @@ -925,7 +922,7 @@ checksum = "16750aae52cd35bd7b60eb61cee883420b250e11b4a290b8d44b2b2941795739" dependencies = [ "ahash 0.7.6", "getrandom", - "hashbrown 0.12.3", + "hashbrown", "instant", "tracing", "uuid", @@ -977,9 +974,9 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.56.0" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239" +checksum = "8a022e58a142a46fea340d68012b9201c094e93ec3d033a944a24f8fd4a4f09a" dependencies = [ "bitflags", "cexpr", @@ -992,13 +989,14 @@ dependencies = [ "regex", "rustc-hash", "shlex", + "syn", ] [[package]] name = "bit-set" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ "bit-vec", ] @@ -1023,24 +1021,24 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bytemuck" -version = "1.8.0" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e851ca7c24871e7336801608a4797d7376545b6928a10d32d75685687141ead" +checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.0.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" +checksum = "5fe233b960f12f8007e3db2d136e3cb1c291bfd7396e384ee76025fc1a3932b4" dependencies = [ "proc-macro2", "quote", @@ -1055,9 +1053,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "cache-padded" @@ -1073,9 +1071,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" dependencies = [ "jobserver", ] @@ -1088,9 +1086,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cexpr" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] @@ -1109,14 +1107,16 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "time", + "wasm-bindgen", "winapi", ] @@ -1149,9 +1149,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" dependencies = [ "glob", "libc", @@ -1181,9 +1181,9 @@ dependencies = [ [[package]] name = "clipboard-win" -version = "4.4.1" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3e1238132dc01f081e1cbb9dace14e5ef4c3a51ee244bd982275fb514605db" +checksum = "c4ab1b92798304eedc095b53942963240037c0516452cb11aeba709d420b2219" dependencies = [ "error-code", "str-buf", @@ -1192,9 +1192,9 @@ dependencies = [ [[package]] name = "cocoa" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" +checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" dependencies = [ "bitflags", "block", @@ -1239,9 +1239,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "combine" -version = "4.6.3" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ "bytes", "memchr", @@ -1249,13 +1249,22 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "1.2.2" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" dependencies = [ "cache-padded", ] +[[package]] +name = "concurrent-queue" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -1325,9 +1334,9 @@ dependencies = [ [[package]] name = "coreaudio-sys" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca4679a59dbd8c15f064c012dfe8c1163b9453224238b59bb9328c142b8b248b" +checksum = "1a9444b94b8024feecc29e01a9706c69c1e26bfee480221c90764200cfd778fb" dependencies = [ "bindgen", ] @@ -1402,11 +1411,17 @@ dependencies = [ "itertools", ] +[[package]] +name = "critical-section" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" + [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -1414,9 +1429,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -1425,26 +1440,24 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", - "memoffset", + "memoffset 0.7.1", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if", - "lazy_static", ] [[package]] @@ -1453,6 +1466,50 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" +[[package]] +name = "cxx" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "d3d12" version = "0.5.0" @@ -1466,9 +1523,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ "darling_core", "darling_macro", @@ -1476,9 +1533,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", @@ -1490,9 +1547,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", @@ -1567,9 +1624,9 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "emath" @@ -1640,9 +1697,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.20" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad132dd8d0d0b546348d7d86cb3191aad14b34e5f979781fc005c80d4ac67ffd" +checksum = "e4ca605381c017ec7a5fef5e548f1cfaa419ed0f6df6367339300db74c92aa7d" dependencies = [ "serde", ] @@ -1659,18 +1716,18 @@ dependencies = [ [[package]] name = "euclid" -version = "0.22.6" +version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da96828553a086d7b18dcebfc579bd9628b016f86590d7453c115e490fa74b80" +checksum = "b52c2ef4a78da0ba68fbe1fd920627411096d2ac478f7f4c9f3a54ba6705bade" dependencies = [ "num-traits", ] [[package]] name = "event-listener" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fallible-iterator" @@ -1686,30 +1743,30 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] [[package]] name = "filetime" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" dependencies = [ "cfg-if", "libc", "redox_syscall", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "fixedbitset" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" @@ -1744,11 +1801,10 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] @@ -1763,15 +1819,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-lite" @@ -1797,34 +1853,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "gethostname" version = "0.2.3" @@ -1837,14 +1865,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.5" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -1976,13 +2004,13 @@ dependencies = [ [[package]] name = "gpu-descriptor" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a538f217be4d405ff4719a283ca68323cc2384003eca5baaa87501e821c81dda" +checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" dependencies = [ "bitflags", "gpu-descriptor-types", - "hashbrown 0.11.2", + "hashbrown", ] [[package]] @@ -2010,15 +2038,6 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" -[[package]] -name = "hash32" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" -dependencies = [ - "byteorder", -] - [[package]] name = "hash32" version = "0.2.1" @@ -2039,15 +2058,6 @@ dependencies = [ "syn", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.6", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -2064,18 +2074,19 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" dependencies = [ - "hashbrown 0.12.3", + "hashbrown", ] [[package]] name = "heapless" -version = "0.6.1" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" +checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" dependencies = [ - "as-slice", - "generic-array 0.14.5", - "hash32 0.1.1", + "atomic-polyfill", + "hash32", + "rustc_version 0.4.0", + "spin", "stable_deref_trait", ] @@ -2088,6 +2099,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -2120,6 +2140,30 @@ dependencies = [ "serde", ] +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2128,11 +2172,10 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -2170,12 +2213,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.0" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown 0.11.2", + "hashbrown", ] [[package]] @@ -2228,18 +2271,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jni" @@ -2277,9 +2320,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] @@ -2312,9 +2355,9 @@ dependencies = [ [[package]] name = "kqueue" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058a107a784f8be94c7d35c1300f4facced2e93d2fbe5b1452b44e905ddca4a9" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" dependencies = [ "kqueue-sys", "libc", @@ -2361,14 +2404,20 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if", "winapi", ] +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + [[package]] name = "libsqlite3-sys" version = "0.25.2" @@ -2390,20 +2439,30 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + [[package]] name = "lock_api" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] @@ -2435,17 +2494,11 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" @@ -2456,6 +2509,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "metal" version = "0.24.0" @@ -2470,6 +2532,12 @@ dependencies = [ "objc", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.3.7" @@ -2500,25 +2568,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", - "miow", - "ntapi", "wasi 0.11.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -2576,21 +2633,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" -[[package]] -name = "ndk-glue" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9ffb7443daba48349d545028777ca98853b018b4c16624aa01223bc29e078da" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk 0.6.0", - "ndk-context", - "ndk-macro", - "ndk-sys 0.3.0", -] - [[package]] name = "ndk-glue" version = "0.7.0" @@ -2659,20 +2701,20 @@ dependencies = [ "cc", "cfg-if", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] name = "nix" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags", "cc", "cfg-if", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -2695,12 +2737,12 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] name = "nom" -version = "5.1.2" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ "memchr", - "version_check", + "minimal-lexical", ] [[package]] @@ -2722,11 +2764,12 @@ dependencies = [ ] [[package]] -name = "ntapi" -version = "0.3.7" +name = "nu-ansi-term" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ + "overload", "winapi", ] @@ -2743,9 +2786,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", @@ -2753,9 +2796,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ "autocfg", "num-integer", @@ -2786,20 +2829,21 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -2865,13 +2909,13 @@ dependencies = [ [[package]] name = "oboe" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2463c8f2e19b4e0d0710a21f8e4011501ff28db1c95d7a5482a553b2100502d2" +checksum = "27f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1" dependencies = [ "jni 0.19.0", "ndk 0.6.0", - "ndk-glue 0.6.1", + "ndk-context", "num-derive", "num-traits", "oboe-sys", @@ -2913,11 +2957,17 @@ version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owned_ttf_parser" -version = "0.15.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1e509cfe7a12db2a90bfa057dfcdbc55a347f5da677c506b53dd099cfec9d" +checksum = "18904d3c65493a9f0d7542293d1a7f69bfdc309a6b9ef4f46dc3e58b0577edc5" dependencies = [ "ttf-parser", ] @@ -2940,23 +2990,17 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.2" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys 0.34.0", + "windows-sys 0.42.0", ] -[[package]] -name = "pdqselect" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27" - [[package]] name = "peeking_take_while" version = "0.1.2" @@ -2965,15 +3009,15 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "petgraph" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" +checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" dependencies = [ "fixedbitset", "indexmap", @@ -2981,21 +3025,21 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plotters" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", @@ -3006,15 +3050,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] @@ -3054,34 +3098,35 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ + "once_cell", "thiserror", "toml", ] [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9145ac0af1d93c638c98c40cf7d25665f427b2a44ad0a99b1dccf3e2f25bb987" +checksum = "74605f360ce573babfe43964cbe520294dcb081afbf8c108fc6e23036b4da2df" [[package]] name = "quote" -version = "1.0.16" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4af2ec4714533fcdf07e886f17025ace8b997b9ce51204ee69b6da831c3da57" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -3118,26 +3163,23 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", "num_cpus", ] @@ -3149,18 +3191,18 @@ checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" [[package]] name = "redox_syscall" -version = "0.2.11" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.5.5" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -3178,9 +3220,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "renderdoc-sys" @@ -3211,13 +3253,12 @@ dependencies = [ [[package]] name = "rstar" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc6fc513b8c3853e43a0c3f909ded14ffa82e5170c9c5f6fb175f9c85c8a433" +checksum = "b40f1bfe5acdab44bc63e6699c28b74f75ec43afb59f3eda01e145aff86a25fa" dependencies = [ "heapless", "num-traits", - "pdqselect", "serde", "smallvec", ] @@ -3248,14 +3289,23 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.16", ] [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "same-file" @@ -3278,6 +3328,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + [[package]] name = "semver" version = "0.9.0" @@ -3287,6 +3343,12 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" + [[package]] name = "semver-parser" version = "0.7.0" @@ -3295,18 +3357,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.136" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -3315,9 +3377,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "itoa", "ryu", @@ -3360,15 +3422,18 @@ dependencies = [ [[package]] name = "shlex" -version = "0.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "slab" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "slotmap" @@ -3381,13 +3446,22 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" dependencies = [ "serde", ] +[[package]] +name = "spin" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +dependencies = [ + "lock_api", +] + [[package]] name = "spirv" version = "0.2.0+1.5.4" @@ -3417,7 +3491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" dependencies = [ "discard", - "rustc_version", + "rustc_version 0.2.3", "stdweb-derive", "stdweb-internal-macros", "stdweb-internal-runtime", @@ -3461,9 +3535,9 @@ checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" [[package]] name = "str-buf" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a" +checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" [[package]] name = "strsim" @@ -3479,13 +3553,13 @@ checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" [[package]] name = "syn" -version = "1.0.89" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea297be220d52398dcc07ce15a209fce436d361735ac1db700cab3b6cdfb9f54" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -3495,7 +3569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec27dea659b100d489dffa57cf0efc6d7bfefb119af817b92cc14006c0b214e3" dependencies = [ "arrayvec", - "hash32 0.2.1", + "hash32", "hash32-derive", "num-traits", "typenum", @@ -3518,18 +3592,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -3558,11 +3632,12 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] @@ -3578,9 +3653,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -3593,18 +3668,18 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "toml" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" dependencies = [ "serde", ] [[package]] name = "tracing" -version = "0.1.32" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "pin-project-lite", @@ -3614,9 +3689,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.20" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", @@ -3625,19 +3700,19 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.23" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ - "lazy_static", + "once_cell", "valuable", ] [[package]] name = "tracing-log" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" dependencies = [ "lazy_static", "log", @@ -3646,13 +3721,13 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.9" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" dependencies = [ - "ansi_term", - "lazy_static", "matchers", + "nu-ansi-term", + "once_cell", "regex", "sharded-slab", "smallvec", @@ -3675,36 +3750,42 @@ dependencies = [ [[package]] name = "ttf-parser" -version = "0.15.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c74c96594835e10fa545e2a51e8709f30b173a092bfd6036ef2cec53376244f3" +checksum = "375812fa44dab6df41c195cd2f7fecb488f6c09fbaafb62807488cefab642bff" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" @@ -3714,13 +3795,12 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -3777,9 +3857,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasi" @@ -3881,9 +3961,9 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" [[package]] name = "wgpu" @@ -3981,9 +4061,9 @@ dependencies = [ [[package]] name = "widestring" -version = "0.5.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "winapi" @@ -4053,19 +4133,6 @@ dependencies = [ "windows_x86_64_msvc 0.42.0", ] -[[package]] -name = "windows-sys" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" -dependencies = [ - "windows_aarch64_msvc 0.34.0", - "windows_i686_gnu 0.34.0", - "windows_i686_msvc 0.34.0", - "windows_x86_64_gnu 0.34.0", - "windows_x86_64_msvc 0.34.0", -] - [[package]] name = "windows-sys" version = "0.36.1" @@ -4080,16 +4147,25 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" +name = "windows-sys" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] [[package]] -name = "windows_aarch64_msvc" -version = "0.34.0" +name = "windows_aarch64_gnullvm" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" [[package]] name = "windows_aarch64_msvc" @@ -4109,12 +4185,6 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" -[[package]] -name = "windows_i686_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" - [[package]] name = "windows_i686_gnu" version = "0.36.1" @@ -4133,12 +4203,6 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" -[[package]] -name = "windows_i686_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" - [[package]] name = "windows_i686_msvc" version = "0.36.1" @@ -4157,12 +4221,6 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" -[[package]] -name = "windows_x86_64_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" - [[package]] name = "windows_x86_64_gnu" version = "0.36.1" @@ -4187,12 +4245,6 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" -[[package]] -name = "windows_x86_64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" - [[package]] name = "windows_x86_64_msvc" version = "0.36.1" @@ -4227,7 +4279,7 @@ dependencies = [ "log", "mio", "ndk 0.7.0", - "ndk-glue 0.7.0", + "ndk-glue", "objc", "once_cell", "parking_lot", @@ -4242,9 +4294,9 @@ dependencies = [ [[package]] name = "x11-dl" -version = "2.19.1" +version = "2.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" +checksum = "b1536d6965a5d4e573c7ef73a2c15ebcd0b2de3347bdf526c34c297c00ac40f0" dependencies = [ "lazy_static", "libc", @@ -4290,9 +4342,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" +version = "2.0.4+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" dependencies = [ "cc", "libc", diff --git a/Cargo.toml b/Cargo.toml index 568902f..bd92839 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ network = {path = "./network"} rusqlite = {version = "0.28.0", features = ["bundled"]} serde = {version = "1.0.136", features = ["derive"]} -zstd = "0.12.1+zstd.1.5.2" +zstd = "0.12" futures-lite = "1.12.0" rayon = "1.5.1" @@ -37,8 +37,9 @@ opt-level = 3 [profile.dev.package.bevy] opt-level = 3 -[profile.dev.package.bevy_prototype_lyon] +[profile.dev.package.rayon] opt-level = 3 + [workspace] members = ["bevy_shapefile", "network", "highway", "tools/dbf_to_sql"] diff --git a/bevy_shapefile/Cargo.toml b/bevy_shapefile/Cargo.toml index 13599c2..d0e6ade 100644 --- a/bevy_shapefile/Cargo.toml +++ b/bevy_shapefile/Cargo.toml @@ -12,7 +12,4 @@ bincode = "1.3.3" rayon = "1.5.1" rstar = {version = "0.9.2", features = ["serde"]} serde = {version = "1.0.136", features = ["derive"]} -shapefile = {version = "0.3.0"} - -[profile.dev.package.bevy] -opt-level = 3 +shapefile = {version = "0.3.0"} \ No newline at end of file diff --git a/bevy_shapefile/src/road_map.rs b/bevy_shapefile/src/road_map.rs index 94f6a7c..7f998c5 100644 --- a/bevy_shapefile/src/road_map.rs +++ b/bevy_shapefile/src/road_map.rs @@ -45,16 +45,16 @@ impl RoadMap { pub fn read>(path: P) -> Self { let file = File::open(path).expect("Could not open file"); - let value = bincode::deserialize_from(file).expect("Could not deserialize"); + - value + bincode::deserialize_from(file).expect("Could not deserialize") } /// Load data from a shapefile pub fn from_shapefile>(path: P) -> Result { println!("Start read of road data"); let roads = - shapefile::read_as::(path).map_err(|x| ShapeError::Shape(x))?; + shapefile::read_as::(path).map_err(ShapeError::Shape)?; println!("Loading junction data"); let junctions = load_junctions(&roads); @@ -67,7 +67,7 @@ impl RoadMap { let spatial_indeces = roads .iter() .map(|(id, section)| RoadSpatialIndex { - id: RoadId::from(*id), + id: *id, aabb: section.aabb.clone(), }) .collect(); diff --git a/examples/layer.rs b/examples/layer.rs index dc27359..6b4a2c3 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -15,7 +15,7 @@ fn main() { let mut layers = vec![calculate_layer(30, &network, 2.0)]; if let Some(x) = layers.first() { - write_file(x, format!("data/0.graph")).expect("Could not write"); + write_file(x, "data/0.graph".to_string()).expect("Could not write"); } for i in 1..7 { @@ -28,7 +28,7 @@ fn main() { ); let next = calculate_layer(30, prev_layer, 3.0); - write_file(&next, format!("data/{}.graph", i)).expect("Could not write"); + write_file(&next, format!("data/{i}.graph")).expect("Could not write"); layers.push(next); } @@ -51,7 +51,7 @@ fn data( a: &DirectedNetworkGraph, b: &DirectedNetworkGraph, ) { - println!("From: {} to {}", level_a, level_b); + println!("From: {level_a} to {level_b}"); let nodes_a = a.nodes().len(); let nodes_b = b.nodes().len(); let percentage = nodes_b as f32 / nodes_a as f32 - 1.0; diff --git a/highway/Cargo.toml b/highway/Cargo.toml index fb55d98..0464743 100644 --- a/highway/Cargo.toml +++ b/highway/Cargo.toml @@ -10,6 +10,3 @@ itertools = "*" network = {path = "../network"} rayon = "1.5.1" serde = {version = "1.0.136", features = ["derive"]} - -[profile.dev.package.rayon] -opt-level = 3 diff --git a/highway/src/generation/core.rs b/highway/src/generation/core.rs index 03edbc6..27fff50 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -27,7 +27,7 @@ pub(crate) fn core_network_with_patch( .map(|x| x.len() as f32) .unwrap_or_default(); - let short_cuts = (out_edges * in_edges) as f32; + let short_cuts = out_edges * in_edges; let contraction = (out_edges + in_edges) * contraction_factor; if short_cuts < contraction { diff --git a/highway/src/generation/dijkstra.rs b/highway/src/generation/dijkstra.rs index d5231f6..efed2b8 100644 --- a/highway/src/generation/dijkstra.rs +++ b/highway/src/generation/dijkstra.rs @@ -13,9 +13,9 @@ pub fn calculate_edges( network: &DirectedNetworkGraph, ) -> Vec<(NodeId, EdgeId)> { let (sorted_order, dag) = create_directed_acyclic_graph(s0, computed, network); - let edges = collect_next_level_edges(s0, sorted_order, dag, computed); + - edges + collect_next_level_edges(s0, sorted_order, dag, computed) } pub fn create_directed_acyclic_graph( @@ -74,7 +74,7 @@ pub fn create_directed_acyclic_graph( parent: ParentEntry { parent: entry.state.current, parent_edge_distance: child_edge.distance(), - parent_edge: id.into(), + parent_edge: id, active, }, }); @@ -147,7 +147,7 @@ fn initialize_heap( parent: ParentEntry { parent: s0, parent_edge_distance: edge.distance(), - parent_edge: id.into(), + parent_edge: id, active: true, }, }); @@ -315,7 +315,7 @@ mod tests { for (parent, id) in next_edges { let edge = network.edge(id); assert_ne!(parent, edge.target()); - println!("ID: {:?} - {:?}", id, edge); + println!("ID: {id:?} - {edge:?}"); } } @@ -339,7 +339,7 @@ mod tests { println!("Added:"); for (_, id) in next_edges { let edge = network.edge(id); - println!("ID: {:?} - {:?}", id, edge); + println!("ID: {id:?} - {edge:?}"); } } } diff --git a/highway/src/generation/intermediate_network.rs b/highway/src/generation/intermediate_network.rs index 96a1a85..600de72 100644 --- a/highway/src/generation/intermediate_network.rs +++ b/highway/src/generation/intermediate_network.rs @@ -109,7 +109,7 @@ impl IntermediateNetwork { self.in_edges .entry(target) .or_default() - .insert(source, edge.clone()); + .insert(source, edge); } pub fn remove_node(&mut self, node: NodeId) { diff --git a/highway/src/query/mod.rs b/highway/src/query/mod.rs index ac1b784..21a0d73 100644 --- a/highway/src/query/mod.rs +++ b/highway/src/query/mod.rs @@ -59,7 +59,7 @@ fn handle_dijkstra_iteration( }; if gap.is_finite() && entry.level == max_level { - top_layer.push(entry.clone()); + top_layer.push(entry); } todo!("Settled from both dirs?"); diff --git a/network/Cargo.toml b/network/Cargo.toml index 11ad0e1..d7ac31e 100644 --- a/network/Cargo.toml +++ b/network/Cargo.toml @@ -11,5 +11,3 @@ rayon = "1.5.1" serde = {version = "1.0.136", features = ["derive"]} itertools = "*" -[profile.dev.package.rayon] -opt-level = 3 diff --git a/network/src/directed_network/builder.rs b/network/src/directed_network/builder.rs index a8161c9..4c46d84 100644 --- a/network/src/directed_network/builder.rs +++ b/network/src/directed_network/builder.rs @@ -35,7 +35,7 @@ impl NodeBuilder for usize { *self as u32 } fn data(&self) -> Self::Data { - () + } } @@ -50,7 +50,7 @@ impl NodeBuilder for DefaultNodeBuilder { } fn data(&self) -> Self::Data { - () + } } @@ -71,7 +71,7 @@ impl EdgeBuilder for DefaultEdgeBuilder { type Data = (); fn data(&self) -> Self::Data { - () + } fn source(&self) -> NodeId { diff --git a/network/src/directed_network/iterators.rs b/network/src/directed_network/iterators.rs index 78ad6ca..f32fc0b 100644 --- a/network/src/directed_network/iterators.rs +++ b/network/src/directed_network/iterators.rs @@ -85,7 +85,7 @@ impl<'a, D: NetworkData> Iterator for ForwardDijkstraIterator<'a, D> { return Some((node, distance)); } - return None; + None } } @@ -109,6 +109,6 @@ impl<'a, D: NetworkData> Iterator for BackwardDijkstraIterator<'a, D> { return Some((node, distance)); } - return None; + None } } diff --git a/network/src/directed_network/mod.rs b/network/src/directed_network/mod.rs index 0efd766..fba0393 100644 --- a/network/src/directed_network/mod.rs +++ b/network/src/directed_network/mod.rs @@ -59,7 +59,7 @@ impl NetworkEdge { // self.id // } pub fn target(&self) -> NodeId { - self.target_node.into() + self.target_node } pub fn distance(&self) -> f32 { diff --git a/network/src/directed_network/node_data.rs b/network/src/directed_network/node_data.rs index 6676fbf..9ea7c7b 100644 --- a/network/src/directed_network/node_data.rs +++ b/network/src/directed_network/node_data.rs @@ -33,6 +33,6 @@ impl NetworkData for () { fn add_edge(&mut self, _: EdgeId, _: Self::EdgeData, _: ShortcutState) {} fn with_size(_: usize, _: usize) -> Self { - () + } } diff --git a/src/main.rs b/src/main.rs index 2c0b13f..cdc4e5b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,6 @@ extern crate test; use bevy::{ - diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, prelude::*, DefaultPlugins, }; diff --git a/src/nwb.rs b/src/nwb.rs index de7d317..02e3fc4 100644 --- a/src/nwb.rs +++ b/src/nwb.rs @@ -73,7 +73,7 @@ impl NodeBuilder for JunctionNode { type Data = (JunctionId, Vec2); fn data(&self) -> Self::Data { - (self.junction_id, self.location.clone()) + (self.junction_id, self.location) } fn id(&self) -> u32 { @@ -171,11 +171,11 @@ pub fn preprocess_roadmap>( let source = builder.add_node(JunctionNode { junction_id: road_id_start, - location: section.points.first().unwrap().clone(), + location: *section.points.first().unwrap(), }); let target = builder.add_node(JunctionNode { junction_id: road_id_end, - location: section.points.last().unwrap().clone(), + location: *section.points.last().unwrap(), }); let distance = section.points.windows(2).map(|w| w[0].distance(w[1])).sum(); diff --git a/src/ui/layers.rs b/src/ui/layers.rs index b6986f6..33a8052 100644 --- a/src/ui/layers.rs +++ b/src/ui/layers.rs @@ -110,7 +110,7 @@ fn clicked_preprocess( neighbourhood: usize, contraction_factor: f32, ) -> PreProcess { - println!("Clicked: {}", layer_count); + println!("Clicked: {layer_count}"); let mut layers = Vec::new(); @@ -127,7 +127,7 @@ fn clicked_preprocess( for i in 1..layer_count { let size = neighbourhood; let network = layers.last().unwrap(); - let path = format!("data/layer_{}.graph", i); + let path = format!("data/layer_{i}.graph"); let next_layer = load_or_calculate(path, || { highway::generation::calculate_layer(size, network, contraction_factor) }); @@ -160,15 +160,12 @@ pub fn colouring_system( } else { query.par_for_each_mut(32, |mut we| { for (i, sel) in ui_state.layers_selected.iter().enumerate() { - if *sel { - if preprocess + if *sel && preprocess .road_data_level .get(&we.id) .map(|&x| x > i as u8) - .unwrap_or_default() - { - we.selected = WorldEntitySelectionType::BaseSelected; - } + .unwrap_or_default() { + we.selected = WorldEntitySelectionType::BaseSelected; } } }); @@ -189,7 +186,7 @@ impl PreProcess { layers: Vec>, ) -> Self { let mut road_data_level = (0..base.edges().len()) - .map(|x| EdgeId::from(x)) + .map(EdgeId::from) .flat_map(|id| Vec::from(base.data.edge_road_id(id))) .map(|x| (RoadId::from(x), 0)) .collect::>(); diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 6b20e9e..43afbd2 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -96,8 +96,6 @@ fn point_system( _ => {} } }); - - return; } } } diff --git a/src/ui/route.rs b/src/ui/route.rs index e0389fd..aba4ba8 100644 --- a/src/ui/route.rs +++ b/src/ui/route.rs @@ -1,5 +1,5 @@ use crate::world::WorldEntitySelectionType; -use crate::{nwb::NWBNetworkData, world::WorldEntity}; +use crate::{world::WorldEntity}; use bevy::prelude::*; use bevy_egui::egui; use bevy_egui::EguiContext; @@ -111,7 +111,7 @@ where // test.push(parent); // println!("GRR: {} > {} of {}", x, old_distance, spare_distance); if current == target { - println!("Evaluated: {}", evaluated); + println!("Evaluated: {evaluated}"); let mut path = Vec::new(); let mut node = current; @@ -136,7 +136,7 @@ where )); } } - println!("Not found but Evaluated: {}", evaluated); + println!("Not found but Evaluated: {evaluated}"); - return Err(String::from("No path found")); + Err(String::from("No path found")) } diff --git a/src/world.rs b/src/world.rs index c43dce7..13bb7c9 100644 --- a/src/world.rs +++ b/src/world.rs @@ -163,7 +163,7 @@ fn load_road_map(config: &Res) -> RoadMap { let road_map = if let Ok(road_map) = crate::read_file(road_map_path) { road_map } else { - println!("File {:?} not found, creating...", road_map_path); + println!("File {road_map_path:?} not found, creating..."); let road_map = bevy_shapefile::from_shapefile(&config.shapefile_path) .expect("Could not read shapefile"); @@ -182,7 +182,7 @@ fn load_graph( let network = if let Ok(network) = crate::read_file(network_path) { network } else { - println!("File {:?} not found, creating...", network_path); + println!("File {network_path:?} not found, creating..."); let network = nwb::preprocess_roadmap(road_map, &config.database_path); crate::write_file(&network, network_path).expect("Could not write network"); network @@ -196,10 +196,8 @@ fn mark_on_changed_preprocess( mut q_camera: Query<(&Camera, &GlobalTransform, &mut Transform), (With,)>, ) { if let Some(preprocess) = preprocess { - if preprocess.is_added() { - if let Ok(_) = q_camera.get_single_mut() { - tracker.map.clear(); - } + if preprocess.is_added() && q_camera.get_single_mut().is_ok() { + tracker.map.clear(); } } } diff --git a/tools/dbf_to_sql/Cargo.toml b/tools/dbf_to_sql/Cargo.toml index b26aff6..9d08850 100644 --- a/tools/dbf_to_sql/Cargo.toml +++ b/tools/dbf_to_sql/Cargo.toml @@ -9,6 +9,3 @@ version = "0.1.0" rusqlite = {version = "0.28.0", features = ["bundled"]} shapefile = {version = "0.3.0"} - -[profile.dev.package.bevy] -opt-level = 3 From 42b51f9f6af174e92b811876253b0a44cffd3589 Mon Sep 17 00:00:00 2001 From: BlockCat Date: Tue, 27 Dec 2022 16:55:29 +0100 Subject: [PATCH 03/17] add petgraph nwb --- Cargo.lock | 3 ++ Cargo.toml | 2 +- src/nwb.rs | 81 +++++++++++++++++++++++++++++++----------------- src/ui/layers.rs | 78 ++++++++++++++++++++++++---------------------- src/ui/mod.rs | 26 +++++++++------- src/ui/route.rs | 32 +++++++++---------- src/world.rs | 13 +++----- 7 files changed, 132 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64d3a59..3539ef0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -410,6 +410,7 @@ dependencies = [ "futures-lite", "highway", "network", + "petgraph", "rayon", "rusqlite", "serde", @@ -3021,6 +3022,8 @@ checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" dependencies = [ "fixedbitset", "indexmap", + "serde", + "serde_derive", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index bd92839..788c2d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ highway = {path = "./highway"} bincode = "1.3.3" network = {path = "./network"} +petgraph = {version = "0.6", features = ["serde-1"]} rusqlite = {version = "0.28.0", features = ["bundled"]} @@ -40,6 +41,5 @@ opt-level = 3 [profile.dev.package.rayon] opt-level = 3 - [workspace] members = ["bevy_shapefile", "network", "highway", "tools/dbf_to_sql"] diff --git a/src/nwb.rs b/src/nwb.rs index 02e3fc4..9468f27 100644 --- a/src/nwb.rs +++ b/src/nwb.rs @@ -1,9 +1,10 @@ use bevy::math::Vec2; use bevy_shapefile::{JunctionId, RoadId, RoadMap}; use network::{ - builder::{DirectedNetworkBuilder, EdgeBuilder, EdgeDirection, NodeBuilder}, - DirectedNetworkGraph, EdgeId, NetworkData, NodeId, ShortcutState, + builder::{EdgeBuilder, EdgeDirection, NodeBuilder}, + EdgeId, NetworkData, NodeId, ShortcutState, }; +use petgraph::stable_graph::{IndexType, StableDiGraph}; use rusqlite::{ types::{FromSql, FromSqlError}, Connection, @@ -11,10 +12,29 @@ use rusqlite::{ use serde::{Deserialize, Serialize}; use std::{collections::HashMap, hash::Hash, path::Path}; +#[derive( + Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize, +)] +pub struct NwbIndex(usize); +unsafe impl IndexType for NwbIndex { + fn new(x: usize) -> Self { + Self(x) + } + + fn index(&self) -> usize { + self.0 + } + + fn max() -> Self { + NwbIndex(usize::MAX) + } +} +pub type NwbGraph = StableDiGraph<(JunctionId, Vec2), RoadId, NwbIndex>; + #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct NWBNetworkData { pub node_junctions: Vec<(JunctionId, Vec2)>, - edge_id: Vec, // for sql, not nwb road_id + edge_id: Vec, } impl NetworkData for NWBNetworkData { @@ -138,15 +158,12 @@ impl FromSql for RijRichting { } } -pub fn preprocess_roadmap>( - roadmap: &RoadMap, - database: P, -) -> DirectedNetworkGraph { +pub fn preprocess_roadmap>(roadmap: &RoadMap, database: P) -> NwbGraph { let database = Connection::open(database).expect("Could not open database"); - let mut builder: DirectedNetworkBuilder = DirectedNetworkBuilder::new(); - let roads = &roadmap.roads; + let mut graph = NwbGraph::default(); + let roads = &roadmap.roads; let statement = database .prepare("SELECT id,junction_id_begin, junction_id_end, rij_richting FROM wegvakken") .expect("Could not prepare statement") @@ -166,28 +183,34 @@ pub fn preprocess_roadmap>( .map(|x| x.unwrap()) .collect::>(); - for (&road_id, section) in roads { - let (road_id_start, road_id_end, rij_richting) = statement[&road_id]; + let junction_to_node = roadmap + .junction_spatial + .iter() + .map(|s| { + let junction_id = s.junction_id; - let source = builder.add_node(JunctionNode { - junction_id: road_id_start, - location: *section.points.first().unwrap(), - }); - let target = builder.add_node(JunctionNode { - junction_id: road_id_end, - location: *section.points.last().unwrap(), - }); + (junction_id, graph.add_node((junction_id, s.location))) + }) + .collect::>(); - let distance = section.points.windows(2).map(|w| w[0].distance(w[1])).sum(); + for (&road_id, _) in roads { + let (road_id_start, road_id_end, rij_richting) = statement[&road_id]; - builder.add_edge(RoadEdge { - source, - target, - direction: rij_richting.0, - distance, - sql_id: road_id, - }); + let source = junction_to_node[&road_id_start]; + let target = junction_to_node[&road_id_end]; + + match rij_richting.0 { + EdgeDirection::Forward => { + graph.add_edge(source, target, road_id); + } + EdgeDirection::Both => { + graph.add_edge(source, target, road_id); + graph.add_edge(target, source, road_id); + } + EdgeDirection::Backward => { + graph.add_edge(target, source, road_id); + } + } } - - builder.build() + graph } diff --git a/src/ui/layers.rs b/src/ui/layers.rs index 33a8052..cf812fd 100644 --- a/src/ui/layers.rs +++ b/src/ui/layers.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, path::Path}; use crate::{ - nwb::NWBNetworkData, + nwb::{NWBNetworkData, NwbGraph}, world::{WorldEntity, WorldEntitySelectionType}, }; use bevy::{ @@ -105,46 +105,48 @@ pub fn handle_preprocess_task( } fn clicked_preprocess( - base: DirectedNetworkGraph, + base: NwbGraph, layer_count: usize, neighbourhood: usize, contraction_factor: f32, ) -> PreProcess { println!("Clicked: {layer_count}"); - let mut layers = Vec::new(); - - layers.push(load_or_calculate("data/layer_0.graph", || { - highway::generation::calculate_layer(neighbourhood, &base, contraction_factor) - })); - - println!( - "Base edges: {}, nodes: {}", - base.edges().len(), - base.nodes().len() - ); - - for i in 1..layer_count { - let size = neighbourhood; - let network = layers.last().unwrap(); - let path = format!("data/layer_{i}.graph"); - let next_layer = load_or_calculate(path, || { - highway::generation::calculate_layer(size, network, contraction_factor) - }); - - println!( - "Layer {} edges: {}/{}, nodes: {}/{}", - i, - next_layer.edges().len(), - network.edges().len() as f32 / next_layer.edges().len() as f32, - next_layer.nodes().len(), - network.nodes().len() as f32 / next_layer.nodes().len() as f32 - ); - - layers.push(next_layer); - } - - PreProcess::new(base, layers) + + unimplemented!("Preprocess disabled") + + // let mut layers = Vec::new(); + // layers.push(load_or_calculate("data/layer_0.graph", || { + // highway::generation::calculate_layer(neighbourhood, &base, contraction_factor) + // })); + + // println!( + // "Base edges: {}, nodes: {}", + // base.edge_count(), + // base.node_count() + // ); + + // for i in 1..layer_count { + // let size = neighbourhood; + // let network = layers.last().unwrap(); + // let path = format!("data/layer_{i}.graph"); + // let next_layer = load_or_calculate(path, || { + // highway::generation::calculate_layer(size, network, contraction_factor) + // }); + + // println!( + // "Layer {} edges: {}/{}, nodes: {}/{}", + // i, + // next_layer.edges().len(), + // network.edges().len() as f32 / next_layer.edges().len() as f32, + // next_layer.nodes().len(), + // network.nodes().len() as f32 / next_layer.nodes().len() as f32 + // ); + + // layers.push(next_layer); + // } + + // PreProcess::new(base, layers) } pub fn colouring_system( @@ -160,11 +162,13 @@ pub fn colouring_system( } else { query.par_for_each_mut(32, |mut we| { for (i, sel) in ui_state.layers_selected.iter().enumerate() { - if *sel && preprocess + if *sel + && preprocess .road_data_level .get(&we.id) .map(|&x| x > i as u8) - .unwrap_or_default() { + .unwrap_or_default() + { we.selected = WorldEntitySelectionType::BaseSelected; } } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 43afbd2..6fbc558 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,12 +1,13 @@ use crate::{ - nwb::NWBNetworkData, + nwb::NwbGraph, world::{WorldEntity, WorldEntitySelectionType}, }; use bevy::prelude::*; use bevy_egui::EguiPlugin; use bevy_shapefile::RoadMap; pub use layers::PreProcess; -use network::{DirectedNetworkGraph, NodeId}; + +use petgraph::visit::IntoNodeReferences; use std::{ collections::HashSet, ops::{Deref, DerefMut}, @@ -20,10 +21,11 @@ mod route; pub struct HighwayUiPlugin; #[derive(Resource, Debug)] -pub struct DirectedNetworkGraphContainer(pub DirectedNetworkGraph); +// pub struct DirectedNetworkGraphContainer(pub DirectedNetworkGraph); +pub struct DirectedNetworkGraphContainer(pub NwbGraph); impl Deref for DirectedNetworkGraphContainer { - type Target = DirectedNetworkGraph; + type Target = NwbGraph; fn deref(&self) -> &Self::Target { &self.0 @@ -73,19 +75,19 @@ fn point_system( .nearest_neighbor(&[world.x, world.y]) .unwrap(); - let node_id = (0..network.nodes().len()) - .map(NodeId::from) - .find(|x| network.node_data(*x).0 == node.junction_id) + let node_id = network + .node_references() + .find(|n| n.1 .0 == node.junction_id) + .map(|n| n.0) .unwrap(); let out_edges = network - .out_edges(node_id) - .map(|(id, _)| *network.edge_data(id)) + .edges_directed(node_id, petgraph::Direction::Outgoing) + .map(|x| *x.weight()) .collect::>(); - let in_edges = network - .in_edges(node_id) - .map(|(id, _)| *network.edge_data(id)) + .edges_directed(node_id, petgraph::Direction::Incoming) + .map(|x| *x.weight()) .collect::>(); query.for_each_mut(|mut we| { diff --git a/src/ui/route.rs b/src/ui/route.rs index aba4ba8..11d1879 100644 --- a/src/ui/route.rs +++ b/src/ui/route.rs @@ -1,16 +1,14 @@ -use crate::world::WorldEntitySelectionType; -use crate::{world::WorldEntity}; +use super::DirectedNetworkGraphContainer; +use crate::world::WorldEntity; use bevy::prelude::*; use bevy_egui::egui; use bevy_egui::EguiContext; use network::{iterators::F32, DirectedNetworkGraph, EdgeId, NetworkData, NodeId}; use std::{ cmp::Reverse, - collections::{BinaryHeap, HashMap, HashSet}, + collections::{BinaryHeap, HashMap}, }; -use super::DirectedNetworkGraphContainer; - pub struct RouteUIPlugin; impl Plugin for RouteUIPlugin { @@ -58,17 +56,19 @@ fn route_draw( mut query: Query<&mut WorldEntity>, network: Res, ) { - if let Some(loaded) = &route_state.edges { - let l = loaded - .iter() - .map(|(_, e)| *network.edge_data(*e)) - .collect::>(); - - query.for_each_mut(|mut a| { - if l.contains(&a.id) { - a.selected = WorldEntitySelectionType::Route;// Some(Color::ALICE_BLUE); - } - }); + if let Some(route) = &route_state.edges { + // Collect all roadIds in the map. + unimplemented!("Road highlighting not implemented"); + // let l = route + // .iter() + // .map(|(_, e)| *network.edge_data(*e)) + // .collect::>(); + + // query.for_each_mut(|mut a| { + // if l.contains(&a.id) { + // a.selected = WorldEntitySelectionType::Route;// Some(Color::ALICE_BLUE); + // } + // }); } } diff --git a/src/world.rs b/src/world.rs index 13bb7c9..d574d3d 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,6 +1,6 @@ use crate::{ camera::MainCamera, - nwb::{self}, + nwb::{self, NwbGraph}, ui::{DirectedNetworkGraphContainer, PreProcess}, }; use bevy::prelude::*; @@ -133,8 +133,8 @@ fn init_road_map(config: Res, mut commands: Commands) { println!("Inserted resources"); println!("Status:"); - println!("Nodes: {}", network.nodes().len()); - println!("Edges: {}", network.edges().len()); + println!("Nodes: {}", network.node_count()); + println!("Edges: {}", network.edge_count()); // let out = network // .nodes() @@ -174,12 +174,9 @@ fn load_road_map(config: &Res) -> RoadMap { road_map } -fn load_graph( - config: Res, - road_map: &RoadMap, -) -> DirectedNetworkGraph { +fn load_graph(config: Res, road_map: &RoadMap) -> NwbGraph { let network_path = Path::new(&config.directed_graph_path); - let network = if let Ok(network) = crate::read_file(network_path) { + let network: NwbGraph = if let Ok(network) = crate::read_file(network_path) { network } else { println!("File {network_path:?} not found, creating..."); From 4da727d8341d0af73afaea51a8d33e92302201c1 Mon Sep 17 00:00:00 2001 From: BlockCat Date: Tue, 27 Dec 2022 17:21:00 +0100 Subject: [PATCH 04/17] updated data --- README.md | 4 +- examples/layer.rs | 59 +++++++------- src/main.rs | 2 +- src/nwb.rs | 152 +++++------------------------------ src/ui/layers.rs | 54 ++++++------- src/world.rs | 1 - tools/dbf_to_sql/database.db | Bin 16384 -> 0 bytes tools/dbf_to_sql/src/main.rs | 2 +- 8 files changed, 80 insertions(+), 194 deletions(-) delete mode 100644 tools/dbf_to_sql/database.db diff --git a/README.md b/README.md index 7b35109..dac1772 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ ## Install: 1. Retrieve latest data from https://www.rijkswaterstaat.nl/apps/geoservices/geodata/dmc/nwb-wegen/geogegevens/shapefile/Nederland_totaal/ 2. Extract contents to /data folder. -3. Create a database using the tools/dbf_to_sql tool. - +3. Create a database using the tools/dbf_to_sql tool. (`cargo.exe run --package dbf_to_sql --bin dbf_to_sql --release`) +4. Copy database to data/database.db ## Structure: ### Visualization diff --git a/examples/layer.rs b/examples/layer.rs index 6b4a2c3..b5b79f4 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -1,48 +1,49 @@ -use bevy_dutch_road_highway_node_network::{nwb::NWBNetworkData, read_file, write_file}; +use bevy_dutch_road_highway_node_network::{nwb::NwbGraph, read_file, write_file}; use highway::generation::calculate_layer; use network::{DirectedNetworkGraph, NetworkData}; fn main() { - let network: DirectedNetworkGraph = - read_file("data/directed_graph.graph").unwrap(); + let network: NwbGraph = read_file("data/directed_graph.graph").unwrap(); println!( "Layer: 0 - n: {}, e: {} ", - network.nodes().len(), - network.edges().len() + network.node_count(), + network.edge_count() ); - let mut layers = vec![calculate_layer(30, &network, 2.0)]; + unimplemented!("Disabled"); - if let Some(x) = layers.first() { - write_file(x, "data/0.graph".to_string()).expect("Could not write"); - } + // let mut layers = vec![calculate_layer(30, &network, 2.0)]; - for i in 1..7 { - let prev_layer = layers.last().unwrap(); - println!( - "Layer: {} - n: {}, e: {} ", - i, - prev_layer.nodes().len(), - prev_layer.edges().len() - ); - let next = calculate_layer(30, prev_layer, 3.0); + // if let Some(x) = layers.first() { + // write_file(x, "data/0.graph".to_string()).expect("Could not write"); + // } - write_file(&next, format!("data/{i}.graph")).expect("Could not write"); - layers.push(next); - } + // for i in 1..7 { + // let prev_layer = layers.last().unwrap(); + // println!( + // "Layer: {} - n: {}, e: {} ", + // i, + // prev_layer.nodes().len(), + // prev_layer.edges().len() + // ); + // let next = calculate_layer(30, prev_layer, 3.0); - data(0, 1, &network, &layers[0]); + // write_file(&next, format!("data/{i}.graph")).expect("Could not write"); + // layers.push(next); + // } - let mut counter = 0; + // data(0, 1, &network, &layers[0]); - for layer in layers.windows(2) { - counter += 1; - let l1 = &layer[0]; - let l2 = &layer[1]; + // let mut counter = 0; - data(counter, counter + 1, l1, l2); - } + // for layer in layers.windows(2) { + // counter += 1; + // let l1 = &layer[0]; + // let l2 = &layer[1]; + + // data(counter, counter + 1, l1, l2); + // } } fn data( diff --git a/src/main.rs b/src/main.rs index cdc4e5b..1e870ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,7 @@ fn main() { .add_plugin(WorldPlugin { config: WorldConfig { database_path: "data/database.db".into(), - shapefile_path: "data/01-03-2022/Wegvakken/Wegvakken.shp".into(), + shapefile_path: "data/01-12-2022/Wegvakken/Wegvakken.shp".into(), road_map_path: "data/road_map.data".into(), directed_graph_path: "data/directed_graph.graph".into(), diff --git a/src/nwb.rs b/src/nwb.rs index 9468f27..df88fae 100644 --- a/src/nwb.rs +++ b/src/nwb.rs @@ -1,9 +1,6 @@ use bevy::math::Vec2; use bevy_shapefile::{JunctionId, RoadId, RoadMap}; -use network::{ - builder::{EdgeBuilder, EdgeDirection, NodeBuilder}, - EdgeId, NetworkData, NodeId, ShortcutState, -}; +use network::builder::EdgeDirection; use petgraph::stable_graph::{IndexType, StableDiGraph}; use rusqlite::{ types::{FromSql, FromSqlError}, @@ -31,133 +28,6 @@ unsafe impl IndexType for NwbIndex { } pub type NwbGraph = StableDiGraph<(JunctionId, Vec2), RoadId, NwbIndex>; -#[derive(Clone, Debug, Default, Serialize, Deserialize)] -pub struct NWBNetworkData { - pub node_junctions: Vec<(JunctionId, Vec2)>, - edge_id: Vec, -} - -impl NetworkData for NWBNetworkData { - type NodeData = (JunctionId, Vec2); - type EdgeData = RoadId; - - fn node_data(&self, node: NodeId) -> &Self::NodeData { - &self.node_junctions[node.0 as usize] - } - - fn edge_data(&self, edge: EdgeId) -> &Self::EdgeData { - &self.edge_id[edge.0 as usize] - } - - fn with_size(node_size: usize, edge_size: usize) -> Self { - NWBNetworkData { - node_junctions: vec![(0.into(), Vec2::ZERO); node_size], - edge_id: vec![0.into(); edge_size], - } - } - - fn add_node(&mut self, node: NodeId, data: Self::NodeData) { - self.node_junctions[node.0 as usize] = data; - } - - fn add_edge(&mut self, edge: EdgeId, data: Self::EdgeData, _: ShortcutState) { - self.edge_id[edge.0 as usize] = data; - } - - fn edge_road_id(&self, edge: EdgeId) -> network::ShortcutState { - ShortcutState::Single(self.edge_id[edge.0 as usize].num()) - } -} - -#[derive(Debug)] -pub struct JunctionNode { - pub junction_id: JunctionId, - pub location: Vec2, -} - -impl PartialEq for JunctionNode { - fn eq(&self, other: &Self) -> bool { - self.junction_id == other.junction_id - } -} - -impl Eq for JunctionNode {} - -impl Hash for JunctionNode { - fn hash(&self, state: &mut H) { - self.junction_id.hash(state); - } -} - -impl NodeBuilder for JunctionNode { - type Data = (JunctionId, Vec2); - - fn data(&self) -> Self::Data { - (self.junction_id, self.location) - } - - fn id(&self) -> u32 { - self.junction_id.num() as u32 - } -} - -#[derive(Debug, Clone)] -pub struct RoadEdge { - sql_id: RoadId, // Points to sql - distance: f32, - source: NodeId, - target: NodeId, - direction: EdgeDirection, -} - -impl EdgeBuilder for RoadEdge { - type Data = RoadId; - - fn data(&self) -> Self::Data { - self.sql_id - } - - fn source(&self) -> network::NodeId { - self.source - } - - fn target(&self) -> network::NodeId { - self.target - } - - fn weight(&self) -> f32 { - self.distance - } - - fn direction(&self) -> network::builder::EdgeDirection { - self.direction - } - - fn road_id(&self) -> ShortcutState { - ShortcutState::Single(self.sql_id.num()) - } -} - -#[derive(Debug, Clone, Copy)] -struct RijRichting(EdgeDirection); - -impl FromSql for RijRichting { - fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult { - let rij_richting = String::column_result(value)?; - let rij_richting = rij_richting - .chars() - .next() - .ok_or(FromSqlError::InvalidType)?; - match rij_richting { - 'H' => Ok(RijRichting(EdgeDirection::Forward)), - 'T' => Ok(RijRichting(EdgeDirection::Backward)), - 'B' => Ok(RijRichting(EdgeDirection::Both)), - 'O' => Ok(RijRichting(EdgeDirection::Both)), - _ => Err(FromSqlError::InvalidType), - } - } -} - pub fn preprocess_roadmap>(roadmap: &RoadMap, database: P) -> NwbGraph { let database = Connection::open(database).expect("Could not open database"); @@ -214,3 +84,23 @@ pub fn preprocess_roadmap>(roadmap: &RoadMap, database: P) -> Nwb } graph } + +#[derive(Debug, Clone, Copy)] +struct RijRichting(EdgeDirection); + +impl FromSql for RijRichting { + fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult { + let rij_richting = String::column_result(value)?; + let rij_richting = rij_richting + .chars() + .next() + .ok_or(FromSqlError::InvalidType)?; + match rij_richting { + 'H' => Ok(RijRichting(EdgeDirection::Forward)), + 'T' => Ok(RijRichting(EdgeDirection::Backward)), + 'B' => Ok(RijRichting(EdgeDirection::Both)), + 'O' => Ok(RijRichting(EdgeDirection::Both)), + _ => Err(FromSqlError::InvalidType), + } + } +} diff --git a/src/ui/layers.rs b/src/ui/layers.rs index cf812fd..c396bcc 100644 --- a/src/ui/layers.rs +++ b/src/ui/layers.rs @@ -1,7 +1,5 @@ -use std::{collections::HashMap, path::Path}; - use crate::{ - nwb::{NWBNetworkData, NwbGraph}, + nwb::NwbGraph, world::{WorldEntity, WorldEntitySelectionType}, }; use bevy::{ @@ -13,6 +11,7 @@ use bevy_shapefile::RoadId; use futures_lite::future; use highway::generation::intermediate_network::IntermediateData; use network::{DirectedNetworkGraph, EdgeId, NetworkData}; +use std::{collections::HashMap, path::Path}; use super::DirectedNetworkGraphContainer; @@ -112,9 +111,7 @@ fn clicked_preprocess( ) -> PreProcess { println!("Clicked: {layer_count}"); - - unimplemented!("Preprocess disabled") - + unimplemented!("Preprocessing is disabled while implementing petgraph"); // let mut layers = Vec::new(); // layers.push(load_or_calculate("data/layer_0.graph", || { // highway::generation::calculate_layer(neighbourhood, &base, contraction_factor) @@ -179,34 +176,33 @@ pub fn colouring_system( #[derive(Resource)] pub struct PreProcess { - pub base: DirectedNetworkGraph, + pub base: NwbGraph, pub layers: Vec>, pub road_data_level: HashMap, } impl PreProcess { - pub fn new( - base: DirectedNetworkGraph, - layers: Vec>, - ) -> Self { - let mut road_data_level = (0..base.edges().len()) - .map(EdgeId::from) - .flat_map(|id| Vec::from(base.data.edge_road_id(id))) - .map(|x| (RoadId::from(x), 0)) - .collect::>(); - - println!("Base line of: {}", road_data_level.len()); - // process_edges(0, &base, &mut road_data_level); - - for (layer_id, layer) in layers.iter().enumerate() { - process_edges(layer_id as u8 + 1, layer, &mut road_data_level); - } - - PreProcess { - base, - layers, - road_data_level, - } + pub fn new(base: NwbGraph, layers: Vec>) -> Self { + unimplemented!("Could not create preprocess") + + // let mut road_data_level = (0..base.edges().len()) + // .map(EdgeId::from) + // .flat_map(|id| Vec::from(base.data.edge_road_id(id))) + // .map(|x| (RoadId::from(x), 0)) + // .collect::>(); + + // println!("Base line of: {}", road_data_level.len()); + // // process_edges(0, &base, &mut road_data_level); + + // for (layer_id, layer) in layers.iter().enumerate() { + // process_edges(layer_id as u8 + 1, layer, &mut road_data_level); + // } + + // PreProcess { + // base, + // layers, + // road_data_level, + // } } } diff --git a/src/world.rs b/src/world.rs index d574d3d..844876e 100644 --- a/src/world.rs +++ b/src/world.rs @@ -6,7 +6,6 @@ use crate::{ use bevy::prelude::*; use bevy_polyline::prelude::{Polyline, PolylineBundle, PolylineMaterial}; use bevy_shapefile::{RoadId, RoadMap, RoadSection, AABB}; -use network::DirectedNetworkGraph; use std::{ collections::{HashMap, HashSet}, path::Path, diff --git a/tools/dbf_to_sql/database.db b/tools/dbf_to_sql/database.db deleted file mode 100644 index f9ce1bcf7904fc342476a1b3b8a6e70477983107..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeH~-)`D46vmTMZ4)Y@cfG7HTdAGK_5uskg%lR8!Cg1?!V2I*3WO~<`||?3+ST4^ z@3hMuW600~+HQwFOEHQ4o%6*%A0oMX-HEkg_p@{wY4*Z7bX?bY$(Z9fE?xU{t=gvN z)!epU*LiyPtWy2yln#97z_0$Oe%~g=I0%3M2!H?xfB*=900@A{-3F&1|4dY~$^o-%3(ZRzr)I`pbKjOBiXyyVrbWGs@z5l1-;7mE@T9b(W=a5+~z%;T>B+*cD+X zXm@SyjiITc6>f_STY_S3G`;# Date: Tue, 27 Dec 2022 19:27:55 +0100 Subject: [PATCH 05/17] cleanup p1 --- Cargo.lock | 1 + Cargo.toml | 4 - benches/phase_1_benchmark.rs | 20 -- highway/src/lib.rs | 2 +- highway/src/query/mod.rs | 2 +- network/Cargo.toml | 3 +- network/src/directed_network/iterators.rs | 4 +- network/src/directed_network/mod.rs | 14 +- network/src/directed_network/node_data.rs | 4 +- network/src/highway/core.rs | 74 ------ network/src/highway/dag.rs | 160 ----------- network/src/highway/dijkstra.rs | 259 ------------------ network/src/highway/intermediate_network.rs | 279 -------------------- network/src/highway/mod.rs | 123 --------- network/src/highway_network/iterators.rs | 54 ---- network/src/highway_network/mod.rs | 170 ------------ network/src/iterators.rs | 155 +++++++++++ network/src/lib.rs | 93 ++----- network/src/neighbourhood.rs | 124 +++++---- network/src/tests.rs | 180 ++++++------- 20 files changed, 339 insertions(+), 1386 deletions(-) delete mode 100644 benches/phase_1_benchmark.rs delete mode 100644 network/src/highway/core.rs delete mode 100644 network/src/highway/dag.rs delete mode 100644 network/src/highway/dijkstra.rs delete mode 100644 network/src/highway/intermediate_network.rs delete mode 100644 network/src/highway/mod.rs delete mode 100644 network/src/highway_network/iterators.rs delete mode 100644 network/src/highway_network/mod.rs create mode 100644 network/src/iterators.rs diff --git a/Cargo.lock b/Cargo.lock index 3539ef0..6ca66cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2688,6 +2688,7 @@ version = "0.1.0" dependencies = [ "bincode", "itertools", + "petgraph", "rayon", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index 788c2d0..d600e56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,10 +28,6 @@ rayon = "1.5.1" [dev-dependencies] criterion = "0.4.0" -[[bench]] -harness = false -name = "phase_1_benchmark" - [profile.dev.package.bevy_shapefile] opt-level = 3 diff --git a/benches/phase_1_benchmark.rs b/benches/phase_1_benchmark.rs deleted file mode 100644 index 33b7f87..0000000 --- a/benches/phase_1_benchmark.rs +++ /dev/null @@ -1,20 +0,0 @@ -use bevy_dutch_road_highway_node_network::{nwb::NWBNetworkData, read_file}; -use criterion::{criterion_group, criterion_main, Criterion}; -use highway::generation::calculate_layer; -use network::DirectedNetworkGraph; - -fn bench(b: &mut Criterion) { - let network: DirectedNetworkGraph = - read_file("data/directed_graph.graph").unwrap(); - - let mut group = b.benchmark_group("sample: 10"); - - group.sample_size(10); - group.bench_function("network::phase_1", |b| { - b.iter(|| calculate_layer(30, &network, 2.0)); - }); - group.finish(); -} - -criterion_group!(benches, bench); -criterion_main!(benches); diff --git a/highway/src/lib.rs b/highway/src/lib.rs index 052fa96..964e2ee 100644 --- a/highway/src/lib.rs +++ b/highway/src/lib.rs @@ -2,4 +2,4 @@ #![feature(is_sorted)] pub mod generation; -pub mod query; +// pub mod query; diff --git a/highway/src/query/mod.rs b/highway/src/query/mod.rs index 21a0d73..f254de5 100644 --- a/highway/src/query/mod.rs +++ b/highway/src/query/mod.rs @@ -1,6 +1,6 @@ use std::collections::BinaryHeap; -use network::{builder::EdgeDirection, highway_network::HighwayNetwork, NodeId}; +use network::{builder::EdgeDirection, NodeId}; pub fn shortest_path(source: NodeId, target: NodeId, network: &HighwayNetwork) { let mut forward = HighwayDijkstraIterator::default(); diff --git a/network/Cargo.toml b/network/Cargo.toml index d7ac31e..642761e 100644 --- a/network/Cargo.toml +++ b/network/Cargo.toml @@ -7,7 +7,8 @@ version = "0.1.0" [dependencies] bincode = "1.3.3" +itertools = "*" rayon = "1.5.1" serde = {version = "1.0.136", features = ["derive"]} -itertools = "*" +petgraph = {version = "0.6", features = ["serde-1"]} diff --git a/network/src/directed_network/iterators.rs b/network/src/directed_network/iterators.rs index f32fc0b..1b7b377 100644 --- a/network/src/directed_network/iterators.rs +++ b/network/src/directed_network/iterators.rs @@ -1,6 +1,4 @@ -use crate::{ - builder::EdgeDirection, DirectedNetworkGraph, EdgeId, NetworkData, NetworkEdge, NodeId, -}; +use crate::{builder::EdgeDirection, DirectedNetworkGraph, NetworkData, NetworkEdge}; use std::{ cmp::Reverse, collections::{BinaryHeap, HashSet}, diff --git a/network/src/directed_network/mod.rs b/network/src/directed_network/mod.rs index fba0393..25aa74d 100644 --- a/network/src/directed_network/mod.rs +++ b/network/src/directed_network/mod.rs @@ -1,15 +1,3 @@ -use self::{ - builder::EdgeDirection, - iterators::{BackwardDijkstraIterator, EdgeIterator, ForwardDijkstraIterator, F32}, -}; -use crate::{BackwardNeighbourhood, EdgeId, ForwardNeighbourhood, NodeId}; -pub use node_data::NetworkData; -use serde::{Deserialize, Serialize}; -use std::{ - cmp::Reverse, - collections::{BinaryHeap, HashSet}, -}; - pub mod builder; pub mod iterators; pub mod node_data; @@ -134,7 +122,7 @@ impl DirectedNetworkGraph { self.create_iterator_raw(node, EdgeDirection::Backward) } - + /// Collect the nodes in order of lowest to highest distance pub fn forward_iterator(&self, node: NodeId) -> ForwardDijkstraIterator<'_, D> { let mut heap = BinaryHeap::new(); heap.push(Reverse((F32(0.0), node))); diff --git a/network/src/directed_network/node_data.rs b/network/src/directed_network/node_data.rs index 9ea7c7b..0717922 100644 --- a/network/src/directed_network/node_data.rs +++ b/network/src/directed_network/node_data.rs @@ -32,7 +32,5 @@ impl NetworkData for () { fn add_edge(&mut self, _: EdgeId, _: Self::EdgeData, _: ShortcutState) {} - fn with_size(_: usize, _: usize) -> Self { - - } + fn with_size(_: usize, _: usize) -> Self {} } diff --git a/network/src/highway/core.rs b/network/src/highway/core.rs deleted file mode 100644 index 84ebb9c..0000000 --- a/network/src/highway/core.rs +++ /dev/null @@ -1,74 +0,0 @@ -use super::intermediate_network::IntermediateNetwork; -use crate::NodeId; -use std::{ - collections::{HashSet, VecDeque}, - hash::Hash, -}; - -pub(crate) fn core_network_with_patch( - mut intermediate_network: IntermediateNetwork, - contraction_factor: f32, -) -> IntermediateNetwork { - let nodes = { - let mut n = intermediate_network.nodes(); - n.sort(); - n - }; - - let mut queue = HashNodeQueue::::from_vec(&nodes); - - while let Some(node) = queue.pop_front() { - let out_edges = &intermediate_network - .out_edges(node) - .map(|x| x.len() as f32) - .unwrap_or_default(); - let in_edges = &intermediate_network - .in_edges(node) - .map(|x| x.len() as f32) - .unwrap_or_default(); - - let short_cuts = (out_edges * in_edges) as f32; - let contraction = (out_edges + in_edges) * contraction_factor; - - if short_cuts < contraction { - let mut touched = intermediate_network.bypass(node); - touched.sort(); - for touched in touched { - queue.push_back(touched); - } - } - } - - intermediate_network -} - -#[derive(Debug, Default, Clone)] -struct HashNodeQueue { - queue: VecDeque, - seen: HashSet, -} - -impl HashNodeQueue { - fn from_vec(items: &[T]) -> Self { - let queue = VecDeque::from_iter(items.iter().cloned()); - let mut seen = HashSet::with_capacity(items.len()); - seen.extend(items.iter().cloned()); - - HashNodeQueue { queue, seen } - } - fn contains(&self, value: &T) -> bool { - self.seen.contains(value) - } - - fn pop_front(&mut self) -> Option { - let value = self.queue.pop_front()?; - self.seen.remove(&value); - Some(value) - } - - fn push_back(&mut self, value: T) { - if self.contains(&value) { - self.queue.push_back(value); - } - } -} diff --git a/network/src/highway/dag.rs b/network/src/highway/dag.rs deleted file mode 100644 index 3f235d5..0000000 --- a/network/src/highway/dag.rs +++ /dev/null @@ -1,160 +0,0 @@ -use crate::{EdgeId, NodeId}; -use std::collections::{BinaryHeap, HashMap}; - -#[derive(Debug, PartialEq, PartialOrd)] -pub struct ParentEntry { - pub parent: NodeId, - pub parent_edge: EdgeId, - pub parent_edge_distance: f32, - pub active: bool, -} - -#[derive(Debug, PartialEq)] -pub struct DijkstraNodeState { - pub distance: f32, - pub current: NodeId, - pub parent: ParentEntry, -} - -impl Ord for DijkstraNodeState { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.partial_cmp(other).unwrap() - } -} - -impl Eq for DijkstraNodeState {} - -impl PartialOrd for DijkstraNodeState { - fn partial_cmp(&self, other: &Self) -> Option { - match self.distance.partial_cmp(&other.distance) { - Some(core::cmp::Ordering::Equal) => {} - Some(core::cmp::Ordering::Greater) => return Some(core::cmp::Ordering::Less), - Some(core::cmp::Ordering::Less) => return Some(core::cmp::Ordering::Greater), - None => return None, - } - - match self.current.partial_cmp(&other.current) { - Some(core::cmp::Ordering::Equal) => {} - ord => return ord, - } - - self.parent.partial_cmp(&other.parent) - } -} - -#[derive(Debug)] -pub struct VisitedState { - pub border_distance: f32, - pub reference_distance: f32, - pub distance: f32, - pub parents: HashMap, f32)>, -} - -pub struct HighwayNodeQueue { - pub heap: BinaryHeap, - pub visited: HashMap, - active: usize, -} - -pub struct HighwayQueueEntry { - pub state: DijkstraNodeState, - pub parents: HashMap, f32)>, - pub border_distance: f32, - pub reference_distance: f32, - pub parent_active: bool, -} - -impl HighwayNodeQueue { - pub fn new(heap_size: usize, visited_size: usize) -> Self { - Self { - heap: BinaryHeap::with_capacity(heap_size), - visited: HashMap::with_capacity(visited_size), - active: 0, - } - } - pub fn push(&mut self, state: DijkstraNodeState) { - if state.parent.active { - self.active += 1; - } - self.heap.push(state); - } - - pub fn pop(&mut self) -> Option { - if !self.is_active() { - return None; - } - while let Some(mut state) = self.heap.pop() { - if state.parent.active { - self.active -= 1; - } - if self.visited.contains_key(&state.current) { - debug_assert!(state.distance > self.visited[&state.current].distance); - continue; - } - - let mut parent_border_distance = self.visited[&state.parent.parent].border_distance; - let mut parent_reference_distance = - self.visited[&state.parent.parent].reference_distance; - let mut parents = HashMap::from([( - state.parent.parent, - ( - Some(state.parent.parent_edge), - state.parent.parent_edge_distance, - ), - )]); - - let mut parent_active = state.parent.active; - - while let Some(peek) = self - .heap - .peek() - .filter(|next| next.current == state.current && next.distance == state.distance) - { - if peek.parent.active { - self.active -= 1; - } - - let visited_parent = &self.visited[&peek.parent.parent]; - - parent_border_distance = - f32::max(parent_border_distance, visited_parent.border_distance); - parent_reference_distance = - f32::max(parent_reference_distance, visited_parent.reference_distance); - - parents.insert( - peek.parent.parent, - ( - Some(peek.parent.parent_edge), - peek.parent.parent_edge_distance, - ), - ); - - parent_active |= peek.parent.active; - - state = self.heap.pop().unwrap(); - } - - return Some(HighwayQueueEntry { - state, - border_distance: parent_border_distance, - reference_distance: parent_reference_distance, - parents, - parent_active, - }); - } - - None - } - - pub fn visited(&mut self, node: NodeId, state: VisitedState) -> Option { - self.visited.insert(node, state) - } - - pub fn is_active(&self) -> bool { - debug_assert_eq!( - self.active, - self.heap.iter().filter(|x| x.parent.active).count() - ); - self.active > 0 - } -} diff --git a/network/src/highway/dijkstra.rs b/network/src/highway/dijkstra.rs deleted file mode 100644 index 557d14c..0000000 --- a/network/src/highway/dijkstra.rs +++ /dev/null @@ -1,259 +0,0 @@ -use super::ComputedState; -use crate::{iterators::F32, DirectedNetworkGraph, EdgeId, NetworkData, NodeId}; -use std::{ - cmp::Reverse, - collections::{HashMap, VecDeque}, -}; - -use super::dag::*; - -pub fn calculate_edges( - s0: NodeId, - computed: &ComputedState, - network: &DirectedNetworkGraph, -) -> Vec<(NodeId, EdgeId)> { - let (sorted_order, dag) = create_directed_acyclic_graph(s0, computed, network); - let edges = collect_next_level_edges(s0, sorted_order, dag, computed); - - edges -} - -pub fn create_directed_acyclic_graph( - s0: NodeId, - computed: &ComputedState, - network: &DirectedNetworkGraph, -) -> ( - VecDeque<(NodeId, (EdgeId, f32))>, - HashMap, -) { - let mut heap = HighwayNodeQueue::new(2000, 3000); - - let mut settled_order = VecDeque::with_capacity(3000); - - // println!("Continue growing the DAG, and stop when there are no more active nodes"); - - initialize_heap(s0, network, &mut heap); - - while let Some(entry) = heap.pop() { - let border_distance = border_distance( - s0, - entry.state.current, - &entry.parents, - computed, - entry.border_distance, - ); - - let reference_distance = reference_distance(&entry, border_distance, &heap.visited); - heap.visited( - entry.state.current, - VisitedState { - distance: entry.state.distance, - border_distance, - reference_distance, - parents: entry.parents, - }, - ); - - settled_order.push_front(( - entry.state.current, - (entry.state.parent.parent_edge, entry.state.distance), - )); - - let should_abort = (reference_distance + computed.backward.radius(entry.state.current)) - < entry.state.distance; - - let active = entry.parent_active && !should_abort; - - for (id, child_edge) in network.out_edges(entry.state.current) { - let child = child_edge.target(); - let next_distance = entry.state.distance + child_edge.distance(); - - heap.push(DijkstraNodeState { - current: child, - distance: next_distance, - parent: ParentEntry { - parent: entry.state.current, - parent_edge_distance: child_edge.distance(), - parent_edge: id.into(), - active, - }, - }); - } - } - - (settled_order, heap.visited) -} - -fn collect_next_level_edges( - s0: NodeId, - mut sorted_nodes: VecDeque<(NodeId, (EdgeId, f32))>, - nodes: HashMap, - computed: &ComputedState, -) -> Vec<(NodeId, EdgeId)> { - let mut collected_edges = Vec::new(); - let mut tentative_slacks = HashMap::new(); - - debug_assert!(sorted_nodes - .iter() - .is_sorted_by_key(|x| Reverse(F32(x.1 .1)))); - - while let Some((node, (_, distance))) = sorted_nodes.pop_front() { - if distance < computed.forward.radius(s0) { - // return collected_edges; - continue; - } - - let slack = *tentative_slacks - .entry(node) - .or_insert_with(|| computed.backward.radius(node)); - - for (parent, (edge_id, distance)) in &nodes[&node].parents { - let slack_parent = slack - distance; - - if slack_parent < 0.0 { - collected_edges.push((*parent, edge_id.unwrap())); - } - - let tentative_slack_parent = tentative_slacks - .entry(*parent) - .or_insert_with(|| computed.backward.radius(*parent)); - - *tentative_slack_parent = f32::min(*tentative_slack_parent, slack_parent); - } - } - - collected_edges -} - -fn initialize_heap( - s0: NodeId, - network: &DirectedNetworkGraph, - heap: &mut HighwayNodeQueue, -) { - heap.visited( - s0, - VisitedState { - border_distance: 0.0, - reference_distance: f32::INFINITY, - distance: 0.0, - parents: HashMap::from([(s0, (None, 0.0))]), - }, - ); - for (id, edge) in network.out_edges(s0) { - assert!(s0 != edge.target()); - heap.push(DijkstraNodeState { - distance: edge.distance(), - current: edge.target(), - parent: ParentEntry { - parent: s0, - parent_edge_distance: edge.distance(), - parent_edge: id.into(), - active: true, - }, - }); - } -} - -fn border_distance( - s0: NodeId, - node: NodeId, - parents: &HashMap, - computed: &ComputedState, - parent_border_distance: f32, -) -> f32 { - if let Some((_, distance)) = parents.get(&s0) { - *distance + computed.forward.radius(node) - } else { - parent_border_distance - } -} - -fn reference_distance( - entry: &HighwayQueueEntry, - border_distance: f32, - visited: &HashMap, -) -> f32 { - let distance = entry.state.distance; - let reference_distance = entry.reference_distance; - let parents = &entry.parents; - if reference_distance == f32::INFINITY && distance > border_distance { - parents - .keys() - .flat_map(|parent| visited[parent].parents.iter()) - .map(|sp| visited[sp.0].distance) - .max_by(|a, b| a.partial_cmp(b).unwrap()) - .unwrap() - } else { - reference_distance - } -} - -#[cfg(test)] -mod tests { - - use std::collections::HashSet; - - use crate::{ - highway::dijkstra::{collect_next_level_edges, create_directed_acyclic_graph}, - tests::{create_ref_network_1, create_undirected_network}, - NodeId, - }; - - use super::ComputedState; - - #[test] - fn forward_test() { - let network = create_ref_network_1(); - let computed = ComputedState::new(3, &network); - - create_directed_acyclic_graph(NodeId(0), &computed, &network); - } - - #[test] - fn level_test() { - let network = create_undirected_network(); - let computed = super::ComputedState::new(4, &network); - let s0 = NodeId(12); - let edges = create_directed_acyclic_graph(s0, &computed, &network); - - println!("DAG:"); - for (n, i) in &edges.1 { - println!("N: {},\t {:?}", n.0, i); - } - - println!("Edges: {:?}", edges.0); - - let next_edges = collect_next_level_edges(s0, edges.0, edges.1, &computed); - - println!("Added:"); - for (parent, id) in next_edges { - let edge = network.edge(id); - assert_ne!(parent, edge.target()); - println!("ID: {:?} - {:?}", id, edge); - } - } - - #[test] - fn test_all() { - let network = create_undirected_network(); - let computed = super::ComputedState::new(4, &network); - - let mut next_edges = HashSet::new(); - - for n in 0..=16 { - let edges = super::calculate_edges(NodeId(n), &computed, &network); - - next_edges.extend(edges); - } - - let mut next_edges = next_edges.into_iter().collect::>(); - - next_edges.sort(); - - println!("Added:"); - for (_, id) in next_edges { - let edge = network.edge(id); - println!("ID: {:?} - {:?}", id, edge); - } - } -} diff --git a/network/src/highway/intermediate_network.rs b/network/src/highway/intermediate_network.rs deleted file mode 100644 index 9e8a100..0000000 --- a/network/src/highway/intermediate_network.rs +++ /dev/null @@ -1,279 +0,0 @@ -use crate::{ - builder::{DirectedNetworkBuilder, EdgeBuilder, EdgeDirection, NodeBuilder}, - DirectedNetworkGraph, EdgeId, NetworkData, NodeId, ShortcutState, -}; -use rayon::iter::{FromParallelIterator, ParallelIterator}; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct IntermediateNode(pub NodeId); - -#[derive(Debug, Clone)] -pub struct IntermediateEdge { - data: ShortcutState, - road_id: ShortcutState, - direction: EdgeDirection, - source: NodeId, - target: NodeId, - weight: f32, -} - -impl NodeBuilder for IntermediateNode { - type Data = NodeId; - - fn data(&self) -> Self::Data { - self.0 - } -} - -impl EdgeBuilder for IntermediateEdge { - type Data = ShortcutState; // Points to road_id - - fn data(&self) -> Self::Data { - self.data.clone() - } - - fn source(&self) -> NodeId { - self.source - } - - fn target(&self) -> NodeId { - self.target - } - - fn weight(&self) -> f32 { - self.weight - } - - fn direction(&self) -> EdgeDirection { - self.direction - } - - fn road_id(&self) -> ShortcutState { - self.road_id.clone() - } -} - -impl IntermediateEdge { - pub fn new( - source: NodeId, - target: NodeId, - weight: f32, - data: ShortcutState, - road_id: ShortcutState, - direction: EdgeDirection, - ) -> Self { - Self { - source, - target, - weight, - data, - direction, - road_id, - } - } -} - -#[derive(Debug, Default)] -pub(crate) struct IntermediateNetwork { - out_edges: HashMap>, - in_edges: HashMap>, -} - -impl IntermediateNetwork { - pub fn nodes(&self) -> Vec { - self.out_edges.keys().cloned().collect::>() - } - pub fn out_edges(&self, node: NodeId) -> Option<&HashMap> { - self.out_edges.get(&node) - } - - pub fn in_edges(&self, node: NodeId) -> Option<&HashMap> { - self.in_edges.get(&node) - } -} -impl IntermediateNetwork { - pub fn add_edge(&mut self, edge: IntermediateEdge) { - let source = edge.source; - let target = edge.target; - self.out_edges - .entry(source) - .or_default() - .insert(target, edge.clone()); - - self.in_edges - .entry(target) - .or_default() - .insert(source, edge.clone()); - } - - pub fn remove_node(&mut self, node: NodeId) { - if let Some(outs) = self.out_edges.get(&node) { - for edge in outs.values() { - self.in_edges.entry(edge.target).and_modify(|x| { - x.remove(&node); - }); - } - } - - if let Some(ins) = self.in_edges.get(&node) { - for edge in ins.values() { - self.out_edges.entry(edge.source).and_modify(|x| { - x.remove(&node); - }); - } - } - - self.out_edges.remove(&node); - self.in_edges.remove(&node); - } - - pub fn bypass(&mut self, node: NodeId) -> Vec { - let parents = if let Some(parents) = self.in_edges(node) { - parents - } else { - self.remove_node(node); - return vec![]; - }; - let children = if let Some(children) = self.out_edges(node) { - children - } else { - self.remove_node(node); - return vec![]; - }; - - let mut collects = Vec::new(); - - for (parent, parent_edge) in parents { - debug_assert_eq!(parent, &parent_edge.source); - for (child, child_edge) in children { - debug_assert_eq!(child, &child_edge.target); - if parent.0 != child.0 { - let distance = parent_edge.weight + child_edge.weight; - let (state, road_ids) = collect_shortcut_data_edges(parent_edge, child_edge); - let shortcut = IntermediateEdge::new( - *parent, - *child, - distance, - ShortcutState::Shortcut(state), - ShortcutState::Shortcut(road_ids), - EdgeDirection::Forward, - ); - - collects.push(shortcut); - } - } - } - - let touched = parents.keys().chain(children.keys()).cloned().collect(); - - self.remove_node(node); - - for shortcut in collects { - self.add_edge(shortcut) - } - - touched - } -} - -fn collect_shortcut_data_edges( - parent_edge: &IntermediateEdge, - child_edge: &IntermediateEdge, -) -> (Vec, Vec) { - let mut edge_id_a = Vec::from(parent_edge.data.clone()); - let mut road_id_a = Vec::from(parent_edge.road_id.clone()); - - edge_id_a.extend(Vec::from(child_edge.data.clone())); - road_id_a.extend(Vec::from(child_edge.road_id.clone())); - - (edge_id_a, road_id_a) -} - -impl FromIterator for IntermediateNetwork { - fn from_iter>(iter: T) -> Self { - let mut intermediate = IntermediateNetwork::default(); - for edge in iter.into_iter() { - intermediate.add_edge(edge); - } - - intermediate - } -} - -impl FromParallelIterator for IntermediateNetwork { - fn from_par_iter(par_iter: I) -> Self - where - I: rayon::iter::IntoParallelIterator, - { - let mut intermediate = IntermediateNetwork::default(); - let edges = par_iter.into_par_iter().collect::>(); - println!("Collected"); - for edge in edges { - intermediate.add_edge(edge); - } - - intermediate - } -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct IntermediateData { - references: HashMap, - shortcuts: HashMap>, - road_ids: HashMap>, -} - -impl NetworkData for IntermediateData { - type NodeData = NodeId; - type EdgeData = ShortcutState; - - fn node_data(&self, node: NodeId) -> &Self::NodeData { - &self.references[&node] - } - - fn edge_data(&self, edge: EdgeId) -> &Self::EdgeData { - &self.shortcuts[&edge] - } - - fn with_size(node_size: usize, edge_size: usize) -> Self { - Self { - references: HashMap::with_capacity(node_size), - shortcuts: HashMap::with_capacity(edge_size), - road_ids: HashMap::with_capacity(edge_size), - } - } - - fn add_node(&mut self, _: NodeId, _: Self::NodeData) {} - - fn add_edge(&mut self, edge: EdgeId, data: Self::EdgeData, road_id: ShortcutState) { - self.shortcuts.insert(edge, data); - self.road_ids.insert(edge, road_id); - } - - fn edge_road_id(&self, edge: EdgeId) -> ShortcutState { - self.road_ids[&edge].clone() - } -} - -impl From for DirectedNetworkGraph { - fn from(val: IntermediateNetwork) -> Self { - let mut builder = DirectedNetworkBuilder::::new(); - - for node in val.nodes() { - for (_, edge) in val.out_edges(node).unwrap() { - let n1 = builder.add_node(IntermediateNode(edge.source)); - let n2 = builder.add_node(IntermediateNode(edge.target)); - - builder.add_edge(IntermediateEdge { - source: n1, - target: n2, - ..edge.clone() - }); - } - } - - builder.build() - } -} diff --git a/network/src/highway/mod.rs b/network/src/highway/mod.rs deleted file mode 100644 index 6b9ecb3..0000000 --- a/network/src/highway/mod.rs +++ /dev/null @@ -1,123 +0,0 @@ -use std::collections::HashSet; - -use self::intermediate_network::{IntermediateData, IntermediateNetwork}; -use crate::{ - highway::intermediate_network::IntermediateEdge, BackwardNeighbourhood, DirectedNetworkGraph, - ForwardNeighbourhood, NetworkData, ShortcutState, -}; -use rayon::prelude::*; - -pub mod core; -pub mod dag; -pub mod dijkstra; -pub mod intermediate_network; - -macro_rules! stopwatch { - ($x:expr) => {{ - let start = std::time::Instant::now(); - let value = $x; - let end = std::time::Instant::now(); - - (end - start, value) - }}; - ($x:block) => {{ - let start = std::time::Instant::now(); - let value = $x; - let end = std::time::Instant::now(); - - (end - start, value) - }}; - - (print $x:block) => {{ - let (duration, value) = stopwatch!($x); - - println!("Duration: {}µs", duration.as_micros()); - - value - }}; - - (print $x:expr) => {{ - let (duration, value) = stopwatch!($x); - - println!("Duration: {}µs", duration.as_micros()); - - value - }}; -} - -pub fn calculate_layer( - size: usize, - network: &DirectedNetworkGraph, - contraction_factor: f32, -) -> DirectedNetworkGraph { - let intermediate = phase_1(size, network); - - let intermediate = phase_2(intermediate, contraction_factor); - - DirectedNetworkGraph::from(intermediate) -} -pub(crate) fn phase_1( - size: usize, - network: &DirectedNetworkGraph, -) -> IntermediateNetwork { - println!("Start computing (forward backward)"); - - let (duration, computed) = stopwatch!(ComputedState::new(size, network)); - - println!( - "Finished computing (forward backward) {}ms", - duration.as_millis() - ); - println!( - "Start computing (edges collections: {})", - network.edges().len() - ); - - let edges = network - .nodes() - .par_iter() - .enumerate() - .flat_map_iter(|(id, _)| dijkstra::calculate_edges(id.into(), &computed, network)) - .collect::>(); - - let edges = edges - .into_iter() - .map(|(source, edge_id)| { - let edge = network.edge(edge_id); - IntermediateEdge::new( - source, - edge.target(), - edge.distance(), - ShortcutState::Single(edge.edge_id), - network.data.edge_road_id(edge_id), - crate::builder::EdgeDirection::Forward, - ) - }) - .collect(); - println!("Finished computing (edges collections)"); - - edges -} - -/** - * Calculate the core network - */ -fn phase_2(intermediate: IntermediateNetwork, contraction_factor: f32) -> IntermediateNetwork { - core::core_network_with_patch(intermediate, contraction_factor) -} - -pub struct ComputedState { - pub forward: ForwardNeighbourhood, - pub backward: BackwardNeighbourhood, -} - -impl ComputedState { - pub fn new(size: usize, network: &DirectedNetworkGraph) -> Self { - let (forward, backward) = rayon::join( - || ForwardNeighbourhood::from_network(size, network), - || BackwardNeighbourhood::from_network(size, network), - ); - - ComputedState { forward, backward } - } -} diff --git a/network/src/highway_network/iterators.rs b/network/src/highway_network/iterators.rs deleted file mode 100644 index 41a6448..0000000 --- a/network/src/highway_network/iterators.rs +++ /dev/null @@ -1,54 +0,0 @@ -use super::{HighwayNetwork, NetworkEdge}; -use crate::{builder::EdgeDirection, EdgeId, NodeId}; -use core::slice::Iter; -use std::ops::Range; - -pub struct EdgeIterator<'a> { - network: &'a HighwayNetwork, - level: u8, - range: Range, - edges: Iter<'a, NetworkEdge>, - direction: EdgeDirection, -} - -impl<'a> EdgeIterator<'a> { - pub fn new( - node: NodeId, - level: u8, - direction: EdgeDirection, - network: &'a HighwayNetwork, - ) -> Option { - let layer_node = network.node_level(node, level)?; - let range = layer_node.start_edge_index..layer_node.last_edge_index; - let edges = network.edges - [layer_node.start_edge_index as usize..layer_node.last_edge_index as usize] - .iter(); - Some(Self { - network, - level, - range, - edges, - direction, - }) - } -} - -impl<'a> Iterator for EdgeIterator<'a> { - type Item = (EdgeId, &'a NetworkEdge); - - fn next(&mut self) -> Option { - let (id, edge) = self - .range - .by_ref() - .zip(self.edges.by_ref()) - .find(|(_, edge)| { - (self.direction == edge.direction || edge.direction == EdgeDirection::Both) - && self - .network - .node_level(edge.target_node, self.level) - .is_some() - })?; - - Some((id.into(), edge)) - } -} diff --git a/network/src/highway_network/mod.rs b/network/src/highway_network/mod.rs deleted file mode 100644 index 6f19cf2..0000000 --- a/network/src/highway_network/mod.rs +++ /dev/null @@ -1,170 +0,0 @@ -use std::collections::HashMap; - -use itertools::Itertools; -use serde::{Deserialize, Serialize}; - -use crate::{builder::EdgeDirection, DirectedNetworkGraph, NodeId}; - -use self::iterators::EdgeIterator; - -mod iterators; - -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -pub struct HighwayNetworkBaseNode { - start_edge_index: u32, - last_edge_index: u32, - start_node_index: u32, - end_node_index: u32, -} - -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -pub struct HighwayNetworkLevelNode { - start_edge_index: u32, - last_edge_index: u32, - pub forward_radius: f32, - pub backward_radius: f32, - pub is_bypassed: bool, -} - -impl Eq for HighwayNetworkLevelNode {} - -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -pub struct NetworkEdge { - pub edge_id: u32, - target_node: NodeId, - edge_weight: f32, - level: u8, - pub direction: EdgeDirection, -} - -impl Eq for NetworkEdge {} - -impl NetworkEdge { - pub fn target(&self) -> NodeId { - self.target_node - } - - pub fn distance(&self) -> f32 { - self.edge_weight - } - - pub fn level(&self) -> u8 { - self.level - } -} - -pub struct HighwayNetwork { - pub max_level: u8, - nodes: Vec, - highway_nodes: Vec, - edges: Vec, -} - -/** - * Requirements: - * - Node - * - Is node in layer - * - Is node bypassed - * - Node forward/backward neighbourhood radius - * - Node starts at edge_index - * - Edge - * - Is edge in layer - * - Is edge bypassed or is a shortcut (starting from which layer) - * - weight - */ -impl HighwayNetwork { - pub fn new(base: DirectedNetworkGraph, layers: Vec) -> Self { - // unimplemented!() - // Level 0 is base, - // Level >1 are layers - // let max_level = layers.len() as u8; - // let mut nodes = Vec::with_capacity(base.nodes().len()); - // let mut highway_nodes = Vec::with_capacity(base.nodes().len() * (max_level / 2u8)); - // let mut edges = Vec::with_capacity(base.edges().len()); - - let mut collect_mapper = HashMap::new(); - - for node in base.nodes() { - let out_edges = base.out_edges_raw(node).collect_vec(); - let in_edges = base.in_edges_raw(node).collect_vec(); - collect_mapper.insert(node.id, vec![(node, out_edges, in_edges)]); - } - - for layer in &layers { - for node in layer.nodes() { - let out_edges = layer.out_edges_raw(node).collect_vec(); - let in_edges = layer.in_edges_raw(node).collect_vec(); - collect_mapper.entry(node.id).and_modify(|d| { - d.push((node, out_edges, in_edges)); - }); - } - } - - unimplemented!() - - - // for base_node in base.nodes() { - // let start_node_index = highway_nodes.len(); - // let start_edge_index = edges.len(); - - // // let node_edges = base.out_edges_raw(node).map(|(id, e)| { - // // NetworkEdge { - // // level: 0, - - // // } - // // }); - - // for layer in layers { - // for n in layer.nodes() { - - // } - // } - - // nodes.push(HighwayNetworkBaseNode { - // start_node_index, - // start_edge_index, - // end_node_index: unimplemented!(), - // last_edge_index: unimplemented!(), - // }); - // } - // Self { - // max_level, - // nodes, - // highway_nodes, - // edges, - // } - } - - pub fn node(&self, node: NodeId) -> &HighwayNetworkBaseNode { - &self.nodes[node.0 as usize] - } - - pub fn node_level(&self, node: NodeId, level: u8) -> Option<&HighwayNetworkLevelNode> { - let node = self.node(node); - let levels = node.end_node_index - node.start_node_index; - - if level as u32 > levels { - return None; - } - - self.highway_nodes - .get(node.start_node_index as usize + level as usize) - } - - pub fn direction_edges( - &self, - node: NodeId, - level: u8, - direction: EdgeDirection, - ) -> Option { - EdgeIterator::new(node, level, direction, self) - } - - pub fn out_edges(&self, node: NodeId, level: u8) -> Option { - self.direction_edges(node, level, EdgeDirection::Forward) - } - - pub fn in_edges(&self, node: NodeId, level: u8) -> Option { - self.direction_edges(node, level, EdgeDirection::Backward) - } -} diff --git a/network/src/iterators.rs b/network/src/iterators.rs new file mode 100644 index 0000000..f839de6 --- /dev/null +++ b/network/src/iterators.rs @@ -0,0 +1,155 @@ +use crate::{HighwayGraph, HighwayNodeIndex}; +use petgraph::Direction::Incoming; +use petgraph::{visit::EdgeRef, Direction::Outgoing}; +use std::collections::{BinaryHeap, HashSet}; + +pub trait Distanceable { + fn distance(&self) -> f32; +} + +impl + Copy> Distanceable for E { + fn distance(&self) -> f32 { + (*self).into() + } +} + +#[derive(Debug, PartialEq)] +struct IteratorHeapEntry { + distance: f32, + node: HighwayNodeIndex, +} + +impl Eq for IteratorHeapEntry {} +impl Ord for IteratorHeapEntry { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.partial_cmp(other).unwrap() + } +} +impl PartialOrd for IteratorHeapEntry { + fn partial_cmp(&self, other: &Self) -> Option { + match self.distance.partial_cmp(&other.distance) { + Some(core::cmp::Ordering::Equal) => {} + Some(ord) => return Some(ord.reverse()), + _ => unreachable!( + "Tried to compare: {} .comp({})", + self.distance, other.distance + ), + } + self.node.partial_cmp(&other.node) + } +} + +pub trait DijkstraIterator { + fn forward_iterator<'a>(&'a self, node: HighwayNodeIndex) -> ForwardDijkstraIterator<'a, N, E>; + fn backward_iterator<'a>( + &'a self, + node: HighwayNodeIndex, + ) -> BackwardDijkstraIterator<'a, N, E>; +} + +impl DijkstraIterator for HighwayGraph { + fn forward_iterator<'a>(&'a self, node: HighwayNodeIndex) -> ForwardDijkstraIterator<'a, N, E> { + let mut heap = BinaryHeap::new(); + heap.push(IteratorHeapEntry { + distance: 0.0, + node, + }); + ForwardDijkstraIterator { + network: self, + distance: 0.0, + visited: HashSet::new(), + heap, + } + } + + fn backward_iterator<'a>( + &'a self, + node: HighwayNodeIndex, + ) -> BackwardDijkstraIterator<'a, N, E> { + let mut heap = BinaryHeap::new(); + heap.push(IteratorHeapEntry { + distance: 0.0, + node, + }); + BackwardDijkstraIterator { + network: self, + distance: 0.0, + visited: HashSet::new(), + heap, + } + } +} + +pub struct ForwardDijkstraIterator<'a, N, E> { + pub distance: f32, + network: &'a HighwayGraph, + visited: HashSet, + heap: BinaryHeap, +} + +pub struct BackwardDijkstraIterator<'a, N, E> { + pub distance: f32, + network: &'a HighwayGraph, + visited: HashSet, + heap: BinaryHeap, +} + +impl<'a, N, E> Iterator for ForwardDijkstraIterator<'a, N, E> +where + E: Distanceable, +{ + type Item = (HighwayNodeIndex, f32); + + fn next(&mut self) -> Option { + while let Some(IteratorHeapEntry { distance, node }) = self.heap.pop() { + if !self.visited.insert(node) { + continue; + } + for edge in self.network.edges_directed(node, Outgoing) { + let target = edge.target(); + let edge_distance = edge.weight().distance(); + + let next_distance = distance + edge_distance; + + self.heap.push(IteratorHeapEntry { + node: target, + distance: next_distance, + }) + } + self.distance = distance; + + return Some((node, distance)); + } + None + } +} + +impl<'a, N, E> Iterator for BackwardDijkstraIterator<'a, N, E> +where + E: Distanceable, +{ + type Item = (HighwayNodeIndex, f32); + + fn next(&mut self) -> Option { + while let Some(IteratorHeapEntry { distance, node }) = self.heap.pop() { + if !self.visited.insert(node) { + continue; + } + for edge in self.network.edges_directed(node, Incoming) { + let target = edge.source(); + let edge_distance = edge.weight().distance(); + + let next_distance = distance + edge_distance; + + self.heap.push(IteratorHeapEntry { + node: target, + distance: next_distance, + }) + } + self.distance = distance; + + return Some((node, distance)); + } + None + } +} diff --git a/network/src/lib.rs b/network/src/lib.rs index 042e327..521a08b 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -1,65 +1,37 @@ #![feature(map_try_insert)] #![feature(is_sorted)] -use std::ops::Deref; - -pub use directed_network::*; -pub use neighbourhood::*; - -pub mod directed_network; -// pub mod highway; -pub mod highway_network; +pub mod iterators; pub mod neighbourhood; -// pub use highway::intermediate_network; - -// pub use highway::calculate_layer; +pub use neighbourhood::*; +use petgraph::adj::EdgeIndex; +use petgraph::stable_graph::IndexType; +use petgraph::stable_graph::NodeIndex; +use petgraph::stable_graph::StableDiGraph; use serde::Deserialize; use serde::Serialize; -#[derive(Debug, Clone, Copy, Hash, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)] -pub struct NodeId(pub u32); - -impl From for NodeId { - fn from(id: usize) -> Self { - Self(id as u32) - } -} - -impl Deref for NodeId { - type Target = u32; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -#[derive(Debug, Clone, Copy, Hash, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)] -pub struct EdgeId(pub u32); +#[derive( + Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize, +)] +pub struct HighwayIndex(usize); -impl From for EdgeId { - fn from(id: usize) -> Self { - Self(id as u32) - } -} +pub type HighwayGraph = StableDiGraph; +pub type HighwayNodeIndex = NodeIndex; +pub type HighwayEdgeIndex = EdgeIndex; -impl From for EdgeId { - fn from(id: u32) -> Self { - Self(id) +unsafe impl IndexType for HighwayIndex { + fn new(x: usize) -> Self { + Self(x) } -} - -impl Deref for EdgeId { - type Target = u32; - fn deref(&self) -> &Self::Target { - &(self.0) + fn index(&self) -> usize { + self.0 } -} -impl From for NodeId { - fn from(id: u32) -> Self { - Self(id) + fn max() -> Self { + HighwayIndex(usize::MAX) } } @@ -80,28 +52,3 @@ impl From> for Vec { #[cfg(test)] pub(crate) mod tests; - -#[macro_export] -macro_rules! create_network { - ($s:literal..$e:literal, $($a:literal => $b:literal; $c: expr),+) => { - { - use $crate::builder::DefaultEdgeBuilder; - use $crate::builder::DirectedNetworkBuilder; - let mut builder = DirectedNetworkBuilder::::new(); - - for x in $s..=$e { - builder.add_node(x); - } - - $({ - let source = builder.add_node($a); - let target = builder.add_node($b); - - builder.add_edge(DefaultEdgeBuilder::forward(source, target, 0, $c)); - - })+ - - builder.build::<()>() - } - }; -} \ No newline at end of file diff --git a/network/src/neighbourhood.rs b/network/src/neighbourhood.rs index 69ccc6e..10415f3 100644 --- a/network/src/neighbourhood.rs +++ b/network/src/neighbourhood.rs @@ -1,7 +1,8 @@ -use std::ops::Deref; - -use crate::{DirectedNetworkGraph, NetworkData, NodeId}; +use crate::iterators::{DijkstraIterator, Distanceable}; +use crate::{HighwayGraph, HighwayNodeIndex}; use rayon::prelude::*; +use std::collections::HashMap; +use std::ops::Deref; #[derive(Debug)] pub struct ForwardNeighbourhood(Neighbourhood); @@ -27,50 +28,60 @@ impl Deref for BackwardNeighbourhood { #[derive(Debug)] pub struct Neighbourhood { - radius: Vec, + radius: HashMap, } impl Neighbourhood { #[inline] - pub fn radius(&self, node: NodeId) -> f32 { - self.radius[node.0 as usize] + pub fn radius(&self, node: HighwayNodeIndex) -> f32 { + self.radius[&node] } } impl ForwardNeighbourhood { - pub fn from_network(size: usize, network: &DirectedNetworkGraph) -> Self { - let mut radius = Vec::with_capacity(network.nodes().len()); - - network - .nodes() - .par_iter() - .enumerate() - .map(|(id, _)| find_forward_neighbourhood_radius(id.into(), size, network).unwrap()) - .collect_into_vec(&mut radius); - + pub fn from_network( + size: usize, + network: &HighwayGraph, + ) -> Self { + let mut radius: HashMap<_, _> = network + .node_indices() + .par_bridge() + .map(|node| { + ( + node, + find_forward_neighbourhood_radius(node, size, network).unwrap(), + ) + }) + .collect(); + radius.shrink_to_fit(); ForwardNeighbourhood(Neighbourhood { radius }) } } impl BackwardNeighbourhood { - pub fn from_network(size: usize, network: &DirectedNetworkGraph) -> Self { - let mut radius = Vec::with_capacity(network.nodes().len()); - - network - .nodes() - .par_iter() - .enumerate() - .map(|(id, _)| find_backward_neighbourhood_radius(id.into(), size, network).unwrap()) - .collect_into_vec(&mut radius); - + pub fn from_network( + size: usize, + network: &HighwayGraph, + ) -> Self { + let mut radius: HashMap<_, _> = network + .node_indices() + .par_bridge() + .map(|node| { + ( + node, + find_backward_neighbourhood_radius(node, size, network).unwrap(), + ) + }) + .collect(); + radius.shrink_to_fit(); BackwardNeighbourhood(Neighbourhood { radius }) } } -fn find_forward_neighbourhood_radius( - node: NodeId, +fn find_forward_neighbourhood_radius( + node: HighwayNodeIndex, size: usize, - network: &DirectedNetworkGraph, + network: &HighwayGraph, ) -> Option { network .forward_iterator(node) @@ -79,10 +90,10 @@ fn find_forward_neighbourhood_radius( .map(|x| x.1) } -fn find_backward_neighbourhood_radius( - node: NodeId, +fn find_backward_neighbourhood_radius( + node: HighwayNodeIndex, size: usize, - network: &DirectedNetworkGraph, + network: &HighwayGraph, ) -> Option { network .backward_iterator(node) @@ -94,27 +105,46 @@ fn find_backward_neighbourhood_radius( #[cfg(test)] mod tests { - use crate::{create_network, ForwardNeighbourhood}; + use std::collections::HashMap; + + use crate::{ForwardNeighbourhood, HighwayGraph, HighwayNodeIndex}; #[test] fn forward_neighbourhood_test() { // https://www.baeldung.com/wp-content/uploads/2017/01/initial-graph.png - let network = create_network!( - 0..5, - 0 => 1; 10.0, // A => B - 0 => 2; 15.0, // A => C - 1 => 3; 5.0, // B => D - 1 => 5; 15.0, // B => F - 2 => 4; 10.0, // C => E - 3 => 4; 2.0, // D => E - 3 => 5; 1.0, // D => F - 5 => 4; 5.0 // F => E - ); - - let forward = ForwardNeighbourhood::from_network(3, &network); + let mut graph = HighwayGraph::default(); + + let nodes = [ + graph.add_node(0), + graph.add_node(1), + graph.add_node(2), + graph.add_node(3), + graph.add_node(4), + graph.add_node(5), + ]; + + graph.add_edge(nodes[0], nodes[1], 10.0); // A => B + graph.add_edge(nodes[0], nodes[2], 10.0); // A => C + graph.add_edge(nodes[1], nodes[3], 10.0); // B => D + graph.add_edge(nodes[1], nodes[5], 10.0); // B => F + graph.add_edge(nodes[2], nodes[4], 10.0); // C => E + graph.add_edge(nodes[3], nodes[4], 10.0); // D => E + graph.add_edge(nodes[3], nodes[5], 10.0); // D => F + graph.add_edge(nodes[5], nodes[4], 10.0); // F => E + + let forward = ForwardNeighbourhood::from_network(3, &graph); let radius = &forward.radius; - assert_eq!(&vec![15.0, 6.0, 10.0, 2.0, 0.0, 5.0], radius); + let map = HashMap::from([ + (HighwayNodeIndex::new(0), 15.0), + (HighwayNodeIndex::new(1), 6.0), + (HighwayNodeIndex::new(2), 10.0), + (HighwayNodeIndex::new(3), 2.0), + (HighwayNodeIndex::new(4), 0.0), + (HighwayNodeIndex::new(5), 5.0), + ]); + + assert_eq!(&map, radius); } } diff --git a/network/src/tests.rs b/network/src/tests.rs index e52ebad..bf006f3 100644 --- a/network/src/tests.rs +++ b/network/src/tests.rs @@ -1,110 +1,88 @@ -use crate::{ - builder::EdgeDirection, create_network, DirectedNetworkGraph, NetworkEdge, NetworkNode, -}; +use petgraph::stable_graph::StableDiGraph; -// https://www.baeldung.com/wp-content/uploads/2017/01/initial-graph.png -pub fn create_ref_network_1() -> DirectedNetworkGraph<()> { - let nodes = vec![ - NetworkNode::new(0, 0, 2), - NetworkNode::new(1, 2, 5), - NetworkNode::new(2, 5, 7), - NetworkNode::new(3, 7, 10), - NetworkNode::new(4, 10, 13), - NetworkNode::new(5, 13, 16), - ]; - let edges = vec![ - NetworkEdge::new(0, 1u32.into(), 10.0, EdgeDirection::Forward), // A -> B - NetworkEdge::new(1, 2u32.into(), 15.0, EdgeDirection::Forward), // A -> C - NetworkEdge::new(2, 3u32.into(), 12.0, EdgeDirection::Forward), // B -> D - NetworkEdge::new(3, 5u32.into(), 15.0, EdgeDirection::Forward), // B -> F - NetworkEdge::new(4, 0u32.into(), 10.0, EdgeDirection::Backward), // A <- B - NetworkEdge::new(5, 4u32.into(), 10.0, EdgeDirection::Forward), // C -> E - NetworkEdge::new(6, 0u32.into(), 15.0, EdgeDirection::Backward), // A <- C - NetworkEdge::new(7, 4u32.into(), 2.0, EdgeDirection::Forward), // D -> E - NetworkEdge::new(8, 5u32.into(), 1.0, EdgeDirection::Forward), // D -> F - NetworkEdge::new(9, 1u32.into(), 12.0, EdgeDirection::Backward), // B <- D - NetworkEdge::new(10, 2u32.into(), 10.0, EdgeDirection::Backward), // C <- E - NetworkEdge::new(11, 3u32.into(), 2.0, EdgeDirection::Backward), // D <- E - NetworkEdge::new(12, 5u32.into(), 5.0, EdgeDirection::Backward), // F <- E - NetworkEdge::new(13, 4u32.into(), 5.0, EdgeDirection::Forward), // F -> E - NetworkEdge::new(14, 1u32.into(), 15.0, EdgeDirection::Backward), // B <- F - NetworkEdge::new(15, 3u32.into(), 1.0, EdgeDirection::Backward), // D <- F - ]; - - DirectedNetworkGraph::new(nodes, edges, ()) -} - -pub fn create_undirected_network() -> DirectedNetworkGraph<()> { - create_network!( - 0..16, - 0 => 1; 3.0, - 1 => 0; 3.0, - 1 => 2; 2.0, - 2 => 1; 2.0, - 2 => 3; 2.0, - 3 => 2; 2.0, - 3 => 0; 2.0, - 0 => 3; 2.0, +use crate::HighwayGraph; - 7 => 6; 2.0, - 6 => 7; 2.0, - 6 => 5; 2.0, - 5 => 6; 2.0, - 4 => 5; 3.0, - 5 => 4; 3.0, - 4 => 7; 2.0, - 7 => 4; 2.0, - - 8 => 9; 3.0, - 9 => 8; 3.0, - 9 => 10; 2.0, - 10 => 9; 2.0, - 10 => 11; 2.0, - 11 => 10; 2.0, - 11 => 8; 2.0, - 8 => 11; 2.0, +// https://www.baeldung.com/wp-content/uploads/2017/01/initial-graph.png +pub fn create_ref_network_1() -> HighwayGraph { + let mut graph = HighwayGraph::default(); - 12 => 13; 2.0, - 13 => 12; 2.0, - 13 => 14; 2.0, - 14 => 13; 2.0, - 14 => 15; 3.0, - 15 => 14; 3.0, - 15 => 12; 2.0, - 12 => 15; 2.0, + let nodes = [ + graph.add_node(0), + graph.add_node(1), + graph.add_node(2), + graph.add_node(3), + graph.add_node(4), + graph.add_node(5), + ]; - 12 => 16; 6.0, - 16 => 12; 6.0, - 16 => 0; 5.0, - 0 => 16; 5.0, + graph.extend_with_edges([ + (nodes[0], nodes[1], 10.0), // A -> B + (nodes[0], nodes[2], 15.0), // A -> C + (nodes[1], nodes[3], 12.0), // B -> D + (nodes[1], nodes[5], 15.0), // B -> F + (nodes[1], nodes[0], 10.0), // A <- B + (nodes[2], nodes[4], 10.0), // C -> E + (nodes[2], nodes[0], 15.0), // A <- C + (nodes[3], nodes[4], 2.0), // D -> E + (nodes[3], nodes[5], 1.0), // D -> F + (nodes[3], nodes[1], 12.0), // B <- D + (nodes[4], nodes[2], 10.0), // C <- E + (nodes[4], nodes[3], 2.0), // D <- E + (nodes[4], nodes[5], 5.0), // F <- E + (nodes[5], nodes[4], 5.0), // F -> E + (nodes[5], nodes[1], 15.0), // B <- F + (nodes[5], nodes[3], 1.0), // D <- F + ]); - 13 => 7; 7.0, - 7 => 13; 7.0, + graph +} - 2 => 4; 6.0, - 4 => 2; 6.0, +pub fn create_undirected_network() -> HighwayGraph { + let mut graph = StableDiGraph::default(); + let nodes = (0..16).map(|x| graph.add_node(x)).collect::>(); - 14 => 11; 14.0, - 11 => 14; 14.0 - ) -} + graph.add_edge(nodes[0], nodes[1], 3.0); + graph.add_edge(nodes[1], nodes[0], 3.0); + graph.add_edge(nodes[1], nodes[2], 2.0); + graph.add_edge(nodes[2], nodes[1], 2.0); + graph.add_edge(nodes[2], nodes[3], 2.0); + graph.add_edge(nodes[3], nodes[2], 2.0); + graph.add_edge(nodes[3], nodes[0], 2.0); + graph.add_edge(nodes[0], nodes[3], 2.0); + graph.add_edge(nodes[7], nodes[6], 2.0); + graph.add_edge(nodes[6], nodes[7], 2.0); + graph.add_edge(nodes[6], nodes[5], 2.0); + graph.add_edge(nodes[5], nodes[6], 2.0); + graph.add_edge(nodes[4], nodes[5], 3.0); + graph.add_edge(nodes[5], nodes[4], 3.0); + graph.add_edge(nodes[4], nodes[7], 2.0); + graph.add_edge(nodes[7], nodes[4], 2.0); + graph.add_edge(nodes[8], nodes[9], 3.0); + graph.add_edge(nodes[9], nodes[8], 3.0); + graph.add_edge(nodes[9], nodes[10], 2.0); + graph.add_edge(nodes[10], nodes[9], 2.0); + graph.add_edge(nodes[10], nodes[11], 2.0); + graph.add_edge(nodes[11], nodes[10], 2.0); + graph.add_edge(nodes[11], nodes[8], 2.0); + graph.add_edge(nodes[8], nodes[11], 2.0); + graph.add_edge(nodes[12], nodes[13], 2.0); + graph.add_edge(nodes[13], nodes[12], 2.0); + graph.add_edge(nodes[13], nodes[14], 2.0); + graph.add_edge(nodes[14], nodes[13], 2.0); + graph.add_edge(nodes[14], nodes[15], 3.0); + graph.add_edge(nodes[15], nodes[14], 3.0); + graph.add_edge(nodes[15], nodes[12], 2.0); + graph.add_edge(nodes[12], nodes[15], 2.0); + graph.add_edge(nodes[12], nodes[16], 6.0); + graph.add_edge(nodes[16], nodes[12], 6.0); + graph.add_edge(nodes[16], nodes[0], 5.0); + graph.add_edge(nodes[0], nodes[16], 5.0); + graph.add_edge(nodes[13], nodes[7], 7.0); + graph.add_edge(nodes[7], nodes[13], 7.0); + graph.add_edge(nodes[2], nodes[4], 6.0); + graph.add_edge(nodes[4], nodes[2], 6.0); + graph.add_edge(nodes[14], nodes[11], 14.0); + graph.add_edge(nodes[11], nodes[14], 14.0); -#[test] -fn create_test() { - let reference_network = create_ref_network_1(); - // Gotta put it in weird order so it sees creation of nodes in correct order, the numbers are labels after all. - let network = create_network!( - 0..5, - 0 => 1; 10.0, - 0 => 2; 15.0, - 1 => 3; 12.0, - 1 => 5; 15.0, - 2 => 4; 10.0, - 3 => 4; 2.0, - 3 => 5; 1.0, - 5 => 4; 5.0 - ); - assert_eq!(network.nodes(), reference_network.nodes(), "Fails on nodes"); - assert_eq!(network.edges(), reference_network.edges(), "Fails on edges"); - assert_eq!(network, reference_network); + graph } From 3817bb5386165191e34609c7d0ac487593b7c5c7 Mon Sep 17 00:00:00 2001 From: BlockCat Date: Tue, 27 Dec 2022 23:16:39 +0100 Subject: [PATCH 06/17] to petgraph --- Cargo.lock | 1 + bevy_shapefile/src/road_map.rs | 5 +- examples/layer.rs | 85 ++-- highway/Cargo.toml | 1 + highway/src/generation/core.rs | 105 +++-- highway/src/generation/dag.rs | 17 +- highway/src/generation/dijkstra.rs | 386 +++++++++--------- .../src/generation/intermediate_network.rs | 5 +- highway/src/generation/mod.rs | 85 ++-- network/src/directed_network/builder.rs | 254 ------------ network/src/directed_network/iterators.rs | 112 ----- network/src/directed_network/mod.rs | 211 ---------- network/src/directed_network/node_data.rs | 36 -- network/src/lib.rs | 17 +- src/nwb.rs | 49 +-- src/ui/layers.rs | 61 +-- src/ui/route.rs | 130 ++---- 17 files changed, 476 insertions(+), 1084 deletions(-) delete mode 100644 network/src/directed_network/builder.rs delete mode 100644 network/src/directed_network/iterators.rs delete mode 100644 network/src/directed_network/mod.rs delete mode 100644 network/src/directed_network/node_data.rs diff --git a/Cargo.lock b/Cargo.lock index 6ca66cd..ccd9ff3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2137,6 +2137,7 @@ version = "0.1.0" dependencies = [ "itertools", "network", + "petgraph", "rayon", "serde", ] diff --git a/bevy_shapefile/src/road_map.rs b/bevy_shapefile/src/road_map.rs index 7f998c5..eb0eced 100644 --- a/bevy_shapefile/src/road_map.rs +++ b/bevy_shapefile/src/road_map.rs @@ -45,7 +45,6 @@ impl RoadMap { pub fn read>(path: P) -> Self { let file = File::open(path).expect("Could not open file"); - bincode::deserialize_from(file).expect("Could not deserialize") } @@ -53,8 +52,7 @@ impl RoadMap { /// Load data from a shapefile pub fn from_shapefile>(path: P) -> Result { println!("Start read of road data"); - let roads = - shapefile::read_as::(path).map_err(ShapeError::Shape)?; + let roads = shapefile::read_as::(path).map_err(ShapeError::Shape)?; println!("Loading junction data"); let junctions = load_junctions(&roads); @@ -153,6 +151,7 @@ fn load_road_sections( Vec3::new(bbox.x_range()[0] as f32, bbox.y_range()[0] as f32, 0.0), Vec3::new(bbox.x_range()[1] as f32, bbox.y_range()[1] as f32, 0.0), ); + let id = RoadId::from(id); (id, RoadSection { id, points, aabb }) diff --git a/examples/layer.rs b/examples/layer.rs index b5b79f4..3677054 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -1,9 +1,24 @@ use bevy_dutch_road_highway_node_network::{nwb::NwbGraph, read_file, write_file}; +use bevy_shapefile::{RoadId, RoadMap}; use highway::generation::calculate_layer; -use network::{DirectedNetworkGraph, NetworkData}; +use network::{iterators::Distanceable, HighwayGraph}; +use petgraph::stable_graph::StableDiGraph; +use rayon::join; + +#[derive(Debug, Clone)] +struct RoadWeight(RoadId, f32); + +impl Distanceable for RoadWeight { + fn distance(&self) -> f32 { + self.1 + } +} fn main() { - let network: NwbGraph = read_file("data/directed_graph.graph").unwrap(); + let (network, road_map) = join( + || read_file::("data/directed_graph.graph").unwrap(), + || read_file::("data/road_map.data").unwrap(), + ); println!( "Layer: 0 - n: {}, e: {} ", @@ -11,50 +26,56 @@ fn main() { network.edge_count() ); - unimplemented!("Disabled"); + let network = network.map( + |_, n| n.clone(), + |_, e| { + let distance = 0.0f32; + RoadWeight(*e, distance) + }, + ); - // let mut layers = vec![calculate_layer(30, &network, 2.0)]; + let mut layers = vec![calculate_layer(30, network.clone(), 2.0)]; - // if let Some(x) = layers.first() { - // write_file(x, "data/0.graph".to_string()).expect("Could not write"); - // } + if let Some(x) = layers.first() { + write_file(x, "data/0.graph".to_string()).expect("Could not write"); + } - // for i in 1..7 { - // let prev_layer = layers.last().unwrap(); - // println!( - // "Layer: {} - n: {}, e: {} ", - // i, - // prev_layer.nodes().len(), - // prev_layer.edges().len() - // ); - // let next = calculate_layer(30, prev_layer, 3.0); + for i in 1..7 { + let prev_layer = layers.last().unwrap(); + println!( + "Layer: {} - n: {}, e: {} ", + i, + prev_layer.node_count(), + prev_layer.edge_count() + ); + let next = calculate_layer(30, prev_layer.clone(), 3.0); - // write_file(&next, format!("data/{i}.graph")).expect("Could not write"); - // layers.push(next); - // } + write_file(&next, format!("data/{i}.graph")).expect("Could not write"); + layers.push(next); + } - // data(0, 1, &network, &layers[0]); + print_data(0, 1, &network, &layers[0]); - // let mut counter = 0; + let mut counter = 0; - // for layer in layers.windows(2) { - // counter += 1; - // let l1 = &layer[0]; - // let l2 = &layer[1]; + for layer in layers.windows(2) { + counter += 1; + let l1 = &layer[0]; + let l2 = &layer[1]; - // data(counter, counter + 1, l1, l2); - // } + print_data(counter, counter + 1, l1, l2); + } } -fn data( +fn print_data( level_a: usize, level_b: usize, - a: &DirectedNetworkGraph, - b: &DirectedNetworkGraph, + a: &HighwayGraph, + b: &HighwayGraph, ) { println!("From: {level_a} to {level_b}"); - let nodes_a = a.nodes().len(); - let nodes_b = b.nodes().len(); + let nodes_a = a.node_count(); + let nodes_b = b.node_count(); let percentage = nodes_b as f32 / nodes_a as f32 - 1.0; println!( "Nodes: {} -> {} {:02}%", diff --git a/highway/Cargo.toml b/highway/Cargo.toml index 0464743..165c46b 100644 --- a/highway/Cargo.toml +++ b/highway/Cargo.toml @@ -8,5 +8,6 @@ version = "0.1.0" [dependencies] itertools = "*" network = {path = "../network"} +petgraph = {version = "0.6", features = ["serde-1"]} rayon = "1.5.1" serde = {version = "1.0.136", features = ["derive"]} diff --git a/highway/src/generation/core.rs b/highway/src/generation/core.rs index 27fff50..8e44197 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -1,45 +1,93 @@ -use super::intermediate_network::IntermediateNetwork; -use network::NodeId; +use itertools::Itertools; +use network::{iterators::Distanceable, HighwayEdgeIndex, HighwayGraph, HighwayNodeIndex}; +use petgraph::visit::EdgeRef; +use serde::{Serialize, Deserialize}; use std::{ collections::{HashSet, VecDeque}, hash::Hash, }; -pub(crate) fn core_network_with_patch( - mut intermediate_network: IntermediateNetwork, +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Shorted { + distance: f32, + /// Points to nodes in the previous layer + skipped_nodes: Vec, + /// Points to edges in the previous layer + skipped_edges: Vec, +} + +impl Distanceable for Shorted { + fn distance(&self) -> f32 { + self.distance + } +} + +pub(crate) fn core_network_with_patch( + old_network: HighwayGraph, contraction_factor: f32, -) -> IntermediateNetwork { - let nodes = { - let mut n = intermediate_network.nodes(); - n.sort(); - n - }; +) -> HighwayGraph { + let nodes = old_network.node_indices(); + let mut queue = HashNodeQueue::::from_iter(nodes); - let mut queue = HashNodeQueue::::from_vec(&nodes); + let mut next_network = old_network.map( + |_, n| n.clone(), + |id, e| Shorted { + distance: e.distance(), + skipped_nodes: vec![], + skipped_edges: vec![id], + }, + ); while let Some(node) = queue.pop_front() { - let out_edges = &intermediate_network - .out_edges(node) - .map(|x| x.len() as f32) - .unwrap_or_default(); - let in_edges = &intermediate_network - .in_edges(node) - .map(|x| x.len() as f32) - .unwrap_or_default(); + let out_edges = old_network + .edges_directed(node, petgraph::Direction::Outgoing) + .count() as f32; + let in_edges = old_network + .edges_directed(node, petgraph::Direction::Outgoing) + .count() as f32; let short_cuts = out_edges * in_edges; let contraction = (out_edges + in_edges) * contraction_factor; if short_cuts < contraction { - let mut touched = intermediate_network.bypass(node); - touched.sort(); - for touched in touched { - queue.push_back(touched); + // Remove from the node from the new network. + next_network.remove_node(node); + let out_edges = old_network + .edges_directed(node, petgraph::Direction::Outgoing) + .collect_vec(); + let in_edges = old_network + .edges_directed(node, petgraph::Direction::Incoming) + .collect_vec(); + + for source_edge in in_edges { + let source = source_edge.source(); + let source_edge_id = source_edge.id(); + let source_edge = source_edge.weight(); + + for target_edge in &out_edges { + let target = target_edge.target(); + let target_edge_id = target_edge.id(); + let target_edge = target_edge.weight(); + // Connect source to target. + let combined_distance = source_edge.distance() + target_edge.distance(); + next_network.add_edge( + source, + target, + Shorted { + distance: combined_distance, + skipped_nodes: vec![node], + skipped_edges: vec![source_edge_id, target_edge_id], + }, + ); + + queue.push_back(target); + } + queue.push_back(source); } } } - intermediate_network + next_network } #[derive(Debug, Default, Clone)] @@ -49,10 +97,15 @@ struct HashNodeQueue { } impl HashNodeQueue { + fn from_iter>(items: I) -> Self { + let queue = VecDeque::from_iter(items); + let seen = HashSet::from_iter(queue.iter().cloned()); + + HashNodeQueue { queue, seen } + } fn from_vec(items: &[T]) -> Self { let queue = VecDeque::from_iter(items.iter().cloned()); - let mut seen = HashSet::with_capacity(items.len()); - seen.extend(items.iter().cloned()); + let seen = HashSet::from_iter(items.iter().cloned()); HashNodeQueue { queue, seen } } diff --git a/highway/src/generation/dag.rs b/highway/src/generation/dag.rs index 2e234e1..86747be 100644 --- a/highway/src/generation/dag.rs +++ b/highway/src/generation/dag.rs @@ -1,10 +1,11 @@ -use network::{EdgeId, NodeId}; use std::collections::{BinaryHeap, HashMap}; +use network::{HighwayEdgeIndex, HighwayNodeIndex}; + #[derive(Debug, PartialEq, PartialOrd)] pub struct ParentEntry { - pub parent: NodeId, - pub parent_edge: EdgeId, + pub parent: HighwayNodeIndex, + pub parent_edge: HighwayEdgeIndex, pub parent_edge_distance: f32, pub active: bool, } @@ -12,7 +13,7 @@ pub struct ParentEntry { #[derive(Debug, PartialEq)] pub struct DijkstraNodeState { pub distance: f32, - pub current: NodeId, + pub current: HighwayNodeIndex, pub parent: ParentEntry, } @@ -47,18 +48,18 @@ pub struct VisitedState { pub border_distance: f32, pub reference_distance: f32, pub distance: f32, - pub parents: HashMap, f32)>, + pub parents: HashMap, f32)>, } pub struct HighwayNodeQueue { pub heap: BinaryHeap, - pub visited: HashMap, + pub visited: HashMap, active: usize, } pub struct HighwayQueueEntry { pub state: DijkstraNodeState, - pub parents: HashMap, f32)>, + pub parents: HashMap, f32)>, pub border_distance: f32, pub reference_distance: f32, pub parent_active: bool, @@ -146,7 +147,7 @@ impl HighwayNodeQueue { None } - pub fn visited(&mut self, node: NodeId, state: VisitedState) -> Option { + pub fn visited(&mut self, node: HighwayNodeIndex, state: VisitedState) -> Option { self.visited.insert(node, state) } diff --git a/highway/src/generation/dijkstra.rs b/highway/src/generation/dijkstra.rs index efed2b8..85437ed 100644 --- a/highway/src/generation/dijkstra.rs +++ b/highway/src/generation/dijkstra.rs @@ -1,30 +1,27 @@ use super::ComputedState; -use network::{iterators::F32, DirectedNetworkGraph, EdgeId, NetworkData, NodeId}; -use std::{ - cmp::Reverse, - collections::{HashMap, VecDeque}, -}; +use network::{iterators::Distanceable, HighwayEdgeIndex, HighwayGraph, HighwayNodeIndex}; +use petgraph::visit::EdgeRef; +use std::collections::{HashMap, VecDeque}; use super::dag::*; -pub fn calculate_edges( - s0: NodeId, +pub fn calculate_edges( + s0: HighwayNodeIndex, computed: &ComputedState, - network: &DirectedNetworkGraph, -) -> Vec<(NodeId, EdgeId)> { + network: &HighwayGraph, +) -> Vec { let (sorted_order, dag) = create_directed_acyclic_graph(s0, computed, network); - collect_next_level_edges(s0, sorted_order, dag, computed) } -pub fn create_directed_acyclic_graph( - s0: NodeId, +pub fn create_directed_acyclic_graph( + s0: HighwayNodeIndex, computed: &ComputedState, - network: &DirectedNetworkGraph, + network: &HighwayGraph, ) -> ( - VecDeque<(NodeId, (EdgeId, f32))>, - HashMap, + VecDeque<(HighwayNodeIndex, (HighwayEdgeIndex, f32))>, + HashMap, ) { let mut heap = HighwayNodeQueue::new(2000, 3000); @@ -64,38 +61,38 @@ pub fn create_directed_acyclic_graph( let active = entry.parent_active && !should_abort; - for (id, child_edge) in network.out_edges(entry.state.current) { - let child = child_edge.target(); - let next_distance = entry.state.distance + child_edge.distance(); - + for edge in network.edges_directed(entry.state.current, petgraph::Direction::Outgoing) { + let child = edge.target(); + let next_distance = entry.state.distance + edge.weight().distance(); heap.push(DijkstraNodeState { current: child, distance: next_distance, parent: ParentEntry { parent: entry.state.current, - parent_edge_distance: child_edge.distance(), - parent_edge: id, + parent_edge_distance: edge.weight().distance(), + parent_edge: edge.id(), active, }, - }); + }) } } (settled_order, heap.visited) } +/// Collect edges that are allowed in the next layer fn collect_next_level_edges( - s0: NodeId, - mut sorted_nodes: VecDeque<(NodeId, (EdgeId, f32))>, - nodes: HashMap, + s0: HighwayNodeIndex, + mut sorted_nodes: VecDeque<(HighwayNodeIndex, (HighwayEdgeIndex, f32))>, + nodes: HashMap, computed: &ComputedState, -) -> Vec<(NodeId, EdgeId)> { +) -> Vec { let mut collected_edges = Vec::new(); let mut tentative_slacks = HashMap::new(); debug_assert!(sorted_nodes .iter() - .is_sorted_by_key(|x| Reverse(F32(x.1 .1)))); + .is_sorted_by(|a, b| { b.1 .1.partial_cmp(&a.1 .1) })); while let Some((node, (_, distance))) = sorted_nodes.pop_front() { if distance < computed.forward.radius(s0) { @@ -111,7 +108,7 @@ fn collect_next_level_edges( let slack_parent = slack - distance; if slack_parent < 0.0 { - collected_edges.push((*parent, edge_id.unwrap())); + collected_edges.push(edge_id.unwrap()); } let tentative_slack_parent = tentative_slacks @@ -125,9 +122,9 @@ fn collect_next_level_edges( collected_edges } -fn initialize_heap( - s0: NodeId, - network: &DirectedNetworkGraph, +fn initialize_heap( + s0: HighwayNodeIndex, + network: &HighwayGraph, heap: &mut HighwayNodeQueue, ) { heap.visited( @@ -139,15 +136,16 @@ fn initialize_heap( parents: HashMap::from([(s0, (None, 0.0))]), }, ); - for (id, edge) in network.out_edges(s0) { + for edge in network.edges_directed(s0, petgraph::Direction::Outgoing) { assert!(s0 != edge.target()); + let distance = edge.weight().distance(); heap.push(DijkstraNodeState { - distance: edge.distance(), + distance, current: edge.target(), parent: ParentEntry { parent: s0, - parent_edge_distance: edge.distance(), - parent_edge: id, + parent_edge_distance: distance, + parent_edge: edge.id(), active: true, }, }); @@ -155,9 +153,9 @@ fn initialize_heap( } fn border_distance( - s0: NodeId, - node: NodeId, - parents: &HashMap, + s0: HighwayNodeIndex, + node: HighwayNodeIndex, + parents: &HashMap, computed: &ComputedState, parent_border_distance: f32, ) -> f32 { @@ -171,7 +169,7 @@ fn border_distance( fn reference_distance( entry: &HighwayQueueEntry, border_distance: f32, - visited: &HashMap, + visited: &HashMap, ) -> f32 { let distance = entry.state.distance; let reference_distance = entry.reference_distance; @@ -188,158 +186,158 @@ fn reference_distance( } } -#[cfg(test)] -mod tests { - - use network::{ - builder::EdgeDirection, create_network, DirectedNetworkGraph, NetworkEdge, NetworkNode, - NodeId, - }; - use std::collections::HashSet; - - use crate::generation::dijkstra::collect_next_level_edges; - - use super::{create_directed_acyclic_graph, ComputedState}; - // https://www.baeldung.com/wp-content/uploads/2017/01/initial-graph.png - pub fn create_ref_network_1() -> DirectedNetworkGraph<()> { - let nodes = vec![ - NetworkNode::new(0, 0, 2), - NetworkNode::new(1, 2, 5), - NetworkNode::new(2, 5, 7), - NetworkNode::new(3, 7, 10), - NetworkNode::new(4, 10, 13), - NetworkNode::new(5, 13, 16), - ]; - let edges = vec![ - NetworkEdge::new(0, 1u32.into(), 10.0, EdgeDirection::Forward), // A -> B - NetworkEdge::new(1, 2u32.into(), 15.0, EdgeDirection::Forward), // A -> C - NetworkEdge::new(2, 3u32.into(), 12.0, EdgeDirection::Forward), // B -> D - NetworkEdge::new(3, 5u32.into(), 15.0, EdgeDirection::Forward), // B -> F - NetworkEdge::new(4, 0u32.into(), 10.0, EdgeDirection::Backward), // A <- B - NetworkEdge::new(5, 4u32.into(), 10.0, EdgeDirection::Forward), // C -> E - NetworkEdge::new(6, 0u32.into(), 15.0, EdgeDirection::Backward), // A <- C - NetworkEdge::new(7, 4u32.into(), 2.0, EdgeDirection::Forward), // D -> E - NetworkEdge::new(8, 5u32.into(), 1.0, EdgeDirection::Forward), // D -> F - NetworkEdge::new(9, 1u32.into(), 12.0, EdgeDirection::Backward), // B <- D - NetworkEdge::new(10, 2u32.into(), 10.0, EdgeDirection::Backward), // C <- E - NetworkEdge::new(11, 3u32.into(), 2.0, EdgeDirection::Backward), // D <- E - NetworkEdge::new(12, 5u32.into(), 5.0, EdgeDirection::Backward), // F <- E - NetworkEdge::new(13, 4u32.into(), 5.0, EdgeDirection::Forward), // F -> E - NetworkEdge::new(14, 1u32.into(), 15.0, EdgeDirection::Backward), // B <- F - NetworkEdge::new(15, 3u32.into(), 1.0, EdgeDirection::Backward), // D <- F - ]; - - DirectedNetworkGraph::new(nodes, edges, ()) - } - - pub fn create_undirected_network() -> DirectedNetworkGraph<()> { - create_network!( - 0..16, - 0 => 1; 3.0, - 1 => 0; 3.0, - 1 => 2; 2.0, - 2 => 1; 2.0, - 2 => 3; 2.0, - 3 => 2; 2.0, - 3 => 0; 2.0, - 0 => 3; 2.0, - - 7 => 6; 2.0, - 6 => 7; 2.0, - 6 => 5; 2.0, - 5 => 6; 2.0, - 4 => 5; 3.0, - 5 => 4; 3.0, - 4 => 7; 2.0, - 7 => 4; 2.0, - - 8 => 9; 3.0, - 9 => 8; 3.0, - 9 => 10; 2.0, - 10 => 9; 2.0, - 10 => 11; 2.0, - 11 => 10; 2.0, - 11 => 8; 2.0, - 8 => 11; 2.0, - - 12 => 13; 2.0, - 13 => 12; 2.0, - 13 => 14; 2.0, - 14 => 13; 2.0, - 14 => 15; 3.0, - 15 => 14; 3.0, - 15 => 12; 2.0, - 12 => 15; 2.0, - - 12 => 16; 6.0, - 16 => 12; 6.0, - 16 => 0; 5.0, - 0 => 16; 5.0, - - 13 => 7; 7.0, - 7 => 13; 7.0, - - 2 => 4; 6.0, - 4 => 2; 6.0, - - 14 => 11; 14.0, - 11 => 14; 14.0 - ) - } - - #[test] - fn forward_test() { - let network = create_ref_network_1(); - let computed = ComputedState::new(3, &network); - - create_directed_acyclic_graph(NodeId(0), &computed, &network); - } - - #[test] - fn level_test() { - let network = create_undirected_network(); - let computed = super::ComputedState::new(4, &network); - let s0 = NodeId(12); - let edges = create_directed_acyclic_graph(s0, &computed, &network); - - println!("DAG:"); - for (n, i) in &edges.1 { - println!("N: {},\t {:?}", n.0, i); - } - - println!("Edges: {:?}", edges.0); - - let next_edges = collect_next_level_edges(s0, edges.0, edges.1, &computed); - - println!("Added:"); - for (parent, id) in next_edges { - let edge = network.edge(id); - assert_ne!(parent, edge.target()); - println!("ID: {id:?} - {edge:?}"); - } - } - - #[test] - fn test_all() { - let network = create_undirected_network(); - let computed = super::ComputedState::new(4, &network); - - let mut next_edges = HashSet::new(); - - for n in 0..=16 { - let edges = super::calculate_edges(NodeId(n), &computed, &network); - - next_edges.extend(edges); - } - - let mut next_edges = next_edges.into_iter().collect::>(); - - next_edges.sort(); - - println!("Added:"); - for (_, id) in next_edges { - let edge = network.edge(id); - println!("ID: {id:?} - {edge:?}"); - } - } -} +// #[cfg(test)] +// mod tests { + +// use network::{ +// builder::EdgeDirection, create_network, DirectedNetworkGraph, NetworkEdge, NetworkNode, +// NodeId, +// }; +// use std::collections::HashSet; + +// use crate::generation::dijkstra::collect_next_level_edges; + +// use super::{create_directed_acyclic_graph, ComputedState}; +// // https://www.baeldung.com/wp-content/uploads/2017/01/initial-graph.png +// pub fn create_ref_network_1() -> DirectedNetworkGraph<()> { +// let nodes = vec![ +// NetworkNode::new(0, 0, 2), +// NetworkNode::new(1, 2, 5), +// NetworkNode::new(2, 5, 7), +// NetworkNode::new(3, 7, 10), +// NetworkNode::new(4, 10, 13), +// NetworkNode::new(5, 13, 16), +// ]; +// let edges = vec![ +// NetworkEdge::new(0, 1u32.into(), 10.0, EdgeDirection::Forward), // A -> B +// NetworkEdge::new(1, 2u32.into(), 15.0, EdgeDirection::Forward), // A -> C +// NetworkEdge::new(2, 3u32.into(), 12.0, EdgeDirection::Forward), // B -> D +// NetworkEdge::new(3, 5u32.into(), 15.0, EdgeDirection::Forward), // B -> F +// NetworkEdge::new(4, 0u32.into(), 10.0, EdgeDirection::Backward), // A <- B +// NetworkEdge::new(5, 4u32.into(), 10.0, EdgeDirection::Forward), // C -> E +// NetworkEdge::new(6, 0u32.into(), 15.0, EdgeDirection::Backward), // A <- C +// NetworkEdge::new(7, 4u32.into(), 2.0, EdgeDirection::Forward), // D -> E +// NetworkEdge::new(8, 5u32.into(), 1.0, EdgeDirection::Forward), // D -> F +// NetworkEdge::new(9, 1u32.into(), 12.0, EdgeDirection::Backward), // B <- D +// NetworkEdge::new(10, 2u32.into(), 10.0, EdgeDirection::Backward), // C <- E +// NetworkEdge::new(11, 3u32.into(), 2.0, EdgeDirection::Backward), // D <- E +// NetworkEdge::new(12, 5u32.into(), 5.0, EdgeDirection::Backward), // F <- E +// NetworkEdge::new(13, 4u32.into(), 5.0, EdgeDirection::Forward), // F -> E +// NetworkEdge::new(14, 1u32.into(), 15.0, EdgeDirection::Backward), // B <- F +// NetworkEdge::new(15, 3u32.into(), 1.0, EdgeDirection::Backward), // D <- F +// ]; + +// DirectedNetworkGraph::new(nodes, edges, ()) +// } + +// pub fn create_undirected_network() -> DirectedNetworkGraph<()> { +// create_network!( +// 0..16, +// 0 => 1; 3.0, +// 1 => 0; 3.0, +// 1 => 2; 2.0, +// 2 => 1; 2.0, +// 2 => 3; 2.0, +// 3 => 2; 2.0, +// 3 => 0; 2.0, +// 0 => 3; 2.0, + +// 7 => 6; 2.0, +// 6 => 7; 2.0, +// 6 => 5; 2.0, +// 5 => 6; 2.0, +// 4 => 5; 3.0, +// 5 => 4; 3.0, +// 4 => 7; 2.0, +// 7 => 4; 2.0, + +// 8 => 9; 3.0, +// 9 => 8; 3.0, +// 9 => 10; 2.0, +// 10 => 9; 2.0, +// 10 => 11; 2.0, +// 11 => 10; 2.0, +// 11 => 8; 2.0, +// 8 => 11; 2.0, + +// 12 => 13; 2.0, +// 13 => 12; 2.0, +// 13 => 14; 2.0, +// 14 => 13; 2.0, +// 14 => 15; 3.0, +// 15 => 14; 3.0, +// 15 => 12; 2.0, +// 12 => 15; 2.0, + +// 12 => 16; 6.0, +// 16 => 12; 6.0, +// 16 => 0; 5.0, +// 0 => 16; 5.0, + +// 13 => 7; 7.0, +// 7 => 13; 7.0, + +// 2 => 4; 6.0, +// 4 => 2; 6.0, + +// 14 => 11; 14.0, +// 11 => 14; 14.0 +// ) +// } + +// #[test] +// fn forward_test() { +// let network = create_ref_network_1(); +// let computed = ComputedState::new(3, &network); + +// create_directed_acyclic_graph(NodeId(0), &computed, &network); +// } + +// #[test] +// fn level_test() { +// let network = create_undirected_network(); +// let computed = super::ComputedState::new(4, &network); +// let s0 = NodeId(12); +// let edges = create_directed_acyclic_graph(s0, &computed, &network); + +// println!("DAG:"); +// for (n, i) in &edges.1 { +// println!("N: {},\t {:?}", n.0, i); +// } + +// println!("Edges: {:?}", edges.0); + +// let next_edges = collect_next_level_edges(s0, edges.0, edges.1, &computed); + +// println!("Added:"); +// for (parent, id) in next_edges { +// let edge = network.edge(id); +// assert_ne!(parent, edge.target()); +// println!("ID: {id:?} - {edge:?}"); +// } +// } + +// #[test] +// fn test_all() { +// let network = create_undirected_network(); +// let computed = super::ComputedState::new(4, &network); + +// let mut next_edges = HashSet::new(); + +// for n in 0..=16 { +// let edges = super::calculate_edges(NodeId(n), &computed, &network); + +// next_edges.extend(edges); +// } + +// let mut next_edges = next_edges.into_iter().collect::>(); + +// next_edges.sort(); + +// println!("Added:"); +// for (_, id) in next_edges { +// let edge = network.edge(id); +// println!("ID: {id:?} - {edge:?}"); +// } +// } +// } diff --git a/highway/src/generation/intermediate_network.rs b/highway/src/generation/intermediate_network.rs index 600de72..fc243d4 100644 --- a/highway/src/generation/intermediate_network.rs +++ b/highway/src/generation/intermediate_network.rs @@ -1,7 +1,4 @@ -use network::{ - builder::{DirectedNetworkBuilder, EdgeBuilder, EdgeDirection, NodeBuilder}, - DirectedNetworkGraph, EdgeId, NetworkData, NodeId, ShortcutState, -}; +use network::ShortcutState; use rayon::iter::{FromParallelIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/highway/src/generation/mod.rs b/highway/src/generation/mod.rs index e88d612..88b548a 100644 --- a/highway/src/generation/mod.rs +++ b/highway/src/generation/mod.rs @@ -1,15 +1,13 @@ -use self::intermediate_network::{IntermediateData, IntermediateNetwork}; -use crate::generation::intermediate_network::IntermediateEdge; -use network::{ - BackwardNeighbourhood, DirectedNetworkGraph, ForwardNeighbourhood, NetworkData, ShortcutState, -}; +use network::{iterators::Distanceable, BackwardNeighbourhood, ForwardNeighbourhood, HighwayGraph}; use rayon::prelude::*; use std::collections::HashSet; +use self::core::Shorted; + pub mod core; pub mod dag; pub mod dijkstra; -pub mod intermediate_network; +// pub mod intermediate_network; macro_rules! stopwatch { ($x:expr) => {{ @@ -44,64 +42,66 @@ macro_rules! stopwatch { }}; } -pub fn calculate_layer( +/// Calculate the next layer from a network. +/// Phase 1: Generate highway network +/// Phase 2: Create a core graph and bypass nodes +pub fn calculate_layer( size: usize, - network: &DirectedNetworkGraph, + network: HighwayGraph, contraction_factor: f32, -) -> DirectedNetworkGraph { - let intermediate = phase_1(size, network); - - let intermediate = phase_2(intermediate, contraction_factor); - - DirectedNetworkGraph::from(intermediate) +) -> HighwayGraph +where + N: Send + Sync + Clone, + E: Send + Sync + Distanceable, +{ + let phase_1_graph = phase_1(size, network); + let phase_2_graph = phase_2(phase_1_graph, contraction_factor); + + phase_2_graph } -pub(crate) fn phase_1( + +/// Phase 1: ... ? +pub(crate) fn phase_1( size: usize, - network: &DirectedNetworkGraph, -) -> IntermediateNetwork { + mut network: HighwayGraph, +) -> HighwayGraph { println!("Start computing (forward backward)"); - let (duration, computed) = stopwatch!(ComputedState::new(size, network)); + let (duration, computed) = stopwatch!(ComputedState::new(size, &network)); println!( - "Finished computing (forward backward) {}ms", + "Finished computing (forward + backward) {}ms", duration.as_millis() ); println!( "Start computing (edges collections: {})", - network.edges().len() + network.edge_count() ); let edges = network - .nodes() - .par_iter() - .enumerate() - .flat_map_iter(|(id, _)| dijkstra::calculate_edges(id.into(), &computed, network)) + .node_indices() + .par_bridge() + .flat_map_iter(|id| dijkstra::calculate_edges(id, &computed, &network)) .collect::>(); - let edges = edges - .into_iter() - .map(|(source, edge_id)| { - let edge = network.edge(edge_id); - IntermediateEdge::new( - source, - edge.target(), - edge.distance(), - ShortcutState::Single(edge.edge_id), - network.data.edge_road_id(edge_id), - network::builder::EdgeDirection::Forward, - ) - }) - .collect(); + network.retain_edges(|_, e| edges.contains(&e)); + println!("Finished computing (edges collections)"); - edges + network } /** * Calculate the core network */ -fn phase_2(intermediate: IntermediateNetwork, contraction_factor: f32) -> IntermediateNetwork { +fn phase_2( + intermediate: HighwayGraph, + contraction_factor: f32, +) -> HighwayGraph +where + N: Clone, + E: Distanceable, +{ core::core_network_with_patch(intermediate, contraction_factor) } @@ -111,7 +111,10 @@ pub struct ComputedState { } impl ComputedState { - pub fn new(size: usize, network: &DirectedNetworkGraph) -> Self { + pub fn new( + size: usize, + network: &HighwayGraph, + ) -> Self { let (forward, backward) = rayon::join( || ForwardNeighbourhood::from_network(size, network), || BackwardNeighbourhood::from_network(size, network), diff --git a/network/src/directed_network/builder.rs b/network/src/directed_network/builder.rs deleted file mode 100644 index 4c46d84..0000000 --- a/network/src/directed_network/builder.rs +++ /dev/null @@ -1,254 +0,0 @@ -use crate::{DirectedNetworkGraph, NetworkData, NetworkEdge, NetworkNode, NodeId, ShortcutState}; -use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, fmt::Debug, hash::Hash, ops::Neg}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum EdgeDirection { - Forward, - Both, - Backward, -} - -impl Neg for EdgeDirection { - type Output = EdgeDirection; - - fn neg(self) -> Self::Output { - match self { - EdgeDirection::Forward => EdgeDirection::Backward, - EdgeDirection::Both => EdgeDirection::Both, - EdgeDirection::Backward => EdgeDirection::Forward, - } - } -} - -pub trait NodeBuilder: Hash + PartialEq + Eq { - type Data: Clone; - - fn id(&self) -> u32; - fn data(&self) -> Self::Data; -} - -impl NodeBuilder for usize { - type Data = (); - - fn id(&self) -> u32 { - *self as u32 - } - fn data(&self) -> Self::Data { - - } -} - -#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] -pub struct DefaultNodeBuilder(pub NodeId); - -impl NodeBuilder for DefaultNodeBuilder { - type Data = (); - - fn id(&self) -> u32 { - self.0 .0 - } - - fn data(&self) -> Self::Data { - - } -} - -pub trait EdgeBuilder: Clone { - type Data: Clone; - fn data(&self) -> Self::Data; - fn road_id(&self) -> ShortcutState; - fn source(&self) -> NodeId; - fn target(&self) -> NodeId; - fn weight(&self) -> f32; - fn direction(&self) -> EdgeDirection; -} - -#[derive(Debug, Clone)] -pub struct DefaultEdgeBuilder(NodeId, NodeId, f32, usize, EdgeDirection); - -impl EdgeBuilder for DefaultEdgeBuilder { - type Data = (); - - fn data(&self) -> Self::Data { - - } - - fn source(&self) -> NodeId { - self.0 - } - - fn target(&self) -> NodeId { - self.1 - } - - fn weight(&self) -> f32 { - self.2 - } - - fn road_id(&self) -> ShortcutState { - ShortcutState::Single(self.3) - } - - fn direction(&self) -> EdgeDirection { - self.4 - } -} - -impl DefaultEdgeBuilder { - pub fn forward( - source: NodeId, - target: NodeId, - road_id: usize, - weight: f32, - ) -> DefaultEdgeBuilder { - Self(source, target, weight, road_id, EdgeDirection::Forward) - } - pub fn backward( - source: NodeId, - target: NodeId, - road_id: usize, - weight: f32, - ) -> DefaultEdgeBuilder { - Self(source, target, weight, road_id, EdgeDirection::Backward) - } - pub fn both(source: NodeId, target: NodeId, road_id: usize, weight: f32) -> DefaultEdgeBuilder { - Self(source, target, weight, road_id, EdgeDirection::Both) - } -} - -#[derive(Debug)] -pub struct DirectedNetworkBuilder { - nodes: HashMap, - edges: HashMap<(NodeId, NodeId), E>, -} - -impl DirectedNetworkBuilder { - pub fn new() -> Self { - DirectedNetworkBuilder { - nodes: HashMap::new(), - edges: HashMap::new(), - } - } - pub fn add_edge(&mut self, edge: E) -> &mut Self { - self.edges.insert((edge.source(), edge.target()), edge); - self - } - - pub fn add_node(&mut self, node: V) -> NodeId { - let id = self.nodes.len(); - *self.nodes.entry(node).or_insert(id.into()) - } - - pub fn build(mut self) -> DirectedNetworkGraph - where - D: NetworkData, - { - self.edges.shrink_to_fit(); - self.nodes.shrink_to_fit(); - - let mut build_nodes = self.nodes.into_iter().collect::>(); - build_nodes.sort_by_key(|d| d.1); - - let mut map = HashMap::>::new(); - - for (_, edge) in &self.edges { - map.entry(edge.source()).or_default().push(edge); - map.entry(edge.target()).or_default().push(edge); - } - - let mut network_data = D::with_size(build_nodes.len(), self.edges.len() * 2); - let mut nodes = Vec::with_capacity(build_nodes.len()); - let mut edges = Vec::with_capacity(self.edges.len() * 2); - - for (node_id, (node, _)) in build_nodes.iter().enumerate() { - let node_id = NodeId::from(node_id); - - network_data.add_node(node_id, node.data()); - - let start_edge_index = edges.len() as u32; - - for (_, direction, target_node, data) in collect_edges(&map, node_id) { - let network_edge = - NetworkEdge::new(edges.len() as u32, target_node, data.weight(), direction); - - network_data.add_edge(network_edge.edge_id.into(), data.data(), data.road_id()); - edges.push(network_edge); - } - - let last_edge_index = edges.len() as u32; - - let network_node = NetworkNode::new(node.id(), start_edge_index, last_edge_index); - - nodes.push(network_node); - } - - DirectedNetworkGraph::new(nodes, edges, network_data) - } -} - -fn collect_edges( - map: &HashMap>, - node_id: NodeId, -) -> Vec<(NodeId, EdgeDirection, NodeId, E)> { - let mut build_edges = map[&node_id] - .iter() - .map(|&edge| { - let node_is_source = edge.source() == node_id; - - let (direction, target) = if edge.direction() == EdgeDirection::Both { - if node_is_source { - (EdgeDirection::Both, edge.target()) - } else { - (EdgeDirection::Both, edge.source()) - } - } else if node_is_source { - (EdgeDirection::Forward, edge.target()) - } else { - debug_assert_eq!(node_id, edge.target()); - (EdgeDirection::Backward, edge.source()) - }; - - (node_id, direction, target, (*edge).clone()) - }) - .collect::>(); - build_edges.sort_by_key(|x| (x.0, x.1, x.2)); - build_edges -} - -#[cfg(test)] -mod tests { - use crate::DirectedNetworkGraph; - - use super::DefaultEdgeBuilder; - - fn create_network() -> DirectedNetworkGraph<()> { - let mut builder = crate::builder::DirectedNetworkBuilder::new(); - - let na = builder.add_node(0); - let nb = builder.add_node(1); - let nc = builder.add_node(2); - let nd = builder.add_node(3); - let ne = builder.add_node(4); - let nf = builder.add_node(5); - - builder.add_edge(DefaultEdgeBuilder::forward(na, nb, 0, 10.0)); - builder.add_edge(DefaultEdgeBuilder::forward(nb, nd, 0, 12.0)); - builder.add_edge(DefaultEdgeBuilder::forward(nd, ne, 0, 2.0)); - builder.add_edge(DefaultEdgeBuilder::forward(na, nc, 0, 15.0)); - builder.add_edge(DefaultEdgeBuilder::forward(nc, ne, 0, 10.0)); - builder.add_edge(DefaultEdgeBuilder::forward(nf, ne, 0, 5.0)); - builder.add_edge(DefaultEdgeBuilder::forward(nb, nf, 0, 15.0)); - builder.add_edge(DefaultEdgeBuilder::forward(nd, nf, 0, 1.0)); - - builder.build() - } - - #[test] - fn builder_test() { - let n1 = crate::tests::create_ref_network_1(); - let n2 = create_network(); - - assert_eq!(n1, n2); - } -} diff --git a/network/src/directed_network/iterators.rs b/network/src/directed_network/iterators.rs deleted file mode 100644 index 1b7b377..0000000 --- a/network/src/directed_network/iterators.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::{builder::EdgeDirection, DirectedNetworkGraph, NetworkData, NetworkEdge}; -use std::{ - cmp::Reverse, - collections::{BinaryHeap, HashSet}, - ops::Range, - slice::Iter, -}; - -#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)] -pub struct F32(pub f32); - -impl Ord for F32 { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.partial_cmp(other).unwrap() - } -} - -impl Eq for F32 {} - -pub struct EdgeIterator<'a> { - range: Range, - edges: Iter<'a, NetworkEdge>, - direction: EdgeDirection, -} - -impl<'a> EdgeIterator<'a> { - pub fn new(range: Range, edges: Iter<'a, NetworkEdge>, direction: EdgeDirection) -> Self { - Self { - range, - edges, - direction, - } - } -} - -impl<'a> Iterator for EdgeIterator<'a> { - type Item = (EdgeId, &'a NetworkEdge); - - fn next(&mut self) -> Option { - let (id, edge) = self - .range - .by_ref() - .zip(self.edges.by_ref()) - .find(|(_, edge)| { - self.direction == edge.direction || edge.direction == EdgeDirection::Both - })?; - - Some((id.into(), edge)) - } -} - -pub struct ForwardDijkstraIterator<'a, D: NetworkData> { - pub network: &'a DirectedNetworkGraph, - pub distance: f32, - pub visited: HashSet, - pub heap: BinaryHeap>, -} - -pub struct BackwardDijkstraIterator<'a, D: NetworkData> { - pub distance: f32, - pub network: &'a DirectedNetworkGraph, - pub visited: HashSet, - pub heap: BinaryHeap>, -} - -impl<'a, D: NetworkData> Iterator for ForwardDijkstraIterator<'a, D> { - type Item = (NodeId, f32); - - fn next(&mut self) -> Option { - while let Some(Reverse((F32(distance), node))) = self.heap.pop() { - if !self.visited.insert(node) { - continue; - } - for (_, edge) in self.network.out_edges(node) { - let target = edge.target(); - let edge_distance = edge.distance(); - - self.heap - .push(Reverse((F32(distance + edge_distance), target))); - } - - self.distance = distance; - - return Some((node, distance)); - } - None - } -} - -impl<'a, D: NetworkData> Iterator for BackwardDijkstraIterator<'a, D> { - type Item = (NodeId, f32); - - fn next(&mut self) -> Option { - while let Some(Reverse((F32(distance), node))) = self.heap.pop() { - if !self.visited.insert(node) { - continue; - } - for (_, edge) in self.network.in_edges(node) { - let source = edge.target(); - let edge_distance = edge.distance(); - - self.heap - .push(Reverse((F32(distance + edge_distance), source))); - } - - self.distance = distance; - - return Some((node, distance)); - } - None - } -} diff --git a/network/src/directed_network/mod.rs b/network/src/directed_network/mod.rs deleted file mode 100644 index 25aa74d..0000000 --- a/network/src/directed_network/mod.rs +++ /dev/null @@ -1,211 +0,0 @@ -pub mod builder; -pub mod iterators; -pub mod node_data; - -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -pub struct NetworkNode { - pub id: u32, - pub start_edge_index: u32, - pub last_edge_index: u32, -} - -impl NetworkNode { - pub fn new(id: u32, start_edge_index: u32, last_edge_index: u32) -> Self { - Self { - id, - start_edge_index, - last_edge_index, - } - } -} - -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -pub struct NetworkEdge { - pub edge_id: u32, - target_node: NodeId, - edge_weight: f32, - direction: EdgeDirection, -} - -impl Eq for NetworkEdge {} - -impl NetworkEdge { - pub fn new( - data_id: u32, - target_node: NodeId, - edge_weight: f32, - direction: EdgeDirection, - ) -> Self { - Self { - edge_id: data_id, - target_node, - edge_weight, - direction, - } - } - // pub fn id(&self) -> EdgeId { - // self.id - // } - pub fn target(&self) -> NodeId { - self.target_node - } - - pub fn distance(&self) -> f32 { - self.edge_weight - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct DirectedNetworkGraph { - pub data: D, - nodes: Vec, - edges: Vec, -} - -impl DirectedNetworkGraph { - pub fn new(nodes: Vec, edges: Vec, data: D) -> Self { - Self { data, nodes, edges } - } - - pub fn node(&self, node: NodeId) -> &NetworkNode { - &self.nodes[node.0 as usize] - } - - pub fn edge_data(&self, edge: EdgeId) -> &D::EdgeData { - self.data.edge_data(edge) - } - - pub fn node_data(&self, node: NodeId) -> &D::NodeData { - self.data.node_data(node) - } - - pub fn nodes(&self) -> &Vec { - &self.nodes - } - - pub fn edge(&self, edge: EdgeId) -> &NetworkEdge { - &self.edges[edge.0 as usize] - } - - pub fn edges(&self) -> &Vec { - &self.edges - } - - fn create_iterator(&self, node: NodeId, direction: EdgeDirection) -> EdgeIterator { - self.create_iterator_raw(self.node(node), direction) - } - - fn create_iterator_raw(&self, node: &NetworkNode, direction: EdgeDirection) -> EdgeIterator { - let edges = - self.edges[node.start_edge_index as usize..node.last_edge_index as usize].iter(); - - EdgeIterator::new( - node.start_edge_index..node.last_edge_index, - edges, - direction, - ) - } - - pub fn out_edges(&self, node: NodeId) -> EdgeIterator { - self.create_iterator(node, EdgeDirection::Forward) - } - - pub fn out_edges_raw(&self, node: &NetworkNode) -> EdgeIterator { - self.create_iterator_raw(node, EdgeDirection::Forward) - } - - pub fn in_edges(&self, node: NodeId) -> EdgeIterator { - self.create_iterator(node, EdgeDirection::Backward) - } - - pub fn in_edges_raw(&self, node: &NetworkNode) -> EdgeIterator { - self.create_iterator_raw(node, EdgeDirection::Backward) - } - - /// Collect the nodes in order of lowest to highest distance - pub fn forward_iterator(&self, node: NodeId) -> ForwardDijkstraIterator<'_, D> { - let mut heap = BinaryHeap::new(); - heap.push(Reverse((F32(0.0), node))); - ForwardDijkstraIterator { - distance: 0.0, - network: self, - heap, - visited: HashSet::new(), - } - } - - pub fn backward_iterator(&self, node: NodeId) -> BackwardDijkstraIterator<'_, D> { - let mut heap = BinaryHeap::new(); - heap.push(Reverse((F32(0.0), node))); - BackwardDijkstraIterator { - distance: 0.0, - network: self, - heap, - visited: HashSet::new(), - } - } - - pub fn forward_neighbourhood(&self, size: usize) -> ForwardNeighbourhood { - ForwardNeighbourhood::from_network(size, self) - } - - pub fn backward_neighbourhood(&self, size: usize) -> BackwardNeighbourhood { - BackwardNeighbourhood::from_network(size, self) - } -} - -#[cfg(test)] -mod tests { - use crate::{tests::create_ref_network_1, NodeId}; - - #[test] - fn test_forward() { - let network = create_ref_network_1(); - let forward = network.forward_iterator(0u32.into()).collect::>(); - - assert_eq!( - vec![ - (NodeId(0), 0.0), // A 0.0 - (NodeId(1), 10.0), // B 10.0 - (NodeId(2), 15.0), // C 15.0 - (NodeId(3), 22.0), // D 22 - (NodeId(5), 23.0), // F 23 - (NodeId(4), 24.0), // E 24 - ], - forward - ); - } - #[test] - fn test_forward_empty() { - let network = create_ref_network_1(); - let forward = network.forward_iterator(4u32.into()).collect::>(); - - assert_eq!(vec![(NodeId(4), 0.0)], forward); - } - - #[test] - fn test_backward() { - let network = create_ref_network_1(); - let backward = network.backward_iterator(4u32.into()).collect::>(); - - assert_eq!( - vec![ - (NodeId(4), 0.0), - (NodeId(3), 2.0), - (NodeId(5), 5.0), - (NodeId(2), 10.0), - (NodeId(1), 14.0), - (NodeId(0), 24.0), - ], - backward - ); - } - - #[test] - fn test_backward_empty() { - let network = create_ref_network_1(); - let backward = network.backward_iterator(0u32.into()).collect::>(); - - assert_eq!(vec![(NodeId(0), 0.0)], backward); - } -} diff --git a/network/src/directed_network/node_data.rs b/network/src/directed_network/node_data.rs deleted file mode 100644 index 0717922..0000000 --- a/network/src/directed_network/node_data.rs +++ /dev/null @@ -1,36 +0,0 @@ -use crate::{EdgeId, NodeId, ShortcutState}; - -pub trait NetworkData: Send + Sync + Default { - type NodeData; - type EdgeData; - fn node_data(&self, node: NodeId) -> &Self::NodeData; - fn edge_data(&self, edge: EdgeId) -> &Self::EdgeData; - fn edge_road_id(&self, edge: EdgeId) -> ShortcutState; - - fn with_size(node_size: usize, edge_size: usize) -> Self; - fn add_node(&mut self, node: NodeId, data: Self::NodeData); - fn add_edge(&mut self, edge: EdgeId, data: Self::EdgeData, road_id: ShortcutState); -} - -impl NetworkData for () { - type NodeData = (); - type EdgeData = (); - - fn node_data(&self, _: NodeId) -> &Self::NodeData { - &() - } - - fn edge_data(&self, _: EdgeId) -> &Self::EdgeData { - &() - } - - fn edge_road_id(&self, edge: EdgeId) -> ShortcutState { - ShortcutState::Single(edge.0 as usize) - } - - fn add_node(&mut self, _: NodeId, _: Self::NodeData) {} - - fn add_edge(&mut self, _: EdgeId, _: Self::EdgeData, _: ShortcutState) {} - - fn with_size(_: usize, _: usize) -> Self {} -} diff --git a/network/src/lib.rs b/network/src/lib.rs index 521a08b..c43e3cc 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -5,7 +5,7 @@ pub mod iterators; pub mod neighbourhood; pub use neighbourhood::*; -use petgraph::adj::EdgeIndex; +use petgraph::stable_graph::EdgeIndex; use petgraph::stable_graph::IndexType; use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::StableDiGraph; @@ -35,20 +35,5 @@ unsafe impl IndexType for HighwayIndex { } } -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -pub enum ShortcutState { - Single(T), - Shortcut(Vec), -} - -impl From> for Vec { - fn from(s: ShortcutState) -> Self { - match s { - ShortcutState::Single(a) => vec![a], - ShortcutState::Shortcut(a) => a, - } - } -} - #[cfg(test)] pub(crate) mod tests; diff --git a/src/nwb.rs b/src/nwb.rs index df88fae..9d54cc7 100644 --- a/src/nwb.rs +++ b/src/nwb.rs @@ -1,32 +1,15 @@ use bevy::math::Vec2; use bevy_shapefile::{JunctionId, RoadId, RoadMap}; -use network::builder::EdgeDirection; -use petgraph::stable_graph::{IndexType, StableDiGraph}; +use network::{HighwayEdgeIndex, HighwayGraph, HighwayNodeIndex}; use rusqlite::{ types::{FromSql, FromSqlError}, Connection, }; -use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, hash::Hash, path::Path}; +use std::{collections::HashMap, path::Path}; -#[derive( - Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize, -)] -pub struct NwbIndex(usize); -unsafe impl IndexType for NwbIndex { - fn new(x: usize) -> Self { - Self(x) - } - - fn index(&self) -> usize { - self.0 - } - - fn max() -> Self { - NwbIndex(usize::MAX) - } -} -pub type NwbGraph = StableDiGraph<(JunctionId, Vec2), RoadId, NwbIndex>; +pub type NwbGraph = HighwayGraph<(JunctionId, Vec2), RoadId>; +pub type NwbNodeIndex = HighwayNodeIndex; //NodeIndex; +pub type NwbEdgeIndex = HighwayEdgeIndex; //EdgeIndex; pub fn preprocess_roadmap>(roadmap: &RoadMap, database: P) -> NwbGraph { let database = Connection::open(database).expect("Could not open database"); @@ -69,15 +52,15 @@ pub fn preprocess_roadmap>(roadmap: &RoadMap, database: P) -> Nwb let source = junction_to_node[&road_id_start]; let target = junction_to_node[&road_id_end]; - match rij_richting.0 { - EdgeDirection::Forward => { + match rij_richting { + RijRichting::Forward => { graph.add_edge(source, target, road_id); } - EdgeDirection::Both => { + RijRichting::Both => { graph.add_edge(source, target, road_id); graph.add_edge(target, source, road_id); } - EdgeDirection::Backward => { + RijRichting::Backward => { graph.add_edge(target, source, road_id); } } @@ -86,7 +69,11 @@ pub fn preprocess_roadmap>(roadmap: &RoadMap, database: P) -> Nwb } #[derive(Debug, Clone, Copy)] -struct RijRichting(EdgeDirection); +enum RijRichting { + Forward, + Backward, + Both, +} impl FromSql for RijRichting { fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult { @@ -96,10 +83,10 @@ impl FromSql for RijRichting { .next() .ok_or(FromSqlError::InvalidType)?; match rij_richting { - 'H' => Ok(RijRichting(EdgeDirection::Forward)), - 'T' => Ok(RijRichting(EdgeDirection::Backward)), - 'B' => Ok(RijRichting(EdgeDirection::Both)), - 'O' => Ok(RijRichting(EdgeDirection::Both)), + 'H' => Ok(RijRichting::Forward), + 'T' => Ok(RijRichting::Backward), + 'B' => Ok(RijRichting::Both), + 'O' => Ok(RijRichting::Both), _ => Err(FromSqlError::InvalidType), } } diff --git a/src/ui/layers.rs b/src/ui/layers.rs index c396bcc..2f956ea 100644 --- a/src/ui/layers.rs +++ b/src/ui/layers.rs @@ -7,10 +7,10 @@ use bevy::{ tasks::{AsyncComputeTaskPool, Task}, }; use bevy_egui::{egui, EguiContext}; -use bevy_shapefile::RoadId; +use bevy_shapefile::{JunctionId, RoadId}; use futures_lite::future; -use highway::generation::intermediate_network::IntermediateData; -use network::{DirectedNetworkGraph, EdgeId, NetworkData}; +use highway::generation::core::Shorted; +use network::HighwayGraph; use std::{collections::HashMap, path::Path}; use super::DirectedNetworkGraphContainer; @@ -70,9 +70,9 @@ pub fn gui_system( fn load_or_calculate, F>( path: P, calculate: F, -) -> DirectedNetworkGraph +) -> HighwayGraph<(JunctionId, Vec2), Shorted> where - F: Fn() -> DirectedNetworkGraph, + F: Fn() -> HighwayGraph<(JunctionId, Vec2), Shorted>, { if let Ok(network) = crate::read_file(&path) { network @@ -177,12 +177,12 @@ pub fn colouring_system( #[derive(Resource)] pub struct PreProcess { pub base: NwbGraph, - pub layers: Vec>, + pub layers: Vec>, pub road_data_level: HashMap, } impl PreProcess { - pub fn new(base: NwbGraph, layers: Vec>) -> Self { + pub fn new(base: NwbGraph, layers: Vec>) -> Self { unimplemented!("Could not create preprocess") // let mut road_data_level = (0..base.edges().len()) @@ -206,26 +206,27 @@ impl PreProcess { } } -fn process_edges( - layer_id: u8, - network: &DirectedNetworkGraph, - road_data: &mut HashMap, -) { - for id in 0..network.edges().len() { - let id = EdgeId::from(id); - match network.data.edge_road_id(id) { - network::ShortcutState::Single(a) => { - road_data.entry(RoadId::from(a)).and_modify(|f| { - *f = layer_id; - }); - } - network::ShortcutState::Shortcut(b) => { - for a in b { - road_data.entry(RoadId::from(a)).and_modify(|f| { - *f = layer_id; - }); - } - } - } - } -} +// Finds the highest layer of roads +// fn process_edges( +// layer_id: u8, +// network: &DirectedNetworkGraph, +// road_data: &mut HashMap, +// ) { +// for id in 0..network.edges().len() { +// let id = EdgeId::from(id); +// match network.data.edge_road_id(id) { +// network::ShortcutState::Single(a) => { +// road_data.entry(RoadId::from(a)).and_modify(|f| { +// *f = layer_id; +// }); +// } +// network::ShortcutState::Shortcut(b) => { +// for a in b { +// road_data.entry(RoadId::from(a)).and_modify(|f| { +// *f = layer_id; +// }); +// } +// } +// } +// } +// } diff --git a/src/ui/route.rs b/src/ui/route.rs index 11d1879..bb15db2 100644 --- a/src/ui/route.rs +++ b/src/ui/route.rs @@ -1,13 +1,16 @@ +use std::collections::HashSet; + use super::DirectedNetworkGraphContainer; +use crate::nwb::NwbEdgeIndex; +use crate::nwb::NwbGraph; +use crate::nwb::NwbNodeIndex; use crate::world::WorldEntity; +use crate::world::WorldEntitySelectionType; use bevy::prelude::*; use bevy_egui::egui; use bevy_egui::EguiContext; -use network::{iterators::F32, DirectedNetworkGraph, EdgeId, NetworkData, NodeId}; -use std::{ - cmp::Reverse, - collections::{BinaryHeap, HashMap}, -}; +use bevy_shapefile::RoadId; +use petgraph::algo; pub struct RouteUIPlugin; @@ -22,9 +25,9 @@ impl Plugin for RouteUIPlugin { #[derive(Debug, Default, Resource)] pub struct RouteState { find_nodes: bool, - node_1: Option, - node_2: Option, - edges: Option>, + node_1: Option, + node_2: Option, + edges: Option>, } pub fn gui_system(mut egui_context: ResMut, mut state: ResMut) { @@ -39,11 +42,11 @@ pub fn gui_system(mut egui_context: ResMut, mut state: ResMut, ) { if let Some(route) = &route_state.edges { - // Collect all roadIds in the map. - unimplemented!("Road highlighting not implemented"); - // let l = route - // .iter() - // .map(|(_, e)| *network.edge_data(*e)) - // .collect::>(); + // Collect all roadIds. + let l = route.iter().map(|e| network[*e]).collect::>(); - // query.for_each_mut(|mut a| { - // if l.contains(&a.id) { - // a.selected = WorldEntitySelectionType::Route;// Some(Color::ALICE_BLUE); - // } - // }); + query.for_each_mut(|mut a| { + if l.contains(&a.id) { + a.selected = WorldEntitySelectionType::Route; + } + }); } } -fn find_route( - source: NodeId, - target: NodeId, - network: &DirectedNetworkGraph, - spare: F, -) -> Result, String> +fn find_route( + source: NwbNodeIndex, + target: NwbNodeIndex, + graph: &NwbGraph, + edge_cost: E, + estimate_to_target: F, +) -> Result, String> where - D: NetworkData, - F: Fn(NodeId, NodeId) -> f32, + E: Fn(&RoadId) -> f32, + F: Fn(NwbNodeIndex, NwbNodeIndex) -> f32, { - let mut map = HashMap::new(); - let mut evaluated = 0usize; - // let mut test = Vec::new(); - - let mut heap = BinaryHeap::new(); - for (id, initial_descendant) in network.out_edges(source) { - let target = initial_descendant.target(); - let distance = initial_descendant.distance(); - - heap.push(( - Reverse(F32(distance + spare(source, target))), - F32(distance), - target, - (source, id), - )); - } - - while let Some((_, F32(old_distance), current, parent)) = heap.pop() { - let spare_distance = spare(current, target); - evaluated += 1; - - if map.contains_key(¤t) { - continue; - } - map.insert(current, parent); - - // test.push(parent); - // println!("GRR: {} > {} of {}", x, old_distance, spare_distance); - if current == target { - println!("Evaluated: {evaluated}"); - let mut path = Vec::new(); - let mut node = current; - - while let Some((parent, edge)) = map.remove(&node) { - path.push((node, edge)); - node = parent; - } - - path.reverse(); - return Ok(path); - } - - for (id, edge) in network.out_edges(current) { - let target = edge.target(); - let distance = edge.distance() + old_distance; - - heap.push(( - Reverse(F32(distance + spare_distance)), - F32(distance), - target, - (current, id), - )); - } - } - println!("Not found but Evaluated: {evaluated}"); - - Err(String::from("No path found")) + let path = algo::astar( + graph, + source, + |finish| finish == target, + |e| edge_cost(e.weight()), + |n| estimate_to_target(n, target), + ); + + path.map(|path| { + path.1 + .windows(2) + .map(|nodes| graph.find_edge(nodes[0], nodes[1]).unwrap()) + .collect::>() + }) + .ok_or_else(|| String::from("No path found")) } From b44c0b262b26ded52a801cc1324438223bd088d1 Mon Sep 17 00:00:00 2001 From: BlockCat Date: Tue, 27 Dec 2022 23:45:13 +0100 Subject: [PATCH 07/17] fix --- bevy_shapefile/src/road_map.rs | 12 ++++++++++++ examples/layer.rs | 8 ++++---- highway/src/generation/core.rs | 5 ----- highway/src/generation/mod.rs | 4 ++-- network/src/iterators.rs | 14 ++++---------- src/nwb.rs | 2 +- src/ui/layers.rs | 8 ++++---- src/ui/route.rs | 4 ++-- src/world.rs | 1 - tools/dbf_to_sql/src/main.rs | 6 +++--- 10 files changed, 32 insertions(+), 32 deletions(-) diff --git a/bevy_shapefile/src/road_map.rs b/bevy_shapefile/src/road_map.rs index eb0eced..ed1a55f 100644 --- a/bevy_shapefile/src/road_map.rs +++ b/bevy_shapefile/src/road_map.rs @@ -27,6 +27,18 @@ pub struct RoadMap { pub road_spatial: rstar::RTree, } +impl RoadMap { + pub fn road_length(&self, road_id: RoadId) -> f32 { + let section = &self.roads[&road_id]; + + section + .points + .windows(2) + .map(|points| points[0].distance(points[1])) + .sum() + } +} + #[derive(Serialize, Deserialize, Debug)] pub struct Params; diff --git a/examples/layer.rs b/examples/layer.rs index 3677054..acd56fc 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -2,7 +2,7 @@ use bevy_dutch_road_highway_node_network::{nwb::NwbGraph, read_file, write_file} use bevy_shapefile::{RoadId, RoadMap}; use highway::generation::calculate_layer; use network::{iterators::Distanceable, HighwayGraph}; -use petgraph::stable_graph::StableDiGraph; + use rayon::join; #[derive(Debug, Clone)] @@ -27,9 +27,9 @@ fn main() { ); let network = network.map( - |_, n| n.clone(), + |_, n| *n, |_, e| { - let distance = 0.0f32; + let distance = road_map.road_length(*e); RoadWeight(*e, distance) }, ); @@ -37,7 +37,7 @@ fn main() { let mut layers = vec![calculate_layer(30, network.clone(), 2.0)]; if let Some(x) = layers.first() { - write_file(x, "data/0.graph".to_string()).expect("Could not write"); + write_file(x, "data/0.graph").expect("Could not write"); } for i in 1..7 { diff --git a/highway/src/generation/core.rs b/highway/src/generation/core.rs index 8e44197..614a72e 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -103,12 +103,7 @@ impl HashNodeQueue { HashNodeQueue { queue, seen } } - fn from_vec(items: &[T]) -> Self { - let queue = VecDeque::from_iter(items.iter().cloned()); - let seen = HashSet::from_iter(items.iter().cloned()); - HashNodeQueue { queue, seen } - } fn contains(&self, value: &T) -> bool { self.seen.contains(value) } diff --git a/highway/src/generation/mod.rs b/highway/src/generation/mod.rs index 88b548a..1f93b8c 100644 --- a/highway/src/generation/mod.rs +++ b/highway/src/generation/mod.rs @@ -55,9 +55,9 @@ where E: Send + Sync + Distanceable, { let phase_1_graph = phase_1(size, network); - let phase_2_graph = phase_2(phase_1_graph, contraction_factor); + - phase_2_graph + phase_2(phase_1_graph, contraction_factor) } /// Phase 1: ... ? diff --git a/network/src/iterators.rs b/network/src/iterators.rs index f839de6..fc8701c 100644 --- a/network/src/iterators.rs +++ b/network/src/iterators.rs @@ -40,15 +40,12 @@ impl PartialOrd for IteratorHeapEntry { } pub trait DijkstraIterator { - fn forward_iterator<'a>(&'a self, node: HighwayNodeIndex) -> ForwardDijkstraIterator<'a, N, E>; - fn backward_iterator<'a>( - &'a self, - node: HighwayNodeIndex, - ) -> BackwardDijkstraIterator<'a, N, E>; + fn forward_iterator(&self, node: HighwayNodeIndex) -> ForwardDijkstraIterator<'_, N, E>; + fn backward_iterator(&self, node: HighwayNodeIndex) -> BackwardDijkstraIterator<'_, N, E>; } impl DijkstraIterator for HighwayGraph { - fn forward_iterator<'a>(&'a self, node: HighwayNodeIndex) -> ForwardDijkstraIterator<'a, N, E> { + fn forward_iterator(&self, node: HighwayNodeIndex) -> ForwardDijkstraIterator<'_, N, E> { let mut heap = BinaryHeap::new(); heap.push(IteratorHeapEntry { distance: 0.0, @@ -62,10 +59,7 @@ impl DijkstraIterator for HighwayGraph { } } - fn backward_iterator<'a>( - &'a self, - node: HighwayNodeIndex, - ) -> BackwardDijkstraIterator<'a, N, E> { + fn backward_iterator(&self, node: HighwayNodeIndex) -> BackwardDijkstraIterator<'_, N, E> { let mut heap = BinaryHeap::new(); heap.push(IteratorHeapEntry { distance: 0.0, diff --git a/src/nwb.rs b/src/nwb.rs index 9d54cc7..e819c9a 100644 --- a/src/nwb.rs +++ b/src/nwb.rs @@ -46,7 +46,7 @@ pub fn preprocess_roadmap>(roadmap: &RoadMap, database: P) -> Nwb }) .collect::>(); - for (&road_id, _) in roads { + for &road_id in roads.keys() { let (road_id_start, road_id_end, rij_richting) = statement[&road_id]; let source = junction_to_node[&road_id_start]; diff --git a/src/ui/layers.rs b/src/ui/layers.rs index 2f956ea..d4c7e96 100644 --- a/src/ui/layers.rs +++ b/src/ui/layers.rs @@ -104,10 +104,10 @@ pub fn handle_preprocess_task( } fn clicked_preprocess( - base: NwbGraph, + _base: NwbGraph, layer_count: usize, - neighbourhood: usize, - contraction_factor: f32, + _neighbourhood: usize, + _contraction_factor: f32, ) -> PreProcess { println!("Clicked: {layer_count}"); @@ -182,7 +182,7 @@ pub struct PreProcess { } impl PreProcess { - pub fn new(base: NwbGraph, layers: Vec>) -> Self { + pub fn new(_base: NwbGraph, _layers: Vec>) -> Self { unimplemented!("Could not create preprocess") // let mut road_data_level = (0..base.edges().len()) diff --git a/src/ui/route.rs b/src/ui/route.rs index bb15db2..57c62a2 100644 --- a/src/ui/route.rs +++ b/src/ui/route.rs @@ -42,11 +42,11 @@ pub fn gui_system(mut egui_context: ResMut, mut state: ResMut Option { let value = record.get(name).unwrap(); if let FieldValue::Numeric(x) = value { - return x.clone(); + return *x; } unreachable!(); } From b9a7a75d7ac2e8e8b70fc3b9b12786bf0e1e8b1f Mon Sep 17 00:00:00 2001 From: BlockCat Date: Wed, 28 Dec 2022 12:17:30 +0100 Subject: [PATCH 08/17] almost done! --- bevy_shapefile/src/road_map.rs | 4 +- bevy_shapefile/src/spatial.rs | 6 +- highway/src/generation/core.rs | 10 +- src/ui/layers.rs | 205 +++++++++++++++++++-------------- 4 files changed, 130 insertions(+), 95 deletions(-) diff --git a/bevy_shapefile/src/road_map.rs b/bevy_shapefile/src/road_map.rs index ed1a55f..8fa10c3 100644 --- a/bevy_shapefile/src/road_map.rs +++ b/bevy_shapefile/src/road_map.rs @@ -20,7 +20,7 @@ use std::{collections::HashMap, fs::File, path::Path}; /// Load shapefile. /// This shapefile is used vor visualization of road data. /// It loads all the road sections, and puts it in spatial data structures. -#[derive(Serialize, Deserialize, Debug, Resource)] +#[derive(Serialize, Deserialize, Debug, Clone, Resource)] pub struct RoadMap { pub roads: HashMap, pub junction_spatial: rstar::RTree, @@ -39,7 +39,7 @@ impl RoadMap { } } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Params; impl RTreeParams for Params { diff --git a/bevy_shapefile/src/spatial.rs b/bevy_shapefile/src/spatial.rs index bb5104b..ef29491 100644 --- a/bevy_shapefile/src/spatial.rs +++ b/bevy_shapefile/src/spatial.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::{JunctionId, RoadId}; /// A road section, with id, points and bounding box -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct RoadSection { pub id: RoadId, pub points: Vec, @@ -19,7 +19,7 @@ pub struct RoadSection { pub aabb: Aabb, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct JunctionSpatialIndex { pub junction_id: JunctionId, pub location: Vec2, @@ -43,7 +43,7 @@ impl PointDistance for JunctionSpatialIndex { } } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct RoadSpatialIndex { pub id: RoadId, // Points to a road in the RoadMap #[serde( diff --git a/highway/src/generation/core.rs b/highway/src/generation/core.rs index 614a72e..165ad3e 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use network::{iterators::Distanceable, HighwayEdgeIndex, HighwayGraph, HighwayNodeIndex}; use petgraph::visit::EdgeRef; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use std::{ collections::{HashSet, VecDeque}, hash::Hash, @@ -9,11 +9,11 @@ use std::{ #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Shorted { - distance: f32, + pub distance: f32, /// Points to nodes in the previous layer - skipped_nodes: Vec, + pub skipped_nodes: Vec, /// Points to edges in the previous layer - skipped_edges: Vec, + pub skipped_edges: Vec, } impl Distanceable for Shorted { @@ -59,6 +59,8 @@ pub(crate) fn core_network_with_patch( .edges_directed(node, petgraph::Direction::Incoming) .collect_vec(); + panic!("Need to be remove from next network. And Shorted can be combined, which is not the case right now"); + for source_edge in in_edges { let source = source_edge.source(); let source_edge_id = source_edge.id(); diff --git a/src/ui/layers.rs b/src/ui/layers.rs index d4c7e96..f780ae5 100644 --- a/src/ui/layers.rs +++ b/src/ui/layers.rs @@ -1,3 +1,4 @@ +use super::DirectedNetworkGraphContainer; use crate::{ nwb::NwbGraph, world::{WorldEntity, WorldEntitySelectionType}, @@ -7,14 +8,13 @@ use bevy::{ tasks::{AsyncComputeTaskPool, Task}, }; use bevy_egui::{egui, EguiContext}; -use bevy_shapefile::{JunctionId, RoadId}; +use bevy_shapefile::{JunctionId, RoadId, RoadMap}; use futures_lite::future; use highway::generation::core::Shorted; -use network::HighwayGraph; +use network::{iterators::Distanceable, HighwayGraph}; +use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use std::{collections::HashMap, path::Path}; -use super::DirectedNetworkGraphContainer; - #[derive(Debug, Default, Resource)] pub struct LayerState { pub preprocess_layers: usize, @@ -25,6 +25,15 @@ pub struct LayerState { pub processing: bool, } +#[derive(Debug, Clone)] +struct RoadWeight(RoadId, f32); + +impl Distanceable for RoadWeight { + fn distance(&self) -> f32 { + self.1 + } +} + #[derive(Component)] pub struct ComputeTask(Task); @@ -32,6 +41,7 @@ pub fn gui_system( mut commands: Commands, mut egui_context: ResMut, mut state: ResMut, + road_map: Res, preprocess: Option>, base_network: Res, ) { @@ -47,9 +57,16 @@ pub fn gui_system( let layer_count = state.preprocess_layers; let neighbourhood_size = state.neighbourhood_size; let contraction_factor = state.contraction_factor; + let road_map = road_map.clone(); let task = AsyncComputeTaskPool::get().spawn(async move { - clicked_preprocess(network, layer_count, neighbourhood_size, contraction_factor) + clicked_preprocess( + network, + road_map, + layer_count, + neighbourhood_size, + contraction_factor, + ) }); state.processing = true; @@ -104,46 +121,48 @@ pub fn handle_preprocess_task( } fn clicked_preprocess( - _base: NwbGraph, + network: NwbGraph, + road_map: RoadMap, layer_count: usize, - _neighbourhood: usize, - _contraction_factor: f32, + neighbourhood: usize, + contraction_factor: f32, ) -> PreProcess { println!("Clicked: {layer_count}"); - unimplemented!("Preprocessing is disabled while implementing petgraph"); - // let mut layers = Vec::new(); - // layers.push(load_or_calculate("data/layer_0.graph", || { - // highway::generation::calculate_layer(neighbourhood, &base, contraction_factor) - // })); - - // println!( - // "Base edges: {}, nodes: {}", - // base.edge_count(), - // base.node_count() - // ); - - // for i in 1..layer_count { - // let size = neighbourhood; - // let network = layers.last().unwrap(); - // let path = format!("data/layer_{i}.graph"); - // let next_layer = load_or_calculate(path, || { - // highway::generation::calculate_layer(size, network, contraction_factor) - // }); - - // println!( - // "Layer {} edges: {}/{}, nodes: {}/{}", - // i, - // next_layer.edges().len(), - // network.edges().len() as f32 / next_layer.edges().len() as f32, - // next_layer.nodes().len(), - // network.nodes().len() as f32 / next_layer.nodes().len() as f32 - // ); - - // layers.push(next_layer); - // } - - // PreProcess::new(base, layers) + let base = network.map(|_, n| *n, |_, e| RoadWeight(*e, road_map.road_length(*e))); + + let mut layers = Vec::new(); + layers.push(load_or_calculate("data/layer_0.graph", || { + highway::generation::calculate_layer(neighbourhood, base.clone(), contraction_factor) + })); + + println!( + "Base edges: {}, nodes: {}", + base.edge_count(), + base.node_count() + ); + + for i in 1..layer_count { + let size = neighbourhood; + let network = layers.last().unwrap(); + let path = format!("data/layer_{i}.graph"); + let next_layer = load_or_calculate(path, || { + highway::generation::calculate_layer(size, network.clone(), contraction_factor) + }); + + println!( + "Layer {} edges: {}/{}, nodes: {}/{}", + i, + next_layer.edge_count(), + network.edge_count() as f32 / next_layer.edge_count() as f32, + next_layer.node_count(), + network.node_count() as f32 / next_layer.node_count() as f32 + ); + + layers.push(next_layer); + } + + PreProcess::new(network, layers) } pub fn colouring_system( @@ -182,51 +201,65 @@ pub struct PreProcess { } impl PreProcess { - pub fn new(_base: NwbGraph, _layers: Vec>) -> Self { - unimplemented!("Could not create preprocess") - - // let mut road_data_level = (0..base.edges().len()) - // .map(EdgeId::from) - // .flat_map(|id| Vec::from(base.data.edge_road_id(id))) - // .map(|x| (RoadId::from(x), 0)) - // .collect::>(); - - // println!("Base line of: {}", road_data_level.len()); - // // process_edges(0, &base, &mut road_data_level); - - // for (layer_id, layer) in layers.iter().enumerate() { - // process_edges(layer_id as u8 + 1, layer, &mut road_data_level); - // } - - // PreProcess { - // base, - // layers, - // road_data_level, - // } + pub fn new( + nwb_graph: NwbGraph, + layers: Vec>, + ) -> Self { + let mut road_data_level = nwb_graph + .edge_weights() + .map(|e| (*e, 0)) + .collect::>(); + + println!("Base line of: {}", road_data_level.len()); + + process_edges(&nwb_graph, &mut road_data_level, &layers); + + PreProcess { + base: nwb_graph, + layers, + road_data_level, + } } } -// Finds the highest layer of roads -// fn process_edges( -// layer_id: u8, -// network: &DirectedNetworkGraph, -// road_data: &mut HashMap, -// ) { -// for id in 0..network.edges().len() { -// let id = EdgeId::from(id); -// match network.data.edge_road_id(id) { -// network::ShortcutState::Single(a) => { -// road_data.entry(RoadId::from(a)).and_modify(|f| { -// *f = layer_id; -// }); -// } -// network::ShortcutState::Shortcut(b) => { -// for a in b { -// road_data.entry(RoadId::from(a)).and_modify(|f| { -// *f = layer_id; -// }); -// } -// } -// } -// } -// } +/// Finds the highest layer of roads +/// Basically, every road stores the highest level where it can be found +fn process_edges( + nwb_graph: &NwbGraph, + road_data: &mut HashMap, + layers: &Vec>, +) { + let base = nwb_graph + .edge_references() + .map(|e| (e.id(), vec![*e.weight()])) + .collect::>(); + + let mut layer_translations = vec![base]; + + for level in 0..layers.len() { + // Add a new layer of translations + layer_translations.push(HashMap::default()); + assert_eq!(layer_translations.len(), level + 2); + + for edge in layers[level].edge_references() { + let edge_id = edge.id(); + let weight = edge.weight(); + let road_ids = weight + .skipped_edges + .iter() + .flat_map(|s| { + // Level is the same as the previous layer translation + layer_translations[level][s].clone() + }) + .collect::>(); + + for road_id in &road_ids { + road_data.insert(*road_id, level as u8 + 1); + } + layer_translations[level + 1] + .entry(edge_id) + .or_default() + .extend(road_ids); + } + } +} From b48a7790a2284e8f1e043e550cfe9972f3efabef Mon Sep 17 00:00:00 2001 From: BlockCat Date: Wed, 28 Dec 2022 17:30:18 +0100 Subject: [PATCH 09/17] help --- README.md | 62 ++++++- bevy_shapefile/src/lib.rs | 3 + bevy_shapefile/src/road_map.rs | 32 +++- examples/layer.rs | 2 + highway/src/generation/core.rs | 72 ++------ highway/src/generation/dijkstra.rs | 3 +- highway/src/generation/mod.rs | 9 +- network/src/lib.rs | 90 ++++++++++ src/nwb.rs | 16 +- src/selection.sql | 3 + src/ui/layers.rs | 3 +- src/world.rs | 18 +- tools/dbf_to_sql/src/create_table.sql | 1 - tools/dbf_to_sql/src/example_shape.txt | 224 +++++++++++++++++++++++++ tools/dbf_to_sql/src/insert.sql | 40 +++-- tools/dbf_to_sql/src/main.rs | 43 +++-- 16 files changed, 483 insertions(+), 138 deletions(-) create mode 100644 src/selection.sql create mode 100644 tools/dbf_to_sql/src/example_shape.txt diff --git a/README.md b/README.md index dac1772..d6619f9 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,12 @@ ![map](docs/map.png) ## Install: + 1. Retrieve latest data from https://www.rijkswaterstaat.nl/apps/geoservices/geodata/dmc/nwb-wegen/geogegevens/shapefile/Nederland_totaal/ 2. Extract contents to /data folder. 3. Create a database using the tools/dbf_to_sql tool. (`cargo.exe run --package dbf_to_sql --bin dbf_to_sql --release`) 4. Copy database to data/database.db + ## Structure: ### Visualization @@ -14,17 +16,67 @@ - main package: Uses bevy for visualization (using weird stuff) - bevy_shapefile: Load spatial data for visualization - ## Changes: Changed old neighbourhood using hashmap to new neighbourhood using radius: -|Ver|Old|Old|New|New| -|---|---|---|---|---| -| N | 4 | 30| 4 | 30| -|ms |696| 4453| 452 |3682| +| Ver | Old | Old | New | New | +| --- | --- | ---- | --- | ---- | +| N | 4 | 30 | 4 | 30 | +| ms | 696 | 4453 | 452 | 3682 | Phase 1 generation: + ``` time: [20.726 s 22.190 s 23.603 s] ``` + +### Changed custom graph to petgraph: Result is that it now is slower. + +One of the reasons is that we are trying to keep things stable. +They need to be stable because we are removing nodeindeces from the network. +We can change this by not removing the node, but by removing the edges. Edges do not need to be stable. + +Another reason is the edge layout. We need to quickly: +- Iterate over outgoing edges +- Iterate over incoming edges +- Iterate over outgoing+incoming edges +- get outgoing edge count +- get incoming edge count +- get total edge count + +## Types + +- VWG (Ventweg) +- PAR (Parallelweg - niet ventweg) +- MRB(Minirotondebaan) +- NRB (Normale rotondebaan - niet minirotondebaan) +- OPR (Toerit - synoniem: oprit) +- AFR (Afrit) +- PST (Puntstuk = snijpunt verharding) +- VBD (Verbindingsweg direct) +- VBI (Verbindingsweg indirect) +- VBS (Verbindingsweg semi-direct) +- VBR (Verbindingsweg rangeerbaan) +- VBK (Verbindingsweg kortsluitend) +- VBW(Verbindingsweg - overig) +- DST (Doorsteek) +- PKP (Verzorgingsbaan van/naar parkeerplaats) +- PKB (verzorgingsbaan van/naar parkeerplaats bij benzinestation) +- BST (Verzorgingsbaan van /naar benzinestation) +- YYY (Overige baan) +- BU(Busbaan) +- FP (Fietspad) +- HR (Hoofdrijbaan) +- TN(Tussenbaan) +- VP(Voetpad) +- OVB (OV-baan) +- CADO (Calamiteiten doorgang) +- TRB (Turborotondebaan) +- RP(Ruiterpad) +- VV (Vliegverkeer) +- PP (Parkeerplaats) +- PC(Parkeerplaats tbv carpool) +- PR(Parkeerplaats P+R) +- VD (Veerdienst) +- (Geen) diff --git a/bevy_shapefile/src/lib.rs b/bevy_shapefile/src/lib.rs index 08fc5a0..f456e06 100644 --- a/bevy_shapefile/src/lib.rs +++ b/bevy_shapefile/src/lib.rs @@ -9,6 +9,9 @@ mod spatial; pub type AABB = rstar::AABB<[f32; 2]>; +// pub const SKIP_TYPES: [&'static str; 7] = ["FP", "BU", "VP", "OVB", "CADO", "RP", "VV"]; +pub const SKIP_TYPES: [&'static str; 0] = []; + pub fn from_shapefile>(path: P) -> Result { println!("Start loading file"); diff --git a/bevy_shapefile/src/road_map.rs b/bevy_shapefile/src/road_map.rs index 8fa10c3..a593c84 100644 --- a/bevy_shapefile/src/road_map.rs +++ b/bevy_shapefile/src/road_map.rs @@ -1,6 +1,6 @@ use crate::{ spatial::{JunctionSpatialIndex, RoadSection, RoadSpatialIndex}, - JunctionId, RoadId, ShapeError, + JunctionId, RoadId, ShapeError, SKIP_TYPES, }; use bevy::{ math::{Vec2, Vec3}, @@ -116,6 +116,15 @@ fn get_usize(record: &Record, name: &str) -> Option { unreachable!(); } +fn get_text(record: &Record, name: &str) -> Option { + let value = record.get(name).unwrap(); + + if let FieldValue::Character(x) = value { + return x.clone(); + } + unreachable!(); +} + /// Load junction point data fn load_junctions(roads: &Vec<(GenericPolyline, Record)>) -> HashMap { roads @@ -123,11 +132,18 @@ fn load_junctions(roads: &Vec<(GenericPolyline, Record)>) -> HashMap>() } diff --git a/examples/layer.rs b/examples/layer.rs index acd56fc..6f6c77e 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -34,6 +34,8 @@ fn main() { }, ); + println!("Translated network"); + let mut layers = vec![calculate_layer(30, network.clone(), 2.0)]; if let Some(x) = layers.first() { diff --git a/highway/src/generation/core.rs b/highway/src/generation/core.rs index 165ad3e..ee991d7 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -1,26 +1,16 @@ use itertools::Itertools; +use network::{BypassNode, Shorted}; use network::{iterators::Distanceable, HighwayEdgeIndex, HighwayGraph, HighwayNodeIndex}; -use petgraph::visit::EdgeRef; +use petgraph::{ + visit::{EdgeRef, IntoEdgesDirected}, + Direction, +}; use serde::{Deserialize, Serialize}; use std::{ collections::{HashSet, VecDeque}, hash::Hash, }; -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Shorted { - pub distance: f32, - /// Points to nodes in the previous layer - pub skipped_nodes: Vec, - /// Points to edges in the previous layer - pub skipped_edges: Vec, -} - -impl Distanceable for Shorted { - fn distance(&self) -> f32 { - self.distance - } -} pub(crate) fn core_network_with_patch( old_network: HighwayGraph, @@ -38,53 +28,23 @@ pub(crate) fn core_network_with_patch( }, ); + drop(old_network); + while let Some(node) = queue.pop_front() { - let out_edges = old_network - .edges_directed(node, petgraph::Direction::Outgoing) + let out_edges = next_network + .edges_directed(node, Direction::Outgoing) .count() as f32; - let in_edges = old_network - .edges_directed(node, petgraph::Direction::Outgoing) + let in_edges = next_network + .edges_directed(node, Direction::Outgoing) .count() as f32; let short_cuts = out_edges * in_edges; let contraction = (out_edges + in_edges) * contraction_factor; - if short_cuts < contraction { - // Remove from the node from the new network. - next_network.remove_node(node); - let out_edges = old_network - .edges_directed(node, petgraph::Direction::Outgoing) - .collect_vec(); - let in_edges = old_network - .edges_directed(node, petgraph::Direction::Incoming) - .collect_vec(); - - panic!("Need to be remove from next network. And Shorted can be combined, which is not the case right now"); - - for source_edge in in_edges { - let source = source_edge.source(); - let source_edge_id = source_edge.id(); - let source_edge = source_edge.weight(); - - for target_edge in &out_edges { - let target = target_edge.target(); - let target_edge_id = target_edge.id(); - let target_edge = target_edge.weight(); - // Connect source to target. - let combined_distance = source_edge.distance() + target_edge.distance(); - next_network.add_edge( - source, - target, - Shorted { - distance: combined_distance, - skipped_nodes: vec![node], - skipped_edges: vec![source_edge_id, target_edge_id], - }, - ); - - queue.push_back(target); - } - queue.push_back(source); + if short_cuts <= contraction { + let touched = next_network.bypass(node); + for touched in touched { + queue.push_back(touched); } } } @@ -117,7 +77,7 @@ impl HashNodeQueue { } fn push_back(&mut self, value: T) { - if self.contains(&value) { + if !self.contains(&value) { self.queue.push_back(value); } } diff --git a/highway/src/generation/dijkstra.rs b/highway/src/generation/dijkstra.rs index 85437ed..ef6ae02 100644 --- a/highway/src/generation/dijkstra.rs +++ b/highway/src/generation/dijkstra.rs @@ -137,7 +137,8 @@ fn initialize_heap( }, ); for edge in network.edges_directed(s0, petgraph::Direction::Outgoing) { - assert!(s0 != edge.target()); + assert_eq!(s0, edge.source()); + assert_ne!(s0, edge.target()); let distance = edge.weight().distance(); heap.push(DijkstraNodeState { distance, diff --git a/highway/src/generation/mod.rs b/highway/src/generation/mod.rs index 1f93b8c..fdb91c2 100644 --- a/highway/src/generation/mod.rs +++ b/highway/src/generation/mod.rs @@ -1,9 +1,9 @@ -use network::{iterators::Distanceable, BackwardNeighbourhood, ForwardNeighbourhood, HighwayGraph}; +use network::{ + iterators::Distanceable, BackwardNeighbourhood, ForwardNeighbourhood, HighwayGraph, Shorted, +}; use rayon::prelude::*; use std::collections::HashSet; -use self::core::Shorted; - pub mod core; pub mod dag; pub mod dijkstra; @@ -55,7 +55,6 @@ where E: Send + Sync + Distanceable, { let phase_1_graph = phase_1(size, network); - phase_2(phase_1_graph, contraction_factor) } @@ -84,6 +83,8 @@ pub(crate) fn phase_1( .flat_map_iter(|id| dijkstra::calculate_edges(id, &computed, &network)) .collect::>(); + println!("Got retained edges"); + network.retain_edges(|_, e| edges.contains(&e)); println!("Finished computing (edges collections)"); diff --git a/network/src/lib.rs b/network/src/lib.rs index c43e3cc..79cfdeb 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -4,11 +4,14 @@ pub mod iterators; pub mod neighbourhood; +use iterators::Distanceable; +use itertools::Itertools; pub use neighbourhood::*; use petgraph::stable_graph::EdgeIndex; use petgraph::stable_graph::IndexType; use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::StableDiGraph; +use petgraph::visit::EdgeRef; use serde::Deserialize; use serde::Serialize; @@ -37,3 +40,90 @@ unsafe impl IndexType for HighwayIndex { #[cfg(test)] pub(crate) mod tests; + +pub trait BypassNode { + /// Bypass a node, and return nodes that have an edge removed + fn bypass(&mut self, node: HighwayNodeIndex) -> Vec; +} + +impl BypassNode for HighwayGraph { + fn bypass(&mut self, node: HighwayNodeIndex) -> Vec { + let in_edges = self + .edges_directed(node, petgraph::Direction::Incoming) + .map(|e| { + debug_assert_eq!(e.target(), node); + (e.source(), e.weight().clone()) + }) + .collect_vec(); + + let out_edges = self + .edges_directed(node, petgraph::Direction::Outgoing) + .map(|e| { + debug_assert_eq!(e.source(), node); + (e.target(), e.weight().clone()) + }) + .collect_vec(); + + // The node has no receiving edges. Only outgoing. Then remove the node. + if in_edges.len() == 0 { + self.remove_node(node); + return vec![]; + } + + // The node has no outgoing edges. Only incoming. Then remove the node. + if out_edges.len() == 0 { + self.remove_node(node); + return vec![]; + } + + let mut touched = Vec::new(); + + for (source, source_shorted) in in_edges { + for (target, target_shorted) in &out_edges { + if &source == target { + continue; + } + // Connect source to target. + let combined_distance = source_shorted.distance() + target_shorted.distance(); + let mut skipped_nodes = vec![node]; + skipped_nodes.extend(source_shorted.skipped_nodes.clone()); + skipped_nodes.extend(target_shorted.skipped_nodes.clone()); + + let mut skipped_edges = Vec::with_capacity( + source_shorted.skipped_edges.len() + target_shorted.skipped_edges.len(), + ); + skipped_edges.extend(source_shorted.skipped_edges.clone()); + skipped_edges.extend(target_shorted.skipped_edges.clone()); + + self.add_edge( + source, + *target, + Shorted { + distance: combined_distance, + skipped_nodes, + skipped_edges, + }, + ); + touched.push(*target); + } + touched.push(source); + } + + touched + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Shorted { + pub distance: f32, + /// Points to nodes in the previous layer + pub skipped_nodes: Vec, + /// Points to edges in the previous layer + pub skipped_edges: Vec, +} + +impl Distanceable for Shorted { + fn distance(&self) -> f32 { + self.distance + } +} diff --git a/src/nwb.rs b/src/nwb.rs index e819c9a..db98440 100644 --- a/src/nwb.rs +++ b/src/nwb.rs @@ -8,8 +8,8 @@ use rusqlite::{ use std::{collections::HashMap, path::Path}; pub type NwbGraph = HighwayGraph<(JunctionId, Vec2), RoadId>; -pub type NwbNodeIndex = HighwayNodeIndex; //NodeIndex; -pub type NwbEdgeIndex = HighwayEdgeIndex; //EdgeIndex; +pub type NwbNodeIndex = HighwayNodeIndex; +pub type NwbEdgeIndex = HighwayEdgeIndex; pub fn preprocess_roadmap>(roadmap: &RoadMap, database: P) -> NwbGraph { let database = Connection::open(database).expect("Could not open database"); @@ -18,7 +18,7 @@ pub fn preprocess_roadmap>(roadmap: &RoadMap, database: P) -> Nwb let roads = &roadmap.roads; let statement = database - .prepare("SELECT id,junction_id_begin, junction_id_end, rij_richting FROM wegvakken") + .prepare(include_str!("selection.sql")) .expect("Could not prepare statement") .query_map([], |f| { let id: usize = f.get(0)?; @@ -46,8 +46,14 @@ pub fn preprocess_roadmap>(roadmap: &RoadMap, database: P) -> Nwb }) .collect::>(); - for &road_id in roads.keys() { - let (road_id_start, road_id_end, rij_richting) = statement[&road_id]; + for (road_id, (road_id_start, road_id_end, rij_richting)) in roads + .keys() + .filter_map(|road_id| statement.get(road_id).map(|a| (*road_id, a))) + { + if road_id_start == road_id_end { + println!("Found a road that starts and ends at the same place"); + continue; + } let source = junction_to_node[&road_id_start]; let target = junction_to_node[&road_id_end]; diff --git a/src/selection.sql b/src/selection.sql new file mode 100644 index 0000000..9b28c62 --- /dev/null +++ b/src/selection.sql @@ -0,0 +1,3 @@ +SELECT id, junction_id_begin, junction_id_end, rij_richting +FROM wegvakken +-- WHERE weg_type NOT IN ('FP', 'BU', 'VP', 'OVB', 'CADO', 'RP', 'VV') \ No newline at end of file diff --git a/src/ui/layers.rs b/src/ui/layers.rs index f780ae5..81ca5e2 100644 --- a/src/ui/layers.rs +++ b/src/ui/layers.rs @@ -10,8 +10,7 @@ use bevy::{ use bevy_egui::{egui, EguiContext}; use bevy_shapefile::{JunctionId, RoadId, RoadMap}; use futures_lite::future; -use highway::generation::core::Shorted; -use network::{iterators::Distanceable, HighwayGraph}; +use network::{iterators::Distanceable, HighwayGraph, Shorted}; use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use std::{collections::HashMap, path::Path}; diff --git a/src/world.rs b/src/world.rs index 2b46299..a42223c 100644 --- a/src/world.rs +++ b/src/world.rs @@ -135,22 +135,6 @@ fn init_road_map(config: Res, mut commands: Commands) { println!("Nodes: {}", network.node_count()); println!("Edges: {}", network.edge_count()); - // let out = network - // .nodes() - // .iter() - // .map(|nn| nn.out_len()) - // .collect::>(); - - // println!( - // "out_edges: [avg: {}, min: {}, max: {}", - // out.iter().sum::() as f32 / out.len() as f32, - // out.iter().min().unwrap(), - // out.iter().max().unwrap() - // ); - - // let next_level_edges = network::calculate_layer(30, &network, 2.0); - // println!("Collected phase1 edges: {}", next_level_edges.len()); - commands.insert_resource(road_map); commands.insert_resource(DirectedNetworkGraphContainer(network)); @@ -275,7 +259,7 @@ fn colour_system( pub fn convert(pos: Vec2, transform: &GlobalTransform, camera: &Camera) -> Vec2 { camera .ndc_to_world(transform, pos.extend(0.0)) - .unwrap() + .unwrap_or(Vec3::ZERO) .truncate() } diff --git a/tools/dbf_to_sql/src/create_table.sql b/tools/dbf_to_sql/src/create_table.sql index f44002b..898c4e5 100644 --- a/tools/dbf_to_sql/src/create_table.sql +++ b/tools/dbf_to_sql/src/create_table.sql @@ -12,7 +12,6 @@ CREATE TABLE IF NOT EXISTS wegvakken beheerder TEXT, --WEGBEHNAAM weg_type TEXT, -- WEGTYPE - weg_type_oms TEXT, -- WGTYPE_OMS huisnummer_structuur_links CHARACTER(1), --HNRSTRLNKS huisnummer_structuur_rechts CHARACTER(1), --HNRSTRRHTS diff --git a/tools/dbf_to_sql/src/example_shape.txt b/tools/dbf_to_sql/src/example_shape.txt new file mode 100644 index 0000000..7016ab7 --- /dev/null +++ b/tools/dbf_to_sql/src/example_shape.txt @@ -0,0 +1,224 @@ +Record { + map: { + "ROUTELTR3": Character( + None, + ), + "WEGBEHSRT": Character( + Some( + "G", + ), + ), + "ROUTELTR": Character( + None, + ), + "ROUTENR4": Numeric( + None, + ), + "ROUTELTR4": Character( + None, + ), + "WEGNR_HMP": Character( + None, + ), + "HNRSTRLNKS": Character( + None, + ), + "WEGNR_AW": Character( + None, + ), + "WVK_ID": Numeric( + Some( + 57172163.0, + ), + ), + "DISTRCODE": Numeric( + Some( + 0.0, + ), + ), + "GEOBRON_ID": Numeric( + Some( + 10.0, + ), + ), + "GME_NAAM": Character( + Some( + "Vlissingen", + ), + ), + "ROUTENR2": Numeric( + None, + ), + "GEOBRON_NM": Character( + Some( + "Hartlijnenbestand Topografische Dienst", + ), + ), + "BAG_ORL": Character( + Some( + "0718300000000716", + ), + ), + "JTE_ID_BEG": Numeric( + Some( + 57172170.0, + ), + ), + "FRC": Character( + Some( + "6", + ), + ), + "HECTO_LTTR": Character( + Some( + "#", + ), + ), + "WVK_BEGDAT": Date( + Some( + Date { + year: 1998, + month: 1, + day: 22, + }, + ), + ), + "JTE_ID_END": Numeric( + Some( + 57172171.0, + ), + ), + "RPE_CODE": Character( + Some( + "#", + ), + ), + "L_HNR_LNKS": Numeric( + None, + ), + "REL_HOOGTE": Numeric( + None, + ), + "HNRSTRRHTS": Character( + None, + ), + "BEGINKM": Numeric( + None, + ), + "E_HNR_LNKS": Numeric( + None, + ), + "BEGAFSTAND": Numeric( + None, + ), + "RIJRICHTNG": Character( + Some( + "B", + ), + ), + "ADMRICHTNG": Character( + None, + ), + "EINDKM": Numeric( + None, + ), + "FOW": Character( + Some( + "3", + ), + ), + "WEGTYPE": Character( + None, + ), + "BRONJAAR": Numeric( + Some( + 1996.0, + ), + ), + "ALT_NAAM": Character( + None, + ), + "POS_TV_WOL": Character( + None, + ), + "DIENSTNAAM": Character( + None, + ), + "L_HNR_RHTS": Numeric( + None, + ), + "WEGBEHCODE": Character( + Some( + "718", + ), + ), + "WEGBEHNAAM": Character( + Some( + "Vlissingen", + ), + ), + "WGTYPE_OMS": Character( + None, + ), + "ROUTENR": Numeric( + None, + ), + "ROUTELTR2": Character( + None, + ), + "WPSNAAM": Character( + Some( + "Vlissingen", + ), + ), + "WEGDEELLTR": Character( + Some( + "#", + ), + ), + "ENDAFSTAND": Numeric( + None, + ), + "ROUTENR3": Numeric( + None, + ), + "DIENSTCODE": Character( + None, + ), + "OPENLR": Character( + Some( + "CwKKUCSWBTPOAAAG//YzHg==", + ), + ), + "STT_NAAM": Character( + Some( + "Scheldestraat", + ), + ), + "ALT_NR": Character( + None, + ), + "GME_ID": Numeric( + Some( + 718.0, + ), + ), + "E_HNR_RHTS": Numeric( + None, + ), + "STT_BRON": Character( + Some( + "BAG schrijfwijze", + ), + ), + "BST_CODE": Character( + None, + ), + "WEGNUMMER": Character( + None, + ), + "DISTRNAAM": Character( + None, + ), + }, +} \ No newline at end of file diff --git a/tools/dbf_to_sql/src/insert.sql b/tools/dbf_to_sql/src/insert.sql index 87a8c35..874705d 100644 --- a/tools/dbf_to_sql/src/insert.sql +++ b/tools/dbf_to_sql/src/insert.sql @@ -12,7 +12,6 @@ INSERT INTO wegvakken beheerder, weg_type, - weg_type_oms, huisnummer_structuur_links, huisnummer_structuur_rechts, @@ -29,32 +28,31 @@ INSERT INTO wegvakken begin_km, eind_km ) VALUES ( - ?, - ?, + :id, + :wegvak_id, - ?, - ?, + :junction_id_begin, + :junction_id_end, - ?, + :rij_richting, - ?, - ?, + :straat_naam, + :beheerder, - ?, - ?, + :weg_type, - ?, - ?, - - ?, - ?, + :huisnummer_structuur_links, + :huisnummer_structuur_rechts, + + :eerste_huisnummer_links, + :eerste_huisnummer_rechts, - ?, - ?, + :laatste_huisnummer_links, + :laatste_huisnummer_rechts, - ?, - ?, + :begin_afstand, + :eind_afstand, - ?, - ? + :begin_km, + :eind_km ); \ No newline at end of file diff --git a/tools/dbf_to_sql/src/main.rs b/tools/dbf_to_sql/src/main.rs index 13bf382..43a75cc 100644 --- a/tools/dbf_to_sql/src/main.rs +++ b/tools/dbf_to_sql/src/main.rs @@ -1,6 +1,6 @@ use std::path::Path; -use rusqlite::{params, Connection, Transaction}; +use rusqlite::{named_params, params, Connection, Transaction}; use shapefile::dbase::{FieldValue, Record}; const CREATE_TABLE_SQL: &str = include_str!("create_table.sql"); @@ -41,27 +41,26 @@ fn execute_transaction>(path: P, tx: &Transaction) { .into_iter() .enumerate() .for_each(|(id, (_, record))| { - stmt.execute(params![ - id, - get_usize(&record, "WVK_ID"), - get_usize(&record, "JTE_ID_BEG"), - get_usize(&record, "JTE_ID_END"), - get_text(&record, "RIJRICHTNG"), - get_text(&record, "STT_NAAM"), - get_text(&record, "WEGBEHNAAM"), - get_text(&record, "WEGTYPE"), - get_text(&record, "WGTYPE_OMS"), - get_text(&record, "HNRSTRLNKS"), - get_text(&record, "HNRSTRRHTS"), - get_usize(&record, "E_HNR_LNKS"), - get_usize(&record, "E_HNR_RHTS"), - get_usize(&record, "L_HNR_LNKS"), - get_usize(&record, "L_HNR_RHTS"), - get_float(&record, "BEGAFSTAND"), - get_float(&record, "ENDAFSTAND"), - get_float(&record, "BEGINKM"), - get_float(&record, "EINDKM") - ]) + stmt.execute(named_params! { + ":id": id, + ":wegvak_id": get_usize(&record, "WVK_ID"), + ":junction_id_begin": get_usize(&record, "JTE_ID_BEG"), + ":junction_id_end": get_usize(&record, "JTE_ID_END"), + ":rij_richting": get_text(&record, "RIJRICHTNG"), + ":straat_naam": get_text(&record, "STT_NAAM"), + ":beheerder": get_text(&record, "WEGBEHNAAM"), + ":weg_type": get_text(&record, "BST_CODE"), + ":huisnummer_structuur_links": get_text(&record, "HNRSTRLNKS"), + ":huisnummer_structuur_rechts": get_text(&record, "HNRSTRRHTS"), + ":eerste_huisnummer_links": get_usize(&record, "E_HNR_LNKS"), + ":eerste_huisnummer_rechts": get_usize(&record, "E_HNR_RHTS"), + ":laatste_huisnummer_links": get_usize(&record, "L_HNR_LNKS"), + ":laatste_huisnummer_rechts": get_usize(&record, "L_HNR_RHTS"), + ":begin_afstand": get_float(&record, "BEGAFSTAND"), + ":eind_afstand": get_float(&record, "ENDAFSTAND"), + ":begin_km": get_float(&record, "BEGINKM"), + ":eind_km": get_float(&record, "EINDKM"), + }) .expect("Could not insert"); }); } From 07c51789757d716ada80f1e6d598c6d038639248 Mon Sep 17 00:00:00 2001 From: BlockCat Date: Thu, 29 Dec 2022 12:12:56 +0100 Subject: [PATCH 10/17] giveup? --- highway/src/generation/core.rs | 10 +- highway/src/generation/dijkstra.rs | 6 +- highway/src/generation/mod.rs | 3 +- network/src/iterators.rs | 1 + network/src/lib.rs | 19 +- network/src/neighbourhood.rs | 5 +- network/src/super_graph.rs | 392 +++++++++++++++++++++++++++++ network/src/tests.rs | 2 +- 8 files changed, 414 insertions(+), 24 deletions(-) create mode 100644 network/src/super_graph.rs diff --git a/highway/src/generation/core.rs b/highway/src/generation/core.rs index ee991d7..b7924ad 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -1,6 +1,6 @@ -use itertools::Itertools; +use network::{iterators::Distanceable, HighwayGraph, HighwayNodeIndex}; use network::{BypassNode, Shorted}; -use network::{iterators::Distanceable, HighwayEdgeIndex, HighwayGraph, HighwayNodeIndex}; +use petgraph::visit::IntoNodeIdentifiers; use petgraph::{ visit::{EdgeRef, IntoEdgesDirected}, Direction, @@ -11,19 +11,17 @@ use std::{ hash::Hash, }; - pub(crate) fn core_network_with_patch( old_network: HighwayGraph, contraction_factor: f32, ) -> HighwayGraph { - let nodes = old_network.node_indices(); + let nodes = old_network.node_identifiers(); let mut queue = HashNodeQueue::::from_iter(nodes); let mut next_network = old_network.map( |_, n| n.clone(), |id, e| Shorted { distance: e.distance(), - skipped_nodes: vec![], skipped_edges: vec![id], }, ); @@ -41,7 +39,7 @@ pub(crate) fn core_network_with_patch( let short_cuts = out_edges * in_edges; let contraction = (out_edges + in_edges) * contraction_factor; - if short_cuts <= contraction { + if short_cuts < contraction { let touched = next_network.bypass(node); for touched in touched { queue.push_back(touched); diff --git a/highway/src/generation/dijkstra.rs b/highway/src/generation/dijkstra.rs index ef6ae02..a74bf51 100644 --- a/highway/src/generation/dijkstra.rs +++ b/highway/src/generation/dijkstra.rs @@ -1,6 +1,6 @@ use super::ComputedState; use network::{iterators::Distanceable, HighwayEdgeIndex, HighwayGraph, HighwayNodeIndex}; -use petgraph::visit::EdgeRef; +use petgraph::visit::{EdgeRef, IntoEdgesDirected}; use std::collections::{HashMap, VecDeque}; use super::dag::*; @@ -137,8 +137,8 @@ fn initialize_heap( }, ); for edge in network.edges_directed(s0, petgraph::Direction::Outgoing) { - assert_eq!(s0, edge.source()); - assert_ne!(s0, edge.target()); + debug_assert_eq!(s0, edge.source()); + debug_assert_ne!(s0, edge.target()); let distance = edge.weight().distance(); heap.push(DijkstraNodeState { distance, diff --git a/highway/src/generation/mod.rs b/highway/src/generation/mod.rs index fdb91c2..bc33257 100644 --- a/highway/src/generation/mod.rs +++ b/highway/src/generation/mod.rs @@ -3,6 +3,7 @@ use network::{ }; use rayon::prelude::*; use std::collections::HashSet; +use petgraph::visit::*; pub mod core; pub mod dag; @@ -78,7 +79,7 @@ pub(crate) fn phase_1( ); let edges = network - .node_indices() + .node_identifiers() .par_bridge() .flat_map_iter(|id| dijkstra::calculate_edges(id, &computed, &network)) .collect::>(); diff --git a/network/src/iterators.rs b/network/src/iterators.rs index fc8701c..b42fe1a 100644 --- a/network/src/iterators.rs +++ b/network/src/iterators.rs @@ -1,5 +1,6 @@ use crate::{HighwayGraph, HighwayNodeIndex}; use petgraph::Direction::Incoming; +use petgraph::visit::*; use petgraph::{visit::EdgeRef, Direction::Outgoing}; use std::collections::{BinaryHeap, HashSet}; diff --git a/network/src/lib.rs b/network/src/lib.rs index 79cfdeb..0192c86 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -3,6 +3,7 @@ pub mod iterators; pub mod neighbourhood; +pub mod super_graph; use iterators::Distanceable; use itertools::Itertools; @@ -10,17 +11,19 @@ pub use neighbourhood::*; use petgraph::stable_graph::EdgeIndex; use petgraph::stable_graph::IndexType; use petgraph::stable_graph::NodeIndex; -use petgraph::stable_graph::StableDiGraph; use petgraph::visit::EdgeRef; +use petgraph::visit::IntoEdgesDirected; +use petgraph::Direction; use serde::Deserialize; use serde::Serialize; +use super_graph::SuperGraph; #[derive( Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize, )] pub struct HighwayIndex(usize); -pub type HighwayGraph = StableDiGraph; +pub type HighwayGraph = SuperGraph; pub type HighwayNodeIndex = NodeIndex; pub type HighwayEdgeIndex = EdgeIndex; @@ -65,13 +68,13 @@ impl BypassNode for HighwayGraph { .collect_vec(); // The node has no receiving edges. Only outgoing. Then remove the node. - if in_edges.len() == 0 { + if self.edges_directed(node, Direction::Outgoing).count() == 0 { self.remove_node(node); return vec![]; } // The node has no outgoing edges. Only incoming. Then remove the node. - if out_edges.len() == 0 { + if self.edges_directed(node, Direction::Incoming).count() == 0 { self.remove_node(node); return vec![]; } @@ -85,9 +88,6 @@ impl BypassNode for HighwayGraph { } // Connect source to target. let combined_distance = source_shorted.distance() + target_shorted.distance(); - let mut skipped_nodes = vec![node]; - skipped_nodes.extend(source_shorted.skipped_nodes.clone()); - skipped_nodes.extend(target_shorted.skipped_nodes.clone()); let mut skipped_edges = Vec::with_capacity( source_shorted.skipped_edges.len() + target_shorted.skipped_edges.len(), @@ -100,7 +100,6 @@ impl BypassNode for HighwayGraph { *target, Shorted { distance: combined_distance, - skipped_nodes, skipped_edges, }, ); @@ -115,9 +114,7 @@ impl BypassNode for HighwayGraph { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Shorted { - pub distance: f32, - /// Points to nodes in the previous layer - pub skipped_nodes: Vec, + pub distance: f32, /// Points to edges in the previous layer pub skipped_edges: Vec, } diff --git a/network/src/neighbourhood.rs b/network/src/neighbourhood.rs index 10415f3..20ee560 100644 --- a/network/src/neighbourhood.rs +++ b/network/src/neighbourhood.rs @@ -1,5 +1,6 @@ use crate::iterators::{DijkstraIterator, Distanceable}; use crate::{HighwayGraph, HighwayNodeIndex}; +use petgraph::visit::*; use rayon::prelude::*; use std::collections::HashMap; use std::ops::Deref; @@ -44,7 +45,7 @@ impl ForwardNeighbourhood { network: &HighwayGraph, ) -> Self { let mut radius: HashMap<_, _> = network - .node_indices() + .node_identifiers() .par_bridge() .map(|node| { ( @@ -64,7 +65,7 @@ impl BackwardNeighbourhood { network: &HighwayGraph, ) -> Self { let mut radius: HashMap<_, _> = network - .node_indices() + .node_identifiers() .par_bridge() .map(|node| { ( diff --git a/network/src/super_graph.rs b/network/src/super_graph.rs new file mode 100644 index 0000000..7c251e7 --- /dev/null +++ b/network/src/super_graph.rs @@ -0,0 +1,392 @@ +use std::{iter::Enumerate, marker::PhantomData, ops::Range, slice}; + +use petgraph::{ + stable_graph::{DefaultIx, EdgeIndex, IndexType, NodeIndex}, + visit::{self, EdgeRef, IntoNeighborsDirected}, + Directed, + Direction::{self, Incoming, Outgoing}, + IntoWeightedEdge, +}; + +/// The graph's node type +#[derive(Debug, Clone)] +pub struct Node { + /// Associated node data + pub weight: N, + /// Next outgoing edge + /// Next incoming edge, starts at first bothways edge + /// Final outgoing edge (exclusive) also start of first incoming only edge + pub next: [EdgeIndex; 3], +} + +impl Node { + pub fn next_edge(&self, dir: Direction) -> EdgeIndex { + self.next[dir.index()] + } +} + +/// The graph's edge type. +#[derive(Debug, Clone)] +pub struct Edge { + /// Associated edge data. + pub weight: E, + /// Me -> Other + node: [NodeIndex; 2], +} + +impl Edge { + /// Comes from + pub fn source(&self) -> NodeIndex { + self.node[0] + } + /// Goes to + pub fn target(&self) -> NodeIndex { + self.node[1] + } +} + +/// Simple graph, +/// Nodes point to the first +#[derive(Debug, Clone, Default)] +pub struct SuperGraph { + nodes: Vec>, + /// per node: Forward|Both|Backward + edges: Vec>, +} + +impl SuperGraph { + pub fn with_capacity(nodes: usize, edges: usize) -> Self { + Self { + nodes: Vec::with_capacity(nodes), + edges: Vec::with_capacity(edges), + } + } + pub fn node_count(&self) -> usize { + self.nodes.len() + } + pub fn edge_count(&self) -> usize { + self.edges.len() + } + #[inline] + pub fn is_directed(&self) -> bool { + true + } + + pub fn node_weight(&self, a: NodeIndex) -> Option<&N> { + self.nodes.get(a.index()).map(|n| &n.weight) + } + pub fn node_weight_mut(&mut self, a: NodeIndex) -> Option<&mut N> { + self.nodes.get_mut(a.index()).map(|n| &mut n.weight) + } + + pub fn edge_weight(&self, a: EdgeIndex) -> Option<&E> { + self.edges.get(a.index()).map(|e| &e.weight) + } + pub fn edge_weight_mut(&mut self, a: EdgeIndex) -> Option<&mut E> { + self.edges.get_mut(a.index()).map(|e| &mut e.weight) + } + pub fn edge_endpoints(&self, a: EdgeIndex) -> Option<(NodeIndex, NodeIndex)> { + self.edges.get(a.index()).map(|e| (e.source(), e.target())) + } + + pub fn neighbors_undirected(&self, a: NodeIndex) -> Neighbors { + let node = self.nodes[a.index()].next[0]; + let next_node = self + .nodes + .get(a.index()) + .map(|x| x.next[0]) + .unwrap_or(EdgeIndex::new(self.edges.len())); + + Neighbors { + range: node.index()..next_node.index(), + edges: &self.edges, + } + } +} + +impl SuperGraph { + // pub fn add_node(&mut self, weight: N) -> NodeIndex { + // let index = self.node_count(); + // self.nodes.push(Node { + // weight, + // next: [ + // EdgeIndex::new(self.edge_count()), + // EdgeIndex::new(self.edge_count()), + // EdgeIndex::new(self.edge_count()), + // ], + // }); + // NodeIndex::new(index) + // } + // pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { + // todo!() + // } + + // pub fn extend_with_edges(&mut self, iterable: I) + // where + // I: IntoIterator, + // I::Item: IntoWeightedEdge, + // >::NodeId: Into>, + // N: Default, + // { + // todo!() + // } + + // pub fn remove_node(&mut self, a: NodeIndex) -> Option { + // todo!() + // } + + // pub fn remove_edge(&mut self, e: EdgeIndex) -> Option { + // todo!() + // } +} + +#[derive(Debug, Clone)] +pub struct Neighbors<'a, E: 'a, Ix: 'a + IndexType> { + range: Range, + edges: &'a [Edge], +} + +impl<'a, E, Ix: IndexType> Iterator for Neighbors<'a, E, Ix> { + type Item = NodeIndex; + + fn next(&mut self) -> Option { + self.range.next().map(|i| self.edges[i].target()) + } + + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } + + fn count(self) -> usize + where + Self: Sized, + { + self.range.len() + } +} + +impl visit::GraphBase for SuperGraph { + type EdgeId = EdgeIndex; + type NodeId = NodeIndex; +} + +// impl visit::Visitable for SuperGraph { +// type Map = ; + +// fn visit_map(self: &Self) -> Self::Map { +// todo!() +// } + +// fn reset_map(self: &Self,map: &mut Self::Map) { +// todo!() +// } +// } + +impl visit::GraphProp for SuperGraph { + type EdgeType = Directed; +} + +impl visit::Data for SuperGraph { + type NodeWeight = N; + type EdgeWeight = E; +} + +impl<'a, N, E, Ix: IndexType> visit::IntoNeighbors for &'a SuperGraph { + type Neighbors = Neighbors<'a, E, Ix>; + + fn neighbors(self, a: Self::NodeId) -> Self::Neighbors { + self.neighbors_directed(a, Outgoing) + } +} + +impl<'a, N, E, Ix: IndexType> visit::IntoNeighborsDirected for &'a SuperGraph { + type NeighborsDirected = Neighbors<'a, E, Ix>; + + fn neighbors_directed(self, a: NodeIndex, dir: Direction) -> Neighbors<'a, E, Ix> { + let node = &self.nodes[a.index()]; + let range = match dir { + Outgoing => node.next[0].index()..node.next[2].index(), + Incoming => { + node.next[1].index() + ..self + .nodes + .get(a.index() + 1) + .map(|n| n.next[0].index()) + .unwrap_or(self.edge_count()) + } + }; + + Neighbors { + range, + edges: &self.edges, + } + } +} + +impl<'a, N: 'a, E: 'a, Ix: IndexType> visit::IntoEdgeReferences for &'a SuperGraph { + type EdgeRef = EdgeReference<'a, E, Ix>; + type EdgeReferences = EdgeReferences<'a, E, Ix>; + + fn edge_references(self) -> Self::EdgeReferences { + (*self).edge_references() + } +} +impl<'a, N, E, Ix: IndexType> visit::IntoEdges for &'a SuperGraph { + type Edges = Edges<'a, E, Ix>; + + fn edges(self, a: Self::NodeId) -> Self::Edges { + todo!() + } +} + +impl<'a, N, E, Ix: IndexType> visit::IntoEdgesDirected for &'a SuperGraph { + type EdgesDirected = Edges<'a, E, Ix>; + + fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected { + todo!() + } +} + +impl<'a, N, E: 'a, Ix: IndexType> visit::IntoNodeIdentifiers for &'a SuperGraph { + type NodeIdentifiers = NodeIndices; + + fn node_identifiers(self) -> Self::NodeIdentifiers { + todo!() + } +} + +#[derive(Debug, Clone)] +pub struct Edges<'a, E: 'a, Ix: 'a> { + range: Range, + edges: &'a [Edge], +} + +impl<'a, E, Ix: IndexType> Iterator for Edges<'a, E, Ix> { + type Item = EdgeReference<'a, E, Ix>; + + fn next(&mut self) -> Option { + self.range.next().map(|i| { + let edge = &self.edges[i]; + EdgeReference { + index: EdgeIndex::new(i), + weight: &edge.weight, + node: edge.node.clone(), + } + }) + } + + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } + + fn count(self) -> usize + where + Self: Sized, + { + self.range.len() + } +} + +#[derive(Debug)] +pub struct EdgeReference<'a, E: 'a, Ix> { + index: EdgeIndex, + node: [NodeIndex; 2], + weight: &'a E, +} + +impl<'a, E: 'a, Ix: IndexType> EdgeRef for EdgeReference<'a, E, Ix> { + type NodeId = NodeIndex; + type EdgeId = EdgeIndex; + type Weight = E; + + fn source(&self) -> Self::NodeId { + self.node[0] + } + + fn target(&self) -> Self::NodeId { + self.node[1] + } + + fn weight(&self) -> &Self::Weight { + self.weight + } + + fn id(&self) -> Self::EdgeId { + self.index + } +} + +impl<'a, E, Ix: IndexType> Clone for EdgeReference<'a, E, Ix> { + fn clone(&self) -> Self { + *self + } +} + +impl<'a, E, Ix: IndexType> Copy for EdgeReference<'a, E, Ix> {} + +impl<'a, E, Ix: IndexType> PartialEq for EdgeReference<'a, E, Ix> +where + E: PartialEq, +{ + fn eq(&self, rhs: &Self) -> bool { + self.index == rhs.index && self.weight == rhs.weight + } +} + +impl<'a, Ix, E> EdgeReference<'a, E, Ix> +where + Ix: IndexType, +{ + /// Access the edge’s weight. + /// + /// **NOTE** that this method offers a longer lifetime + /// than the trait (unfortunately they don't match yet). + pub fn weight(&self) -> &'a E { + self.weight + } +} + +pub struct NodeIndices { + r: Range, + ty: PhantomData, +} + +impl Iterator for NodeIndices { + type Item = NodeIndex; + + fn next(&mut self) -> Option { + self.r.next().map(NodeIndex::new) + } + + fn size_hint(&self) -> (usize, Option) { + self.r.size_hint() + } +} + +#[derive(Debug, Clone)] +pub struct EdgeReferences<'a, E: 'a, Ix: IndexType> { + iter: Enumerate>>, +} + +impl<'a, E, Ix: IndexType> Iterator for EdgeReferences<'a, E, Ix> { + type Item = EdgeReference<'a, E, Ix>; + + fn next(&mut self) -> Option { + self.iter.next().map(|(i, edge)| EdgeReference { + index: EdgeIndex::new(i), + node: edge.node.clone(), + weight: &edge.weight, + }) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + fn count(self) -> usize + where + Self: Sized, + { + self.iter.count() + } +} diff --git a/network/src/tests.rs b/network/src/tests.rs index bf006f3..0a81638 100644 --- a/network/src/tests.rs +++ b/network/src/tests.rs @@ -38,7 +38,7 @@ pub fn create_ref_network_1() -> HighwayGraph { } pub fn create_undirected_network() -> HighwayGraph { - let mut graph = StableDiGraph::default(); + let mut graph = HighwayGraph::default(); let nodes = (0..16).map(|x| graph.add_node(x)).collect::>(); graph.add_edge(nodes[0], nodes[1], 3.0); From 5447ab873e1610698e60d587dd59687f46a69654 Mon Sep 17 00:00:00 2001 From: BlockCat Date: Thu, 29 Dec 2022 19:58:12 +0100 Subject: [PATCH 11/17] almost --- highway/src/generation/core.rs | 14 +++++--------- highway/src/generation/mod.rs | 12 +++++++----- network/src/lib.rs | 8 ++++++-- network/src/neighbourhood.rs | 6 ++++-- network/src/super_graph.rs | 16 +++++++++++++++- network/src/tests.rs | 10 +++++----- 6 files changed, 42 insertions(+), 24 deletions(-) diff --git a/highway/src/generation/core.rs b/highway/src/generation/core.rs index 1a0ec67..f9821a5 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -1,20 +1,16 @@ -use network::{iterators::Distanceable, HighwayGraph, HighwayNodeIndex}; -use network::{BypassNode, Shorted}; +use network::{iterators::Distanceable, HighwayNodeIndex}; +use network::{BypassNode, IntermediateGraph, Shorted}; use petgraph::visit::IntoNodeIdentifiers; -use petgraph::{ - visit::{EdgeRef, IntoEdgesDirected}, - Direction, -}; -use serde::{Deserialize, Serialize}; +use petgraph::Direction; use std::{ collections::{HashSet, VecDeque}, hash::Hash, }; pub(crate) fn core_network_with_patch( - old_network: HighwayGraph, + old_network: IntermediateGraph, contraction_factor: f32, -) -> HighwayGraph { +) -> IntermediateGraph { let nodes = old_network.node_identifiers(); let mut queue = HashNodeQueue::::from_iter(nodes); diff --git a/highway/src/generation/mod.rs b/highway/src/generation/mod.rs index bc33257..23b4e63 100644 --- a/highway/src/generation/mod.rs +++ b/highway/src/generation/mod.rs @@ -1,5 +1,5 @@ use network::{ - iterators::Distanceable, BackwardNeighbourhood, ForwardNeighbourhood, HighwayGraph, Shorted, + iterators::Distanceable, BackwardNeighbourhood, ForwardNeighbourhood, HighwayGraph, Shorted, IntermediateGraph, }; use rayon::prelude::*; use std::collections::HashSet; @@ -57,14 +57,16 @@ where { let phase_1_graph = phase_1(size, network); - phase_2(phase_1_graph, contraction_factor) + let phase_2_graph = phase_2(phase_1_graph, contraction_factor); + + HighwayGraph::from(phase_2_graph) } /// Phase 1: ... ? pub(crate) fn phase_1( size: usize, mut network: HighwayGraph, -) -> HighwayGraph { +) -> IntermediateGraph { println!("Start computing (forward backward)"); let (duration, computed) = stopwatch!(ComputedState::new(size, &network)); @@ -97,9 +99,9 @@ pub(crate) fn phase_1( * Calculate the core network */ fn phase_2( - intermediate: HighwayGraph, + intermediate: IntermediateGraph, contraction_factor: f32, -) -> HighwayGraph +) -> IntermediateGraph where N: Clone, E: Distanceable, diff --git a/network/src/lib.rs b/network/src/lib.rs index 0192c86..abdcb43 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -8,10 +8,13 @@ pub mod super_graph; use iterators::Distanceable; use itertools::Itertools; pub use neighbourhood::*; +use petgraph::data::FromElements; use petgraph::stable_graph::EdgeIndex; use petgraph::stable_graph::IndexType; use petgraph::stable_graph::NodeIndex; +use petgraph::stable_graph::StableDiGraph; use petgraph::visit::EdgeRef; +use petgraph::visit::IntoEdgeReferences; use petgraph::visit::IntoEdgesDirected; use petgraph::Direction; use serde::Deserialize; @@ -24,6 +27,7 @@ use super_graph::SuperGraph; pub struct HighwayIndex(usize); pub type HighwayGraph = SuperGraph; +pub type IntermediateGraph = StableDiGraph; pub type HighwayNodeIndex = NodeIndex; pub type HighwayEdgeIndex = EdgeIndex; @@ -49,7 +53,7 @@ pub trait BypassNode { fn bypass(&mut self, node: HighwayNodeIndex) -> Vec; } -impl BypassNode for HighwayGraph { +impl BypassNode for IntermediateGraph { fn bypass(&mut self, node: HighwayNodeIndex) -> Vec { let in_edges = self .edges_directed(node, petgraph::Direction::Incoming) @@ -114,7 +118,7 @@ impl BypassNode for HighwayGraph { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Shorted { - pub distance: f32, + pub distance: f32, /// Points to edges in the previous layer pub skipped_edges: Vec, } diff --git a/network/src/neighbourhood.rs b/network/src/neighbourhood.rs index 20ee560..950fb07 100644 --- a/network/src/neighbourhood.rs +++ b/network/src/neighbourhood.rs @@ -108,12 +108,12 @@ mod tests { use std::collections::HashMap; - use crate::{ForwardNeighbourhood, HighwayGraph, HighwayNodeIndex}; + use crate::{ForwardNeighbourhood, HighwayGraph, HighwayNodeIndex, IntermediateGraph}; #[test] fn forward_neighbourhood_test() { // https://www.baeldung.com/wp-content/uploads/2017/01/initial-graph.png - let mut graph = HighwayGraph::default(); + let mut graph = IntermediateGraph::default(); let nodes = [ graph.add_node(0), @@ -133,6 +133,8 @@ mod tests { graph.add_edge(nodes[3], nodes[5], 10.0); // D => F graph.add_edge(nodes[5], nodes[4], 10.0); // F => E + let graph = HighwayGraph::from(graph); + let forward = ForwardNeighbourhood::from_network(3, &graph); let radius = &forward.radius; diff --git a/network/src/super_graph.rs b/network/src/super_graph.rs index 7c251e7..895001c 100644 --- a/network/src/super_graph.rs +++ b/network/src/super_graph.rs @@ -1,7 +1,7 @@ use std::{iter::Enumerate, marker::PhantomData, ops::Range, slice}; use petgraph::{ - stable_graph::{DefaultIx, EdgeIndex, IndexType, NodeIndex}, + stable_graph::{DefaultIx, EdgeIndex, IndexType, NodeIndex, StableDiGraph}, visit::{self, EdgeRef, IntoNeighborsDirected}, Directed, Direction::{self, Incoming, Outgoing}, @@ -390,3 +390,17 @@ impl<'a, E, Ix: IndexType> Iterator for EdgeReferences<'a, E, Ix> { self.iter.count() } } + +/// Node indices are not invalidated +impl From> for StableDiGraph { + fn from(value: SuperGraph) -> Self { + todo!() + } +} + +/// Node indices are invalidated +impl From> for SuperGraph { + fn from(value: StableDiGraph) -> Self { + todo!() + } +} diff --git a/network/src/tests.rs b/network/src/tests.rs index 0a81638..a34521d 100644 --- a/network/src/tests.rs +++ b/network/src/tests.rs @@ -1,10 +1,10 @@ use petgraph::stable_graph::StableDiGraph; -use crate::HighwayGraph; +use crate::{HighwayGraph, IntermediateGraph}; // https://www.baeldung.com/wp-content/uploads/2017/01/initial-graph.png pub fn create_ref_network_1() -> HighwayGraph { - let mut graph = HighwayGraph::default(); + let mut graph = IntermediateGraph::default(); let nodes = [ graph.add_node(0), @@ -34,11 +34,11 @@ pub fn create_ref_network_1() -> HighwayGraph { (nodes[5], nodes[3], 1.0), // D <- F ]); - graph + HighwayGraph::from(graph) } pub fn create_undirected_network() -> HighwayGraph { - let mut graph = HighwayGraph::default(); + let mut graph = IntermediateGraph::default(); let nodes = (0..16).map(|x| graph.add_node(x)).collect::>(); graph.add_edge(nodes[0], nodes[1], 3.0); @@ -84,5 +84,5 @@ pub fn create_undirected_network() -> HighwayGraph { graph.add_edge(nodes[14], nodes[11], 14.0); graph.add_edge(nodes[11], nodes[14], 14.0); - graph + HighwayGraph::from(graph) } From 5f382ae6c6960c5c0776757d1610df0004fc46be Mon Sep 17 00:00:00 2001 From: BlockCat Date: Thu, 29 Dec 2022 20:48:26 +0100 Subject: [PATCH 12/17] help --- .gitignore | 2 + bevy_shapefile/src/lib.rs | 4 +- .../src/generation/intermediate_network.rs | 280 ------------------ highway/src/generation/mod.rs | 42 ++- network/src/lib.rs | 4 +- network/src/super_graph.rs | 123 ++++---- network/src/tests.rs | 2 +- src/nwb.rs | 4 +- src/ui/layers.rs | 3 +- tools/dbf_to_sql/src/main.rs | 4 +- 10 files changed, 108 insertions(+), 360 deletions(-) delete mode 100644 highway/src/generation/intermediate_network.rs diff --git a/.gitignore b/.gitignore index ea8c4bf..ac0e9df 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +database.db +database.db-journal \ No newline at end of file diff --git a/bevy_shapefile/src/lib.rs b/bevy_shapefile/src/lib.rs index f456e06..4d4d239 100644 --- a/bevy_shapefile/src/lib.rs +++ b/bevy_shapefile/src/lib.rs @@ -9,8 +9,8 @@ mod spatial; pub type AABB = rstar::AABB<[f32; 2]>; -// pub const SKIP_TYPES: [&'static str; 7] = ["FP", "BU", "VP", "OVB", "CADO", "RP", "VV"]; -pub const SKIP_TYPES: [&'static str; 0] = []; +pub const SKIP_TYPES: [&'static str; 7] = ["FP", "BU", "VP", "OVB", "CADO", "RP", "VV"]; +// pub const SKIP_TYPES: [&'static str; 0] = []; pub fn from_shapefile>(path: P) -> Result { println!("Start loading file"); diff --git a/highway/src/generation/intermediate_network.rs b/highway/src/generation/intermediate_network.rs deleted file mode 100644 index fc243d4..0000000 --- a/highway/src/generation/intermediate_network.rs +++ /dev/null @@ -1,280 +0,0 @@ -use network::ShortcutState; -use rayon::iter::{FromParallelIterator, ParallelIterator}; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct IntermediateNode(pub NodeId); - -#[derive(Debug, Clone)] -pub struct IntermediateEdge { - data: ShortcutState, - road_id: ShortcutState, - direction: EdgeDirection, - source: NodeId, - target: NodeId, - weight: f32, -} - -impl NodeBuilder for IntermediateNode { - type Data = NodeId; - - fn id(&self) -> u32 { - self.0 .0 - } - - fn data(&self) -> Self::Data { - self.0 - } -} - -impl EdgeBuilder for IntermediateEdge { - type Data = ShortcutState; // Points to road_id - - fn data(&self) -> Self::Data { - self.data.clone() - } - - fn source(&self) -> NodeId { - self.source - } - - fn target(&self) -> NodeId { - self.target - } - - fn weight(&self) -> f32 { - self.weight - } - - fn direction(&self) -> EdgeDirection { - self.direction - } - - fn road_id(&self) -> ShortcutState { - self.road_id.clone() - } -} - -impl IntermediateEdge { - pub fn new( - source: NodeId, - target: NodeId, - weight: f32, - data: ShortcutState, - road_id: ShortcutState, - direction: EdgeDirection, - ) -> Self { - Self { - source, - target, - weight, - data, - direction, - road_id, - } - } -} - -#[derive(Debug, Default)] -pub(crate) struct IntermediateNetwork { - out_edges: HashMap>, - in_edges: HashMap>, -} - -impl IntermediateNetwork { - pub fn nodes(&self) -> Vec { - self.out_edges.keys().cloned().collect::>() - } - pub fn out_edges(&self, node: NodeId) -> Option<&HashMap> { - self.out_edges.get(&node) - } - - pub fn in_edges(&self, node: NodeId) -> Option<&HashMap> { - self.in_edges.get(&node) - } -} -impl IntermediateNetwork { - pub fn add_edge(&mut self, edge: IntermediateEdge) { - let source = edge.source; - let target = edge.target; - self.out_edges - .entry(source) - .or_default() - .insert(target, edge.clone()); - - self.in_edges - .entry(target) - .or_default() - .insert(source, edge); - } - - pub fn remove_node(&mut self, node: NodeId) { - if let Some(outs) = self.out_edges.get(&node) { - for edge in outs.values() { - self.in_edges.entry(edge.target).and_modify(|x| { - x.remove(&node); - }); - } - } - - if let Some(ins) = self.in_edges.get(&node) { - for edge in ins.values() { - self.out_edges.entry(edge.source).and_modify(|x| { - x.remove(&node); - }); - } - } - - self.out_edges.remove(&node); - self.in_edges.remove(&node); - } - - pub fn bypass(&mut self, node: NodeId) -> Vec { - let parents = if let Some(parents) = self.in_edges(node) { - parents - } else { - self.remove_node(node); - return vec![]; - }; - let children = if let Some(children) = self.out_edges(node) { - children - } else { - self.remove_node(node); - return vec![]; - }; - - let mut collects = Vec::new(); - - for (parent, parent_edge) in parents { - debug_assert_eq!(parent, &parent_edge.source); - for (child, child_edge) in children { - debug_assert_eq!(child, &child_edge.target); - if parent.0 != child.0 { - let distance = parent_edge.weight + child_edge.weight; - let (state, road_ids) = collect_shortcut_data_edges(parent_edge, child_edge); - let shortcut = IntermediateEdge::new( - *parent, - *child, - distance, - ShortcutState::Shortcut(state), - ShortcutState::Shortcut(road_ids), - EdgeDirection::Forward, - ); - - collects.push(shortcut); - } - } - } - - let touched = parents.keys().chain(children.keys()).cloned().collect(); - - self.remove_node(node); - - for shortcut in collects { - self.add_edge(shortcut) - } - - touched - } -} - -fn collect_shortcut_data_edges( - parent_edge: &IntermediateEdge, - child_edge: &IntermediateEdge, -) -> (Vec, Vec) { - let mut edge_id_a = Vec::from(parent_edge.data.clone()); - let mut road_id_a = Vec::from(parent_edge.road_id.clone()); - - edge_id_a.extend(Vec::from(child_edge.data.clone())); - road_id_a.extend(Vec::from(child_edge.road_id.clone())); - - (edge_id_a, road_id_a) -} - -impl FromIterator for IntermediateNetwork { - fn from_iter>(iter: T) -> Self { - let mut intermediate = IntermediateNetwork::default(); - for edge in iter.into_iter() { - intermediate.add_edge(edge); - } - - intermediate - } -} - -impl FromParallelIterator for IntermediateNetwork { - fn from_par_iter(par_iter: I) -> Self - where - I: rayon::iter::IntoParallelIterator, - { - let mut intermediate = IntermediateNetwork::default(); - let edges = par_iter.into_par_iter().collect::>(); - println!("Collected"); - for edge in edges { - intermediate.add_edge(edge); - } - - intermediate - } -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct IntermediateData { - references: HashMap, - shortcuts: HashMap>, - road_ids: HashMap>, -} - -impl NetworkData for IntermediateData { - type NodeData = NodeId; - type EdgeData = ShortcutState; - - fn node_data(&self, node: NodeId) -> &Self::NodeData { - &self.references[&node] - } - - fn edge_data(&self, edge: EdgeId) -> &Self::EdgeData { - &self.shortcuts[&edge] - } - - fn with_size(node_size: usize, edge_size: usize) -> Self { - Self { - references: HashMap::with_capacity(node_size), - shortcuts: HashMap::with_capacity(edge_size), - road_ids: HashMap::with_capacity(edge_size), - } - } - - fn add_node(&mut self, _: NodeId, _: Self::NodeData) {} - - fn add_edge(&mut self, edge: EdgeId, data: Self::EdgeData, road_id: ShortcutState) { - self.shortcuts.insert(edge, data); - self.road_ids.insert(edge, road_id); - } - - fn edge_road_id(&self, edge: EdgeId) -> ShortcutState { - self.road_ids[&edge].clone() - } -} - -impl From for DirectedNetworkGraph { - fn from(val: IntermediateNetwork) -> Self { - let mut builder = DirectedNetworkBuilder::::new(); - - for node in val.nodes() { - for (_, edge) in val.out_edges(node).unwrap() { - let n1 = builder.add_node(IntermediateNode(edge.source)); - let n2 = builder.add_node(IntermediateNode(edge.target)); - - builder.add_edge(IntermediateEdge { - source: n1, - target: n2, - ..edge.clone() - }); - } - } - - builder.build() - } -} diff --git a/highway/src/generation/mod.rs b/highway/src/generation/mod.rs index 23b4e63..c752aba 100644 --- a/highway/src/generation/mod.rs +++ b/highway/src/generation/mod.rs @@ -1,14 +1,14 @@ use network::{ - iterators::Distanceable, BackwardNeighbourhood, ForwardNeighbourhood, HighwayGraph, Shorted, IntermediateGraph, + iterators::Distanceable, BackwardNeighbourhood, ForwardNeighbourhood, HighwayGraph, + IntermediateGraph, Shorted, }; -use rayon::prelude::*; -use std::collections::HashSet; use petgraph::visit::*; +use rayon::prelude::*; +use std::collections::{HashMap, HashSet}; pub mod core; pub mod dag; pub mod dijkstra; -// pub mod intermediate_network; macro_rules! stopwatch { ($x:expr) => {{ @@ -53,7 +53,7 @@ pub fn calculate_layer( ) -> HighwayGraph where N: Send + Sync + Clone, - E: Send + Sync + Distanceable, + E: Send + Sync + Distanceable + Clone, { let phase_1_graph = phase_1(size, network); @@ -63,7 +63,7 @@ where } /// Phase 1: ... ? -pub(crate) fn phase_1( +pub(crate) fn phase_1( size: usize, mut network: HighwayGraph, ) -> IntermediateGraph { @@ -88,11 +88,37 @@ pub(crate) fn phase_1( println!("Got retained edges"); - network.retain_edges(|_, e| edges.contains(&e)); + let mut new_network = IntermediateGraph::default(); + + let mut nodes = edges + .iter() + .flat_map(|e| { + let edge = network.edge_reference(*e); + [ + (edge.source(), &network[edge.source()]), + (edge.target(), &network[edge.target()]), + ] + }) + .collect::>(); + + nodes.dedup_by_key(|x| x.0); + nodes.sort_by_key(|x| x.0); + + for (node, we) in nodes { + let a = new_network.add_node(we.clone()); + assert_eq!(a, node); + } + + for edge in edges { + let edge = network.edge_reference(edge); + new_network.update_edge(edge.source(), edge.target(), edge.weight().clone()); + } + + // network.retain_edges(|_, e| edges.contains(&e)); println!("Finished computing (edges collections)"); - network + new_network } /** diff --git a/network/src/lib.rs b/network/src/lib.rs index abdcb43..90ff101 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -8,13 +8,13 @@ pub mod super_graph; use iterators::Distanceable; use itertools::Itertools; pub use neighbourhood::*; -use petgraph::data::FromElements; + use petgraph::stable_graph::EdgeIndex; use petgraph::stable_graph::IndexType; use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::StableDiGraph; use petgraph::visit::EdgeRef; -use petgraph::visit::IntoEdgeReferences; + use petgraph::visit::IntoEdgesDirected; use petgraph::Direction; use serde::Deserialize; diff --git a/network/src/super_graph.rs b/network/src/super_graph.rs index 895001c..447710e 100644 --- a/network/src/super_graph.rs +++ b/network/src/super_graph.rs @@ -1,16 +1,21 @@ -use std::{iter::Enumerate, marker::PhantomData, ops::Range, slice}; +use std::{ + iter::Enumerate, + marker::PhantomData, + ops::{Index, Range}, + slice, +}; use petgraph::{ stable_graph::{DefaultIx, EdgeIndex, IndexType, NodeIndex, StableDiGraph}, - visit::{self, EdgeRef, IntoNeighborsDirected}, + visit::{self, EdgeRef, IntoEdgesDirected, IntoNeighborsDirected}, Directed, Direction::{self, Incoming, Outgoing}, - IntoWeightedEdge, }; +use serde::{Deserialize, Serialize}; /// The graph's node type -#[derive(Debug, Clone)] -pub struct Node { +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Node { /// Associated node data pub weight: N, /// Next outgoing edge @@ -26,8 +31,8 @@ impl Node { } /// The graph's edge type. -#[derive(Debug, Clone)] -pub struct Edge { +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Edge { /// Associated edge data. pub weight: E, /// Me -> Other @@ -47,13 +52,22 @@ impl Edge { /// Simple graph, /// Nodes point to the first -#[derive(Debug, Clone, Default)] -pub struct SuperGraph { +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SuperGraph { nodes: Vec>, /// per node: Forward|Both|Backward edges: Vec>, } +impl Default for SuperGraph { + fn default() -> Self { + Self { + nodes: Default::default(), + edges: Default::default(), + } + } +} + impl SuperGraph { pub fn with_capacity(nodes: usize, edges: usize) -> Self { Self { @@ -72,6 +86,14 @@ impl SuperGraph { true } + pub fn edge_reference(&self, e: EdgeIndex) -> EdgeReference<'_, E, Ix> { + EdgeReference { + index: e, + node: self.edges[e.index()].node.clone(), + weight: &self.edges[e.index()].weight, + } + } + pub fn node_weight(&self, a: NodeIndex) -> Option<&N> { self.nodes.get(a.index()).map(|n| &n.weight) } @@ -104,41 +126,7 @@ impl SuperGraph { } } -impl SuperGraph { - // pub fn add_node(&mut self, weight: N) -> NodeIndex { - // let index = self.node_count(); - // self.nodes.push(Node { - // weight, - // next: [ - // EdgeIndex::new(self.edge_count()), - // EdgeIndex::new(self.edge_count()), - // EdgeIndex::new(self.edge_count()), - // ], - // }); - // NodeIndex::new(index) - // } - // pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { - // todo!() - // } - - // pub fn extend_with_edges(&mut self, iterable: I) - // where - // I: IntoIterator, - // I::Item: IntoWeightedEdge, - // >::NodeId: Into>, - // N: Default, - // { - // todo!() - // } - - // pub fn remove_node(&mut self, a: NodeIndex) -> Option { - // todo!() - // } - - // pub fn remove_edge(&mut self, e: EdgeIndex) -> Option { - // todo!() - // } -} +impl SuperGraph {} #[derive(Debug, Clone)] pub struct Neighbors<'a, E: 'a, Ix: 'a + IndexType> { @@ -170,18 +158,6 @@ impl visit::GraphBase for SuperGraph { type NodeId = NodeIndex; } -// impl visit::Visitable for SuperGraph { -// type Map = ; - -// fn visit_map(self: &Self) -> Self::Map { -// todo!() -// } - -// fn reset_map(self: &Self,map: &mut Self::Map) { -// todo!() -// } -// } - impl visit::GraphProp for SuperGraph { type EdgeType = Directed; } @@ -228,21 +204,23 @@ impl<'a, N: 'a, E: 'a, Ix: IndexType> visit::IntoEdgeReferences for &'a SuperGra type EdgeReferences = EdgeReferences<'a, E, Ix>; fn edge_references(self) -> Self::EdgeReferences { - (*self).edge_references() + EdgeReferences { + iter: self.edges.iter().enumerate(), + } } } impl<'a, N, E, Ix: IndexType> visit::IntoEdges for &'a SuperGraph { type Edges = Edges<'a, E, Ix>; fn edges(self, a: Self::NodeId) -> Self::Edges { - todo!() + self.edges_directed(a, Direction::Outgoing) } } impl<'a, N, E, Ix: IndexType> visit::IntoEdgesDirected for &'a SuperGraph { type EdgesDirected = Edges<'a, E, Ix>; - fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected { + fn edges_directed(self, _a: Self::NodeId, _dir: Direction) -> Self::EdgesDirected { todo!() } } @@ -251,12 +229,15 @@ impl<'a, N, E: 'a, Ix: IndexType> visit::IntoNodeIdentifiers for &'a SuperGraph< type NodeIdentifiers = NodeIndices; fn node_identifiers(self) -> Self::NodeIdentifiers { - todo!() + NodeIndices { + r: 0..self.nodes.len(), + ty: Default::default(), + } } } #[derive(Debug, Clone)] -pub struct Edges<'a, E: 'a, Ix: 'a> { +pub struct Edges<'a, E: 'a, Ix: 'a + IndexType> { range: Range, edges: &'a [Edge], } @@ -393,14 +374,30 @@ impl<'a, E, Ix: IndexType> Iterator for EdgeReferences<'a, E, Ix> { /// Node indices are not invalidated impl From> for StableDiGraph { - fn from(value: SuperGraph) -> Self { + fn from(_value: SuperGraph) -> Self { todo!() } } /// Node indices are invalidated impl From> for SuperGraph { - fn from(value: StableDiGraph) -> Self { + fn from(_value: StableDiGraph) -> Self { todo!() } } + +impl Index> for SuperGraph { + type Output = E; + + fn index(&self, index: EdgeIndex) -> &Self::Output { + &self.edges[index.index()].weight + } +} + +impl Index> for SuperGraph { + type Output = N; + + fn index(&self, index: NodeIndex) -> &Self::Output { + &self.nodes[index.index()].weight + } +} diff --git a/network/src/tests.rs b/network/src/tests.rs index a34521d..f42c399 100644 --- a/network/src/tests.rs +++ b/network/src/tests.rs @@ -1,4 +1,4 @@ -use petgraph::stable_graph::StableDiGraph; + use crate::{HighwayGraph, IntermediateGraph}; diff --git a/src/nwb.rs b/src/nwb.rs index db98440..7e21b2b 100644 --- a/src/nwb.rs +++ b/src/nwb.rs @@ -1,13 +1,13 @@ use bevy::math::Vec2; use bevy_shapefile::{JunctionId, RoadId, RoadMap}; -use network::{HighwayEdgeIndex, HighwayGraph, HighwayNodeIndex}; +use network::{HighwayEdgeIndex, HighwayGraph, HighwayNodeIndex, IntermediateGraph}; use rusqlite::{ types::{FromSql, FromSqlError}, Connection, }; use std::{collections::HashMap, path::Path}; -pub type NwbGraph = HighwayGraph<(JunctionId, Vec2), RoadId>; +pub type NwbGraph = IntermediateGraph<(JunctionId, Vec2), RoadId>; pub type NwbNodeIndex = HighwayNodeIndex; pub type NwbEdgeIndex = HighwayEdgeIndex; diff --git a/src/ui/layers.rs b/src/ui/layers.rs index 81ca5e2..b19a2f8 100644 --- a/src/ui/layers.rs +++ b/src/ui/layers.rs @@ -128,7 +128,8 @@ fn clicked_preprocess( ) -> PreProcess { println!("Clicked: {layer_count}"); - let base = network.map(|_, n| *n, |_, e| RoadWeight(*e, road_map.road_length(*e))); + let base = + HighwayGraph::from(network.map(|_, n| *n, |_, e| RoadWeight(*e, road_map.road_length(*e)))); let mut layers = Vec::new(); layers.push(load_or_calculate("data/layer_0.graph", || { diff --git a/tools/dbf_to_sql/src/main.rs b/tools/dbf_to_sql/src/main.rs index 43a75cc..75bec0d 100644 --- a/tools/dbf_to_sql/src/main.rs +++ b/tools/dbf_to_sql/src/main.rs @@ -1,8 +1,10 @@ use std::path::Path; -use rusqlite::{named_params, params, Connection, Transaction}; +use rusqlite::{named_params, Connection, Transaction}; use shapefile::dbase::{FieldValue, Record}; +pub const SKIP_TYPES: [&'static str; 7] = ["FP", "BU", "VP", "OVB", "CADO", "RP", "VV"]; + const CREATE_TABLE_SQL: &str = include_str!("create_table.sql"); const INSERT_SQL: &str = include_str!("insert.sql"); From be140425d3f913d941ccb57306bda09c97e76aef Mon Sep 17 00:00:00 2001 From: BlockCat Date: Fri, 30 Dec 2022 17:27:07 +0100 Subject: [PATCH 13/17] ... --- examples/layer.rs | 2 + highway/src/generation/core.rs | 15 +-- highway/src/generation/mod.rs | 64 +++++----- network/src/count_stable_graph.rs | 198 ++++++++++++++++++++++++++++++ network/src/lib.rs | 18 ++- network/src/super_graph.rs | 152 +++++++++++++++++++---- src/nwb.rs | 2 +- src/ui/mod.rs | 2 - src/ui/route.rs | 2 +- 9 files changed, 376 insertions(+), 79 deletions(-) create mode 100644 network/src/count_stable_graph.rs diff --git a/examples/layer.rs b/examples/layer.rs index 6f6c77e..3883312 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -34,6 +34,8 @@ fn main() { }, ); + let network = HighwayGraph::from(network); + println!("Translated network"); let mut layers = vec![calculate_layer(30, network.clone(), 2.0)]; diff --git a/highway/src/generation/core.rs b/highway/src/generation/core.rs index f9821a5..1d36942 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -1,7 +1,7 @@ use network::{iterators::Distanceable, HighwayNodeIndex}; use network::{BypassNode, IntermediateGraph, Shorted}; use petgraph::visit::IntoNodeIdentifiers; -use petgraph::Direction; + use std::{ collections::{HashSet, VecDeque}, hash::Hash, @@ -25,17 +25,13 @@ pub(crate) fn core_network_with_patch( drop(old_network); while let Some(node) = queue.pop_front() { - let out_edges = next_network - .edges_directed(node, Direction::Outgoing) - .count() as f32; - let in_edges = next_network - .edges_directed(node, Direction::Outgoing) - .count() as f32; + let out_edges = next_network.edge_count_out(node) as f32; + let in_edges = next_network.edge_count_in(node) as f32; let short_cuts = out_edges * in_edges; let contraction = (out_edges + in_edges) * contraction_factor; - if short_cuts < contraction { + if short_cuts <= contraction { let touched = next_network.bypass(node); for touched in touched { queue.push_back(touched); @@ -71,8 +67,7 @@ impl HashNodeQueue { } fn push_back(&mut self, value: T) { - if !self.contains(&value) { - self.seen.insert(value); + if self.seen.insert(value) { self.queue.push_back(value); } } diff --git a/highway/src/generation/mod.rs b/highway/src/generation/mod.rs index c752aba..2c7c5c2 100644 --- a/highway/src/generation/mod.rs +++ b/highway/src/generation/mod.rs @@ -4,7 +4,7 @@ use network::{ }; use petgraph::visit::*; use rayon::prelude::*; -use std::collections::{HashMap, HashSet}; +use std::collections::{HashSet}; pub mod core; pub mod dag; @@ -65,9 +65,13 @@ where /// Phase 1: ... ? pub(crate) fn phase_1( size: usize, - mut network: HighwayGraph, + network: HighwayGraph, ) -> IntermediateGraph { - println!("Start computing (forward backward)"); + println!( + "Start computing (forward backward): {}, {}", + network.node_count(), + network.edge_count() + ); let (duration, computed) = stopwatch!(ComputedState::new(size, &network)); @@ -88,33 +92,33 @@ pub(crate) fn phase_1>(); - - nodes.dedup_by_key(|x| x.0); - nodes.sort_by_key(|x| x.0); - - for (node, we) in nodes { - let a = new_network.add_node(we.clone()); - assert_eq!(a, node); - } - - for edge in edges { - let edge = network.edge_reference(edge); - new_network.update_edge(edge.source(), edge.target(), edge.weight().clone()); - } - - // network.retain_edges(|_, e| edges.contains(&e)); + let mut new_network = IntermediateGraph::from(network); + + // let mut nodes = edges + // .iter() + // .flat_map(|e| { + // let edge = network.edge_reference(*e); + // [ + // (edge.source(), &network[edge.source()]), + // (edge.target(), &network[edge.target()]), + // ] + // }) + // .collect::>(); + + // nodes.dedup_by_key(|x| x.0); + // nodes.sort_by_key(|x| x.0); + + // for (node, we) in nodes { + // let a = new_network.add_node(we.clone()); + // assert_eq!(a, node); + // } + + // for edge in edges { + // let edge = network.edge_reference(edge); + // new_network.update_edge(edge.source(), edge.target(), edge.weight().clone()); + // } + + new_network.retain_edges(|_, e| edges.contains(&e)); println!("Finished computing (edges collections)"); diff --git a/network/src/count_stable_graph.rs b/network/src/count_stable_graph.rs new file mode 100644 index 0000000..c249c92 --- /dev/null +++ b/network/src/count_stable_graph.rs @@ -0,0 +1,198 @@ +use petgraph::{ + graph::Frozen, + stable_graph::{ + EdgeIndex, EdgeReference, EdgeReferences, Edges, IndexType, NodeIndex, NodeIndices, + NodeReferences, StableDiGraph, + }, + visit::{self, IntoEdgeReferences, IntoNodeReferences}, + Direction, IntoWeightedEdge, +}; +use serde::{Serialize, Deserialize}; +use std::{ + collections::HashMap, + ops::{Index}, +}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CountStableGraph { + pub graph: StableDiGraph, + out_edge: HashMap, usize>, + in_edge: HashMap, usize>, +} + +impl Default for CountStableGraph { + fn default() -> Self { + Self { + graph: Default::default(), + out_edge: Default::default(), + in_edge: Default::default(), + } + } +} + +impl CountStableGraph { + pub fn edges_directed( + &self, + n: NodeIndex, + dir: Direction, + ) -> Edges { + self.graph.edges_directed(n, dir) + } + + pub fn node_count(&self) -> usize { + self.graph.node_count() + } + pub fn edge_count(&self) -> usize { + self.graph.edge_count() + } + + pub fn edge_count_out(&self, n: NodeIndex) -> usize { + self.out_edge[&n] + } + pub fn edge_count_in(&self, n: NodeIndex) -> usize { + self.in_edge[&n] + } + + pub fn add_node(&mut self, weight: N) -> NodeIndex { + let n = self.graph.add_node(weight); + + self.out_edge.insert(n, 0); + self.in_edge.insert(n, 0); + + n + } + + pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { + let i = self.graph.add_edge(a, b, weight); + *self.out_edge.entry(a).or_default() += 1; + *self.in_edge.entry(b).or_default() += 1; + i + } + + pub fn remove_node(&mut self, a: NodeIndex) -> Option { + let o = self.graph.remove_node(a); + + self.out_edge.remove(&a); + self.in_edge.remove(&a); + + o + } + + pub fn extend_with_edges(&mut self, iterable: I) + where + I: IntoIterator, + I::Item: IntoWeightedEdge, + >::NodeId: Into>, + N: Default, + { + let iter = iterable.into_iter(); + + for elt in iter { + let (source, target, weight) = elt.into_weighted_edge(); + let (source, target) = (source.into(), target.into()); + + self.add_edge(source, target, weight); + } + } + + pub fn map<'a, F, G, N2, E2>(&'a self, node_map: F, edge_map: G) -> CountStableGraph + where + F: FnMut(NodeIndex, &'a N) -> N2, + G: FnMut(EdgeIndex, &'a E) -> E2, + { + let graph = self.graph.map(node_map, edge_map); + + CountStableGraph { + graph, + in_edge: self.in_edge.clone(), + out_edge: self.out_edge.clone(), + } + } + + pub fn retain_edges(&mut self, visit: F) + where + F: FnMut(Frozen>, EdgeIndex) -> bool, + { + self.graph.retain_edges(visit); + + self.out_edge = self + .graph + .node_indices() + .map(|n| (n, self.graph.edges_directed(n, Direction::Outgoing).count())) + .collect(); + self.in_edge = self + .graph + .node_indices() + .map(|n| (n, self.graph.edges_directed(n, Direction::Incoming).count())) + .collect(); + } + + pub fn edge_weights(&self) -> impl Iterator { + self.graph.edge_weights() + } + + pub fn node_references(&self) -> NodeReferences<'_, N, Ix> { + self.graph.node_references() + } + + pub fn edge_references(&self) -> EdgeReferences<'_, E, Ix> { + self.graph.edge_references() + } + + pub fn find_edge(&self, a: NodeIndex, b: NodeIndex) -> Option> { + self.graph.find_edge(a, b) + } +} + +impl<'a, N, E, Ix: IndexType> visit::GraphBase for CountStableGraph { + type EdgeId = EdgeIndex; + type NodeId = NodeIndex; +} + +impl<'a, N, E: 'a, Ix> visit::IntoNodeIdentifiers for &'a CountStableGraph +where + Ix: IndexType, +{ + type NodeIdentifiers = NodeIndices<'a, N, Ix>; + fn node_identifiers(self) -> Self::NodeIdentifiers { + self.graph.node_identifiers() + } +} +impl Index> for CountStableGraph { + type Output = E; + + fn index(&self, index: EdgeIndex) -> &Self::Output { + &self.graph[index] + } +} + +impl Index> for CountStableGraph { + type Output = N; + + fn index(&self, index: NodeIndex) -> &Self::Output { + &self.graph[index] + } +} + +impl visit::Data for CountStableGraph +where + Ix: IndexType, +{ + type NodeWeight = N; + type EdgeWeight = E; +} + +impl<'a, N: 'a, E: 'a, Ix> visit::IntoEdgeReferences for &'a CountStableGraph +where + Ix: IndexType, +{ + type EdgeRef = EdgeReference<'a, E, Ix>; + type EdgeReferences = EdgeReferences<'a, E, Ix>; + + /// Create an iterator over all edges in the graph, in indexed order. + /// + /// Iterator element type is `EdgeReference`. + fn edge_references(self) -> Self::EdgeReferences { + self.graph.edge_references() + } +} diff --git a/network/src/lib.rs b/network/src/lib.rs index 90ff101..1907224 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -4,19 +4,17 @@ pub mod iterators; pub mod neighbourhood; pub mod super_graph; +pub mod count_stable_graph; +use count_stable_graph::CountStableGraph; use iterators::Distanceable; use itertools::Itertools; pub use neighbourhood::*; - use petgraph::stable_graph::EdgeIndex; use petgraph::stable_graph::IndexType; use petgraph::stable_graph::NodeIndex; -use petgraph::stable_graph::StableDiGraph; -use petgraph::visit::EdgeRef; - -use petgraph::visit::IntoEdgesDirected; use petgraph::Direction; +use petgraph::visit::EdgeRef; use serde::Deserialize; use serde::Serialize; use super_graph::SuperGraph; @@ -24,24 +22,24 @@ use super_graph::SuperGraph; #[derive( Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize, )] -pub struct HighwayIndex(usize); +pub struct HighwayIndex(u32); pub type HighwayGraph = SuperGraph; -pub type IntermediateGraph = StableDiGraph; +pub type IntermediateGraph = CountStableGraph; pub type HighwayNodeIndex = NodeIndex; pub type HighwayEdgeIndex = EdgeIndex; unsafe impl IndexType for HighwayIndex { fn new(x: usize) -> Self { - Self(x) + Self(x as u32) } fn index(&self) -> usize { - self.0 + self.0 as usize } fn max() -> Self { - HighwayIndex(usize::MAX) + HighwayIndex(u32::MAX) } } diff --git a/network/src/super_graph.rs b/network/src/super_graph.rs index 447710e..9c7a9ad 100644 --- a/network/src/super_graph.rs +++ b/network/src/super_graph.rs @@ -1,18 +1,24 @@ use std::{ + collections::{HashMap}, iter::Enumerate, marker::PhantomData, ops::{Index, Range}, slice, }; +use itertools::Itertools; use petgraph::{ - stable_graph::{DefaultIx, EdgeIndex, IndexType, NodeIndex, StableDiGraph}, - visit::{self, EdgeRef, IntoEdgesDirected, IntoNeighborsDirected}, + stable_graph::{DefaultIx, EdgeIndex, IndexType, NodeIndex}, + visit::{ + self, EdgeRef, IntoEdgesDirected, IntoNeighborsDirected, IntoNodeIdentifiers, NodeCount, + }, Directed, Direction::{self, Incoming, Outgoing}, }; use serde::{Deserialize, Serialize}; +use crate::count_stable_graph::CountStableGraph; + /// The graph's node type #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Node { @@ -54,9 +60,9 @@ impl Edge { /// Nodes point to the first #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SuperGraph { - nodes: Vec>, + pub(self) nodes: Vec>, /// per node: Forward|Both|Backward - edges: Vec>, + pub(self) edges: Vec>, } impl Default for SuperGraph { @@ -68,6 +74,22 @@ impl Default for SuperGraph { } } +impl Index> for SuperGraph { + type Output = E; + + fn index(&self, index: EdgeIndex) -> &Self::Output { + &self.edges[index.index()].weight + } +} + +impl Index> for SuperGraph { + type Output = N; + + fn index(&self, index: NodeIndex) -> &Self::Output { + &self.nodes[index.index()].weight + } +} + impl SuperGraph { pub fn with_capacity(nodes: usize, edges: usize) -> Self { Self { @@ -101,6 +123,10 @@ impl SuperGraph { self.nodes.get_mut(a.index()).map(|n| &mut n.weight) } + pub fn node_weights(&self) -> impl Iterator { + self.nodes.iter().map(|n| &n.weight) + } + pub fn edge_weight(&self, a: EdgeIndex) -> Option<&E> { self.edges.get(a.index()).map(|e| &e.weight) } @@ -220,8 +246,12 @@ impl<'a, N, E, Ix: IndexType> visit::IntoEdges for &'a SuperGraph { impl<'a, N, E, Ix: IndexType> visit::IntoEdgesDirected for &'a SuperGraph { type EdgesDirected = Edges<'a, E, Ix>; - fn edges_directed(self, _a: Self::NodeId, _dir: Direction) -> Self::EdgesDirected { - todo!() + fn edges_directed(self, a: Self::NodeId, _dir: Direction) -> Self::EdgesDirected { + let node = &self.nodes[a.index()]; + Edges { + range: node.next[0].index()..node.next[2].index(), + edges: &self.edges, + } } } @@ -373,31 +403,103 @@ impl<'a, E, Ix: IndexType> Iterator for EdgeReferences<'a, E, Ix> { } /// Node indices are not invalidated -impl From> for StableDiGraph { - fn from(_value: SuperGraph) -> Self { - todo!() - } -} +impl From> for CountStableGraph { + fn from(value: SuperGraph) -> Self { + let mut graph = Self::default(); -/// Node indices are invalidated -impl From> for SuperGraph { - fn from(_value: StableDiGraph) -> Self { - todo!() - } -} + for weight in &value.nodes { + graph.add_node(weight.weight.clone()); + } -impl Index> for SuperGraph { - type Output = E; + for index in value.node_identifiers() { + for o in value.edges_directed(index, Outgoing) { + debug_assert_eq!(index, o.source()); + graph.add_edge(o.source(), o.target(), o.weight.clone()); + } + } - fn index(&self, index: EdgeIndex) -> &Self::Output { - &self.edges[index.index()].weight + graph } } -impl Index> for SuperGraph { - type Output = N; +/// Node indices are invalidated +impl From> for SuperGraph { + fn from(value: CountStableGraph) -> Self { + let mut graph = Self::default(); + + let nodes = value + .node_identifiers() + .map(|n| { + let node = &value[n]; + let out_edges_map = value + .edges_directed(n, Outgoing) + .map(|e| (e.id(), e)) + .collect::>(); + + let in_edges_map = value + .edges_directed(n, Incoming) + .map(|e| (e.id(), e)) + .collect::>(); + + let both_edges = out_edges_map + .iter() + .filter(|(e, _)| in_edges_map.contains_key(*e)) + .map(|x| x.1.clone()) + .collect_vec(); + + let out_edges = out_edges_map + .iter() + .filter(|(e, _)| !in_edges_map.contains_key(e)) + .map(|e| e.1.clone()) + .collect_vec(); + + let in_edges = in_edges_map + .iter() + .filter(|(e, _)| !out_edges_map.contains_key(e)) + .map(|e| e.1.clone()) + .collect_vec(); + + (n, node, out_edges, in_edges, both_edges) + }) + .collect_vec(); + + let old_to_node = nodes + .iter() + .map(|(id, weight, out_edges, in_edges, both_edges)| { + let start_edge = graph.edges.len(); + let mid_edge = start_edge + out_edges.len(); + let end_edge = mid_edge + both_edges.len(); + let old_index = *id; + let new_index = NodeIndex::::new(graph.node_count()); + graph.nodes.push(Node { + weight: (*weight).clone(), + next: [ + EdgeIndex::new(start_edge), + EdgeIndex::new(mid_edge), + EdgeIndex::new(end_edge), + ], + }); + graph.edges.extend(out_edges.iter().map(|e| Edge { + weight: e.weight().clone(), + node: [e.source(), e.target()], + })); + graph.edges.extend(both_edges.iter().map(|e| Edge { + weight: e.weight().clone(), + node: [e.source(), e.target()], + })); + graph.edges.extend(in_edges.iter().map(|e| Edge { + weight: e.weight().clone(), + node: [e.source(), e.target()], + })); + (old_index, new_index) + }) + .collect::>(); + + for edge in &mut graph.edges { + edge.node[0] = old_to_node[&edge.node[0]]; + edge.node[1] = old_to_node[&edge.node[1]]; + } - fn index(&self, index: NodeIndex) -> &Self::Output { - &self.nodes[index.index()].weight + graph } } diff --git a/src/nwb.rs b/src/nwb.rs index 7e21b2b..aea19b0 100644 --- a/src/nwb.rs +++ b/src/nwb.rs @@ -1,6 +1,6 @@ use bevy::math::Vec2; use bevy_shapefile::{JunctionId, RoadId, RoadMap}; -use network::{HighwayEdgeIndex, HighwayGraph, HighwayNodeIndex, IntermediateGraph}; +use network::{HighwayEdgeIndex, HighwayNodeIndex, IntermediateGraph}; use rusqlite::{ types::{FromSql, FromSqlError}, Connection, diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 6fbc558..841961f 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -6,8 +6,6 @@ use bevy::prelude::*; use bevy_egui::EguiPlugin; use bevy_shapefile::RoadMap; pub use layers::PreProcess; - -use petgraph::visit::IntoNodeReferences; use std::{ collections::HashSet, ops::{Deref, DerefMut}, diff --git a/src/ui/route.rs b/src/ui/route.rs index 57c62a2..14df44c 100644 --- a/src/ui/route.rs +++ b/src/ui/route.rs @@ -83,7 +83,7 @@ where F: Fn(NwbNodeIndex, NwbNodeIndex) -> f32, { let path = algo::astar( - graph, + &graph.graph, source, |finish| finish == target, |e| edge_cost(e.weight()), From 8e3fc8db6780c6b09113a062a62cc4453dce6b6d Mon Sep 17 00:00:00 2001 From: BlockCat Date: Fri, 30 Dec 2022 20:45:49 +0100 Subject: [PATCH 14/17] help --- examples/layer.rs | 2 +- highway/src/generation/core.rs | 40 ++++++++++++++++--- network/src/count_stable_graph.rs | 66 ++++++++++++++++++++++--------- network/src/lib.rs | 57 ++++++++++++++++++-------- network/src/super_graph.rs | 30 +++++++++----- 5 files changed, 143 insertions(+), 52 deletions(-) diff --git a/examples/layer.rs b/examples/layer.rs index 3883312..1afbaf9 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -52,7 +52,7 @@ fn main() { prev_layer.node_count(), prev_layer.edge_count() ); - let next = calculate_layer(30, prev_layer.clone(), 3.0); + let next = calculate_layer(30, prev_layer.clone(), 2.0); write_file(&next, format!("data/{i}.graph")).expect("Could not write"); layers.push(next); diff --git a/highway/src/generation/core.rs b/highway/src/generation/core.rs index 1d36942..21e147f 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -1,6 +1,7 @@ use network::{iterators::Distanceable, HighwayNodeIndex}; use network::{BypassNode, IntermediateGraph, Shorted}; use petgraph::visit::IntoNodeIdentifiers; +use petgraph::Direction::{Incoming, Outgoing}; use std::{ collections::{HashSet, VecDeque}, @@ -24,18 +25,45 @@ pub(crate) fn core_network_with_patch( drop(old_network); + next_network.recount(); + println!("Recounted"); while let Some(node) = queue.pop_front() { - let out_edges = next_network.edge_count_out(node) as f32; - let in_edges = next_network.edge_count_in(node) as f32; + if !next_network.graph.contains_node(node) { + continue; + } + + let out_edges = next_network.edge_count_out(node); + let in_edges = next_network.edge_count_in(node); + + debug_assert_eq!( + next_network.edge_count_out(node), + next_network.edges_directed(node, Outgoing).count() + ); + debug_assert_eq!( + next_network.edge_count_in(node), + next_network.edges_directed(node, Incoming).count() + ); - let short_cuts = out_edges * in_edges; - let contraction = (out_edges + in_edges) * contraction_factor; + let short_cuts = (out_edges * in_edges) as f32; + let contraction = (out_edges + in_edges) as f32 * contraction_factor; + + if queue.queue.len() % 10000 == 0 { + println!( + "Si: {}, n: {}, e: {}, {} < {}", + queue.queue.len(), + next_network.node_count(), + next_network.edge_count(), + out_edges * in_edges, + (out_edges + in_edges) as f32 * contraction_factor, + ); + } if short_cuts <= contraction { - let touched = next_network.bypass(node); - for touched in touched { + for touched in next_network.bypass(node) { queue.push_back(touched); } + } else { + println!("does happen"); } } diff --git a/network/src/count_stable_graph.rs b/network/src/count_stable_graph.rs index c249c92..dc9b4f0 100644 --- a/network/src/count_stable_graph.rs +++ b/network/src/count_stable_graph.rs @@ -1,4 +1,5 @@ use petgraph::{ + data::Build, graph::Frozen, stable_graph::{ EdgeIndex, EdgeReference, EdgeReferences, Edges, IndexType, NodeIndex, NodeIndices, @@ -7,11 +8,10 @@ use petgraph::{ visit::{self, IntoEdgeReferences, IntoNodeReferences}, Direction, IntoWeightedEdge, }; -use serde::{Serialize, Deserialize}; -use std::{ - collections::HashMap, - ops::{Index}, -}; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, ops::Index, slice::SliceIndex}; + +use crate::iterators::Distanceable; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CountStableGraph { @@ -30,6 +30,19 @@ impl Default for CountStableGraph { } } +impl CountStableGraph { + pub fn update_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { + if let Some(ix) = self.find_edge(a, b) { + let ow = self.graph[ix].distance(); + if weight.distance() < ow { + self.graph[ix] = weight; + } + return ix; + } + self.add_edge(a, b, weight) + } +} + impl CountStableGraph { pub fn edges_directed( &self, @@ -62,6 +75,19 @@ impl CountStableGraph { n } + pub fn recount(&mut self) { + self.out_edge = self + .graph + .node_indices() + .map(|n| (n, self.graph.edges_directed(n, Direction::Outgoing).count())) + .collect(); + self.in_edge = self + .graph + .node_indices() + .map(|n| (n, self.graph.edges_directed(n, Direction::Incoming).count())) + .collect(); + } + pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { let i = self.graph.add_edge(a, b, weight); *self.out_edge.entry(a).or_default() += 1; @@ -69,11 +95,22 @@ impl CountStableGraph { i } - pub fn remove_node(&mut self, a: NodeIndex) -> Option { - let o = self.graph.remove_node(a); + pub fn remove_node(&mut self, n: NodeIndex) -> Option { + self.graph + .neighbors_directed(n, Direction::Outgoing) + .for_each(|n| { + *self.in_edge.get_mut(&n).unwrap() -= 1; + }); + + self.graph + .neighbors_directed(n, Direction::Incoming) + .for_each(|n| { + *self.out_edge.get_mut(&n).unwrap() -= 1; + }); + let o = self.graph.remove_node(n); - self.out_edge.remove(&a); - self.in_edge.remove(&a); + self.out_edge.remove(&n); + self.in_edge.remove(&n); o } @@ -115,16 +152,7 @@ impl CountStableGraph { { self.graph.retain_edges(visit); - self.out_edge = self - .graph - .node_indices() - .map(|n| (n, self.graph.edges_directed(n, Direction::Outgoing).count())) - .collect(); - self.in_edge = self - .graph - .node_indices() - .map(|n| (n, self.graph.edges_directed(n, Direction::Incoming).count())) - .collect(); + self.recount(); } pub fn edge_weights(&self) -> impl Iterator { diff --git a/network/src/lib.rs b/network/src/lib.rs index 1907224..eb34837 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -1,10 +1,10 @@ #![feature(map_try_insert)] #![feature(is_sorted)] +pub mod count_stable_graph; pub mod iterators; pub mod neighbourhood; pub mod super_graph; -pub mod count_stable_graph; use count_stable_graph::CountStableGraph; use iterators::Distanceable; @@ -13,8 +13,9 @@ pub use neighbourhood::*; use petgraph::stable_graph::EdgeIndex; use petgraph::stable_graph::IndexType; use petgraph::stable_graph::NodeIndex; -use petgraph::Direction; use petgraph::visit::EdgeRef; +use petgraph::Direction::Incoming; +use petgraph::Direction::Outgoing; use serde::Deserialize; use serde::Serialize; use super_graph::SuperGraph; @@ -53,6 +54,31 @@ pub trait BypassNode { impl BypassNode for IntermediateGraph { fn bypass(&mut self, node: HighwayNodeIndex) -> Vec { + // The node has no receiving edges. Only outgoing. Then remove the node. + + if self.edge_count_out(node) == 0 { + self.remove_node(node); + return self + .edges_directed(node, Incoming) + .map(|x| { + debug_assert_eq!(node, x.target()); + x.source() + }) + .collect(); + } + + // The node has no outgoing edges. Only incoming. Then remove the node. + if self.edge_count_in(node) == 0 { + self.remove_node(node); + return self + .edges_directed(node, Outgoing) + .map(|x| { + debug_assert_eq!(node, x.source()); + x.target() + }) + .collect(); + } + let in_edges = self .edges_directed(node, petgraph::Direction::Incoming) .map(|e| { @@ -62,32 +88,25 @@ impl BypassNode for IntermediateGraph { .collect_vec(); let out_edges = self - .edges_directed(node, petgraph::Direction::Outgoing) + .edges_directed(node, Outgoing) .map(|e| { debug_assert_eq!(e.source(), node); (e.target(), e.weight().clone()) }) .collect_vec(); - // The node has no receiving edges. Only outgoing. Then remove the node. - if self.edges_directed(node, Direction::Outgoing).count() == 0 { - self.remove_node(node); - return vec![]; - } - - // The node has no outgoing edges. Only incoming. Then remove the node. - if self.edges_directed(node, Direction::Incoming).count() == 0 { - self.remove_node(node); - return vec![]; - } + debug_assert_eq!(out_edges.len(), self.edge_count_out(node)); + debug_assert_eq!(in_edges.len(), self.edge_count_in(node)); let mut touched = Vec::new(); for (source, source_shorted) in in_edges { + let mut changed = false; for (target, target_shorted) in &out_edges { if &source == target { continue; } + // Connect source to target. let combined_distance = source_shorted.distance() + target_shorted.distance(); @@ -97,7 +116,7 @@ impl BypassNode for IntermediateGraph { skipped_edges.extend(source_shorted.skipped_edges.clone()); skipped_edges.extend(target_shorted.skipped_edges.clone()); - self.add_edge( + self.update_edge( source, *target, Shorted { @@ -106,10 +125,16 @@ impl BypassNode for IntermediateGraph { }, ); touched.push(*target); + changed = true; + } + + if changed { + touched.push(source); } - touched.push(source); } + self.remove_node(node); + touched } } diff --git a/network/src/super_graph.rs b/network/src/super_graph.rs index 9c7a9ad..7f91ca0 100644 --- a/network/src/super_graph.rs +++ b/network/src/super_graph.rs @@ -1,5 +1,5 @@ use std::{ - collections::{HashMap}, + collections::HashMap, iter::Enumerate, marker::PhantomData, ops::{Index, Range}, @@ -479,17 +479,27 @@ impl From> for Sup EdgeIndex::new(end_edge), ], }); - graph.edges.extend(out_edges.iter().map(|e| Edge { - weight: e.weight().clone(), - node: [e.source(), e.target()], + + graph.edges.extend(out_edges.iter().map(|e| { + debug_assert_eq!(e.source(), *id); + Edge { + weight: e.weight().clone(), + node: [e.source(), e.target()], + } })); - graph.edges.extend(both_edges.iter().map(|e| Edge { - weight: e.weight().clone(), - node: [e.source(), e.target()], + graph.edges.extend(both_edges.iter().map(|e| { + debug_assert_eq!(e.source(), *id); + Edge { + weight: e.weight().clone(), + node: [e.source(), e.target()], + } })); - graph.edges.extend(in_edges.iter().map(|e| Edge { - weight: e.weight().clone(), - node: [e.source(), e.target()], + graph.edges.extend(in_edges.iter().map(|e| { + debug_assert_eq!(e.target(), *id); + Edge { + weight: e.weight().clone(), + node: [e.target(), e.source()], + } })); (old_index, new_index) }) From 006bad332608ef952cbb79360bbe85d97f31cd3b Mon Sep 17 00:00:00 2001 From: BlockCat Date: Fri, 30 Dec 2022 22:27:35 +0100 Subject: [PATCH 15/17] help --- examples/layer.rs | 23 ++++- highway/src/generation/core.rs | 36 ++++---- network/src/count_stable_graph.rs | 27 +++--- network/src/lib.rs | 45 +++++---- network/src/super_graph.rs | 146 ++++++++++++------------------ src/ui/mod.rs | 1 + src/ui/route.rs | 2 +- 7 files changed, 130 insertions(+), 150 deletions(-) diff --git a/examples/layer.rs b/examples/layer.rs index 1afbaf9..7ddde75 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -1,8 +1,9 @@ use bevy_dutch_road_highway_node_network::{nwb::NwbGraph, read_file, write_file}; use bevy_shapefile::{RoadId, RoadMap}; use highway::generation::calculate_layer; -use network::{iterators::Distanceable, HighwayGraph}; +use network::{iterators::Distanceable, HighwayGraph, IntermediateGraph}; +use petgraph::{algo, Graph}; use rayon::join; #[derive(Debug, Clone)] @@ -34,9 +35,29 @@ fn main() { }, ); + println!( + "A- Connected: {} -- {} -- {}", + algo::connected_components(&Graph::from(network.clone())), + network.node_count(), + network.edge_count() + ); + let network = HighwayGraph::from(network); + let back = IntermediateGraph::from(network.clone()); + + println!( + "B- Connected: {} -- {} -- {}", + algo::connected_components(&Graph::from(back.clone())), + network.node_count(), + network.edge_count() + ); + + println!("C - ? {} -- {}", back.node_count(), back.edge_count()); + + println!("Translated network"); + // panic!(); let mut layers = vec![calculate_layer(30, network.clone(), 2.0)]; diff --git a/highway/src/generation/core.rs b/highway/src/generation/core.rs index 21e147f..106f9e4 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -2,6 +2,7 @@ use network::{iterators::Distanceable, HighwayNodeIndex}; use network::{BypassNode, IntermediateGraph, Shorted}; use petgraph::visit::IntoNodeIdentifiers; use petgraph::Direction::{Incoming, Outgoing}; +use petgraph::{algo, Graph}; use std::{ collections::{HashSet, VecDeque}, @@ -23,31 +24,32 @@ pub(crate) fn core_network_with_patch( }, ); - drop(old_network); + // drop(old_network); + + // next_network.recount(); - next_network.recount(); println!("Recounted"); while let Some(node) = queue.pop_front() { - if !next_network.graph.contains_node(node) { + if !next_network.contains_node(node) { continue; } - let out_edges = next_network.edge_count_out(node); - let in_edges = next_network.edge_count_in(node); + let out_edges = next_network.edges_directed(node, Outgoing).count(); + let in_edges = next_network.edges_directed(node, Incoming).count(); - debug_assert_eq!( - next_network.edge_count_out(node), - next_network.edges_directed(node, Outgoing).count() - ); - debug_assert_eq!( - next_network.edge_count_in(node), - next_network.edges_directed(node, Incoming).count() - ); + // debug_assert_eq!( + // next_network.edge_count_out(node), + // next_network.edges_directed(node, Outgoing).count() + // ); + // debug_assert_eq!( + // next_network.edge_count_in(node), + // next_network.edges_directed(node, Incoming).count() + // ); let short_cuts = (out_edges * in_edges) as f32; let contraction = (out_edges + in_edges) as f32 * contraction_factor; - if queue.queue.len() % 10000 == 0 { + if queue.queue.len() % 1000 == 0 { println!( "Si: {}, n: {}, e: {}, {} < {}", queue.queue.len(), @@ -62,8 +64,6 @@ pub(crate) fn core_network_with_patch( for touched in next_network.bypass(node) { queue.push_back(touched); } - } else { - println!("does happen"); } } @@ -84,10 +84,6 @@ impl HashNodeQueue { HashNodeQueue { queue, seen } } - fn contains(&self, value: &T) -> bool { - self.seen.contains(value) - } - fn pop_front(&mut self) -> Option { let value = self.queue.pop_front()?; self.seen.remove(&value); diff --git a/network/src/count_stable_graph.rs b/network/src/count_stable_graph.rs index dc9b4f0..4996e0a 100644 --- a/network/src/count_stable_graph.rs +++ b/network/src/count_stable_graph.rs @@ -1,5 +1,4 @@ use petgraph::{ - data::Build, graph::Frozen, stable_graph::{ EdgeIndex, EdgeReference, EdgeReferences, Edges, IndexType, NodeIndex, NodeIndices, @@ -9,7 +8,7 @@ use petgraph::{ Direction, IntoWeightedEdge, }; use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, ops::Index, slice::SliceIndex}; +use std::{collections::HashMap, ops::Index}; use crate::iterators::Distanceable; @@ -30,18 +29,18 @@ impl Default for CountStableGraph { } } -impl CountStableGraph { - pub fn update_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { - if let Some(ix) = self.find_edge(a, b) { - let ow = self.graph[ix].distance(); - if weight.distance() < ow { - self.graph[ix] = weight; - } - return ix; - } - self.add_edge(a, b, weight) - } -} +// impl CountStableGraph { +// pub fn update_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { +// if let Some(ix) = self.find_edge(a, b) { +// let ow = self.graph[ix].distance(); +// if weight.distance() < ow { +// self.graph[ix] = weight; +// } +// return ix; +// } +// self.add_edge(a, b, weight) +// } +// } impl CountStableGraph { pub fn edges_directed( diff --git a/network/src/lib.rs b/network/src/lib.rs index eb34837..a458b78 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -6,13 +6,13 @@ pub mod iterators; pub mod neighbourhood; pub mod super_graph; -use count_stable_graph::CountStableGraph; use iterators::Distanceable; use itertools::Itertools; pub use neighbourhood::*; use petgraph::stable_graph::EdgeIndex; use petgraph::stable_graph::IndexType; use petgraph::stable_graph::NodeIndex; +use petgraph::stable_graph::StableDiGraph; use petgraph::visit::EdgeRef; use petgraph::Direction::Incoming; use petgraph::Direction::Outgoing; @@ -26,7 +26,7 @@ use super_graph::SuperGraph; pub struct HighwayIndex(u32); pub type HighwayGraph = SuperGraph; -pub type IntermediateGraph = CountStableGraph; +pub type IntermediateGraph = StableDiGraph; pub type HighwayNodeIndex = NodeIndex; pub type HighwayEdgeIndex = EdgeIndex; @@ -56,7 +56,23 @@ impl BypassNode for IntermediateGraph { fn bypass(&mut self, node: HighwayNodeIndex) -> Vec { // The node has no receiving edges. Only outgoing. Then remove the node. - if self.edge_count_out(node) == 0 { + let in_edges = self + .edges_directed(node, petgraph::Direction::Incoming) + .map(|e| { + debug_assert_eq!(e.target(), node); + (e.source(), e.weight().clone()) + }) + .collect_vec(); + + let out_edges = self + .edges_directed(node, Outgoing) + .map(|e| { + debug_assert_eq!(e.source(), node); + (e.target(), e.weight().clone()) + }) + .collect_vec(); + + if in_edges.len() == 0 { self.remove_node(node); return self .edges_directed(node, Incoming) @@ -68,7 +84,7 @@ impl BypassNode for IntermediateGraph { } // The node has no outgoing edges. Only incoming. Then remove the node. - if self.edge_count_in(node) == 0 { + if out_edges.len() == 0 { self.remove_node(node); return self .edges_directed(node, Outgoing) @@ -79,25 +95,6 @@ impl BypassNode for IntermediateGraph { .collect(); } - let in_edges = self - .edges_directed(node, petgraph::Direction::Incoming) - .map(|e| { - debug_assert_eq!(e.target(), node); - (e.source(), e.weight().clone()) - }) - .collect_vec(); - - let out_edges = self - .edges_directed(node, Outgoing) - .map(|e| { - debug_assert_eq!(e.source(), node); - (e.target(), e.weight().clone()) - }) - .collect_vec(); - - debug_assert_eq!(out_edges.len(), self.edge_count_out(node)); - debug_assert_eq!(in_edges.len(), self.edge_count_in(node)); - let mut touched = Vec::new(); for (source, source_shorted) in in_edges { @@ -116,7 +113,7 @@ impl BypassNode for IntermediateGraph { skipped_edges.extend(source_shorted.skipped_edges.clone()); skipped_edges.extend(target_shorted.skipped_edges.clone()); - self.update_edge( + self.add_edge( source, *target, Shorted { diff --git a/network/src/super_graph.rs b/network/src/super_graph.rs index 7f91ca0..55f9150 100644 --- a/network/src/super_graph.rs +++ b/network/src/super_graph.rs @@ -1,3 +1,11 @@ +use itertools::Itertools; +use petgraph::{ + stable_graph::{DefaultIx, EdgeIndex, IndexType, NodeIndex, StableDiGraph}, + visit::{self, EdgeRef, IntoEdgesDirected, IntoNeighborsDirected, IntoNodeIdentifiers}, + Directed, + Direction::{self, Incoming, Outgoing}, +}; +use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, iter::Enumerate, @@ -6,27 +14,16 @@ use std::{ slice, }; -use itertools::Itertools; -use petgraph::{ - stable_graph::{DefaultIx, EdgeIndex, IndexType, NodeIndex}, - visit::{ - self, EdgeRef, IntoEdgesDirected, IntoNeighborsDirected, IntoNodeIdentifiers, NodeCount, - }, - Directed, - Direction::{self, Incoming, Outgoing}, -}; -use serde::{Deserialize, Serialize}; - -use crate::count_stable_graph::CountStableGraph; +use crate::HighwayNodeIndex; /// The graph's node type #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Node { /// Associated node data pub weight: N, - /// Next outgoing edge - /// Next incoming edge, starts at first bothways edge - /// Final outgoing edge (exclusive) also start of first incoming only edge + /// 1. Next outgoing edge + /// 2. Next incoming edge, starts at first bothways edge + /// 3. Final outgoing edge (exclusive) also start of first incoming only edge pub next: [EdgeIndex; 3], } @@ -46,10 +43,10 @@ pub struct Edge { } impl Edge { - /// Comes from - pub fn source(&self) -> NodeIndex { - self.node[0] - } + // /// Comes from + // pub fn source(&self) -> NodeIndex { + // self.node[0] + // } /// Goes to pub fn target(&self) -> NodeIndex { self.node[1] @@ -103,53 +100,6 @@ impl SuperGraph { pub fn edge_count(&self) -> usize { self.edges.len() } - #[inline] - pub fn is_directed(&self) -> bool { - true - } - - pub fn edge_reference(&self, e: EdgeIndex) -> EdgeReference<'_, E, Ix> { - EdgeReference { - index: e, - node: self.edges[e.index()].node.clone(), - weight: &self.edges[e.index()].weight, - } - } - - pub fn node_weight(&self, a: NodeIndex) -> Option<&N> { - self.nodes.get(a.index()).map(|n| &n.weight) - } - pub fn node_weight_mut(&mut self, a: NodeIndex) -> Option<&mut N> { - self.nodes.get_mut(a.index()).map(|n| &mut n.weight) - } - - pub fn node_weights(&self) -> impl Iterator { - self.nodes.iter().map(|n| &n.weight) - } - - pub fn edge_weight(&self, a: EdgeIndex) -> Option<&E> { - self.edges.get(a.index()).map(|e| &e.weight) - } - pub fn edge_weight_mut(&mut self, a: EdgeIndex) -> Option<&mut E> { - self.edges.get_mut(a.index()).map(|e| &mut e.weight) - } - pub fn edge_endpoints(&self, a: EdgeIndex) -> Option<(NodeIndex, NodeIndex)> { - self.edges.get(a.index()).map(|e| (e.source(), e.target())) - } - - pub fn neighbors_undirected(&self, a: NodeIndex) -> Neighbors { - let node = self.nodes[a.index()].next[0]; - let next_node = self - .nodes - .get(a.index()) - .map(|x| x.next[0]) - .unwrap_or(EdgeIndex::new(self.edges.len())); - - Neighbors { - range: node.index()..next_node.index(), - edges: &self.edges, - } - } } impl SuperGraph {} @@ -403,7 +353,7 @@ impl<'a, E, Ix: IndexType> Iterator for EdgeReferences<'a, E, Ix> { } /// Node indices are not invalidated -impl From> for CountStableGraph { +impl From> for StableDiGraph { fn from(value: SuperGraph) -> Self { let mut graph = Self::default(); @@ -411,6 +361,8 @@ impl From> for CountStab graph.add_node(weight.weight.clone()); } + assert_eq!(value.node_count(), graph.node_count()); + for index in value.node_identifiers() { for o in value.edges_directed(index, Outgoing) { debug_assert_eq!(index, o.source()); @@ -423,22 +375,21 @@ impl From> for CountStab } /// Node indices are invalidated -impl From> for SuperGraph { - fn from(value: CountStableGraph) -> Self { - let mut graph = Self::default(); - - let nodes = value +impl From> for SuperGraph { + fn from(value: StableDiGraph) -> Self { + let mut nodes = value .node_identifiers() .map(|n| { let node = &value[n]; + let out_edges_map = value .edges_directed(n, Outgoing) - .map(|e| (e.id(), e)) + .map(|e| (e.target(), e)) .collect::>(); let in_edges_map = value .edges_directed(n, Incoming) - .map(|e| (e.id(), e)) + .map(|e| (e.source(), e)) .collect::>(); let both_edges = out_edges_map @@ -463,14 +414,23 @@ impl From> for Sup }) .collect_vec(); - let old_to_node = nodes + nodes.sort_by_key(|x| x.0); + + let mut graph = Self::default(); + + let old_to_new_node = nodes .iter() - .map(|(id, weight, out_edges, in_edges, both_edges)| { + .enumerate() + .map(|(new_index, old_index)| (old_index.0, NodeIndex::::new(new_index))) + .collect::>(); + + nodes + .into_iter() + .for_each(|(id, weight, out_edges, in_edges, both_edges)| { let start_edge = graph.edges.len(); let mid_edge = start_edge + out_edges.len(); let end_edge = mid_edge + both_edges.len(); - let old_index = *id; - let new_index = NodeIndex::::new(graph.node_count()); + graph.nodes.push(Node { weight: (*weight).clone(), next: [ @@ -481,33 +441,39 @@ impl From> for Sup }); graph.edges.extend(out_edges.iter().map(|e| { - debug_assert_eq!(e.source(), *id); + debug_assert_eq!(e.source(), id); Edge { weight: e.weight().clone(), - node: [e.source(), e.target()], + node: [old_to_new_node[&e.source()], old_to_new_node[&e.target()]], } })); graph.edges.extend(both_edges.iter().map(|e| { - debug_assert_eq!(e.source(), *id); + debug_assert_eq!(e.source(), id); Edge { weight: e.weight().clone(), - node: [e.source(), e.target()], + node: [old_to_new_node[&e.source()], old_to_new_node[&e.target()]], } })); graph.edges.extend(in_edges.iter().map(|e| { - debug_assert_eq!(e.target(), *id); + debug_assert_eq!(e.target(), id); Edge { weight: e.weight().clone(), - node: [e.target(), e.source()], + node: [old_to_new_node[&e.target()], old_to_new_node[&e.source()]], } })); - (old_index, new_index) - }) - .collect::>(); - for edge in &mut graph.edges { - edge.node[0] = old_to_node[&edge.node[0]]; - edge.node[1] = old_to_node[&edge.node[1]]; + assert_eq!(end_edge + in_edges.len(), graph.edge_count()); + }); + + { + debug_assert!({ + for x in graph.node_identifiers() { + assert!(graph.edges_directed(x, Outgoing).all(|s| s.source() == x)); + assert!(graph.edges_directed(x, Incoming).all(|s| s.source() == x)); + } + true + }); + // println!("remove"); } graph diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 841961f..585d6a7 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -6,6 +6,7 @@ use bevy::prelude::*; use bevy_egui::EguiPlugin; use bevy_shapefile::RoadMap; pub use layers::PreProcess; +use petgraph::visit::IntoNodeReferences; use std::{ collections::HashSet, ops::{Deref, DerefMut}, diff --git a/src/ui/route.rs b/src/ui/route.rs index 14df44c..57c62a2 100644 --- a/src/ui/route.rs +++ b/src/ui/route.rs @@ -83,7 +83,7 @@ where F: Fn(NwbNodeIndex, NwbNodeIndex) -> f32, { let path = algo::astar( - &graph.graph, + graph, source, |finish| finish == target, |e| edge_cost(e.weight()), From 906106a28397defd1c240154a66058e8860da4fd Mon Sep 17 00:00:00 2001 From: BlockCat Date: Fri, 30 Dec 2022 23:46:52 +0100 Subject: [PATCH 16/17] temp to stabledigraph --- examples/layer.rs | 19 --- network/src/count_stable_graph.rs | 225 ------------------------------ network/src/iterators.rs | 6 +- network/src/lib.rs | 3 +- network/src/super_graph.rs | 146 +++++-------------- 5 files changed, 41 insertions(+), 358 deletions(-) delete mode 100644 network/src/count_stable_graph.rs diff --git a/examples/layer.rs b/examples/layer.rs index 7ddde75..01670b9 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -35,26 +35,7 @@ fn main() { }, ); - println!( - "A- Connected: {} -- {} -- {}", - algo::connected_components(&Graph::from(network.clone())), - network.node_count(), - network.edge_count() - ); - let network = HighwayGraph::from(network); - let back = IntermediateGraph::from(network.clone()); - - println!( - "B- Connected: {} -- {} -- {}", - algo::connected_components(&Graph::from(back.clone())), - network.node_count(), - network.edge_count() - ); - - println!("C - ? {} -- {}", back.node_count(), back.edge_count()); - - println!("Translated network"); // panic!(); diff --git a/network/src/count_stable_graph.rs b/network/src/count_stable_graph.rs deleted file mode 100644 index 4996e0a..0000000 --- a/network/src/count_stable_graph.rs +++ /dev/null @@ -1,225 +0,0 @@ -use petgraph::{ - graph::Frozen, - stable_graph::{ - EdgeIndex, EdgeReference, EdgeReferences, Edges, IndexType, NodeIndex, NodeIndices, - NodeReferences, StableDiGraph, - }, - visit::{self, IntoEdgeReferences, IntoNodeReferences}, - Direction, IntoWeightedEdge, -}; -use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, ops::Index}; - -use crate::iterators::Distanceable; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CountStableGraph { - pub graph: StableDiGraph, - out_edge: HashMap, usize>, - in_edge: HashMap, usize>, -} - -impl Default for CountStableGraph { - fn default() -> Self { - Self { - graph: Default::default(), - out_edge: Default::default(), - in_edge: Default::default(), - } - } -} - -// impl CountStableGraph { -// pub fn update_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { -// if let Some(ix) = self.find_edge(a, b) { -// let ow = self.graph[ix].distance(); -// if weight.distance() < ow { -// self.graph[ix] = weight; -// } -// return ix; -// } -// self.add_edge(a, b, weight) -// } -// } - -impl CountStableGraph { - pub fn edges_directed( - &self, - n: NodeIndex, - dir: Direction, - ) -> Edges { - self.graph.edges_directed(n, dir) - } - - pub fn node_count(&self) -> usize { - self.graph.node_count() - } - pub fn edge_count(&self) -> usize { - self.graph.edge_count() - } - - pub fn edge_count_out(&self, n: NodeIndex) -> usize { - self.out_edge[&n] - } - pub fn edge_count_in(&self, n: NodeIndex) -> usize { - self.in_edge[&n] - } - - pub fn add_node(&mut self, weight: N) -> NodeIndex { - let n = self.graph.add_node(weight); - - self.out_edge.insert(n, 0); - self.in_edge.insert(n, 0); - - n - } - - pub fn recount(&mut self) { - self.out_edge = self - .graph - .node_indices() - .map(|n| (n, self.graph.edges_directed(n, Direction::Outgoing).count())) - .collect(); - self.in_edge = self - .graph - .node_indices() - .map(|n| (n, self.graph.edges_directed(n, Direction::Incoming).count())) - .collect(); - } - - pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { - let i = self.graph.add_edge(a, b, weight); - *self.out_edge.entry(a).or_default() += 1; - *self.in_edge.entry(b).or_default() += 1; - i - } - - pub fn remove_node(&mut self, n: NodeIndex) -> Option { - self.graph - .neighbors_directed(n, Direction::Outgoing) - .for_each(|n| { - *self.in_edge.get_mut(&n).unwrap() -= 1; - }); - - self.graph - .neighbors_directed(n, Direction::Incoming) - .for_each(|n| { - *self.out_edge.get_mut(&n).unwrap() -= 1; - }); - let o = self.graph.remove_node(n); - - self.out_edge.remove(&n); - self.in_edge.remove(&n); - - o - } - - pub fn extend_with_edges(&mut self, iterable: I) - where - I: IntoIterator, - I::Item: IntoWeightedEdge, - >::NodeId: Into>, - N: Default, - { - let iter = iterable.into_iter(); - - for elt in iter { - let (source, target, weight) = elt.into_weighted_edge(); - let (source, target) = (source.into(), target.into()); - - self.add_edge(source, target, weight); - } - } - - pub fn map<'a, F, G, N2, E2>(&'a self, node_map: F, edge_map: G) -> CountStableGraph - where - F: FnMut(NodeIndex, &'a N) -> N2, - G: FnMut(EdgeIndex, &'a E) -> E2, - { - let graph = self.graph.map(node_map, edge_map); - - CountStableGraph { - graph, - in_edge: self.in_edge.clone(), - out_edge: self.out_edge.clone(), - } - } - - pub fn retain_edges(&mut self, visit: F) - where - F: FnMut(Frozen>, EdgeIndex) -> bool, - { - self.graph.retain_edges(visit); - - self.recount(); - } - - pub fn edge_weights(&self) -> impl Iterator { - self.graph.edge_weights() - } - - pub fn node_references(&self) -> NodeReferences<'_, N, Ix> { - self.graph.node_references() - } - - pub fn edge_references(&self) -> EdgeReferences<'_, E, Ix> { - self.graph.edge_references() - } - - pub fn find_edge(&self, a: NodeIndex, b: NodeIndex) -> Option> { - self.graph.find_edge(a, b) - } -} - -impl<'a, N, E, Ix: IndexType> visit::GraphBase for CountStableGraph { - type EdgeId = EdgeIndex; - type NodeId = NodeIndex; -} - -impl<'a, N, E: 'a, Ix> visit::IntoNodeIdentifiers for &'a CountStableGraph -where - Ix: IndexType, -{ - type NodeIdentifiers = NodeIndices<'a, N, Ix>; - fn node_identifiers(self) -> Self::NodeIdentifiers { - self.graph.node_identifiers() - } -} -impl Index> for CountStableGraph { - type Output = E; - - fn index(&self, index: EdgeIndex) -> &Self::Output { - &self.graph[index] - } -} - -impl Index> for CountStableGraph { - type Output = N; - - fn index(&self, index: NodeIndex) -> &Self::Output { - &self.graph[index] - } -} - -impl visit::Data for CountStableGraph -where - Ix: IndexType, -{ - type NodeWeight = N; - type EdgeWeight = E; -} - -impl<'a, N: 'a, E: 'a, Ix> visit::IntoEdgeReferences for &'a CountStableGraph -where - Ix: IndexType, -{ - type EdgeRef = EdgeReference<'a, E, Ix>; - type EdgeReferences = EdgeReferences<'a, E, Ix>; - - /// Create an iterator over all edges in the graph, in indexed order. - /// - /// Iterator element type is `EdgeReference`. - fn edge_references(self) -> Self::EdgeReferences { - self.graph.edge_references() - } -} diff --git a/network/src/iterators.rs b/network/src/iterators.rs index b42fe1a..48f8320 100644 --- a/network/src/iterators.rs +++ b/network/src/iterators.rs @@ -1,6 +1,6 @@ use crate::{HighwayGraph, HighwayNodeIndex}; -use petgraph::Direction::Incoming; use petgraph::visit::*; +use petgraph::Direction::Incoming; use petgraph::{visit::EdgeRef, Direction::Outgoing}; use std::collections::{BinaryHeap, HashSet}; @@ -52,6 +52,7 @@ impl DijkstraIterator for HighwayGraph { distance: 0.0, node, }); + ForwardDijkstraIterator { network: self, distance: 0.0, @@ -66,6 +67,7 @@ impl DijkstraIterator for HighwayGraph { distance: 0.0, node, }); + BackwardDijkstraIterator { network: self, distance: 0.0, @@ -101,6 +103,7 @@ where continue; } for edge in self.network.edges_directed(node, Outgoing) { + assert_eq!(edge.source(), node); let target = edge.target(); let edge_distance = edge.weight().distance(); @@ -131,6 +134,7 @@ where continue; } for edge in self.network.edges_directed(node, Incoming) { + assert_eq!(edge.target(), node); let target = edge.source(); let edge_distance = edge.weight().distance(); diff --git a/network/src/lib.rs b/network/src/lib.rs index a458b78..b2f9588 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -1,7 +1,6 @@ #![feature(map_try_insert)] #![feature(is_sorted)] -pub mod count_stable_graph; pub mod iterators; pub mod neighbourhood; pub mod super_graph; @@ -25,7 +24,7 @@ use super_graph::SuperGraph; )] pub struct HighwayIndex(u32); -pub type HighwayGraph = SuperGraph; +pub type HighwayGraph = StableDiGraph; pub type IntermediateGraph = StableDiGraph; pub type HighwayNodeIndex = NodeIndex; pub type HighwayEdgeIndex = EdgeIndex; diff --git a/network/src/super_graph.rs b/network/src/super_graph.rs index 55f9150..3d8b978 100644 --- a/network/src/super_graph.rs +++ b/network/src/super_graph.rs @@ -14,8 +14,6 @@ use std::{ slice, }; -use crate::HighwayNodeIndex; - /// The graph's node type #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Node { @@ -27,12 +25,6 @@ pub struct Node { pub next: [EdgeIndex; 3], } -impl Node { - pub fn next_edge(&self, dir: Direction) -> EdgeIndex { - self.next[dir.index()] - } -} - /// The graph's edge type. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Edge { @@ -42,17 +34,6 @@ pub struct Edge { node: [NodeIndex; 2], } -impl Edge { - // /// Comes from - // pub fn source(&self) -> NodeIndex { - // self.node[0] - // } - /// Goes to - pub fn target(&self) -> NodeIndex { - self.node[1] - } -} - /// Simple graph, /// Nodes point to the first #[derive(Debug, Clone, Serialize, Deserialize)] @@ -108,13 +89,14 @@ impl SuperGraph {} pub struct Neighbors<'a, E: 'a, Ix: 'a + IndexType> { range: Range, edges: &'a [Edge], + node: usize, } impl<'a, E, Ix: IndexType> Iterator for Neighbors<'a, E, Ix> { type Item = NodeIndex; fn next(&mut self) -> Option { - self.range.next().map(|i| self.edges[i].target()) + self.range.next().map(|i| self.edges[i].node[self.node]) } fn size_hint(&self) -> (usize, Option) { @@ -168,9 +150,15 @@ impl<'a, N, E, Ix: IndexType> visit::IntoNeighborsDirected for &'a SuperGraph 1, + Incoming => 0, + }; + Neighbors { range, edges: &self.edges, + node, } } } @@ -377,103 +365,39 @@ impl From> for StableDiG /// Node indices are invalidated impl From> for SuperGraph { fn from(value: StableDiGraph) -> Self { - let mut nodes = value + let old_to_new_nodes = value .node_identifiers() - .map(|n| { - let node = &value[n]; - - let out_edges_map = value - .edges_directed(n, Outgoing) - .map(|e| (e.target(), e)) - .collect::>(); - - let in_edges_map = value - .edges_directed(n, Incoming) - .map(|e| (e.source(), e)) - .collect::>(); - - let both_edges = out_edges_map - .iter() - .filter(|(e, _)| in_edges_map.contains_key(*e)) - .map(|x| x.1.clone()) - .collect_vec(); - - let out_edges = out_edges_map - .iter() - .filter(|(e, _)| !in_edges_map.contains_key(e)) - .map(|e| e.1.clone()) - .collect_vec(); - - let in_edges = in_edges_map - .iter() - .filter(|(e, _)| !out_edges_map.contains_key(e)) - .map(|e| e.1.clone()) - .collect_vec(); - - (n, node, out_edges, in_edges, both_edges) - }) - .collect_vec(); - - nodes.sort_by_key(|x| x.0); - - let mut graph = Self::default(); - - let old_to_new_node = nodes - .iter() .enumerate() - .map(|(new_index, old_index)| (old_index.0, NodeIndex::::new(new_index))) + .map(|(ni, oid)| (oid, NodeIndex::::new(ni))) .collect::>(); - nodes - .into_iter() - .for_each(|(id, weight, out_edges, in_edges, both_edges)| { - let start_edge = graph.edges.len(); - let mid_edge = start_edge + out_edges.len(); - let end_edge = mid_edge + both_edges.len(); - - graph.nodes.push(Node { - weight: (*weight).clone(), - next: [ - EdgeIndex::new(start_edge), - EdgeIndex::new(mid_edge), - EdgeIndex::new(end_edge), - ], - }); - - graph.edges.extend(out_edges.iter().map(|e| { - debug_assert_eq!(e.source(), id); - Edge { - weight: e.weight().clone(), - node: [old_to_new_node[&e.source()], old_to_new_node[&e.target()]], - } - })); - graph.edges.extend(both_edges.iter().map(|e| { - debug_assert_eq!(e.source(), id); - Edge { - weight: e.weight().clone(), - node: [old_to_new_node[&e.source()], old_to_new_node[&e.target()]], - } - })); - graph.edges.extend(in_edges.iter().map(|e| { - debug_assert_eq!(e.target(), id); - Edge { - weight: e.weight().clone(), - node: [old_to_new_node[&e.target()], old_to_new_node[&e.source()]], - } - })); - - assert_eq!(end_edge + in_edges.len(), graph.edge_count()); + let mut graph = Self::default(); + for node in value.node_identifiers() { + let out_edges = value.edges_directed(node, Outgoing).collect_vec(); + let in_edges = value.edges_directed(node, Incoming).collect_vec(); + + let start_edge = graph.edge_count(); + let mid_edge = start_edge + out_edges.len(); + + graph.nodes.push(Node { + weight: value[node].clone(), + next: [ + EdgeIndex::new(start_edge), + EdgeIndex::new(mid_edge), + EdgeIndex::new(mid_edge), + ], }); - { - debug_assert!({ - for x in graph.node_identifiers() { - assert!(graph.edges_directed(x, Outgoing).all(|s| s.source() == x)); - assert!(graph.edges_directed(x, Incoming).all(|s| s.source() == x)); - } - true - }); - // println!("remove"); + graph.edges.extend(out_edges.into_iter().map(|e| Edge { + weight: e.weight().clone(), + node: [old_to_new_nodes[&e.source()], old_to_new_nodes[&e.target()]], + })); + + assert_eq!(mid_edge, graph.edge_count()); + graph.edges.extend(in_edges.into_iter().map(|e| Edge { + weight: e.weight().clone(), + node: [old_to_new_nodes[&e.source()], old_to_new_nodes[&e.target()]], + })); } graph From 7a2e3cdb0bbaa7e564cd1516b1caca2e2d6fd4e1 Mon Sep 17 00:00:00 2001 From: BlockCat Date: Sat, 31 Dec 2022 15:19:56 +0100 Subject: [PATCH 17/17] ok done --- Cargo.lock | 42 +++++- Cargo.toml | 6 +- examples/layer.rs | 16 ++- highway/Cargo.toml | 2 +- network/Cargo.toml | 2 +- network/src/lib.rs | 4 +- network/src/super_graph.rs | 261 ++++++++++++++++++++++++++++++++++--- src/main.rs | 5 +- src/ui/mod.rs | 12 ++ src/ui/route.rs | 95 ++++++++++---- 10 files changed, 389 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ccd9ff3..555aa51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1585,6 +1585,26 @@ dependencies = [ "byteorder", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "discard" version = "1.0.4" @@ -2944,9 +2964,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "oorandom" @@ -3203,6 +3223,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + [[package]] name = "regex" version = "1.7.0" @@ -3950,11 +3981,14 @@ dependencies = [ [[package]] name = "webbrowser" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0cc7962b5aaa0dfcebaeef0161eec6edf5f4606c12e6777fd7d392f52033a5" +checksum = "aa61ff77f695a94d9c8558e0bb5c362a8fd1f27c74663770fbc633acbafedbb6" dependencies = [ + "core-foundation", + "dirs", "jni 0.20.0", + "log", "ndk-context", "objc", "raw-window-handle 0.5.0", diff --git a/Cargo.toml b/Cargo.toml index d600e56..67d6be0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,17 +8,15 @@ version = "0.1.0" [dependencies] bevy = {version = "0.9", features = ["dynamic"]} bevy_egui = {version = "0.18"} -# bevy_prototype_lyon = "0.7" + bevy_polyline = "0.4.0" bevy_shapefile = {path = "./bevy_shapefile"} highway = {path = "./highway"} bincode = "1.3.3" network = {path = "./network"} -petgraph = {version = "0.6", features = ["serde-1"]} - +petgraph = {version = "0.6.2", features = ["serde-1"]} rusqlite = {version = "0.28.0", features = ["bundled"]} - serde = {version = "1.0.136", features = ["derive"]} zstd = "0.12" diff --git a/examples/layer.rs b/examples/layer.rs index 01670b9..60a2761 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -3,7 +3,11 @@ use bevy_shapefile::{RoadId, RoadMap}; use highway::generation::calculate_layer; use network::{iterators::Distanceable, HighwayGraph, IntermediateGraph}; -use petgraph::{algo, Graph}; +use petgraph::{ + algo, + visit::{EdgeRef, IntoEdgesDirected, IntoNeighborsDirected, IntoNodeIdentifiers}, + Graph, +}; use rayon::join; #[derive(Debug, Clone)] @@ -38,7 +42,15 @@ fn main() { let network = HighwayGraph::from(network); println!("Translated network"); - // panic!(); + + for ni in network.node_identifiers() { + assert!(network + .edges_directed(ni, petgraph::Direction::Outgoing) + .all(|s| s.source() == ni)); + assert!(network + .edges_directed(ni, petgraph::Direction::Incoming) + .all(|s| s.target() == ni)); + } let mut layers = vec![calculate_layer(30, network.clone(), 2.0)]; diff --git a/highway/Cargo.toml b/highway/Cargo.toml index 165c46b..abb31b1 100644 --- a/highway/Cargo.toml +++ b/highway/Cargo.toml @@ -8,6 +8,6 @@ version = "0.1.0" [dependencies] itertools = "*" network = {path = "../network"} -petgraph = {version = "0.6", features = ["serde-1"]} +petgraph = {version = "0.6.2", features = ["serde-1"]} rayon = "1.5.1" serde = {version = "1.0.136", features = ["derive"]} diff --git a/network/Cargo.toml b/network/Cargo.toml index 0b6ef96..2db7b72 100644 --- a/network/Cargo.toml +++ b/network/Cargo.toml @@ -10,4 +10,4 @@ bincode = "1.3.3" itertools = "*" rayon = "1.5.1" serde = {version = "1.0.136", features = ["derive"]} -petgraph = {version = "0.6", features = ["serde-1"]} +petgraph = {version = "0.6.2", features = ["serde-1"]} diff --git a/network/src/lib.rs b/network/src/lib.rs index b2f9588..df8aa2a 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -76,7 +76,7 @@ impl BypassNode for IntermediateGraph { return self .edges_directed(node, Incoming) .map(|x| { - debug_assert_eq!(node, x.target()); + assert_eq!(node, x.target()); x.source() }) .collect(); @@ -88,7 +88,7 @@ impl BypassNode for IntermediateGraph { return self .edges_directed(node, Outgoing) .map(|x| { - debug_assert_eq!(node, x.source()); + assert_eq!(node, x.source()); x.target() }) .collect(); diff --git a/network/src/super_graph.rs b/network/src/super_graph.rs index 3d8b978..642dbc5 100644 --- a/network/src/super_graph.rs +++ b/network/src/super_graph.rs @@ -26,7 +26,7 @@ pub struct Node { } /// The graph's edge type. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Edge { /// Associated edge data. pub weight: E, @@ -150,10 +150,11 @@ impl<'a, N, E, Ix: IndexType> visit::IntoNeighborsDirected for &'a SuperGraph 1, - Incoming => 0, - }; + let node = 1 - dir.index(); + + debug_assert!(self.edges[range.clone()] + .iter() + .all(|s| s.node[dir.index()] == a)); Neighbors { range, @@ -184,10 +185,22 @@ impl<'a, N, E, Ix: IndexType> visit::IntoEdges for &'a SuperGraph { impl<'a, N, E, Ix: IndexType> visit::IntoEdgesDirected for &'a SuperGraph { type EdgesDirected = Edges<'a, E, Ix>; - fn edges_directed(self, a: Self::NodeId, _dir: Direction) -> Self::EdgesDirected { + fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected { let node = &self.nodes[a.index()]; + let range = match dir { + Outgoing => node.next[0].index()..node.next[2].index(), + Incoming => { + node.next[1].index() + ..self + .nodes + .get(a.index() + 1) + .map(|n| n.next[0].index()) + .unwrap_or(self.edge_count()) + } + }; + Edges { - range: node.next[0].index()..node.next[2].index(), + range, edges: &self.edges, } } @@ -373,8 +386,11 @@ impl From> for SuperG let mut graph = Self::default(); for node in value.node_identifiers() { - let out_edges = value.edges_directed(node, Outgoing).collect_vec(); - let in_edges = value.edges_directed(node, Incoming).collect_vec(); + let mut out_edges = value.edges_directed(node, Outgoing).collect_vec(); + let mut in_edges = value.edges_directed(node, Incoming).collect_vec(); + + out_edges.sort_by_key(|e| (e.source(), e.target())); + in_edges.sort_by_key(|e| (e.source(), e.target())); let start_edge = graph.edge_count(); let mid_edge = start_edge + out_edges.len(); @@ -388,18 +404,233 @@ impl From> for SuperG ], }); - graph.edges.extend(out_edges.into_iter().map(|e| Edge { - weight: e.weight().clone(), - node: [old_to_new_nodes[&e.source()], old_to_new_nodes[&e.target()]], + graph.edges.extend(out_edges.into_iter().map(|e| { + assert_eq!(e.source(), node); + Edge { + weight: e.weight().clone(), + node: [old_to_new_nodes[&e.source()], old_to_new_nodes[&e.target()]], + } })); assert_eq!(mid_edge, graph.edge_count()); - graph.edges.extend(in_edges.into_iter().map(|e| Edge { - weight: e.weight().clone(), - node: [old_to_new_nodes[&e.source()], old_to_new_nodes[&e.target()]], + graph.edges.extend(in_edges.into_iter().map(|e| { + assert_eq!(e.target(), node); + Edge { + weight: e.weight().clone(), + node: [old_to_new_nodes[&e.source()], old_to_new_nodes[&e.target()]], + } })); } graph } } + +#[cfg(test)] +mod tests { + use itertools::Itertools; + use petgraph::{ + stable_graph::NodeIndex, + visit::{IntoEdgesDirected, IntoNeighborsDirected}, + }; + + use crate::{super_graph::Edge, HighwayNodeIndex, IntermediateGraph}; + + use super::SuperGraph; + + // https://i.stack.imgur.com/hF3mQ.png + fn create_graph() -> SuperGraph { + let mut graph = IntermediateGraph::default(); + + let node = [ + graph.add_node('A'), // 0, A + graph.add_node('B'), // 1, B + graph.add_node('C'), // 2, C + graph.add_node('D'), // 3, D + graph.add_node('E'), // 4, E + graph.add_node('F'), // 5, F + ]; + + graph.extend_with_edges([ + (node[0], node[4], 0.1), + (node[0], node[5], 0.9), + (node[1], node[0], 0.3), + (node[1], node[3], 0.4), + (node[1], node[2], 0.3), + (node[2], node[4], 0.4), + (node[2], node[3], 0.6), + (node[3], node[4], 1.0), + (node[4], node[5], 0.45), + (node[4], node[0], 0.55), + (node[5], node[3], 1.0), + ]); + + SuperGraph::from(graph) + } + + #[test] + fn test_conversion_nodes() { + let graph = create_graph(); + let gnodes = graph + .nodes + .iter() + .map(|n| { + ( + n.weight, + [n.next[0].index(), n.next[1].index(), n.next[2].index()], + ) + }) + .collect_vec(); + + assert_eq!( + gnodes, + vec![ + ('A', [0, 2, 2]), + ('B', [4, 7, 7]), + ('C', [7, 9, 9]), + ('D', [10, 11, 11]), + ('E', [14, 16, 16]), + ('F', [19, 20, 20]), + ] + ); + assert_eq!(graph.edge_count(), 22); + } + + #[test] + fn test_conversion_edges() { + let graph = create_graph(); + let edges = graph.edges; + + macro_rules! assert_edge { + ($num:expr => ($weight:expr, $s:expr, $t: expr)) => { + assert_eq!( + edges[$num], + Edge { + weight: $weight, + node: [HighwayNodeIndex::new($s), HighwayNodeIndex::new($t)] + } + ); + }; + } + assert_edge!(0 => (0.1, 0, 4)); + assert_edge!(1 => (0.9, 0, 5)); + assert_edge!(2 => (0.3, 1, 0)); + assert_edge!(3 => (0.55, 4, 0)); + assert_edge!(4 => (0.3, 1, 0)); + assert_edge!(5 => (0.3, 1, 2)); + assert_edge!(6 => (0.4, 1, 3)); + assert_edge!(7 => (0.6, 2, 3)); + assert_edge!(8 => (0.4, 2, 4)); + assert_edge!(9 => (0.3, 1, 2)); + assert_edge!(10 => (1.0, 3, 4)); + assert_edge!(11 => (0.4, 1, 3)); + assert_edge!(12 => (0.6, 2, 3)); + assert_edge!(13 => (1.0, 5, 3)); + assert_edge!(14 => (0.55, 4, 0)); + assert_edge!(15 => (0.45, 4, 5)); + assert_edge!(16 => (0.1, 0, 4)); + assert_edge!(17 => (0.4, 2, 4)); + assert_edge!(18 => (1.0, 3, 4)); + assert_edge!(19 => (1.0, 5, 3)); + assert_edge!(20 => (0.9, 0, 5)); + assert_edge!(21 => (0.45, 4, 5)); + + assert_eq!(edges.len(), 22); + } + + #[test] + fn test_neighbor_directed_out() { + let graph = create_graph(); + + macro_rules! test_neighbours { + ($index:expr => [$($e:expr),*]) => { + assert_eq!( + graph + .neighbors_directed(NodeIndex::new($index), petgraph::Direction::Outgoing) + .collect_vec(), + vec![$( + NodeIndex::new($e) + ),*] + ) + }; + } + + test_neighbours!(0 => [4, 5]); + test_neighbours!(1 => [0, 2, 3]); + test_neighbours!(2 => [3, 4]); + test_neighbours!(3 => [4]); + test_neighbours!(4 => [0, 5]); + test_neighbours!(5 => [3]); + } + + #[test] + fn test_edges_directed_out() { + let graph = create_graph(); + + macro_rules! test_edges { + ($index:expr => [$(($a:expr, $b:expr, $c:expr)),*]) => { + assert_eq!(graph + .edges_directed(NodeIndex::new($index), petgraph::Direction::Outgoing) + .map(|x| (*x.weight(), x.node[0], x.node[1])) + .collect_vec(), + vec![$(($a, NodeIndex::new($b), NodeIndex::new($c))),*] + ); + }; + } + + test_edges!(0 => [(0.1, 0, 4), (0.9, 0, 5)]); + test_edges!(1 => [(0.3, 1, 0), (0.3, 1, 2), (0.4, 1, 3)]); + test_edges!(2 => [(0.6, 2, 3), (0.4, 2, 4)]); + test_edges!(3 => [(1.0, 3, 4)]); + test_edges!(4 => [(0.55, 4, 0), (0.45, 4, 5)]); + test_edges!(5 => [(1.0, 5, 3)]); + } + + #[test] + fn test_neighbor_directed_in() { + let graph = create_graph(); + + macro_rules! test_neighbours { + ($index:expr => [$($e:expr),*]) => { + assert_eq!( + graph + .neighbors_directed(NodeIndex::new($index), petgraph::Direction::Incoming) + .collect_vec(), + vec![$( + NodeIndex::new($e) + ),*] + ) + }; + } + + test_neighbours!(0 => [1, 4]); + test_neighbours!(1 => []); + test_neighbours!(2 => [1]); + test_neighbours!(3 => [1,2,5]); + test_neighbours!(4 => [0, 2, 3]); + test_neighbours!(5 => [0, 4]); + } + + #[test] + fn test_edges_directed_in() { + let graph = create_graph(); + + macro_rules! test_edges { + ($index:expr => [$(($a:expr, $b:expr, $c:expr)),*]) => { + assert_eq!(graph + .edges_directed(NodeIndex::new($index), petgraph::Direction::Incoming) + .map(|x| (*x.weight(), x.node[0], x.node[1])) + .collect_vec(), + vec![$(($a, NodeIndex::new($b), NodeIndex::new($c))),*] + ); + }; + } + + test_edges!(0 => [(0.3, 1, 0), (0.55, 4, 0)]); + test_edges!(1 => []); + test_edges!(2 => [(0.3, 1, 2)]); + test_edges!(3 => [(0.4, 1, 3), (0.6, 2, 3), (1.0, 5, 3)]); + test_edges!(4 => [(0.1, 0, 4), (0.4, 2, 4), (1.0, 3, 4)]); + test_edges!(5 => [(0.9, 0, 5), (0.45, 4, 5)]); + } +} diff --git a/src/main.rs b/src/main.rs index 1e870ff..abbfc25 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,10 +3,7 @@ #![feature(test)] extern crate test; -use bevy::{ - prelude::*, - DefaultPlugins, -}; +use bevy::{prelude::*, DefaultPlugins}; use bevy_dutch_road_highway_node_network::{ camera::{CameraConfig, CameraPlugin}, ui::HighwayUiPlugin, diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 585d6a7..d958d56 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -6,6 +6,7 @@ use bevy::prelude::*; use bevy_egui::EguiPlugin; use bevy_shapefile::RoadMap; pub use layers::PreProcess; +use network::HighwayNodeIndex; use petgraph::visit::IntoNodeReferences; use std::{ collections::HashSet, @@ -39,6 +40,8 @@ impl DerefMut for DirectedNetworkGraphContainer { impl Plugin for HighwayUiPlugin { fn build(&self, app: &mut bevy::prelude::App) { app.add_plugin(EguiPlugin) + .add_plugin(route::RouteUIPlugin) + .add_event::() .insert_resource(LayerState { preprocess_layers: 6, neighbourhood_size: 30, @@ -59,6 +62,8 @@ fn point_system( network: Res, road_map: Res, camera_q: Query<(&GlobalTransform, &Camera)>, + mut event_writer: EventWriter, + buttons: Res>, mut query: Query<&mut WorldEntity>, ) { if let Some(window) = windows.get_primary() { @@ -97,7 +102,14 @@ fn point_system( _ => {} } }); + + if buttons.just_released(MouseButton::Left) { + event_writer.send(PointClickedEvent(node_id)); + } } } } } + +#[derive(Debug, Clone)] +pub struct PointClickedEvent(pub HighwayNodeIndex); diff --git a/src/ui/route.rs b/src/ui/route.rs index 57c62a2..eb5541a 100644 --- a/src/ui/route.rs +++ b/src/ui/route.rs @@ -1,65 +1,114 @@ -use std::collections::HashSet; - use super::DirectedNetworkGraphContainer; +use super::PointClickedEvent; use crate::nwb::NwbEdgeIndex; use crate::nwb::NwbGraph; use crate::nwb::NwbNodeIndex; use crate::world::WorldEntity; use crate::world::WorldEntitySelectionType; use bevy::prelude::*; +use bevy::tasks::AsyncComputeTaskPool; +use bevy::tasks::Task; use bevy_egui::egui; use bevy_egui::EguiContext; use bevy_shapefile::RoadId; +use bevy_shapefile::RoadMap; +use futures_lite::future; use petgraph::algo; +use std::collections::HashSet; pub struct RouteUIPlugin; impl Plugin for RouteUIPlugin { fn build(&self, app: &mut App) { - app.insert_resource(RouteState::default()) + app.insert_resource(NodeSelectionState::default()) .add_system(gui_system) + .add_system(waiting_for_task) .add_system(route_draw); } } #[derive(Debug, Default, Resource)] -pub struct RouteState { - find_nodes: bool, - node_1: Option, - node_2: Option, - edges: Option>, +pub enum NodeSelectionState { + #[default] + NoRoute, + FindingNode1, + FindingNode2(NwbNodeIndex), + FindingRoute(Task, String>>), + FoundRoute(Vec), } -pub fn gui_system(mut egui_context: ResMut, mut state: ResMut) { - egui::Window::new("Preprocessing").show(egui_context.ctx_mut(), |ui| { +pub fn gui_system( + graph: Res, + road_map: Res, + mut egui_context: ResMut, + mut state: ResMut, + mut event_reader: EventReader, +) { + + egui::Window::new("Routing").show(egui_context.ctx_mut(), |ui| { ui.label("Routing"); if ui.button("Start route").clicked() { - state.find_nodes = false; - state.node_1 = None; - state.node_2 = None; + *state = NodeSelectionState::FindingNode1; + event_reader.clear(); + } else { + match (state.as_ref(), event_reader.iter().next()) { + (NodeSelectionState::NoRoute, Some(_)) => {} + (NodeSelectionState::FindingNode1, Some(n)) => { + *state = NodeSelectionState::FindingNode2(n.0); + } + (NodeSelectionState::FindingNode2(n0), Some(n)) => { + let source = *n0; + let target = n.0; + let graph = graph.0.clone(); + let distance_map = road_map.clone(); + let pool = AsyncComputeTaskPool::get(); + let task = pool.spawn(async move { + find_route( + source, + target, + &graph, + |e| distance_map.road_length(*e), + |_, _| 0.0, + ) + }); + *state = NodeSelectionState::FindingRoute(task); + } + _ => {} + } } - let n1 = state - .node_1 - .map(|x| format!("Node: {x:?}")) - .unwrap_or("Node: none".into()); - let n2 = state - .node_1 - .map(|x| format!("Node: {x:?}")) - .unwrap_or("Node: none".into()); + let (n1, n2) = match state.as_ref() { + NodeSelectionState::NoRoute => ("No route".to_string(), "".to_string()), + NodeSelectionState::FindingNode1 => ("Finding node 1".to_string(), "".to_string()), + NodeSelectionState::FindingNode2(n1) => (format!("Node: {:?}", n1), "".to_string()), + NodeSelectionState::FindingRoute(_) => ("Searching route".to_string(), "".to_string()), + NodeSelectionState::FoundRoute(_) => ("Found route".to_string(), "".to_string()), + }; ui.label(n1); ui.label(n2); }); } +fn waiting_for_task(mut route_state: ResMut) { + if let NodeSelectionState::FindingRoute(task) = route_state.as_mut() { + if let Some(task) = future::block_on(future::poll_once(task)) { + let state = match task { + Ok(a) => NodeSelectionState::FoundRoute(a), + Err(_) => NodeSelectionState::NoRoute, + }; + *route_state = state + }; + } +} + fn route_draw( - route_state: Res, + route_state: Res, mut query: Query<&mut WorldEntity>, network: Res, ) { - if let Some(route) = &route_state.edges { + if let NodeSelectionState::FoundRoute(route) = route_state.as_ref() { // Collect all roadIds. let l = route.iter().map(|e| network[*e]).collect::>();