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/Cargo.lock b/Cargo.lock index 8888274..555aa51 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 = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "atomic-polyfill" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +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", @@ -413,6 +410,7 @@ dependencies = [ "futures-lite", "highway", "network", + "petgraph", "rayon", "rusqlite", "serde", @@ -589,7 +587,7 @@ dependencies = [ "bevy_utils", "bevy_window", "bevy_winit", - "ndk-glue 0.7.0", + "ndk-glue", ] [[package]] @@ -833,7 +831,7 @@ dependencies = [ "async-channel", "async-executor", "async-task", - "concurrent-queue", + "concurrent-queue 1.2.4", "futures-lite", "once_cell", "wasm-bindgen-futures", @@ -925,7 +923,7 @@ checksum = "16750aae52cd35bd7b60eb61cee883420b250e11b4a290b8d44b2b2941795739" dependencies = [ "ahash 0.7.6", "getrandom", - "hashbrown 0.12.3", + "hashbrown", "instant", "tracing", "uuid", @@ -977,9 +975,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 +990,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 +1022,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 +1054,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 +1072,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 +1087,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 +1108,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 +1150,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 +1182,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 +1193,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 +1240,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 +1250,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 +1335,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 +1412,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 +1430,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 +1441,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 +1467,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 +1524,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 +1534,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 +1548,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", @@ -1527,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" @@ -1567,9 +1645,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 +1718,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 +1737,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 +1764,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 +1822,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 +1840,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 +1874,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 +1886,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 +2025,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 +2059,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 +2079,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 +2095,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 +2120,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" @@ -2116,10 +2157,35 @@ version = "0.1.0" dependencies = [ "itertools", "network", + "petgraph", "rayon", "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 +2194,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 +2235,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 +2293,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 +2342,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 +2377,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 +2426,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 +2461,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 +2516,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 +2531,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 +2554,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 +2590,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 +2655,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" @@ -2645,6 +2709,7 @@ version = "0.1.0" dependencies = [ "bincode", "itertools", + "petgraph", "rayon", "serde", ] @@ -2659,20 +2724,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 +2760,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 +2787,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 +2809,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 +2819,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 +2852,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 +2932,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", @@ -2897,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" @@ -2913,11 +2980,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 +3013,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,37 +3032,39 @@ 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", + "serde", + "serde_derive", ] [[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 +3075,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 +3123,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 +3188,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 +3216,29 @@ 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 = "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.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 +3256,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 +3289,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 +3325,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 +3364,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 +3379,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 +3393,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 +3413,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 +3458,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 +3482,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 +3527,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 +3571,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 +3589,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 +3605,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 +3628,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 +3668,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 +3689,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 +3704,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 +3725,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 +3736,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 +3757,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 +3786,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 = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +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 +3831,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 +3893,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" @@ -3865,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", @@ -3881,9 +4000,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 +4100,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 +4172,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 +4186,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 +4224,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 +4242,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 +4260,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 +4284,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 +4318,7 @@ dependencies = [ "log", "mio", "ndk 0.7.0", - "ndk-glue 0.7.0", + "ndk-glue", "objc", "once_cell", "parking_lot", @@ -4242,9 +4333,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 +4381,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 284590b..67d6be0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,16 +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.2", features = ["serde-1"]} rusqlite = {version = "0.28.0", features = ["bundled"]} - serde = {version = "1.0.136", features = ["derive"]} zstd = "0.12" @@ -27,15 +26,14 @@ 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 [profile.dev.package.bevy] opt-level = 3 +[profile.dev.package.rayon] +opt-level = 3 + [workspace] members = ["bevy_shapefile", "network", "highway", "tools/dbf_to_sql"] diff --git a/README.md b/README.md index 7b35109..d6619f9 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,11 @@ ![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. +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: @@ -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/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/bevy_shapefile/src/lib.rs b/bevy_shapefile/src/lib.rs index 08fc5a0..4d4d239 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 f41da83..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}, @@ -20,14 +20,26 @@ 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, pub road_spatial: rstar::RTree, } -#[derive(Serialize, Deserialize, Debug)] +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, Clone)] pub struct Params; impl RTreeParams for Params { @@ -45,16 +57,14 @@ 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))?; + let roads = shapefile::read_as::(path).map_err(ShapeError::Shape)?; println!("Loading junction data"); let junctions = load_junctions(&roads); @@ -67,7 +77,7 @@ impl RoadMap { let spatial_indeces = roads .iter() .map(|(id, section)| RoadSpatialIndex { - id: RoadId::from(*id), + id: *id, aabb: section.aabb.clone(), }) .collect(); @@ -106,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 @@ -113,11 +132,18 @@ fn load_junctions(roads: &Vec<(GenericPolyline, Record)>) -> HashMap, Record)>) -> HashMap, Record)>, ) -> HashMap { - let roads = roads + roads .into_par_iter() .enumerate() - .map(|(id, (line, _))| { + .filter_map(|(id, (line, record))| { + let weg_type = get_text(&record, "BST_CODE") + .map(|wt| SKIP_TYPES.contains(&&wt.as_ref())) + .unwrap_or(false); + + if weg_type { + return None; + } + assert!(line.parts().len() == 1); let points = line @@ -153,10 +187,10 @@ 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 }) + Some((id, RoadSection { id, points, aabb })) }) - .collect::>(); - roads + .collect::>() } 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/examples/layer.rs b/examples/layer.rs index dc27359..60a2761 100644 --- a/examples/layer.rs +++ b/examples/layer.rs @@ -1,21 +1,61 @@ -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 bevy_shapefile::{RoadId, RoadMap}; use highway::generation::calculate_layer; -use network::{DirectedNetworkGraph, NetworkData}; +use network::{iterators::Distanceable, HighwayGraph, IntermediateGraph}; + +use petgraph::{ + algo, + visit::{EdgeRef, IntoEdgesDirected, IntoNeighborsDirected, IntoNodeIdentifiers}, + Graph, +}; +use rayon::join; + +#[derive(Debug, Clone)] +struct RoadWeight(RoadId, f32); + +impl Distanceable for RoadWeight { + fn distance(&self) -> f32 { + self.1 + } +} fn main() { - let network: DirectedNetworkGraph = - 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: {} ", - network.nodes().len(), - network.edges().len() + network.node_count(), + network.edge_count() ); - let mut layers = vec![calculate_layer(30, &network, 2.0)]; + let network = network.map( + |_, n| *n, + |_, e| { + let distance = road_map.road_length(*e); + RoadWeight(*e, distance) + }, + ); + + let network = HighwayGraph::from(network); + + println!("Translated network"); + + 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)]; if let Some(x) = layers.first() { - write_file(x, format!("data/0.graph")).expect("Could not write"); + write_file(x, "data/0.graph").expect("Could not write"); } for i in 1..7 { @@ -23,16 +63,16 @@ fn main() { println!( "Layer: {} - n: {}, e: {} ", i, - prev_layer.nodes().len(), - prev_layer.edges().len() + prev_layer.node_count(), + prev_layer.edge_count() ); - let next = calculate_layer(30, prev_layer, 3.0); + let next = calculate_layer(30, prev_layer.clone(), 2.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); } - data(0, 1, &network, &layers[0]); + print_data(0, 1, &network, &layers[0]); let mut counter = 0; @@ -41,19 +81,19 @@ fn main() { 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: {} to {}", level_a, level_b); - let nodes_a = a.nodes().len(); - let nodes_b = b.nodes().len(); + println!("From: {level_a} to {level_b}"); + 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..abb31b1 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.2", 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 ba3811d..106f9e4 100644 --- a/highway/src/generation/core.rs +++ b/highway/src/generation/core.rs @@ -1,45 +1,73 @@ -use super::intermediate_network::IntermediateNetwork; -use network::NodeId; +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}, hash::Hash, }; -pub(crate) fn core_network_with_patch( - mut intermediate_network: IntermediateNetwork, +pub(crate) fn core_network_with_patch( + old_network: IntermediateGraph, contraction_factor: f32, -) -> IntermediateNetwork { - let nodes = { - let mut n = intermediate_network.nodes(); - n.sort(); - n - }; +) -> IntermediateGraph { + 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_edges: vec![id], + }, + ); + + // drop(old_network); - let mut queue = HashNodeQueue::::from_vec(&nodes); + // next_network.recount(); + println!("Recounted"); 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(); + if !next_network.contains_node(node) { + continue; + } + + 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() + // ); let short_cuts = (out_edges * in_edges) as f32; - let contraction = (out_edges + in_edges) * contraction_factor; + let contraction = (out_edges + in_edges) as f32 * contraction_factor; + + if queue.queue.len() % 1000 == 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 mut touched = intermediate_network.bypass(node); - touched.sort(); - for touched in touched { + if short_cuts <= contraction { + for touched in next_network.bypass(node) { queue.push_back(touched); } } } - intermediate_network + next_network } #[derive(Debug, Default, Clone)] @@ -49,16 +77,12 @@ struct HashNodeQueue { } 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()); + fn from_iter>(items: I) -> Self { + let queue = VecDeque::from_iter(items); + let seen = HashSet::from_iter(queue.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()?; @@ -67,8 +91,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/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 5220f7b..a74bf51 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, IntoEdgesDirected}; +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); - 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( - 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.into(), + 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,17 @@ fn initialize_heap( parents: HashMap::from([(s0, (None, 0.0))]), }, ); - for (id, edge) in network.out_edges(s0) { - // assert!(s0 != edge.target()); + for edge in network.edges_directed(s0, petgraph::Direction::Outgoing) { + debug_assert_eq!(s0, edge.source()); + debug_assert_ne!(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.into(), + parent_edge_distance: distance, + parent_edge: edge.id(), active: true, }, }); @@ -155,9 +154,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 +170,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 +187,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 deleted file mode 100644 index 96a1a85..0000000 --- a/highway/src/generation/intermediate_network.rs +++ /dev/null @@ -1,283 +0,0 @@ -use network::{ - 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 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.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/highway/src/generation/mod.rs b/highway/src/generation/mod.rs index e88d612..2c7c5c2 100644 --- a/highway/src/generation/mod.rs +++ b/highway/src/generation/mod.rs @@ -1,15 +1,14 @@ -use self::intermediate_network::{IntermediateData, IntermediateNetwork}; -use crate::generation::intermediate_network::IntermediateEdge; use network::{ - BackwardNeighbourhood, DirectedNetworkGraph, ForwardNeighbourhood, NetworkData, ShortcutState, + iterators::Distanceable, BackwardNeighbourhood, ForwardNeighbourhood, HighwayGraph, + IntermediateGraph, Shorted, }; +use petgraph::visit::*; use rayon::prelude::*; -use std::collections::HashSet; +use std::collections::{HashSet}; pub mod core; pub mod dag; pub mod dijkstra; -pub mod intermediate_network; macro_rules! stopwatch { ($x:expr) => {{ @@ -44,64 +43,99 @@ 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); +) -> HighwayGraph +where + N: Send + Sync + Clone, + E: Send + Sync + Distanceable + Clone, +{ + let phase_1_graph = phase_1(size, network); - let intermediate = phase_2(intermediate, contraction_factor); + let phase_2_graph = phase_2(phase_1_graph, contraction_factor); - DirectedNetworkGraph::from(intermediate) + HighwayGraph::from(phase_2_graph) } -pub(crate) fn phase_1( + +/// Phase 1: ... ? +pub(crate) fn phase_1( size: usize, - network: &DirectedNetworkGraph, -) -> IntermediateNetwork { - println!("Start computing (forward backward)"); + network: HighwayGraph, +) -> IntermediateGraph { + println!( + "Start computing (forward backward): {}, {}", + network.node_count(), + network.edge_count() + ); - 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_identifiers() + .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(); + println!("Got retained edges"); + + 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)"); - edges + new_network } /** * Calculate the core network */ -fn phase_2(intermediate: IntermediateNetwork, contraction_factor: f32) -> IntermediateNetwork { +fn phase_2( + intermediate: IntermediateGraph, + contraction_factor: f32, +) -> IntermediateGraph +where + N: Clone, + E: Distanceable, +{ core::core_network_with_patch(intermediate, contraction_factor) } @@ -111,7 +145,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/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 ac1b784..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(); @@ -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 0bae1b5..2db7b72 100644 --- a/network/Cargo.toml +++ b/network/Cargo.toml @@ -7,6 +7,7 @@ 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.2", features = ["serde-1"]} diff --git a/network/src/directed_network/builder.rs b/network/src/directed_network/builder.rs deleted file mode 100644 index a8161c9..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 78ad6ca..0000000 --- a/network/src/directed_network/iterators.rs +++ /dev/null @@ -1,114 +0,0 @@ -use crate::{ - builder::EdgeDirection, DirectedNetworkGraph, EdgeId, NetworkData, NetworkEdge, NodeId, -}; -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)); - } - return 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)); - } - return None; - } -} diff --git a/network/src/directed_network/mod.rs b/network/src/directed_network/mod.rs deleted file mode 100644 index 0efd766..0000000 --- a/network/src/directed_network/mod.rs +++ /dev/null @@ -1,223 +0,0 @@ -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; - -#[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.into() - } - - 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) - } - - - 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 6676fbf..0000000 --- a/network/src/directed_network/node_data.rs +++ /dev/null @@ -1,38 +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/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..48f8320 --- /dev/null +++ b/network/src/iterators.rs @@ -0,0 +1,154 @@ +use crate::{HighwayGraph, HighwayNodeIndex}; +use petgraph::visit::*; +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(&self, node: HighwayNodeIndex) -> ForwardDijkstraIterator<'_, N, E>; + fn backward_iterator(&self, node: HighwayNodeIndex) -> BackwardDijkstraIterator<'_, N, E>; +} + +impl DijkstraIterator for HighwayGraph { + fn forward_iterator(&self, node: HighwayNodeIndex) -> ForwardDijkstraIterator<'_, 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(&self, node: HighwayNodeIndex) -> BackwardDijkstraIterator<'_, 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) { + assert_eq!(edge.source(), node); + 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) { + assert_eq!(edge.target(), node); + 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..df8aa2a 100644 --- a/network/src/lib.rs +++ b/network/src/lib.rs @@ -1,107 +1,149 @@ #![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 mod super_graph; -// pub use highway::intermediate_network; - -// pub use highway::calculate_layer; +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; use serde::Deserialize; use serde::Serialize; +use super_graph::SuperGraph; -#[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) - } -} +#[derive( + Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize, +)] +pub struct HighwayIndex(u32); -impl Deref for NodeId { - type Target = u32; +pub type HighwayGraph = StableDiGraph; +pub type IntermediateGraph = StableDiGraph; +pub type HighwayNodeIndex = NodeIndex; +pub type HighwayEdgeIndex = EdgeIndex; - fn deref(&self) -> &Self::Target { - &self.0 +unsafe impl IndexType for HighwayIndex { + fn new(x: usize) -> Self { + Self(x as u32) } -} - -#[derive(Debug, Clone, Copy, Hash, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)] -pub struct EdgeId(pub u32); -impl From for EdgeId { - fn from(id: usize) -> Self { - Self(id as u32) + fn index(&self) -> usize { + self.0 as usize } -} - -impl From for EdgeId { - fn from(id: u32) -> Self { - Self(id) - } -} - -impl Deref for EdgeId { - type Target = u32; - fn deref(&self) -> &Self::Target { - &(self.0) + fn max() -> Self { + HighwayIndex(u32::MAX) } } -impl From for NodeId { - fn from(id: u32) -> Self { - Self(id) - } -} +#[cfg(test)] +pub(crate) mod tests; -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -pub enum ShortcutState { - Single(T), - Shortcut(Vec), +pub trait BypassNode { + /// Bypass a node, and return nodes that have an edge removed + fn bypass(&mut self, node: HighwayNodeIndex) -> Vec; } -impl From> for Vec { - fn from(s: ShortcutState) -> Self { - match s { - ShortcutState::Single(a) => vec![a], - ShortcutState::Shortcut(a) => a, +impl BypassNode for IntermediateGraph { + fn bypass(&mut self, node: HighwayNodeIndex) -> Vec { + // The node has no receiving edges. Only outgoing. Then remove the node. + + 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) + .map(|x| { + assert_eq!(node, x.target()); + x.source() + }) + .collect(); } - } -} - -#[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(); + // The node has no outgoing edges. Only incoming. Then remove the node. + if out_edges.len() == 0 { + self.remove_node(node); + return self + .edges_directed(node, Outgoing) + .map(|x| { + assert_eq!(node, x.source()); + x.target() + }) + .collect(); + } - for x in $s..=$e { - builder.add_node(x); + 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(); + + 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_edges, + }, + ); + touched.push(*target); + changed = true; + } + + if changed { + touched.push(source); + } } - $({ - let source = builder.add_node($a); - let target = builder.add_node($b); + self.remove_node(node); - builder.add_edge(DefaultEdgeBuilder::forward(source, target, 0, $c)); + touched + } +} - })+ +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Shorted { + pub distance: f32, + /// Points to edges in the previous layer + pub skipped_edges: Vec, +} - builder.build::<()>() +impl Distanceable for Shorted { + fn distance(&self) -> f32 { + self.distance } - }; -} \ No newline at end of file +} diff --git a/network/src/neighbourhood.rs b/network/src/neighbourhood.rs index 69ccc6e..950fb07 100644 --- a/network/src/neighbourhood.rs +++ b/network/src/neighbourhood.rs @@ -1,7 +1,9 @@ -use std::ops::Deref; - -use crate::{DirectedNetworkGraph, NetworkData, NodeId}; +use crate::iterators::{DijkstraIterator, Distanceable}; +use crate::{HighwayGraph, HighwayNodeIndex}; +use petgraph::visit::*; use rayon::prelude::*; +use std::collections::HashMap; +use std::ops::Deref; #[derive(Debug)] pub struct ForwardNeighbourhood(Neighbourhood); @@ -27,50 +29,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_identifiers() + .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_identifiers() + .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 +91,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 +106,48 @@ fn find_backward_neighbourhood_radius( #[cfg(test)] mod tests { - use crate::{create_network, ForwardNeighbourhood}; + use std::collections::HashMap; + + use crate::{ForwardNeighbourhood, HighwayGraph, HighwayNodeIndex, IntermediateGraph}; #[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 = IntermediateGraph::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 graph = HighwayGraph::from(graph); + + 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/super_graph.rs b/network/src/super_graph.rs new file mode 100644 index 0000000..642dbc5 --- /dev/null +++ b/network/src/super_graph.rs @@ -0,0 +1,636 @@ +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, + marker::PhantomData, + ops::{Index, Range}, + slice, +}; + +/// The graph's node type +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Node { + /// Associated node data + pub weight: N, + /// 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], +} + +/// The graph's edge type. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct Edge { + /// Associated edge data. + pub weight: E, + /// Me -> Other + node: [NodeIndex; 2], +} + +/// Simple graph, +/// Nodes point to the first +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SuperGraph { + pub(self) nodes: Vec>, + /// per node: Forward|Both|Backward + pub(self) edges: Vec>, +} + +impl Default for SuperGraph { + fn default() -> Self { + Self { + nodes: Default::default(), + edges: Default::default(), + } + } +} + +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 { + 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() + } +} + +impl SuperGraph {} + +#[derive(Debug, Clone)] +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].node[self.node]) + } + + 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::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()) + } + }; + + let node = 1 - dir.index(); + + debug_assert!(self.edges[range.clone()] + .iter() + .all(|s| s.node[dir.index()] == a)); + + Neighbors { + range, + edges: &self.edges, + node, + } + } +} + +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 { + 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 { + 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 { + 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, + edges: &self.edges, + } + } +} + +impl<'a, N, E: 'a, Ix: IndexType> visit::IntoNodeIdentifiers for &'a SuperGraph { + type NodeIdentifiers = NodeIndices; + + fn node_identifiers(self) -> Self::NodeIdentifiers { + NodeIndices { + r: 0..self.nodes.len(), + ty: Default::default(), + } + } +} + +#[derive(Debug, Clone)] +pub struct Edges<'a, E: 'a, Ix: 'a + IndexType> { + 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() + } +} + +/// Node indices are not invalidated +impl From> for StableDiGraph { + fn from(value: SuperGraph) -> Self { + let mut graph = Self::default(); + + for weight in &value.nodes { + 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()); + graph.add_edge(o.source(), o.target(), o.weight.clone()); + } + } + + graph + } +} + +/// Node indices are invalidated +impl From> for SuperGraph { + fn from(value: StableDiGraph) -> Self { + let old_to_new_nodes = value + .node_identifiers() + .enumerate() + .map(|(ni, oid)| (oid, NodeIndex::::new(ni))) + .collect::>(); + + let mut graph = Self::default(); + for node in value.node_identifiers() { + 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(); + + graph.nodes.push(Node { + weight: value[node].clone(), + next: [ + EdgeIndex::new(start_edge), + EdgeIndex::new(mid_edge), + EdgeIndex::new(mid_edge), + ], + }); + + 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| { + 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/network/src/tests.rs b/network/src/tests.rs index e52ebad..f42c399 100644 --- a/network/src/tests.rs +++ b/network/src/tests.rs @@ -1,110 +1,88 @@ -use crate::{ - builder::EdgeDirection, create_network, DirectedNetworkGraph, NetworkEdge, NetworkNode, -}; -// 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, IntermediateGraph}; - 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 = IntermediateGraph::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, + HighwayGraph::from(graph) +} - 2 => 4; 6.0, - 4 => 2; 6.0, +pub fn create_undirected_network() -> HighwayGraph { + let mut graph = IntermediateGraph::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); + HighwayGraph::from(graph) } 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/main.rs b/src/main.rs index 2c0b13f..abbfc25 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,11 +3,7 @@ #![feature(test)] extern crate test; -use bevy::{ - diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, - prelude::*, - DefaultPlugins, -}; +use bevy::{prelude::*, DefaultPlugins}; use bevy_dutch_road_highway_node_network::{ camera::{CameraConfig, CameraPlugin}, ui::HighwayUiPlugin, @@ -27,7 +23,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 de7d317..aea19b0 100644 --- a/src/nwb.rs +++ b/src/nwb.rs @@ -1,154 +1,24 @@ use bevy::math::Vec2; use bevy_shapefile::{JunctionId, RoadId, RoadMap}; -use network::{ - builder::{DirectedNetworkBuilder, EdgeBuilder, EdgeDirection, NodeBuilder}, - DirectedNetworkGraph, EdgeId, NetworkData, NodeId, ShortcutState, -}; +use network::{HighwayEdgeIndex, HighwayNodeIndex, IntermediateGraph}; use rusqlite::{ types::{FromSql, FromSqlError}, Connection, }; -use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, hash::Hash, path::Path}; - -#[derive(Clone, Debug, Default, Serialize, Deserialize)] -pub struct NWBNetworkData { - pub node_junctions: Vec<(JunctionId, Vec2)>, - edge_id: Vec, // for sql, not nwb road_id -} - -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.clone()) - } - - 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 - } +use std::{collections::HashMap, path::Path}; - 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 type NwbGraph = IntermediateGraph<(JunctionId, Vec2), RoadId>; +pub type NwbNodeIndex = HighwayNodeIndex; +pub type NwbEdgeIndex = HighwayEdgeIndex; -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") + .prepare(include_str!("selection.sql")) .expect("Could not prepare statement") .query_map([], |f| { let id: usize = f.get(0)?; @@ -166,28 +36,64 @@ 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().clone(), - }); - let target = builder.add_node(JunctionNode { - junction_id: road_id_end, - location: section.points.last().unwrap().clone(), - }); + (junction_id, graph.add_node((junction_id, s.location))) + }) + .collect::>(); + + 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 distance = section.points.windows(2).map(|w| w[0].distance(w[1])).sum(); + let source = junction_to_node[&road_id_start]; + let target = junction_to_node[&road_id_end]; - builder.add_edge(RoadEdge { - source, - target, - direction: rij_richting.0, - distance, - sql_id: road_id, - }); + match rij_richting { + RijRichting::Forward => { + graph.add_edge(source, target, road_id); + } + RijRichting::Both => { + graph.add_edge(source, target, road_id); + graph.add_edge(target, source, road_id); + } + RijRichting::Backward => { + graph.add_edge(target, source, road_id); + } + } } + graph +} - builder.build() +#[derive(Debug, Clone, Copy)] +enum RijRichting { + Forward, + Backward, + Both, +} + +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::Forward), + 'T' => Ok(RijRichting::Backward), + 'B' => Ok(RijRichting::Both), + 'O' => Ok(RijRichting::Both), + _ => Err(FromSqlError::InvalidType), + } + } } 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 b6986f6..b19a2f8 100644 --- a/src/ui/layers.rs +++ b/src/ui/layers.rs @@ -1,7 +1,6 @@ -use std::{collections::HashMap, path::Path}; - +use super::DirectedNetworkGraphContainer; use crate::{ - nwb::NWBNetworkData, + nwb::NwbGraph, world::{WorldEntity, WorldEntitySelectionType}, }; use bevy::{ @@ -9,12 +8,11 @@ use bevy::{ tasks::{AsyncComputeTaskPool, Task}, }; use bevy_egui::{egui, EguiContext}; -use bevy_shapefile::RoadId; +use bevy_shapefile::{JunctionId, RoadId, RoadMap}; use futures_lite::future; -use highway::generation::intermediate_network::IntermediateData; -use network::{DirectedNetworkGraph, EdgeId, NetworkData}; - -use super::DirectedNetworkGraphContainer; +use network::{iterators::Distanceable, HighwayGraph, Shorted}; +use petgraph::visit::{EdgeRef, IntoEdgeReferences}; +use std::{collections::HashMap, path::Path}; #[derive(Debug, Default, Resource)] pub struct LayerState { @@ -26,6 +24,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); @@ -33,6 +40,7 @@ pub fn gui_system( mut commands: Commands, mut egui_context: ResMut, mut state: ResMut, + road_map: Res, preprocess: Option>, base_network: Res, ) { @@ -48,9 +56,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; @@ -71,9 +86,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 @@ -105,46 +120,49 @@ pub fn handle_preprocess_task( } fn clicked_preprocess( - base: DirectedNetworkGraph, + network: NwbGraph, + road_map: RoadMap, layer_count: usize, neighbourhood: usize, contraction_factor: f32, ) -> PreProcess { - println!("Clicked: {}", layer_count); + println!("Clicked: {layer_count}"); - let mut layers = Vec::new(); + 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", || { - highway::generation::calculate_layer(neighbourhood, &base, contraction_factor) + highway::generation::calculate_layer(neighbourhood, base.clone(), contraction_factor) })); println!( "Base edges: {}, nodes: {}", - base.edges().len(), - base.nodes().len() + 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_{}.graph", i); + let path = format!("data/layer_{i}.graph"); let next_layer = load_or_calculate(path, || { - highway::generation::calculate_layer(size, network, contraction_factor) + highway::generation::calculate_layer(size, network.clone(), 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 + 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(base, layers) + PreProcess::new(network, layers) } pub fn colouring_system( @@ -160,15 +178,14 @@ 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; - } + { + we.selected = WorldEntitySelectionType::BaseSelected; } } }); @@ -178,57 +195,71 @@ pub fn colouring_system( #[derive(Resource)] pub struct PreProcess { - pub base: DirectedNetworkGraph, - pub layers: Vec>, + pub base: NwbGraph, + pub layers: Vec>, pub road_data_level: HashMap, } impl PreProcess { pub fn new( - base: DirectedNetworkGraph, - layers: Vec>, + nwb_graph: NwbGraph, + layers: Vec>, ) -> Self { - let mut road_data_level = (0..base.edges().len()) - .map(|x| EdgeId::from(x)) - .flat_map(|id| Vec::from(base.data.edge_road_id(id))) - .map(|x| (RoadId::from(x), 0)) + let mut road_data_level = nwb_graph + .edge_weights() + .map(|e| (*e, 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); - } + process_edges(&nwb_graph, &mut road_data_level, &layers); PreProcess { - base, + base: nwb_graph, layers, road_data_level, } } } -fn process_edges( - layer_id: u8, - network: &DirectedNetworkGraph, +/// 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>, ) { - 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; - }); - } + 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); } } } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 6b20e9e..d958d56 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 network::HighwayNodeIndex; +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 @@ -38,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, @@ -58,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() { @@ -73,19 +79,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| { @@ -97,8 +103,13 @@ fn point_system( } }); - return; + 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 e0389fd..eb5541a 100644 --- a/src/ui/route.rs +++ b/src/ui/route.rs @@ -1,142 +1,149 @@ +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 crate::{nwb::NWBNetworkData, world::WorldEntity}; use bevy::prelude::*; +use bevy::tasks::AsyncComputeTaskPool; +use bevy::tasks::Task; use bevy_egui::egui; use bevy_egui::EguiContext; -use network::{iterators::F32, DirectedNetworkGraph, EdgeId, NetworkData, NodeId}; -use std::{ - cmp::Reverse, - collections::{BinaryHeap, HashMap, HashSet}, -}; - -use super::DirectedNetworkGraphContainer; +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(loaded) = &route_state.edges { - let l = loaded - .iter() - .map(|(_, e)| *network.edge_data(*e)) - .collect::>(); + if let NodeSelectionState::FoundRoute(route) = route_state.as_ref() { + // 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); + 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); - - return 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")) } diff --git a/src/world.rs b/src/world.rs index 0a93b7c..a42223c 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,18 +1,13 @@ use crate::{ camera::MainCamera, - nwb::{self}, + nwb::{self, NwbGraph}, 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 +86,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() @@ -137,24 +132,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()); - - // 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()); + println!("Nodes: {}", network.node_count()); + println!("Edges: {}", network.edge_count()); commands.insert_resource(road_map); commands.insert_resource(DirectedNetworkGraphContainer(network)); @@ -167,7 +146,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"); @@ -178,15 +157,12 @@ 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 {:?} 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 @@ -200,10 +176,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(); } } } @@ -285,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() } @@ -296,16 +270,16 @@ 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(), + }); 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() }) diff --git a/tools/dbf_to_sql/database.db b/tools/dbf_to_sql/database.db deleted file mode 100644 index f9ce1bc..0000000 Binary files a/tools/dbf_to_sql/database.db and /dev/null differ 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 17124d4..75bec0d 100644 --- a/tools/dbf_to_sql/src/main.rs +++ b/tools/dbf_to_sql/src/main.rs @@ -1,10 +1,12 @@ use std::path::Path; -use rusqlite::{params, Connection, Transaction}; +use rusqlite::{named_params, Connection, Transaction}; use shapefile::dbase::{FieldValue, Record}; -const CREATE_TABLE_SQL: &'static str = include_str!("create_table.sql"); -const INSERT_SQL: &'static str = include_str!("insert.sql"); +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"); fn main() { let mut connection = Connection::open("database.db").expect("Could not create database"); @@ -21,7 +23,7 @@ fn main() { .transaction() .expect("Could not start transaction"); - execute_transaction("data/01-03-2022/Wegvakken/Wegvakken.shp", &transaction); + execute_transaction("data/01-12-2022/Wegvakken/Wegvakken.shp", &transaction); println!("Start committing"); @@ -41,27 +43,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"); }); } @@ -88,7 +89,7 @@ fn get_float(record: &Record, name: &str) -> Option { let value = record.get(name).unwrap(); if let FieldValue::Numeric(x) = value { - return x.clone(); + return *x; } unreachable!(); }