Initial commit. WIP blur implementation. Grid struct is tentatively ready. Model struct is in its nascency.
This commit is contained in:
commit
e21a61250e
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/target
|
||||||
|
|
||||||
|
# CLion
|
||||||
|
**/.idea
|
||||||
472
Cargo.lock
generated
Normal file
472
Cargo.lock
generated
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler32"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.67"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color_quant"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d60ab4a8dba064f2fbb5aa270c28da5cf4bbd0e72dae1140a6b0353a779dbe00"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"lazy_static",
|
||||||
|
"loom",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bae8f328835f8f5a6ceb6a7842a7f2d0c03692adb5c889347235d59194731fe3"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"lazy_static",
|
||||||
|
"loom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deflate"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
|
||||||
|
dependencies = [
|
||||||
|
"adler32",
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generator"
|
||||||
|
version = "0.6.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9fed24fd1e18827652b4d55652899a1e9da8e54d91624dc3437a5bc3a9f9a9c"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"rustversion",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gif"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02efba560f227847cb41463a7395c514d127d4f74fff12ef0137fff1b84b96c4"
|
||||||
|
dependencies = [
|
||||||
|
"color_quant",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image"
|
||||||
|
version = "0.23.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "293f07a1875fa7e9c5897b51aa68b2d8ed8271b87e1a44cb64b9c3d98aabbc0d"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"byteorder",
|
||||||
|
"color_quant",
|
||||||
|
"gif",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"png",
|
||||||
|
"scoped_threadpool",
|
||||||
|
"tiff",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jpeg-decoder"
|
||||||
|
version = "0.1.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
|
||||||
|
dependencies = [
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.86"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "loom"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d44c73b4636e497b4917eb21c33539efa3816741a2d3ff26c6316f1b529481a4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"generator",
|
||||||
|
"scoped-tls",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
|
||||||
|
dependencies = [
|
||||||
|
"adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "physarum"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"image",
|
||||||
|
"rand",
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.16.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"crc32fast",
|
||||||
|
"deflate",
|
||||||
|
"miniz_oxide 0.3.7",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
"rand_hc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_hc"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"lazy_static",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped-tls"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped_threadpool"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiff"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
|
||||||
|
dependencies = [
|
||||||
|
"jpeg-decoder",
|
||||||
|
"miniz_oxide 0.4.3",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.10.2+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "weezl"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "physarum"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["mindv0rtex <mindv0rtex@users.noreply.github.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
image = "*"
|
||||||
|
rand = "*"
|
||||||
|
rayon = "*"
|
||||||
1
rust-toolchain
Normal file
1
rust-toolchain
Normal file
@ -0,0 +1 @@
|
|||||||
|
nightly
|
||||||
4
rustfmt.toml
Normal file
4
rustfmt.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
unstable_features = true
|
||||||
|
imports_granularity = "Crate"
|
||||||
|
wrap_comments = true
|
||||||
|
comment_width = 100
|
||||||
124
src/blur.rs
Normal file
124
src/blur.rs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/// Approximate 1D Gaussian filter of standard deviation sigma with N box filter passes. Each
|
||||||
|
/// element in the output array contains the radius of the box filter for the corresponding pass.
|
||||||
|
pub fn boxes_for_gaussian<const N: usize>(sigma: f32) -> ([usize; N]) {
|
||||||
|
let w_ideal = (12.0 * sigma * sigma / N as f32 + 1.0).sqrt();
|
||||||
|
let mut w = w_ideal as usize;
|
||||||
|
w -= 1 - w & 1;
|
||||||
|
|
||||||
|
let mut m = ((w * w + 4 * w + 3) * N) as f32;
|
||||||
|
m -= 12.0 * sigma * sigma;
|
||||||
|
m *= 0.25;
|
||||||
|
m /= (w + 1) as f32;
|
||||||
|
let m = m.round() as usize;
|
||||||
|
|
||||||
|
let mut result = [0; N];
|
||||||
|
for (i, value) in result.iter_mut().enumerate() {
|
||||||
|
*value = (if i < m { w - 1 } else { w + 1 }) / 2;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Blur an image with 3 box filter passes. The result will be written to the src slice, while the
|
||||||
|
/// buf slice is used as a scratch space.
|
||||||
|
pub fn approximate_gauss_blur(
|
||||||
|
src: &mut [f32],
|
||||||
|
buf: &mut [f32],
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
sigma: f32,
|
||||||
|
decay: f32,
|
||||||
|
) {
|
||||||
|
let boxes = boxes_for_gaussian::<3>(sigma);
|
||||||
|
box_blur(src, buf, width, height, boxes[0], 1.0);
|
||||||
|
box_blur(src, buf, width, height, boxes[1], 1.0);
|
||||||
|
box_blur(src, buf, width, height, boxes[2], decay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform one pass of the 2D box filter of the given radius. The result will be written to the src
|
||||||
|
/// slice, while the buf slice is used as a scratch space.
|
||||||
|
fn box_blur(
|
||||||
|
src: &mut [f32],
|
||||||
|
buf: &mut [f32],
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
radius: usize,
|
||||||
|
decay: f32,
|
||||||
|
) {
|
||||||
|
box_blur_h(src, buf, width, height, radius, 1.0);
|
||||||
|
box_blur_v(buf, src, width, height, radius, decay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform one pass of the 1D box filter of the given radius along x axis. Applies the decay factor
|
||||||
|
/// to the destination buffer.
|
||||||
|
fn box_blur_h(
|
||||||
|
src: &[f32],
|
||||||
|
dst: &mut [f32],
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
radius: usize,
|
||||||
|
decay: f32,
|
||||||
|
) {
|
||||||
|
let weight = decay / (2 * radius + 1) as f32;
|
||||||
|
|
||||||
|
// TODO: Parallelize with rayon
|
||||||
|
for i in 0..height {
|
||||||
|
// First we build a value for the beginning of each row. We assume periodic boundary
|
||||||
|
// conditions, so we need to push the left index to the opposite side of the row.
|
||||||
|
let mut value = src[(i + 1) * width - radius - 1];
|
||||||
|
for j in 0..radius {
|
||||||
|
value += src[(i + 1) * width - radius + j] + src[i * width + j];
|
||||||
|
}
|
||||||
|
// At this point "value" contains the unweighted sum for the right-most row element.
|
||||||
|
|
||||||
|
for current_id in i * width..(i + 1) * width {
|
||||||
|
let left_id = ((current_id + width - radius - 1) & (width - 1)) + i * width;
|
||||||
|
let right_id = ((current_id + radius) & (width - 1)) + i * width;
|
||||||
|
value += src[right_id] - src[left_id];
|
||||||
|
dst[current_id] = value * weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform one pass of the 1D box filter of the given radius along y axis. Applies the decay factor
|
||||||
|
/// to the destination buffer.
|
||||||
|
fn box_blur_v(
|
||||||
|
src: &[f32],
|
||||||
|
dst: &mut [f32],
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
radius: usize,
|
||||||
|
decay: f32,
|
||||||
|
) {
|
||||||
|
let weight = decay / (2 * radius + 1) as f32;
|
||||||
|
|
||||||
|
// TODO: Parallelize with rayon
|
||||||
|
for i in 0..width {
|
||||||
|
// First we build a value for the beginning of each column. We assume periodic boundary
|
||||||
|
// conditions, so we need to push the bottom index to the opposite side of the column.
|
||||||
|
let mut value = src[i + (height - radius - 1) * width];
|
||||||
|
for j in 0..radius {
|
||||||
|
value += src[i + (height - radius + j) * width] + src[i + j * width];
|
||||||
|
}
|
||||||
|
// At this point "value" contains the unweighted sum for the top-most column element.
|
||||||
|
|
||||||
|
for current_id in (i..i + height * width).step_by(width) {
|
||||||
|
let bottom_id = (current_id + (height - radius - 1) * width) & (width * height - 1);
|
||||||
|
let top_id = (current_id + radius * width) & (width * height - 1);
|
||||||
|
value += src[top_id] - src[bottom_id];
|
||||||
|
dst[current_id] = value * weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_blur() {
|
||||||
|
let src = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
|
||||||
|
let mut dst = vec![0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
|
||||||
|
box_blur_v(&src, &mut dst, 2, 4, 1, 1.0);
|
||||||
|
println!("Out: {:?}", dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
95
src/grid.rs
Normal file
95
src/grid.rs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
use crate::blur::approximate_gauss_blur;
|
||||||
|
use rand::{distributions::Uniform, Rng};
|
||||||
|
|
||||||
|
/// A 2D grid with a scalar value per each grid block.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Grid {
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
data: Vec<f32>,
|
||||||
|
buf: Vec<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn is_power_of_two(x: usize) -> bool {
|
||||||
|
(x & (x - 1)) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Grid {
|
||||||
|
/// Create a new grid filled with random floats in the [0.0..1.0) range.
|
||||||
|
pub fn new(width: usize, height: usize) -> Self {
|
||||||
|
if !is_power_of_two(width) || !is_power_of_two(height) {
|
||||||
|
panic!("Grid dimensitions must be a power of two.");
|
||||||
|
}
|
||||||
|
let rng = rand::thread_rng();
|
||||||
|
let range = Uniform::from(0.0..1.0);
|
||||||
|
let data = rng.sample_iter(range).take(width * height).collect();
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
data,
|
||||||
|
buf: vec![0.0; width * height],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Truncate x and y and return a corresponding index into the data slice.
|
||||||
|
fn index(&self, x: f32, y: f32) -> usize {
|
||||||
|
let i = (x as usize + self.width) & (self.width - 1);
|
||||||
|
let j = (y as usize + self.height) & (self.height - 1);
|
||||||
|
j * self.width + i
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the data value at a given position. The implementation effectively treats data as
|
||||||
|
/// periodic, hence any finite position will produce a value.
|
||||||
|
pub fn get(&self, x: f32, y: f32) -> f32 {
|
||||||
|
self.data[self.index(x, y)]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the buffer value at a given position. The implementation effectively treats data as
|
||||||
|
/// periodic, hence any finite position will produce a value.
|
||||||
|
pub fn get_buf(&self, x: f32, y: f32) -> f32 {
|
||||||
|
self.buf[self.index(x, y)]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a value to the grid data at a given position.
|
||||||
|
pub fn add(&mut self, x: f32, y: f32, value: f32) {
|
||||||
|
let idx = self.index(x, y);
|
||||||
|
self.data[idx] += value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Diffuse grid data and apply a decay multiplier.
|
||||||
|
pub fn diffuse(&mut self, radius: usize, decay_factor: f32) {
|
||||||
|
approximate_gauss_blur(
|
||||||
|
&mut self.data,
|
||||||
|
&mut self.buf,
|
||||||
|
self.width,
|
||||||
|
self.height,
|
||||||
|
radius as f32,
|
||||||
|
decay_factor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_grid_new_panics() {
|
||||||
|
let _ = Grid::new(5, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_grid_new() {
|
||||||
|
let grid = Grid::new(8, 8);
|
||||||
|
assert_eq!(grid.index(0.5, 0.6), 0);
|
||||||
|
assert_eq!(grid.index(1.5, 0.6), 1);
|
||||||
|
assert_eq!(grid.index(0.5, 1.6), 8);
|
||||||
|
assert_eq!(grid.index(2.5, 0.6), 2);
|
||||||
|
assert_eq!(grid.index(2.5, 1.6), 10);
|
||||||
|
assert_eq!(grid.index(7.9, 7.9), 63);
|
||||||
|
assert_eq!(grid.index(-0.5, -0.6), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/main.rs
Normal file
8
src/main.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
mod blur;
|
||||||
|
mod grid;
|
||||||
|
mod model;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let boxes = blur::boxes_for_gaussian::<3>(2.5);
|
||||||
|
println!("boxes: {:?}", boxes);
|
||||||
|
}
|
||||||
32
src/model.rs
Normal file
32
src/model.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use crate::grid::Grid;
|
||||||
|
|
||||||
|
/// A single Physarum agent. The x and y positions are continuous, hence we use floating point
|
||||||
|
/// numbers instead of integers.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Agent {
|
||||||
|
pub x: f32,
|
||||||
|
pub y: f32,
|
||||||
|
pub angle: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A model configuration. We make it into a separate type, because we will eventually have multiple
|
||||||
|
/// configurations in one model.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PopulationConfig {
|
||||||
|
pub sensor_angle: f32,
|
||||||
|
pub sensor_distance: f32,
|
||||||
|
pub rotation_angle: f32,
|
||||||
|
pub step_distance: f32,
|
||||||
|
pub decay_factor: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PopulationConfig {}
|
||||||
|
|
||||||
|
/// Top-level simulation class.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Model {
|
||||||
|
grid: Grid,
|
||||||
|
agents: Vec<Agent>,
|
||||||
|
|
||||||
|
config: PopulationConfig,
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user