This commit is contained in:
Tsuki 2024-01-16 21:22:32 +08:00
parent 79189212c2
commit 322461371f
26 changed files with 861 additions and 332 deletions

243
Cargo.lock generated
View File

@ -78,13 +78,13 @@ dependencies = [
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.73" version = "0.1.77"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -149,8 +149,8 @@ dependencies = [
"lazycell", "lazycell",
"log", "log",
"peeking_take_while", "peeking_take_while",
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"regex", "regex",
"rustc-hash", "rustc-hash",
"shlex", "shlex",
@ -208,6 +208,12 @@ version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]] [[package]]
name = "bzip2" name = "bzip2"
version = "0.4.4" version = "0.4.4"
@ -308,6 +314,7 @@ name = "cinrad_g"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait",
"cairo-rs", "cairo-rs",
"epoxy", "epoxy",
"femtovg", "femtovg",
@ -322,11 +329,13 @@ dependencies = [
"glue", "glue",
"gtk4", "gtk4",
"image", "image",
"lazy_static",
"libadwaita", "libadwaita",
"libloading 0.8.0", "libloading 0.8.0",
"ndarray", "ndarray",
"npyz", "npyz",
"num-traits", "num-traits",
"once_cell",
"plotters", "plotters",
"plotters-backend", "plotters-backend",
"proj", "proj",
@ -335,6 +344,7 @@ dependencies = [
"quadtree_rs", "quadtree_rs",
"relm4", "relm4",
"relm4-components", "relm4-components",
"relm4-icons",
"rstar", "rstar",
"shapefile", "shapefile",
"svg", "svg",
@ -941,9 +951,9 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -1075,9 +1085,9 @@ dependencies = [
name = "geo-macros" name = "geo-macros"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -1239,8 +1249,8 @@ dependencies = [
"heck", "heck",
"proc-macro-crate", "proc-macro-crate",
"proc-macro-error", "proc-macro-error",
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 1.0.109", "syn 1.0.109",
] ]
@ -1380,8 +1390,8 @@ dependencies = [
"anyhow", "anyhow",
"proc-macro-crate", "proc-macro-crate",
"proc-macro-error", "proc-macro-error",
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 1.0.109", "syn 1.0.109",
] ]
@ -1404,6 +1414,24 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "gvdb"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7139233c0ecb66f285c47a3c1c02b35c8d52a42ca4c7448d0163e5637bb4bd3"
dependencies = [
"byteorder",
"flate2",
"lazy_static",
"memmap2",
"quick-xml",
"safe-transmute",
"serde",
"serde_json",
"walkdir",
"zvariant",
]
[[package]] [[package]]
name = "half" name = "half"
version = "2.2.1" version = "2.2.1"
@ -1730,6 +1758,15 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memmap2"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.9.0" version = "0.9.0"
@ -1930,9 +1967,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.18.0" version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]] [[package]]
name = "pango" name = "pango"
@ -2055,9 +2092,9 @@ checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190"
dependencies = [ dependencies = [
"pest", "pest",
"pest_meta", "pest_meta",
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -2086,9 +2123,9 @@ version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -2185,8 +2222,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [ dependencies = [
"proc-macro-error-attr", "proc-macro-error-attr",
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 1.0.109", "syn 1.0.109",
"version_check", "version_check",
] ]
@ -2197,8 +2234,8 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"version_check", "version_check",
] ]
@ -2219,9 +2256,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.63" version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -2293,6 +2330,16 @@ dependencies = [
"num", "num",
] ]
[[package]]
name = "quick-xml"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51"
dependencies = [
"memchr",
"serde",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "0.6.13" version = "0.6.13"
@ -2304,11 +2351,11 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.29" version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
] ]
[[package]] [[package]]
@ -2420,15 +2467,25 @@ dependencies = [
"tracker", "tracker",
] ]
[[package]]
name = "relm4-icons"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e28bcc718a587bcfa31b034e0b8f4efe5b70e945b7de9d7d154b45357a0dadc"
dependencies = [
"gtk4",
"gvdb",
]
[[package]] [[package]]
name = "relm4-macros" name = "relm4-macros"
version = "0.6.1" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ad8d946cf33654b1df3e2e7d1c4952a154f008368cdda03a99c1840a6fcab3b" checksum = "8ad8d946cf33654b1df3e2e7d1c4952a154f008368cdda03a99c1840a6fcab3b"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -2500,6 +2557,12 @@ version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "safe-transmute"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98a01dab6acf992653be49205bdd549f32f17cb2803e8eacf1560bf97259aae8"
[[package]] [[package]]
name = "same-file" name = "same-file"
version = "1.0.6" version = "1.0.6"
@ -2542,9 +2605,9 @@ version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -2661,6 +2724,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.7.0" version = "0.7.0"
@ -2702,19 +2771,19 @@ version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.29" version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"unicode-ident", "unicode-ident",
] ]
@ -2781,9 +2850,9 @@ version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -2820,8 +2889,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes",
"num_cpus", "num_cpus",
"pin-project-lite", "pin-project-lite",
"tokio-macros",
]
[[package]]
name = "tokio-macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2 1.0.76",
"quote 1.0.35",
"syn 2.0.48",
] ]
[[package]] [[package]]
@ -2888,9 +2970,9 @@ version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -2917,9 +2999,9 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca029746fbe0efda3298205de77bf759d7fef23ac97902641e0b49a623b0455f" checksum = "ca029746fbe0efda3298205de77bf759d7fef23ac97902641e0b49a623b0455f"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -3053,9 +3135,9 @@ dependencies = [
"bumpalo", "bumpalo",
"log", "log",
"once_cell", "once_cell",
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3065,7 +3147,7 @@ version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
dependencies = [ dependencies = [
"quote 1.0.29", "quote 1.0.35",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
] ]
@ -3075,9 +3157,9 @@ version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.76",
"quote 1.0.29", "quote 1.0.35",
"syn 2.0.29", "syn 2.0.48",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3394,3 +3476,40 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
dependencies = [ dependencies = [
"simd-adler32", "simd-adler32",
] ]
[[package]]
name = "zvariant"
version = "3.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c"
dependencies = [
"byteorder",
"libc",
"serde",
"static_assertions",
"zvariant_derive",
]
[[package]]
name = "zvariant_derive"
version = "3.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd"
dependencies = [
"proc-macro-crate",
"proc-macro2 1.0.76",
"quote 1.0.35",
"syn 1.0.109",
"zvariant_utils",
]
[[package]]
name = "zvariant_utils"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200"
dependencies = [
"proc-macro2 1.0.76",
"quote 1.0.35",
"syn 1.0.109",
]

View File

@ -40,14 +40,17 @@ topojson = "0.5.1"
geojson = "0.24.1" geojson = "0.24.1"
plotters = "0.3.5" plotters = "0.3.5"
plotters-backend = "0.3.5" plotters-backend = "0.3.5"
tokio = "1.35.1" tokio = { version = "1.35.1", features = ["time", "fs", "io-std", "macros", "num_cpus", "bytes", "io-util"] }
async-trait = "0.1.77"
lazy_static = "1.4.0"
once_cell = "1.19.0"
relm4-icons = "0.6.0"
# plotters-cairo = "0.5.0" # plotters-cairo = "0.5.0"
[build-dependencies] [build-dependencies]
glib-build-tools = "0.17.0" glib-build-tools = "0.17.0"
[dependencies.geo-macros] [dependencies.geo-macros]
path = "geo-macros" path = "geo-macros"

178
back.txt
View File

@ -85,3 +85,181 @@
// Npz, // Npz,
// BoundaryNorm::default(), // BoundaryNorm::default(),
// ) // )
// fn resample(
// &self,
// width_rate: f64,
// height_rate: f64,
// filter_len: f64,
// ) -> Result<RadarData2d<T, OwnedRepr<T>>, DataError> {
// let width_rate = width_rate.min(1.0);
// let height_rate = height_rate.min(1.0);
// match self.coord_type {
// CoordType::Polar => Err(DataError::FormatError),
// CoordType::LatLon => {
// let width_filtered: ArrayBase<ndarray::OwnedRepr<T>, Ix2> =
// Self::_resample(&self.data, width_rate, filter_len);
// let result: ArrayBase<OwnedRepr<T>, Ix2> =
// Self::_resample(&width_filtered.t(), height_rate, filter_len)
// .t()
// .to_owned();
// let new_dim1: ArrayBase<OwnedRepr<f64>, Ix1> = Self::_resample(
// &Array2::from_shape_vec((1, self.dim1.len()), self.dim1.to_vec()).unwrap(),
// width_rate,
// filter_len,
// )
// .slice(s![0, ..])
// .to_owned();
// let new_dim2: ArrayBase<OwnedRepr<f64>, Ix1> = Self::_resample(
// &Array2::from_shape_vec((1, self.dim2.len()), self.dim2.to_vec()).unwrap(),
// height_rate,
// filter_len,
// )
// .slice(s![0, ..])
// .to_owned();
// Ok(RadarData2d {
// dim1: new_dim1,
// dim2: new_dim2,
// data: result,
// coord_type: self.coord_type.to_owned(),
// })
// }
// }
// }
// fn _resample<'a, V, R: ndarray::Data<Elem = V>>(
// data: &'a ArrayBase<R, Ix2>,
// rate: f64,
// filter_len: f64,
// ) -> Array2<V>
// where
// V: Num + Clone + AsPrimitive<f64> + FromPrimitive,
// {
// let ori_width = data.ncols();
// let ori_height = data.nrows();
// let new_width = (ori_width as f64 * rate).ceil() as usize;
// let mut result: Array2<V> = Array2::zeros((ori_height, new_width));
// (0..ori_height).into_iter().for_each(|height| {
// for width in 0..new_width {
// let center_x = (width as f64 + 0.5) / new_width as f64 * ori_width as f64;
// let filter_start = center_x - filter_len / 2.0;
// let start_idx = (filter_start - 0.5).ceil() as usize;
// let mut value_sum = 0.0;
// let mut filter_sum = 0.0;
// for i in 0..filter_len as usize {
// let input_x = start_idx + i;
// let weight = windowed_sinc(
// (input_x as f64 + 0.5 - center_x) * rate,
// (input_x as f64 + 0.5 - filter_start) / filter_len,
// );
// value_sum += weight * data[[height, input_x.clamp(0, ori_width - 1)]].as_();
// filter_sum += weight;
// }
// result[[height, width]] = V::from_f64(value_sum / filter_sum).unwrap();
// }
// });
// result
// }
// pub struct LevelData<T: Num + Clone + PartialEq + PartialOrd>(
// pub Quadtree<i64, RadarData2d<T, OwnedRepr<T>>>,
// );
// impl<T> LevelData<T>
// where
// T: Num + Clone + AsPrimitive<f64> + FromPrimitive + Debug + PartialEq + PartialOrd,
// {
// fn value(
// level_data: Vec<RadarData2d<T, OwnedRepr<T>>>,
// level_num: usize,
// ) -> Vec<RadarData2d<T, OwnedRepr<T>>> {
// if level_num == 0 {
// return level_data;
// }
// let mut result: Vec<RadarData2d<T, OwnedRepr<T>>> =
// Vec::with_capacity(level_data.len() * 4);
// let results = level_data
// .iter()
// .flat_map(|v| v.split().into_iter().map(|x| x.value_to_owned()));
// result.extend(results);
// return Self::value(result, level_num - 1);
// }
// fn new(data: &RadarData2d<T, OwnedRepr<T>>, level: usize, rate: f64) -> Self {
// // let rate = 1.0 / level as f64;
// let resampled = data.resample(rate, rate, 2.0).unwrap();
// let blocks = Self::value(vec![resampled], level);
// let mut tree: Quadtree<i64, RadarData2d<T, OwnedRepr<T>>> =
// quadtree_rs::Quadtree::new(level);
// blocks.into_iter().for_each(|block| {
// tree.insert(
// AreaBuilder::default()
// .anchor(quadtree_rs::point::Point {
// x: *block.dim1.first().unwrap() as i64,
// y: *block.dim2.first().unwrap() as i64,
// })
// .dimensions((block.dim1.len() as i64, block.dim2.len() as i64))
// .build()
// .unwrap(),
// block,
// );
// });
// Self(tree)
// }
// }
// pub fn levels<T>(data: Radar2d<T>, levels: usize) -> Vec<LevelData<T>>
// where
// T: Num + Clone + AsPrimitive<f64> + FromPrimitive + Debug,
// T: PartialEq + PartialOrd,
// {
// let numerator = 1.0 / levels as f64;
// (0..levels)
// .into_iter()
// .map(|level| LevelData::new(&data, level + 1, 1.0 - level as f64 * numerator))
// .collect()
// }
#[inline]
fn windowed_sinc(x: f64, y: f64) -> f64 {
let x = x * PI;
let sinc = if x != 0.0 { f64::sin(x) / x } else { 1.0 };
let window = if 0f64 <= y && y <= 1.0 {
1.0 - (y - 0.5).abs() * 2.0
} else {
0f64
};
sinc * window
}
pub enum DownSampleMeth {
STD,
MEAN,
VAR,
}
#[derive(Clone, Copy, Debug)]
pub enum CoordType {
Polar,
LatLon,
}

View File

@ -59,21 +59,6 @@ impl SimpleComponent for AppModel {
gtk::Inhibit(true) gtk::Inhibit(true)
} }
} }
// main_window = gtk::ApplicationWindow {
// set_default_width: 1200,
// set_default_height: 900,
// set_focus_on_click:true,
// set_titlebar: Some(&gtk::HeaderBar::new()),
// gtk::Box{
// set_orientation: gtk::Orientation::Vertical,
// set_valign:gtk::Align::Fill,
// },
// connect_close_request[sender] => move |_| {
// sender.input(AppMsg::CloseRequest);
// gtk::Inhibit(true)
// }
// }
} }
fn init( fn init(

View File

View File

@ -1,4 +1,4 @@
mod render_panel;
mod messages; mod messages;
mod monitor; mod monitor;
mod render_panel;
pub use render_panel::RenderPanelModel; pub use render_panel::RenderPanelModel;

View File

@ -1,4 +1,3 @@
pub mod monitor; pub mod monitor;
pub mod render;
pub mod sidebar; pub mod sidebar;
pub use monitor::MonitorModel; pub use monitor::MonitorModel;

View File

@ -1,11 +1,18 @@
use crate::{ use crate::{
components::render_panel::messages::{MonitorInputMsg, MonitorOutputMsg}, components::render_panel::messages::{MonitorInputMsg, MonitorOutputMsg},
render::{Layer, Render}, data::Npz,
render::{predefined::color_mapper::BoundaryNorm, Layer, Render},
}; };
use std::sync::Arc;
use super::{render::render::RenderModel, sidebar::{sidebar::SideBarModel, SideBarOutputMsg}}; use super::sidebar::{sidebar::SideBarModel, Msg, SideBarOutputMsg};
use adw::prelude::*; use adw::prelude::*;
use relm4::*; use gtk::subclass::root;
use relm4::{
component::{AsyncComponent, AsyncComponentParts},
loading_widgets::LoadingWidgets,
*,
};
pub struct MonitorModel { pub struct MonitorModel {
sidebar_open: bool, sidebar_open: bool,
sidebar_width: i32, sidebar_width: i32,
@ -17,11 +24,12 @@ pub struct MonitorWidgets {
paned: gtk::Paned, paned: gtk::Paned,
} }
#[relm4::component(pub)] #[relm4::component(async, pub)]
impl SimpleComponent for MonitorModel { impl AsyncComponent for MonitorModel {
type Init = (); type Init = ();
type Output = MonitorOutputMsg; type Output = MonitorOutputMsg;
type Input = MonitorInputMsg; type Input = MonitorInputMsg;
type CommandOutput = ();
view! { view! {
adw::BreakpointBin { adw::BreakpointBin {
@ -44,16 +52,18 @@ impl SimpleComponent for MonitorModel {
} }
} }
fn init( async fn init(
init: Self::Init, init: Self::Init,
root: &Self::Root, root: Self::Root,
sender: relm4::ComponentSender<Self>, sender: relm4::AsyncComponentSender<Self>,
) -> relm4::ComponentParts<Self> { ) -> AsyncComponentParts<Self> {
let sidebar: Controller<SideBarModel> = SideBarModel::builder() let sidebar: Controller<SideBarModel> =
.launch(()) SideBarModel::builder()
.forward(sender.input_sender(), |msg| match msg { .launch(())
SideBarOutputMsg::NewLayer(layer) => MonitorInputMsg::AddLayer(layer), .forward(sender.input_sender(), |msg| match msg {
}); SideBarOutputMsg::NewLayer(layer) => MonitorInputMsg::AddLayer(layer),
_ => MonitorInputMsg::None,
});
let model = MonitorModel { let model = MonitorModel {
sidebar_open: true, sidebar_open: true,
sidebar_width: 400, sidebar_width: 400,
@ -62,10 +72,16 @@ impl SimpleComponent for MonitorModel {
}; };
let widgets = view_output! {}; let widgets = view_output! {};
ComponentParts { model, widgets } AsyncComponentParts { model, widgets }
} }
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) { async fn update(
&mut self,
msg: Self::Input,
_sender: AsyncComponentSender<Self>,
_root: &Self::Root,
) {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
match msg { match msg {
MonitorInputMsg::AddLayer(layer) => { MonitorInputMsg::AddLayer(layer) => {
self.layers.push(layer); self.layers.push(layer);
@ -73,6 +89,10 @@ impl SimpleComponent for MonitorModel {
.output_sender() .output_sender()
.send(MonitorOutputMsg::LayerAdded(0)) .send(MonitorOutputMsg::LayerAdded(0))
.unwrap(); .unwrap();
self.sidebar
.sender()
.send(Msg::RefreshList(self.layers.clone()));
} }
MonitorInputMsg::RemoveLayer(index) => { MonitorInputMsg::RemoveLayer(index) => {
self.layers.remove(index); self.layers.remove(index);
@ -91,5 +111,4 @@ impl SimpleComponent for MonitorModel {
MonitorInputMsg::None => {} MonitorInputMsg::None => {}
} }
} }
} }

View File

@ -1,2 +0,0 @@
pub mod render;
pub use render::*;

View File

@ -1,40 +0,0 @@
use crate::coords::proj::Mercator;
use crate::coords::Mapper;
use crate::render::{Render, RenderConfig};
use relm4::*;
pub struct RenderModel {
config: RenderConfig,
mapper: Mapper,
}
#[relm4::component(pub)]
impl SimpleComponent for RenderModel {
type Init = (Option<Mapper>, Option<RenderConfig>);
type Output = ();
type Input = ();
view! {
Render{
set_mapper = model.mapper.clone(),
set_cfg = model.config.clone(),
}
}
fn init(
init: Self::Init,
root: &Self::Root,
sender: relm4::ComponentSender<Self>,
) -> relm4::ComponentParts<Self> {
let (mapper, config) = init;
let config = config.unwrap_or(RenderConfig::default());
let mapper = mapper.unwrap_or(Mercator::default().into());
let model = RenderModel { config, mapper };
let widgets = view_output!();
ComponentParts { model, widgets }
}
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {}
}

View File

@ -0,0 +1,51 @@
use gtk::prelude::*;
use relm4::{
factory::FactoryView,
gtk,
prelude::{DynamicIndex, FactoryComponent},
FactorySender,
};
use super::Msg;
#[derive(Debug)]
pub enum TestMsg {
Delete,
MoveUp,
MoveDown,
Add,
}
pub struct BottomBarModel {
icon: String,
msg: TestMsg,
}
#[relm4::factory(pub)]
impl FactoryComponent for BottomBarModel {
type ParentWidget = gtk::Box;
type ParentInput = Msg;
type Input = ();
type Output = TextMsg;
type Init = BottomBarModel;
type CommandOutput = ();
view! {
#[root]
gtk::Box{
gtk::Button{
#[wrap(Some)]
set_icon_name= model.icon.as_str(),
}
}
}
fn init_model(init: Self::Init, index: &DynamicIndex, sender: FactorySender<Self>) -> Self {
init
}
fn update(&mut self, message: Self::Input, sender: FactorySender<Self>) {
match message {}
}
}

View File

@ -1,2 +1,3 @@
pub mod sidebar; pub mod sidebar;
pub use sidebar::*; pub use sidebar::*;
pub mod bottom_bar;

View File

@ -1,23 +1,30 @@
use glib::clone; use glib::clone;
use gtk::prelude::WidgetExt;
use gtk::prelude::*; use gtk::prelude::*;
use relm4::{ use relm4::{
binding::{Binding, U8Binding}, binding::{Binding, U8Binding},
factory::{DynamicIndex, FactoryComponent, FactorySender, FactoryVecDeque},
prelude::*, prelude::*,
typed_list_view::{RelmListItem, TypedListView}, typed_list_view::{RelmListItem, TypedListView},
RelmObjectExt, RelmObjectExt,
}; };
use crate::{chart::Chart, render::{Layer, predefined::color_mapper::BoundaryNorm}, data::Npz}; use crate::{
chart::Chart,
data::Npz,
render::{predefined::color_mapper::BoundaryNorm, Layer},
};
use super::bottom_bar::BottomBarModel;
pub struct SideBarModel { pub struct SideBarModel {
counter: u8, counter: u8,
list_view_wrapper: TypedListView<MyListItem, gtk::SingleSelection>, list_view_wrapper: TypedListView<LayerItem, gtk::SingleSelection>,
bottom_bar_vec: FactoryVecDeque<BottomBarModel>,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum Msg { pub enum Msg {
Append, RefreshList(Vec<Layer>),
Remove,
OnlyShowEven(bool),
} }
#[derive(Debug)] #[derive(Debug)]
@ -32,13 +39,24 @@ impl SimpleComponent for SideBarModel {
type Input = Msg; type Input = Msg;
view! { view! {
gtk::Box { gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 5,
set_margin_all: 5,
gtk::Paned{
set_orientation: gtk::Orientation::Vertical, set_orientation: gtk::Orientation::Vertical,
set_position: 300,
#[wrap(Some)]
set_start_child = &gtk::Box{
set_orientation: gtk::Orientation::Vertical,
set_spacing: 5, set_spacing: 5,
set_margin_all: 5, #[local]
gtk::Notebook { top_panel -> gtk::Notebook{},
set_vexpand: true, gtk::Button {
append_page:(&page_1, Some(&label)), set_label: "Add Layers",
connect_clicked[sender] => move |_| {
},
}, },
gtk::Button { gtk::Button {
set_label: "Add Layer", set_label: "Add Layer",
@ -47,6 +65,7 @@ impl SimpleComponent for SideBarModel {
SideBarOutputMsg::NewLayer( SideBarOutputMsg::NewLayer(
Layer::grid_render_layer_with_path( Layer::grid_render_layer_with_path(
"/users/tsuki/projects/radar-g/test2.npz", "/users/tsuki/projects/radar-g/test2.npz",
"DBZ".to_string(),
Npz, Npz,
BoundaryNorm::default(), BoundaryNorm::default(),
) )
@ -54,13 +73,26 @@ impl SimpleComponent for SideBarModel {
).unwrap() ).unwrap()
}, },
}, },
gtk::ScrolledWindow { },
set_vexpand: true,
#[local_ref] #[wrap(Some)]
my_view -> gtk::ListView {} set_end_child=&gtk::Box{
} set_orientation: gtk::Orientation::Vertical,
set_vexpand: true,
set_hexpand: true,
#[local]
bottom_panel -> gtk::Notebook{
set_margin_top: 10,
set_margin_bottom: 10,
},
#[local_ref]
counter_box -> gtk::Box{}
} }
} },
}
}
fn init( fn init(
init: Self::Init, init: Self::Init,
@ -68,33 +100,33 @@ impl SimpleComponent for SideBarModel {
sender: ComponentSender<Self>, sender: ComponentSender<Self>,
) -> ComponentParts<Self> { ) -> ComponentParts<Self> {
// Initialize the ListView wrapper // Initialize the ListView wrapper
let mut list_view_wrapper: TypedListView<MyListItem, gtk::SingleSelection> = let mut list_view_wrapper: TypedListView<LayerItem, gtk::SingleSelection> =
TypedListView::with_sorting(); TypedListView::with_sorting();
// Add a filter and disable it let bottom_bar_vec = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender());
list_view_wrapper.add_filter(|item| item.value % 2 == 0);
list_view_wrapper.set_filter_status(0, false);
let model = SideBarModel { let model = SideBarModel {
counter: 0, counter: 0,
list_view_wrapper, list_view_wrapper,
bottom_bar_vec,
}; };
let my_view = &model.list_view_wrapper.view;
let page_1 = gtk::Box::builder() let my_view = &model.list_view_wrapper.view;
.orientation(gtk::Orientation::Vertical) let top_panel = gtk::Notebook::builder().vexpand(true).build();
top_panel.append_page(&Chart::new(), Some(&gtk::Label::new(Some("Chart"))));
let bottom_panel = gtk::Notebook::builder().vexpand(true).build();
let layer_page = gtk::ScrolledWindow::builder()
.vexpand(true) .vexpand(true)
.hexpand(true) .hexpand(true)
.build(); .build();
let chart = Chart::new(); let counter_box = model.bottom_bar_vec.widgets();
chart.connect_resize(clone!(@weak chart as my_view => move |_, w,h|{ layer_page.set_child(Some(my_view));
my_view.set_height_request((w as f32 / 16.0 * 3.0) as i32); layer_page.set_margin_horizontal(5);
})); layer_page.set_margin_vertical(3);
bottom_panel.append_page(&layer_page, Some(&gtk::Label::new(Some("Layers"))));
page_1.append(&chart);
let label = gtk::Label::new(Some("Page 1"));
let widgets = view_output!(); let widgets = view_output!();
ComponentParts { model, widgets } ComponentParts { model, widgets }
@ -102,49 +134,33 @@ impl SimpleComponent for SideBarModel {
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) { fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
match message { match message {
Msg::Append => { Msg::RefreshList(layers) => {
// Add 10 items for layer in layers {
for _ in 0..10 { self.list_view_wrapper
self.counter = self.counter.wrapping_add(1); .append(LayerItem::new(layer.name, true));
self.list_view_wrapper.append(MyListItem::new(self.counter));
} }
// Count up the first item
let first_item = self.list_view_wrapper.get(0).unwrap();
let first_binding = &mut first_item.borrow_mut().binding;
let mut guard = first_binding.guard();
*guard += 1;
}
Msg::Remove => {
// Remove the second item
self.list_view_wrapper.remove(1);
}
Msg::OnlyShowEven(show_only_even) => {
// Disable or enable the first filter
self.list_view_wrapper.set_filter_status(0, show_only_even);
} }
} }
} }
} }
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct MyListItem { struct LayerItem {
value: u8, layer_name: String,
binding: U8Binding, visiable: bool,
} }
impl MyListItem { impl LayerItem {
fn new(value: u8) -> Self { fn new(name: String, visiable: bool) -> Self {
Self { Self {
value, layer_name: name,
binding: U8Binding::new(0), visiable,
} }
} }
} }
struct Widgets { struct Widgets {
label: gtk::Label, label: gtk::Label,
label2: gtk::Label,
button: gtk::CheckButton, button: gtk::CheckButton,
} }
@ -154,7 +170,7 @@ impl Drop for Widgets {
} }
} }
impl RelmListItem for MyListItem { impl RelmListItem for LayerItem {
type Root = gtk::Box; type Root = gtk::Box;
type Widgets = Widgets; type Widgets = Widgets;
@ -162,34 +178,28 @@ impl RelmListItem for MyListItem {
relm4::view! { relm4::view! {
my_box = gtk::Box { my_box = gtk::Box {
#[name = "label"] #[name = "label"]
gtk::Label, gtk::Label{
set_halign: gtk::Align::Start,
#[name = "label2"] },
gtk::Label, gtk::Label{
set_hexpand: true,
},
#[name = "button"] #[name = "button"]
gtk::CheckButton, gtk::CheckButton{
set_halign: gtk::Align::End,
},
} }
} }
let widgets = Widgets { let widgets = Widgets { label, button };
label,
label2,
button,
};
(my_box, widgets) (my_box, widgets)
} }
fn bind(&mut self, widgets: &mut Self::Widgets, _root: &mut Self::Root) { fn bind(&mut self, widgets: &mut Self::Widgets, _root: &mut Self::Root) {
let Widgets { let Widgets { label, button } = widgets;
label,
label2,
button,
} = widgets;
label.set_label(&format!("Value: {} ", self.value)); label.set_label(&format!("Layer: {} ", &self.layer_name));
label2.add_write_only_binding(&self.binding, "label"); button.set_active(self.visiable);
button.set_active(self.value % 2 == 0);
} }
} }

View File

@ -1,9 +1,15 @@
use super::messages::RenderInputMsg; use super::messages::RenderInputMsg;
use gtk::prelude::*;
use super::monitor::MonitorModel; use super::monitor::MonitorModel;
use relm4::*; use gtk::prelude::*;
use relm4::component::AsyncComponentController;
use relm4::{
component::{AsyncComponent, AsyncController},
RelmWidgetExt, *,
};
pub struct RenderPanelModel { pub struct RenderPanelModel {
monitor: Controller<MonitorModel>, // monitor: Controller<MonitorModel>,
monitor: AsyncController<MonitorModel>,
} }
#[relm4::component(pub)] #[relm4::component(pub)]
@ -26,7 +32,8 @@ impl SimpleComponent for RenderPanelModel {
root: &Self::Root, root: &Self::Root,
sender: relm4::ComponentSender<Self>, sender: relm4::ComponentSender<Self>,
) -> relm4::ComponentParts<Self> { ) -> relm4::ComponentParts<Self> {
let monitor: Controller<MonitorModel> = MonitorModel::builder()
let monitor: AsyncController<MonitorModel> = MonitorModel::builder()
.launch(()) .launch(())
.forward(sender.input_sender(), |msg| {}); .forward(sender.input_sender(), |msg| {});

View File

@ -1,12 +1,14 @@
use crate::errors::DataError; use crate::errors::DataError;
use image::RgbImage; use async_trait::async_trait;
use ndarray::{ use ndarray::{
s, Array, Array1, Array2, Array3, ArrayBase, Axis, DataMut, Dimension, Ix1, Ix2, OwnedRepr, s, Array1, Array2, Array3, ArrayBase, DataMut, Dimension, Ix1, Ix2, OwnedRepr, RawDataClone,
RawDataClone, ViewRepr,
}; };
use npyz::{npz::NpzArchive, Deserialize}; use npyz::{npz::NpzArchive, Deserialize};
use num_traits::{AsPrimitive, FromPrimitive, Num}; use num_traits::{AsPrimitive, FromPrimitive, Num};
use std::io::{Cursor, Seek};
use std::{self, f64::consts::PI, fmt::Debug, io::BufReader, path::Path}; use std::{self, f64::consts::PI, fmt::Debug, io::BufReader, path::Path};
use tokio::fs::File;
use tokio::io::{self, AsyncReadExt};
pub type Radar2d<T> = RadarData2d<T, OwnedRepr<T>>; pub type Radar2d<T> = RadarData2d<T, OwnedRepr<T>>;
@ -107,7 +109,6 @@ where
*self.dim2.last().unwrap(), *self.dim2.last().unwrap(),
output_shape.0, output_shape.0,
); );
// let mut dim2 = Array1::zeros(output_shape.0);
output.iter_mut().enumerate().for_each(|(s, vv)| { output.iter_mut().enumerate().for_each(|(s, vv)| {
let ri = s / output_shape.1; let ri = s / output_shape.1;
@ -280,13 +281,21 @@ where
fn load<P: AsRef<Path>>(&self, path: P) -> Result<T, DataError>; fn load<P: AsRef<Path>>(&self, path: P) -> Result<T, DataError>;
} }
#[async_trait]
pub trait AsyncDataLoader<V, T>
where
V: Num + Clone + PartialEq + PartialOrd,
T: MultiDimensionData<V> + Send + Sync,
{
async fn load<P: AsRef<Path> + Send>(&self, path: P) -> Result<T, DataError>;
}
pub struct Npz; pub struct Npz;
impl Npz { impl Npz {
#[inline] #[inline]
fn load_1d<T: Num + Deserialize>( fn load_1d<T: Num + Deserialize, R: std::io::Read + Seek>(
&self, &self,
// path: &Path, data: &mut NpzArchive<R>,
data: &mut NpzArchive<BufReader<std::fs::File>>,
name: &str, name: &str,
) -> Result<Array1<T>, DataError> { ) -> Result<Array1<T>, DataError> {
// let mut data = npyz::npz::NpzArchive::open(path)?; // let mut data = npyz::npz::NpzArchive::open(path)?;
@ -296,10 +305,10 @@ impl Npz {
Ok(Array1::from_shape_vec(b.len(), b).unwrap()) Ok(Array1::from_shape_vec(b.len(), b).unwrap())
} }
#[inline] #[inline]
fn load_2d<T: Num + Deserialize>( fn load_2d<T: Num + Deserialize, R: std::io::Read + Seek>(
&self, &self,
// path: &Path, // path: &Path,
data: &mut NpzArchive<BufReader<std::fs::File>>, data: &mut NpzArchive<R>,
name: &str, name: &str,
) -> Result<Array2<T>, DataError> { ) -> Result<Array2<T>, DataError> {
// let mut data = npyz::npz::NpzArchive::open(path)?; // let mut data = npyz::npz::NpzArchive::open(path)?;
@ -320,9 +329,9 @@ where
{ {
fn load<P: AsRef<Path>>(&self, path: P) -> Result<RadarData2d<T, OwnedRepr<T>>, DataError> { fn load<P: AsRef<Path>>(&self, path: P) -> Result<RadarData2d<T, OwnedRepr<T>>, DataError> {
let mut data: NpzArchive<BufReader<std::fs::File>> = npyz::npz::NpzArchive::open(path)?; let mut data: NpzArchive<BufReader<std::fs::File>> = npyz::npz::NpzArchive::open(path)?;
let dim1 = self.load_1d::<f64>(&mut data, "lon")?; let dim1 = self.load_1d::<f64, BufReader<std::fs::File>>(&mut data, "lon")?;
let dim2 = self.load_1d::<f64>(&mut data, "lat")?; let dim2 = self.load_1d::<f64, BufReader<std::fs::File>>(&mut data, "lat")?;
let value = self.load_2d::<T>(&mut data, "value")?; let value = self.load_2d::<T, BufReader<std::fs::File>>(&mut data, "value")?;
Ok(RadarData2d { Ok(RadarData2d {
dim1: dim1, dim1: dim1,
@ -334,6 +343,47 @@ where
} }
} }
impl<T> AsyncDataLoader<T, RadarData2d<T, OwnedRepr<T>>> for Npz
where
T: Num + Clone + Deserialize + FromPrimitive,
T: PartialEq + PartialOrd + Send + Sync,
{
fn load<'life0, 'async_trait, P>(
&'life0 self,
path: P,
) -> core::pin::Pin<
Box<
dyn core::future::Future<Output = Result<RadarData2d<T, OwnedRepr<T>>, DataError>>
+ core::marker::Send
+ 'async_trait,
>,
>
where
P: 'async_trait + AsRef<Path> + Send,
'life0: 'async_trait,
Self: 'async_trait,
{
Box::pin(async {
let mut f = File::open(path).await?;
let mut buffer = Vec::new();
f.read_to_end(&mut buffer).await?;
let mut data = npyz::npz::NpzArchive::new(Cursor::new(buffer))?;
let dim1 = self.load_1d::<f64, Cursor<Vec<u8>>>(&mut data, "lon")?;
let dim2 = self.load_1d::<f64, Cursor<Vec<u8>>>(&mut data, "lat")?;
let value = self.load_2d::<T, Cursor<Vec<u8>>>(&mut data, "value")?;
Ok(RadarData2d {
dim1: dim1,
dim2: dim2,
fill_value: T::from_f64(-125.0).unwrap(),
data: value,
coord_type: CoordType::LatLon,
})
})
}
}
// fn resample( // fn resample(
// &self, // &self,
// width_rate: f64, // width_rate: f64,

View File

@ -6,10 +6,7 @@ pub enum DataError {
#[error("value")] #[error("value")]
FormatError, FormatError,
#[error("")] #[error("")]
IOError { IOError(#[from] std::io::Error),
#[from]
source: std::io::Error,
},
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]

View File

@ -3,6 +3,7 @@ use gtk::prelude::*;
use gtk::{gio, glib, Application, ApplicationWindow}; use gtk::{gio, glib, Application, ApplicationWindow};
use relm4::menu; use relm4::menu;
use relm4::RelmApp; use relm4::RelmApp;
use tokio::runtime::Runtime;
use std::ptr; use std::ptr;
mod chart; mod chart;
mod components; mod components;
@ -14,9 +15,13 @@ mod pipeline;
mod render; mod render;
mod window; mod window;
use components::app::{AppMode, AppModel}; use components::app::{AppMode, AppModel};
use once_cell::sync::Lazy;
const APP_ID: &str = "org.gtk_rs.HelloWorld2"; const APP_ID: &str = "org.gtk_rs.HelloWorld2";
static RUNTIME: Lazy<Runtime> =
Lazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed."));
fn main() { fn main() {
// Load GL pointers from epoxy (GL context management library used by GTK). // Load GL pointers from epoxy (GL context management library used by GTK).
{ {

View File

@ -3,7 +3,7 @@ use super::interior::InteriorWidget;
use super::{Layer, WindowCoord}; use super::{Layer, WindowCoord};
use crate::coords::proj::Mercator; use crate::coords::proj::Mercator;
use crate::coords::Mapper; use crate::coords::Mapper;
use femtovg::{Canvas, Color, FontId}; use femtovg::{Canvas, Color, FontId, Renderer};
use gtk::glib; use gtk::glib;
use gtk::subclass::prelude::*; use gtk::subclass::prelude::*;
use gtk::traits::{GLAreaExt, WidgetExt}; use gtk::traits::{GLAreaExt, WidgetExt};
@ -119,23 +119,23 @@ impl GLAreaImpl for Render {
fn render(&self, context: &gtk::gdk::GLContext) -> bool { fn render(&self, context: &gtk::gdk::GLContext) -> bool {
self.ensure_canvas(); self.ensure_canvas();
let mut canvas = self.canvas.borrow_mut();
let canvas = canvas.as_mut().unwrap();
let dpi = self.obj().scale_factor();
let w = canvas.width();
let h = canvas.height();
let configs = self.config.borrow(); let configs = self.config.borrow();
{
let mut canvas = self.canvas.borrow_mut();
let canvas = canvas.as_mut().unwrap();
canvas.clear_rect( let dpi = self.obj().scale_factor();
0, let w = canvas.width();
0, let h = canvas.height();
(w as i32 * dpi) as u32,
(h as i32 * dpi) as u32, canvas.clear_rect(
Color::rgba(0, 0, 0, 255), 0,
); 0,
(w as i32 * dpi) as u32,
(h as i32 * dpi) as u32,
Color::rgba(0, 0, 0, 255),
);
}
{ {
let mut status = self.status.borrow_mut(); let mut status = self.status.borrow_mut();
@ -170,20 +170,18 @@ impl GLAreaImpl for Render {
} }
} }
let c = &(*self.interior_layers.borrow()); let c = &(*self.interior_layers.borrow());
self.interior
.borrow()
.draw(c, &self.obj(), self.status.borrow(), configs);
{
let mut canvas = self.canvas.borrow_mut();
let canvas = canvas.as_mut().unwrap();
self.exterior.borrow().draw(canvas, &self.obj());
canvas.flush();
}
self.interior.borrow().draw(
c,
canvas,
&self.obj(),
self.status.borrow(),
configs,
);
self.exterior.borrow().draw(canvas, &self.obj());
canvas.flush();
true true
} }
} }
@ -219,6 +217,7 @@ impl Render {
canvas canvas
.add_font_dir("/Users/tsuki/projects/radar-g/src/assets") .add_font_dir("/Users/tsuki/projects/radar-g/src/assets")
.unwrap(); .unwrap();
self.canvas.replace(Some(canvas)); self.canvas.replace(Some(canvas));
} }

View File

@ -1,19 +1,31 @@
use crate::{coords::Range, render::Render}; use crate::{coords::Range, render::Render};
use femtovg::Paint;
use femtovg::{renderer::OpenGl, Canvas, ImageId}; use femtovg::{renderer::OpenGl, Canvas, ImageId};
use ndarray::AssignElem;
use std::{ use std::{
cell::{Ref, RefCell}, cell::{Ref, RefCell},
fmt::Debug, sync::Arc, fmt::Debug,
future::Future,
pin::Pin,
sync::{Arc, Mutex},
}; };
type PrepareFunc =
Box<dyn FnOnce(Arc<Layer>, Render) -> Pin<Box<dyn Future<Output = ()>>> + Sync + Send>;
type DrawFunc = Box<dyn Fn(&Layer, Render, (f32, f32)) + Send + Sync>;
type LayerImplSync = Box<dyn LayerImpl + Send + Sync>;
#[derive(Clone)] #[derive(Clone)]
pub struct Layer { pub struct Layer {
pub visiable: bool, pub visiable: bool,
pub name: String,
snapshot: Option<gtk::gdk::Texture>,
target: RefCell<Option<Target>>, target: RefCell<Option<Target>>,
imp: RefCell<Option<Arc<dyn LayerImpl>>>, prepare: Arc<Option<PrepareFunc>>,
draw: Arc<dyn Fn(&Self, &mut Canvas<OpenGl>, &Render, (f32, f32))>, imp: RefCell<Option<Arc<LayerImplSync>>>,
draw: Arc<DrawFunc>,
} }
impl Debug for Layer { impl Debug for Layer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Layer") f.debug_struct("Layer")
@ -25,32 +37,53 @@ impl Debug for Layer {
} }
pub trait LayerImpl: Debug { pub trait LayerImpl: Debug {
fn draw(&self, canvas: &mut Canvas<OpenGl>, render: &Render) -> Option<Target>; fn draw(&self, render: Render) -> Option<Target>;
} }
impl Layer { impl Layer {
pub fn new< pub fn new<
F: 'static + Fn(&Self, &mut Canvas<OpenGl>, &Render, (f32, f32)), FU: Future<Output = ()> + 'static,
IMP: LayerImpl + 'static, F: 'static + Fn(&Self, Render, (f32, f32)) + Send + Sync,
PREPARE: FnOnce(Arc<Layer>, Render) -> FU + Send + Sync + 'static,
IMP: LayerImpl + Sync + Send + 'static,
>( >(
visiable: bool, visiable: bool,
draw: F, draw: F,
layer_name: String,
prepare: Option<PREPARE>,
imp: Option<IMP>, imp: Option<IMP>,
) -> Self { ) -> Self {
Layer { Layer {
visiable, visiable,
target: RefCell::new(None), target: RefCell::new(None),
draw: Arc::new(draw), name: layer_name,
imp: RefCell::new(imp.map(|x| Arc::new(x) as Arc<dyn LayerImpl>)), snapshot: None,
// prepare: Arc::new(prepare),
prepare: Arc::new(prepare.map(|p| {
Box::new(
move |layer: Arc<Layer>, render: Render| -> Pin<Box<dyn Future<Output = ()>>> {
Box::pin(p(layer, render))
},
) as PrepareFunc
})),
draw: Arc::new(Box::new(draw)),
imp: RefCell::new(
imp.map(|x| Arc::new(Box::new(x) as Box<dyn LayerImpl + Send + Sync>)),
),
} }
} }
pub fn draw(&self, canvas: &mut Canvas<OpenGl>, render: &Render, window_size: (f32, f32)) { pub fn draw(&self, render: &Render, window_size: (f32, f32)) {
if self.visiable { if self.visiable {
(self.draw)(self, canvas, render, window_size); let drawer = &self.draw;
drawer(self, render.clone(), window_size);
} }
} }
pub fn get_prepare(&self) -> Option<&PrepareFunc> {
self.prepare.as_ref().as_ref()
}
pub fn set_render_target(&self, target: Target) { pub fn set_render_target(&self, target: Target) {
*self.target.borrow_mut() = Some(target); *self.target.borrow_mut() = Some(target);
} }
@ -59,7 +92,7 @@ impl Layer {
self.target.borrow().clone() self.target.borrow().clone()
} }
pub fn get_imp(&self) -> Ref<Option<Arc<dyn LayerImpl>>> { pub fn get_imp(&self) -> Ref<Option<Arc<LayerImplSync>>> {
let im = self.imp.borrow(); let im = self.imp.borrow();
im im
} }

View File

@ -23,19 +23,15 @@ impl InteriorWidget {
this this
} }
pub fn draw( pub fn draw(
&self, &self,
layers: &Vec<Layer>, layers: &Vec<Layer>,
canvas: &mut Canvas<OpenGl>,
render: &Render, render: &Render,
status: Ref<'_, RenderStatus>, status: Ref<'_, RenderStatus>,
_c: Ref<'_, RenderConfig>, _c: Ref<'_, RenderConfig>,
) { ) {
let (x, y) = (canvas.width(), canvas.height());
for layer in layers.iter().filter(|x| x.visiable) { for layer in layers.iter().filter(|x| x.visiable) {
layer.draw(canvas, &render, (x, y)); layer.draw(render, (1000.0, 1000.0));
} }
} }
} }

View File

@ -1,20 +1,24 @@
mod cms; mod cms;
mod imp;
mod exterior; mod exterior;
mod imp;
mod interior; mod interior;
pub mod predefined; pub mod predefined;
mod renders; mod renders;
use self::cms::CMS; use self::cms::CMS;
pub use self::imp::{RenderConfig, RenderMotion, RenderStatus}; pub use self::imp::{RenderConfig, RenderMotion, RenderStatus};
use crate::coords::Mapper; use crate::coords::Mapper;
use crate::RUNTIME;
use adw::prelude::{GLAreaExt, GestureDragExt}; use adw::prelude::{GLAreaExt, GestureDragExt};
use geo_types::LineString; use geo_types::LineString;
use glib::clone; use glib::clone;
pub use glib::subclass::prelude::*;
use gtk::traits::WidgetExt; use gtk::traits::WidgetExt;
use gtk::{EventControllerScrollFlags, Inhibit}; use gtk::{EventControllerScrollFlags, Inhibit};
use std::cell::Ref;
pub use glib::subclass::prelude::*;
pub use interior::{Layer, LayerImpl, Target}; pub use interior::{Layer, LayerImpl, Target};
use relm4::once_cell::sync::Lazy;
use std::cell::{Ref, RefCell, RefMut};
use std::sync::{Arc, Mutex};
use tokio::runtime::Runtime;
pub(super) type WindowCoord = (f32, f32); pub(super) type WindowCoord = (f32, f32);
@ -41,7 +45,6 @@ impl Render {
this.set_mapper(mapper); this.set_mapper(mapper);
} }
let pointer_location_detecture = gtk::EventControllerMotion::new(); let pointer_location_detecture = gtk::EventControllerMotion::new();
pointer_location_detecture.connect_motion( pointer_location_detecture.connect_motion(
clone!( @weak this as r => move |_context, x, y| { clone!( @weak this as r => move |_context, x, y| {
@ -104,6 +107,10 @@ impl Render {
f(&mut cfg); f(&mut cfg);
} }
pub fn get_canvas(&self) -> RefMut<'_, Option<femtovg::Canvas<femtovg::renderer::OpenGl>>> {
self.imp().canvas.borrow_mut()
}
pub fn set_cfg(&self, cfg: RenderConfig) { pub fn set_cfg(&self, cfg: RenderConfig) {
self.imp().config.replace(cfg); self.imp().config.replace(cfg);
} }

View File

@ -2,7 +2,7 @@ use std::fmt::Debug;
use femtovg::Color; use femtovg::Color;
use num_traits::NumOps; use num_traits::NumOps;
pub trait ColorMapper<T: NumOps + PartialOrd> : Debug { pub trait ColorMapper<T: NumOps + PartialOrd> : Debug + Send + Sync {
fn map_value_to_color(&self, value: T, invalid_value: T) -> Option<femtovg::Color>; fn map_value_to_color(&self, value: T, invalid_value: T) -> Option<femtovg::Color>;
} }
@ -65,7 +65,7 @@ impl<T: NumOps + PartialOrd> BoundaryNorm<T> {
} }
} }
impl<T: NumOps + PartialOrd + Debug> ColorMapper<T> for BoundaryNorm<T> { impl<T: NumOps + PartialOrd + Debug + Send + Sync> ColorMapper<T> for BoundaryNorm<T> {
fn map_value_to_color(&self, value: T, invalid_value: T) -> Option<femtovg::Color> { fn map_value_to_color(&self, value: T, invalid_value: T) -> Option<femtovg::Color> {
self.map_value_to_color(value, invalid_value) self.map_value_to_color(value, invalid_value)
} }

View File

@ -1,15 +1,71 @@
use crate::coords::Range;
use std::borrow::BorrowMut;
use std::path::Path;
use crate::coords::Mapper; use crate::coords::Mapper;
use crate::render::Render; use crate::render::{Layer, LayerImpl, Render};
use femtovg::renderer::OpenGl; use femtovg::renderer::OpenGl;
use femtovg::{Canvas, Paint}; use femtovg::{Canvas, Paint};
use geo_types::LineString; use geo_types::LineString;
use geojson::GeoJson; use geojson::GeoJson;
pub struct MapRender; impl Layer {
pub fn map_layer_with_geojson_by_path(path: impl AsRef<Path>) -> Self {
let geojson = std::fs::read_to_string(path).unwrap();
let json = geojson.parse::<GeoJson>().unwrap();
Self::map_layer_with_geojson(json)
}
impl MapRender { pub fn map_layer_with_geojson(json: GeoJson) -> Self {
pub fn test(geojson: &GeoJson, canvas: &mut Canvas<OpenGl>, render: &Render) { let mut layer = Layer::new(
true,
|s, render, _| {
if let Some(renderer) = s.get_imp().as_ref() {
renderer.draw(render.clone());
}
},
"Map".into(),
Some(|_, _| async {}),
Some(GeoJsonMapImpl::new(json)),
);
layer
}
pub fn meshgrid_layer() -> Self {
let mut layer = Layer::new(
true,
|s, render, _| {
if let Some(renderer) = s.get_imp().as_ref() {
renderer.draw(render.clone());
}
},
"MeshGrid".into(),
Some(|_, _| async {}),
Some(MeshGridImpl),
);
layer
}
}
#[derive(Debug)]
struct GeoJsonMapImpl {
geojson: GeoJson,
}
impl GeoJsonMapImpl {
fn new(json: GeoJson) -> Self {
Self { geojson: json }
}
}
impl LayerImpl for GeoJsonMapImpl {
fn draw(&self, render: Render) -> Option<crate::render::Target> {
let paint = Paint::color(femtovg::Color::rgb(255, 255, 255)); let paint = Paint::color(femtovg::Color::rgb(255, 255, 255));
let geojson = &self.geojson;
let mut canvas = render.get_canvas();
let canvas = canvas.as_mut().unwrap();
if let GeoJson::FeatureCollection(ref feature_collection) = geojson { if let GeoJson::FeatureCollection(ref feature_collection) = geojson {
for feature in &feature_collection.features { for feature in &feature_collection.features {
@ -59,5 +115,45 @@ impl MapRender {
}); });
} }
} }
None
}
}
#[derive(Debug)]
struct MeshGridImpl;
impl LayerImpl for MeshGridImpl {
fn draw(&self, render: Render) -> Option<crate::render::Target> {
let mut canvas = render.get_canvas();
let canvas = canvas.as_mut().unwrap();
let (lon_range, lat_range) = render.render_range();
let (lon_range, lat_range): (Range, Range) = (lon_range.into(), lat_range.into());
let lon_keypoints = lon_range.key_points(10);
let lat_keypoints = lat_range.key_points(5);
for lon in lon_keypoints.iter() {
let mut path = femtovg::Path::new();
render
.map((*lon, lat_range.0))
.map(|(x, y)| path.move_to(x, y));
render
.map((*lon, lat_range.1))
.map(|(x, y)| path.line_to(x, y));
canvas.stroke_path(&mut path, &Paint::color(femtovg::Color::rgb(255, 255, 255)));
}
for lat in lat_keypoints.iter() {
let mut path = femtovg::Path::new();
render
.map((lon_range.0, *lat))
.map(|(x, y)| path.move_to(x, y));
render
.map((lon_range.1, *lat))
.map(|(x, y)| path.line_to(x, y));
canvas.stroke_path(&mut path, &Paint::color(femtovg::Color::rgb(255, 255, 255)));
}
None
} }
} }

View File

@ -3,12 +3,13 @@ use femtovg::{ImageFlags, Paint, Path, PixelFormat::Rgba8, RenderTarget};
use geo_types::LineString; use geo_types::LineString;
use ndarray::ArrayView2; use ndarray::ArrayView2;
use num_traits::{Num, NumOps}; use num_traits::{Num, NumOps};
use std::{marker::PhantomData, fmt::Debug}; use std::{fmt::Debug, marker::PhantomData};
use super::super::renders::DataRenderer; use super::super::renders::DataRenderer;
use crate::{ use crate::{
data::Radar2d, data::Radar2d,
utils::meshgrid, render::{Render, Target, LayerImpl}, render::{LayerImpl, Render, Target},
utils::meshgrid,
}; };
#[derive(Debug)] #[derive(Debug)]
@ -37,7 +38,6 @@ impl<T: NumOps + PartialOrd + Copy, CMAP: ColorMapper<T>> GridFieldRenderer<CMAP
window_size: (f32, f32), window_size: (f32, f32),
fill_value: T, fill_value: T,
) { ) {
let shape = data.shape(); let shape = data.shape();
let (rows, cols) = (shape[0], shape[1]); let (rows, cols) = (shape[0], shape[1]);
let (dim1, dim2) = dims; let (dim1, dim2) = dims;
@ -96,12 +96,10 @@ where
CMAP: ColorMapper<T>, CMAP: ColorMapper<T>,
{ {
type Data = Radar2d<T>; type Data = Radar2d<T>;
fn render( fn render(&self, render: Render, data: &Self::Data) -> Target {
&self, let mut canvas = render.get_canvas();
render: &Render, let canvas = canvas.as_mut().unwrap();
canvas: &mut femtovg::Canvas<femtovg::renderer::OpenGl>,
data: &Self::Data,
) -> Target {
let new_img = canvas let new_img = canvas
.create_image_empty(3000, 3000, Rgba8, ImageFlags::empty()) .create_image_empty(3000, 3000, Rgba8, ImageFlags::empty())
.expect("Can't Create Image"); .expect("Can't Create Image");
@ -116,7 +114,7 @@ where
self.draw_2d( self.draw_2d(
canvas, canvas,
_data, _data,
render, &render,
(_dim1.view(), _dim2.view()), (_dim1.view(), _dim2.view()),
(3000.0, 3000.0), (3000.0, 3000.0),
data.fill_value, data.fill_value,
@ -144,7 +142,7 @@ where
#[derive(Debug)] #[derive(Debug)]
pub struct GridLayerImpl<CMAP, T> pub struct GridLayerImpl<CMAP, T>
where where
T: Num + NumOps + PartialOrd + Copy + Clone, T: Num + NumOps + PartialOrd + Copy + Clone + Send + Sync + Debug,
CMAP: ColorMapper<T>, CMAP: ColorMapper<T>,
{ {
renderer: GridFieldRenderer<CMAP, T>, renderer: GridFieldRenderer<CMAP, T>,
@ -155,7 +153,7 @@ pub type DbzGridLayerImpl = GridLayerImpl<BoundaryNorm<i8>, i8>;
impl<CMAP, T> GridLayerImpl<CMAP, T> impl<CMAP, T> GridLayerImpl<CMAP, T>
where where
T: Num + NumOps + PartialOrd + Copy + Clone, T: Num + NumOps + PartialOrd + Copy + Clone + Send + Sync + Debug,
CMAP: ColorMapper<T>, CMAP: ColorMapper<T>,
{ {
pub fn new(renderer: GridFieldRenderer<CMAP, T>, data: Radar2d<T>) -> Self { pub fn new(renderer: GridFieldRenderer<CMAP, T>, data: Radar2d<T>) -> Self {
@ -165,14 +163,10 @@ where
impl<CMAP, T> LayerImpl for GridLayerImpl<CMAP, T> impl<CMAP, T> LayerImpl for GridLayerImpl<CMAP, T>
where where
T: Num + NumOps + PartialOrd + Copy + Clone + Debug, T: Num + NumOps + PartialOrd + Copy + Clone + Debug + Send + Sync,
CMAP: ColorMapper<T> + Debug, CMAP: ColorMapper<T> + Debug,
{ {
fn draw( fn draw(&self, render: Render) -> Option<Target> {
&self, Some(self.renderer.render(render, &self.data))
canvas: &mut femtovg::Canvas<femtovg::renderer::OpenGl>,
render: &Render,
) -> Option<Target> {
Some(self.renderer.render(render, canvas, &self.data))
} }
} }

View File

@ -1,10 +1,11 @@
use femtovg::Paint; use femtovg::{renderer::OpenGl, Canvas, Paint};
use num_traits::{Num, NumOps}; use num_traits::{Num, NumOps};
use std::path::Path; use std::path::Path;
use std::sync::Arc;
use crate::{ use crate::{
data::{DataLoader, Radar2d}, data::{AsyncDataLoader, DataLoader, Radar2d},
render::Layer render::{Layer, Render},
}; };
use super::{ use super::{
@ -13,18 +14,20 @@ use super::{
}; };
impl Layer { impl Layer {
pub fn grid_render_layer<T, CMAP>(data: Radar2d<T>, color_map: CMAP) -> Self pub fn grid_render_layer<T, CMAP>(data: Radar2d<T>, layer_name: String, color_map: CMAP) -> Self
where where
T: std::fmt::Debug + Num + NumOps + PartialOrd + Copy + Clone + 'static, T: std::fmt::Debug + Num + NumOps + PartialOrd + Copy + Clone + 'static + Send + Sync,
CMAP: ColorMapper<T> + 'static, CMAP: ColorMapper<T> + 'static,
{ {
Self::new( Self::new(
true, true,
|s, c, render, _| { |s, render, _| {
if let Some(target) = s.render_target() { if let Some(target) = s.render_target() {
let mut c = render.get_canvas();
let c = c.as_mut().unwrap();
if let Ok(_) = c.image_size(target.target) { if let Ok(_) = c.image_size(target.target) {
let (x, y) = target.size(render); let (x, y) = target.size(&render);
let (ox, oy) = target.origin(render); let (ox, oy) = target.origin(&render);
let painter = Paint::image(target.target, ox, oy, x, y, 0.0, 1.0); let painter = Paint::image(target.target, ox, oy, x, y, 0.0, 1.0);
let mut path = femtovg::Path::new(); let mut path = femtovg::Path::new();
path.rect(ox, oy, x, y); path.rect(ox, oy, x, y);
@ -32,36 +35,60 @@ impl Layer {
} }
} else { } else {
if let Some(renderer) = s.get_imp().as_ref() { if let Some(renderer) = s.get_imp().as_ref() {
let img = renderer.draw(c, render).unwrap(); let img = renderer.draw(render.clone()).unwrap();
let mut c = render.get_canvas();
let c = c.as_mut().unwrap();
if let Ok(_) = c.image_size(img.target) { if let Ok(_) = c.image_size(img.target) {
let (x, y) = img.size(render); let (x, y) = img.size(&render);
let (ox, oy) = img.origin(render); let (ox, oy) = img.origin(&render);
println!("{} {} {} {}", x, y, ox, oy); println!("{} {} {} {}", x, y, ox, oy);
let painter = Paint::image(img.target, ox, oy, x, y, 0.0, 1.0); let painter = Paint::image(img.target, ox, oy, x, y, 0.0, 1.0);
let mut path = femtovg::Path::new(); let mut path = femtovg::Path::new();
path.rect(ox, oy, x, y); path.rect(ox, oy, x, y);
s.set_render_target(img); s.set_render_target(img);
c.fill_path(&path, &painter); c.fill_path(&path, &painter);
c.flush();
} }
} }
} }
}, },
layer_name,
Some(|s: Arc<Layer>, render: Render| async move {
if let None = s.render_target() {
if let Some(renderer) = s.get_imp().as_ref() {}
}
}),
Some(GridLayerImpl::new(GridFieldRenderer::new(color_map), data)), Some(GridLayerImpl::new(GridFieldRenderer::new(color_map), data)),
) )
} }
pub fn grid_render_layer_with_path<T, CMAP, LOADER>( pub fn grid_render_layer_with_path<T, CMAP, LOADER>(
path: impl AsRef<Path>, path: impl AsRef<Path>,
layer_name: String,
loader: LOADER, loader: LOADER,
color_map: CMAP, color_map: CMAP,
) -> Self ) -> Self
where where
T: Num + NumOps + PartialOrd + Copy + Clone + 'static + std::fmt::Debug, T: Num + NumOps + PartialOrd + Copy + Clone + 'static + std::fmt::Debug + Sync + Send,
CMAP: ColorMapper<T> + 'static, CMAP: ColorMapper<T> + 'static,
LOADER: DataLoader<T, Radar2d<T>>, LOADER: DataLoader<T, Radar2d<T>>,
{ {
let data = loader.load(path).unwrap(); let data = loader.load(path).unwrap();
self::Layer::grid_render_layer(data, color_map) self::Layer::grid_render_layer(data, layer_name, color_map)
}
pub async fn grid_render_layer_with_path_async<T, CMAP, LOADER>(
path: impl AsRef<Path> + Send,
layer_name: String,
loader: LOADER,
color_map: CMAP,
) -> Self
where
T: Num + NumOps + PartialOrd + Copy + Clone + 'static + std::fmt::Debug + Send + Sync,
CMAP: ColorMapper<T> + 'static,
LOADER: AsyncDataLoader<T, Radar2d<T>>,
{
let data = loader.load(path).await.unwrap();
self::Layer::grid_render_layer(data, layer_name, color_map)
} }
} }

View File

@ -1,13 +1,8 @@
use femtovg::{renderer::OpenGl, Canvas};
use super::Target;
use super::Render; use super::Render;
use super::Target;
use femtovg::{renderer::OpenGl, Canvas};
pub trait DataRenderer { pub trait DataRenderer {
type Data; type Data;
fn render( fn render(&self, render: Render, data: &Self::Data) -> Target;
&self,
render: &Render,
canvas: &mut Canvas<OpenGl>,
data: &Self::Data,
) -> Target;
} }