mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1625220 - Use euclid 0.20.8. r=gw
Differential Revision: https://phabricator.services.mozilla.com/D68469 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
ee5c428fbf
commit
430e8ef7b4
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -1197,9 +1197,9 @@ checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
||||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.20.0"
|
||||
version = "0.20.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"
|
||||
checksum = "57d9ae79e19d69ffb5b47b0a744c4215c115dfed4039314c9ca1b8ddc6c333be"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"serde",
|
||||
|
@ -11,7 +11,7 @@ webrender_debugger = ["webrender/debugger"]
|
||||
rayon = "1"
|
||||
num_cpus = "1.7.0"
|
||||
tracy-rs = "0.1"
|
||||
euclid = { version = "0.20.0", features = ["serde"] }
|
||||
euclid = { version = "0.20.8", features = ["serde"] }
|
||||
app_units = "0.7"
|
||||
gleam = "0.10.0"
|
||||
log = "0.4"
|
||||
|
59
gfx/wr/Cargo.lock
generated
59
gfx/wr/Cargo.lock
generated
@ -44,7 +44,7 @@ name = "app_units"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -53,7 +53,7 @@ name = "approx"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -79,6 +79,11 @@ name = "autocfg"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.12"
|
||||
@ -428,7 +433,7 @@ dependencies = [
|
||||
name = "direct-composition"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozangle 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender 0.61.0",
|
||||
@ -485,10 +490,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.20.0"
|
||||
version = "0.20.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -745,7 +750,7 @@ dependencies = [
|
||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"png 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -822,7 +827,7 @@ name = "line_drawing"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -988,7 +993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -996,7 +1001,7 @@ name = "num-integer"
|
||||
version = "0.1.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1005,7 +1010,7 @@ version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1014,13 +1019,16 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.4"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
@ -1048,7 +1056,7 @@ name = "ordered-float"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1097,7 +1105,7 @@ dependencies = [
|
||||
name = "peek-poke"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke-derive 0.2.1",
|
||||
]
|
||||
|
||||
@ -1133,9 +1141,9 @@ version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1633,7 +1641,7 @@ dependencies = [
|
||||
name = "tileview"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender 0.61.0",
|
||||
@ -1821,7 +1829,7 @@ dependencies = [
|
||||
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cstr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1831,7 +1839,7 @@ dependencies = [
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozangle 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plane-split 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"png 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1856,7 +1864,7 @@ dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1874,7 +1882,7 @@ dependencies = [
|
||||
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke 0.2.0",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1965,7 +1973,7 @@ name = "wr_malloc_size_of"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1983,7 +1991,7 @@ dependencies = [
|
||||
"crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"font-loader 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2074,6 +2082,7 @@ dependencies = [
|
||||
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
|
||||
"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1"
|
||||
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
|
||||
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
"checksum backtrace 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eff3830839471718ef8522b9025b399bfb713e25bc220da721364efb660d7d"
|
||||
"checksum backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5b3a000b9c543553af61bc01cbfc403b04b5caa9e421033866f2e98061eb3e61"
|
||||
"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"
|
||||
@ -2118,7 +2127,7 @@ dependencies = [
|
||||
"checksum dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0bd1369e02db5e9b842a9b67bce8a2fcc043beafb2ae8a799dd482d46ea1ff0d"
|
||||
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
|
||||
"checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a"
|
||||
"checksum euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"
|
||||
"checksum euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)" = "57d9ae79e19d69ffb5b47b0a744c4215c115dfed4039314c9ca1b8ddc6c333be"
|
||||
"checksum expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c470ccb972f2088549b023db8029ed9da9426f5affbf9b62efff7009ab8ed5b1"
|
||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
"checksum font-loader 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd330f40acb3016432cbfa4c54b3d6e6e893a538df79d8df8fd8c26e21c36aaa"
|
||||
@ -2180,7 +2189,7 @@ dependencies = [
|
||||
"checksum num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac0ea58d64a89d9d6b7688031b3be9358d6c919badcf7fbb0527ccfd891ee45"
|
||||
"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"
|
||||
"checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"
|
||||
"checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28"
|
||||
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
|
||||
"checksum objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d"
|
||||
"checksum opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51ecbcb821e1bd256d456fe858aaa7f380b63863eab2eb86eee1bd9f33dd6682"
|
||||
|
@ -4590,15 +4590,10 @@ impl PicturePrimitive {
|
||||
let world_min = map_raster_to_world.map_vector(raster_min);
|
||||
let world_max = map_raster_to_world.map_vector(raster_max);
|
||||
|
||||
let top_left = -world_max.max(vec2(0.0, 0.0));
|
||||
let bottom_right = -world_min.min(vec2(0.0, 0.0));
|
||||
|
||||
// Grow the clip in the opposite direction of the shadow's offset.
|
||||
SideOffsets2D::new(
|
||||
-top_left.y,
|
||||
bottom_right.x,
|
||||
bottom_right.y,
|
||||
-top_left.x,
|
||||
SideOffsets2D::from_vectors_outer(
|
||||
-world_max.max(vec2(0.0, 0.0)),
|
||||
-world_min.min(vec2(0.0, 0.0)),
|
||||
)
|
||||
}
|
||||
_ => SideOffsets2D::zero(),
|
||||
|
2
third_party/rust/euclid/.cargo-checksum.json
vendored
2
third_party/rust/euclid/.cargo-checksum.json
vendored
@ -1 +1 @@
|
||||
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"7ae5531c88ac476361c06e6ee5531839eff3b301c66ba05619570b3ab7926467","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/approxord.rs":"087e0a8d24b8a9bed4c1cc571eec5e50cc7afa184c6ac4961c7409a69456ec7b","src/box2d.rs":"0dc013b9bfe088e62df8675674a5430580ecfaff202d0966ba5d316e7ff0165e","src/box3d.rs":"f15962fa34ef4dec099ca7403651ac92d5be55eba7aee0300b1a2837643dcb86","src/homogen.rs":"5c14355182b4fb7c148fc65c1f63b25607019ae8d763e187d659925e2ca210a3","src/length.rs":"b1f44beb961b193bea814f5a15aee713cab97d076de13e51e294891fd7153f27","src/lib.rs":"d58eecf5847b37f68ac6604c5b5a16962756faf04f9af1f5293228486b120378","src/macros.rs":"3b475e84d00cceee6c7e96e9f2c97ba15d8dc7f4094efb82c5ed10bd60d86a64","src/nonempty.rs":"865d51dc1ae785ee2e6e94eb2ee935f29a86b9efa8daa322bca7992fa9ae70fc","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"b0eeed9f99cdd81525dd32b4d76caff862447e129b29bf55d003a35425e93ab6","src/rect.rs":"8298e2b67c7aadd255a53d42a6e5b19968aa47fcff05f8c60f4073da0a808dfc","src/rigid.rs":"aab59591562938695e63487230504b2d94df6e3a7b7740069166c8499d4fa930","src/rotation.rs":"307b22df279f30e4ac4aa35a0d69fb7f9196bd553c06b7f519692655e1e353d3","src/scale.rs":"6a4c3da9444c72e967d5217bbe5442a8517448857cb32472f883d6da58b8f846","src/side_offsets.rs":"eaa52aa64f0fa041fbd5c1c9165a01614db6c37d4746a56c3294a388bd5e0616","src/size.rs":"b3478be99f4409d3083e7553f5906c8ac314beddb83cc87492415c02785b8311","src/transform2d.rs":"8a0b4f097c8e98408dfe709b3ef0e8530562a6e1b68f62d6cd86c906cc0bb7eb","src/transform3d.rs":"6a6d56b67fdb1b6d4bfd725959d6b95cf4fa5ffbc272ae9f1508a400a3a4b30e","src/translation.rs":"67afb126179e3cb5a2c1bd462a8f5c87630233a68f63ff6a2194dbd3b229d734","src/trig.rs":"97a263c4f178b0332501659ca8143f9f637a0755aca189dd31ac551bcd4cb73c","src/vector.rs":"ca39c30729f781dd5e64b5fea1516e676b6ab4fc57788895fa2ca5309ad73ec3"},"package":"2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"}
|
||||
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"c4a674cb74720c00564b769ece718e999df001023762356400c943b89424a578","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/angle.rs":"e16bf0419d8dcfac421c097ce744d0b1ca0887c479e779124388d9da9b009c1c","src/approxeq.rs":"8ad9ab7336e1924b0543eb46f975367f4388a4dda91839b7cda7d21eec8991fb","src/approxord.rs":"f1b11ea7603b3dddb0002c7ded934816f5a8bb108e150028b49595b8e3382ac1","src/box2d.rs":"232dea6d2684851f190e7eca97a9ef956f2813ae1f1d18e500e036cf2d7fb0d4","src/box3d.rs":"1372dc7a0e610d07696ec275682b49a3b2b1c97bed50de6532862317793690d2","src/homogen.rs":"37c9bc61e557b155b4f7e0a002078f0d2fa6ed5b498cefb4742affb521f6ceb4","src/length.rs":"fadb8c272acbbd34fa4c531450f6aee5450408a186cc3ccdf2d1102ee9430545","src/lib.rs":"4a7eac719427b4a907c81da2d2294f1904421b7fd440cf9a211e1eb7b1918c8a","src/macros.rs":"3b475e84d00cceee6c7e96e9f2c97ba15d8dc7f4094efb82c5ed10bd60d86a64","src/nonempty.rs":"69d62da24751efe2e8af2bb26713633c7445dbbd02e82b8146bad602002792df","src/num.rs":"189286d1dc06df5d31430e161fe45fd4da4fc2b3df5059d88044b7b30b87f2b2","src/point.rs":"4c94c1265f5629753f0e5a4040aeb617583ca81d4c9e2652bfc6c22019b57458","src/rect.rs":"018c3d4f82c07257e1b369f6c877dcfe19a9a105577d88ba39b6f713978d4328","src/rigid.rs":"b2b9c17fb75cb2b748ee8c78fab85a30961cc1fa7c4cc794244284b1aaf9bd08","src/rotation.rs":"2f2e92febee5e76c4fe94bda560b2b31cdaaaf068d35cae0e4ec3831901a2f6c","src/scale.rs":"b1a26dbcce145149c13bd8541838fb33a5e1c919717153adc716857d3acf49c2","src/side_offsets.rs":"e0d95daf9dd4e4ceb709a369dcdea10aa0dbde17e059b6a3c6d05a256f134838","src/size.rs":"3c76c1e35163bdd9ba45847154ce3e0f8fd5c1bb8ac5686bb4e239e328766447","src/transform2d.rs":"505fb0380353bd11d718228822d46a71f6c8b02f7fc360ab14168e6a87604b60","src/transform3d.rs":"b4d4e427ce047c9dc8055ed0d8be2411a4eeb0874627bf5ca004d3aae8b2e752","src/translation.rs":"d01894715e99c314a475b9e6b94a60062cf13a75428932012360d11ab6b0fa8e","src/trig.rs":"ab09a8503d04ac1d0d6848d074ac18a22d324184e5bb186bbd4287c977894886","src/vector.rs":"94ad9104a0a540d3441105d7b2a37ec1eb368273f0b68534dec19ffaf313c4d7"},"package":"57d9ae79e19d69ffb5b47b0a744c4215c115dfed4039314c9ca1b8ddc6c333be"}
|
9
third_party/rust/euclid/Cargo.toml
vendored
9
third_party/rust/euclid/Cargo.toml
vendored
@ -12,7 +12,7 @@
|
||||
|
||||
[package]
|
||||
name = "euclid"
|
||||
version = "0.20.0"
|
||||
version = "0.20.8"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "Geometry primitives"
|
||||
documentation = "https://docs.rs/euclid/"
|
||||
@ -25,14 +25,19 @@ version = "0.5.1"
|
||||
optional = true
|
||||
|
||||
[dependencies.num-traits]
|
||||
version = "0.2"
|
||||
version = "0.2.10"
|
||||
default-features = false
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
features = ["serde_derive"]
|
||||
optional = true
|
||||
default-features = false
|
||||
[dev-dependencies.serde_test]
|
||||
version = "1.0"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
libm = ["num-traits/libm"]
|
||||
std = ["num-traits/std"]
|
||||
unstable = []
|
||||
|
244
third_party/rust/euclid/src/angle.rs
vendored
Normal file
244
third_party/rust/euclid/src/angle.rs
vendored
Normal file
@ -0,0 +1,244 @@
|
||||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use num_traits::{Float, FloatConst, Zero};
|
||||
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
use trig::Trig;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
|
||||
/// An angle in radians
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Angle<T> {
|
||||
pub radians: T,
|
||||
}
|
||||
|
||||
impl<T> Angle<T> {
|
||||
#[inline]
|
||||
pub fn radians(radians: T) -> Self {
|
||||
Angle { radians }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(self) -> T {
|
||||
self.radians
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
where
|
||||
T: Trig,
|
||||
{
|
||||
#[inline]
|
||||
pub fn degrees(deg: T) -> Self {
|
||||
Angle {
|
||||
radians: T::degrees_to_radians(deg),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_degrees(self) -> T {
|
||||
T::radians_to_degrees(self.radians)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
where
|
||||
T: Rem<Output = T> + Sub<Output = T> + Add<Output = T> + Zero + FloatConst + PartialOrd + Copy,
|
||||
{
|
||||
/// Returns this angle in the [0..2*PI[ range.
|
||||
pub fn positive(&self) -> Self {
|
||||
let two_pi = T::PI() + T::PI();
|
||||
let mut a = self.radians % two_pi;
|
||||
if a < T::zero() {
|
||||
a = a + two_pi;
|
||||
}
|
||||
Angle::radians(a)
|
||||
}
|
||||
|
||||
/// Returns this angle in the ]-PI..PI] range.
|
||||
pub fn signed(&self) -> Self {
|
||||
Angle::pi() - (Angle::pi() - *self).positive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
where
|
||||
T: Float,
|
||||
{
|
||||
/// Returns (sin(self), cos(self)).
|
||||
pub fn sin_cos(self) -> (T, T) {
|
||||
self.radians.sin_cos()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
where
|
||||
T: Zero,
|
||||
{
|
||||
pub fn zero() -> Self {
|
||||
Angle::radians(T::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
where
|
||||
T: FloatConst + Add<Output = T>,
|
||||
{
|
||||
pub fn pi() -> Self {
|
||||
Angle::radians(T::PI())
|
||||
}
|
||||
|
||||
pub fn two_pi() -> Self {
|
||||
Angle::radians(T::PI() + T::PI())
|
||||
}
|
||||
|
||||
pub fn frac_pi_2() -> Self {
|
||||
Angle::radians(T::FRAC_PI_2())
|
||||
}
|
||||
|
||||
pub fn frac_pi_3() -> Self {
|
||||
Angle::radians(T::FRAC_PI_3())
|
||||
}
|
||||
|
||||
pub fn frac_pi_4() -> Self {
|
||||
Angle::radians(T::FRAC_PI_4())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Add<T, Output = T>> Add for Angle<T> {
|
||||
type Output = Angle<T>;
|
||||
fn add(self, other: Angle<T>) -> Angle<T> {
|
||||
Angle::radians(self.radians + other.radians)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AddAssign<T>> AddAssign for Angle<T> {
|
||||
fn add_assign(&mut self, other: Angle<T>) {
|
||||
self.radians += other.radians;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Sub<T, Output = T>> Sub<Angle<T>> for Angle<T> {
|
||||
type Output = Angle<T>;
|
||||
fn sub(self, other: Angle<T>) -> <Self as Sub>::Output {
|
||||
Angle::radians(self.radians - other.radians)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SubAssign<T>> SubAssign for Angle<T> {
|
||||
fn sub_assign(&mut self, other: Angle<T>) {
|
||||
self.radians -= other.radians;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Div<T, Output = T>> Div<Angle<T>> for Angle<T> {
|
||||
type Output = T;
|
||||
#[inline]
|
||||
fn div(self, other: Angle<T>) -> T {
|
||||
self.radians / other.radians
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Div<T, Output = T>> Div<T> for Angle<T> {
|
||||
type Output = Angle<T>;
|
||||
#[inline]
|
||||
fn div(self, factor: T) -> Angle<T> {
|
||||
Angle::radians(self.radians / factor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: DivAssign<T>> DivAssign<T> for Angle<T> {
|
||||
fn div_assign(&mut self, factor: T) {
|
||||
self.radians /= factor;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Mul<T, Output = T>> Mul<T> for Angle<T> {
|
||||
type Output = Angle<T>;
|
||||
#[inline]
|
||||
fn mul(self, factor: T) -> Angle<T> {
|
||||
Angle::radians(self.radians * factor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MulAssign<T>> MulAssign<T> for Angle<T> {
|
||||
fn mul_assign(&mut self, factor: T) {
|
||||
self.radians *= factor;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Neg<Output = T>> Neg for Angle<T> {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self {
|
||||
Angle::radians(-self.radians)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrap_angles() {
|
||||
use approxeq::ApproxEq;
|
||||
use core::f32::consts::{FRAC_PI_2, PI};
|
||||
|
||||
assert!(Angle::radians(0.0).positive().radians.approx_eq(&0.0));
|
||||
assert!(
|
||||
Angle::radians(FRAC_PI_2)
|
||||
.positive()
|
||||
.radians
|
||||
.approx_eq(&FRAC_PI_2)
|
||||
);
|
||||
assert!(
|
||||
Angle::radians(-FRAC_PI_2)
|
||||
.positive()
|
||||
.radians
|
||||
.approx_eq(&(3.0 * FRAC_PI_2))
|
||||
);
|
||||
assert!(
|
||||
Angle::radians(3.0 * FRAC_PI_2)
|
||||
.positive()
|
||||
.radians
|
||||
.approx_eq(&(3.0 * FRAC_PI_2))
|
||||
);
|
||||
assert!(
|
||||
Angle::radians(5.0 * FRAC_PI_2)
|
||||
.positive()
|
||||
.radians
|
||||
.approx_eq(&FRAC_PI_2)
|
||||
);
|
||||
assert!(Angle::radians(2.0 * PI).positive().radians.approx_eq(&0.0));
|
||||
assert!(Angle::radians(-2.0 * PI).positive().radians.approx_eq(&0.0));
|
||||
assert!(Angle::radians(PI).positive().radians.approx_eq(&PI));
|
||||
assert!(Angle::radians(-PI).positive().radians.approx_eq(&PI));
|
||||
|
||||
assert!(
|
||||
Angle::radians(FRAC_PI_2)
|
||||
.signed()
|
||||
.radians
|
||||
.approx_eq(&FRAC_PI_2)
|
||||
);
|
||||
assert!(
|
||||
Angle::radians(3.0 * FRAC_PI_2)
|
||||
.signed()
|
||||
.radians
|
||||
.approx_eq(&-FRAC_PI_2)
|
||||
);
|
||||
assert!(
|
||||
Angle::radians(5.0 * FRAC_PI_2)
|
||||
.signed()
|
||||
.radians
|
||||
.approx_eq(&FRAC_PI_2)
|
||||
);
|
||||
assert!(Angle::radians(2.0 * PI).signed().radians.approx_eq(&0.0));
|
||||
assert!(Angle::radians(-2.0 * PI).signed().radians.approx_eq(&0.0));
|
||||
assert!(Angle::radians(-PI).signed().radians.approx_eq(&PI));
|
||||
assert!(Angle::radians(PI).signed().radians.approx_eq(&PI));
|
||||
}
|
23
third_party/rust/euclid/src/approxeq.rs
vendored
23
third_party/rust/euclid/src/approxeq.rs
vendored
@ -9,26 +9,33 @@
|
||||
|
||||
/// Trait for testing approximate equality
|
||||
pub trait ApproxEq<Eps> {
|
||||
/// Default epsilon value
|
||||
fn approx_epsilon() -> Eps;
|
||||
fn approx_eq(&self, other: &Self) -> bool;
|
||||
|
||||
/// Returns `true` is this object is approximately equal to the other one, using
|
||||
/// a provided epsilon value.
|
||||
fn approx_eq_eps(&self, other: &Self, approx_epsilon: &Eps) -> bool;
|
||||
|
||||
/// Returns `true` is this object is approximately equal to the other one, using
|
||||
/// the `approx_epsilon()` epsilon value.
|
||||
fn approx_eq(&self, other: &Self) -> bool {
|
||||
self.approx_eq_eps(other, &Self::approx_epsilon())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! approx_eq {
|
||||
($ty:ty, $eps:expr) => (
|
||||
($ty:ty, $eps:expr) => {
|
||||
impl ApproxEq<$ty> for $ty {
|
||||
#[inline]
|
||||
fn approx_epsilon() -> $ty { $eps }
|
||||
#[inline]
|
||||
fn approx_eq(&self, other: &$ty) -> bool {
|
||||
self.approx_eq_eps(other, &$eps)
|
||||
fn approx_epsilon() -> $ty {
|
||||
$eps
|
||||
}
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$ty, approx_epsilon: &$ty) -> bool {
|
||||
(*self - *other).abs() < *approx_epsilon
|
||||
num_traits::Float::abs(*self - *other) < *approx_epsilon
|
||||
}
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
approx_eq!(f32, 1.0e-6);
|
||||
|
5
third_party/rust/euclid/src/approxord.rs
vendored
5
third_party/rust/euclid/src/approxord.rs
vendored
@ -7,8 +7,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/// Utilities for testing approximate ordering - especially true for
|
||||
/// floating point types, where NaN's cannot be ordered.
|
||||
//! Utilities for testing approximate ordering - especially true for
|
||||
//! floating point types, where NaN's cannot be ordered.
|
||||
|
||||
pub fn min<T: PartialOrd>(x: T, y: T) -> T {
|
||||
if x <= y {
|
||||
x
|
||||
|
182
third_party/rust/euclid/src/box2d.rs
vendored
182
third_party/rust/euclid/src/box2d.rs
vendored
@ -47,9 +47,9 @@ impl<T: Hash, U> Hash for Box2D<T, U> {
|
||||
|
||||
impl<T: Copy, U> Copy for Box2D<T, U> {}
|
||||
|
||||
impl<T: Copy, U> Clone for Box2D<T, U> {
|
||||
impl<T: Clone, U> Clone for Box2D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
Self::new(self.min.clone(), self.max.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +75,8 @@ impl<T: fmt::Display, U> fmt::Display for Box2D<T, U> {
|
||||
|
||||
impl<T, U> Box2D<T, U> {
|
||||
/// Constructor.
|
||||
pub fn new(min: Point2D<T, U>, max: Point2D<T, U>) -> Self {
|
||||
#[inline]
|
||||
pub const fn new(min: Point2D<T, U>, max: Point2D<T, U>) -> Self {
|
||||
Box2D {
|
||||
min,
|
||||
max,
|
||||
@ -98,7 +99,7 @@ where
|
||||
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
T: PartialOrd,
|
||||
{
|
||||
/// Returns true if the box has a negative area.
|
||||
///
|
||||
@ -115,16 +116,7 @@ where
|
||||
self.max.x <= self.min.x || self.max.y <= self.min.y
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_non_empty(&self) -> Option<NonEmpty<Self>> {
|
||||
if self.is_empty_or_negative() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(NonEmpty(*self))
|
||||
}
|
||||
|
||||
/// Returns true if the two boxes intersect.
|
||||
/// Returns `true` if the two boxes intersect.
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
self.min.x < other.max.x
|
||||
@ -133,6 +125,38 @@ where
|
||||
&& self.max.y > other.min.y
|
||||
}
|
||||
|
||||
/// Returns `true` if this box contains the point. Points are considered
|
||||
/// in the box if they are on the front, left or top faces, but outside if they
|
||||
/// are on the back, right or bottom faces.
|
||||
#[inline]
|
||||
pub fn contains(&self, p: Point2D<T, U>) -> bool {
|
||||
self.min.x <= p.x && p.x < self.max.x
|
||||
&& self.min.y <= p.y && p.y < self.max.y
|
||||
}
|
||||
|
||||
/// Returns `true` if this box contains the interior of the other box. Always
|
||||
/// returns `true` if other is empty, and always returns `false` if other is
|
||||
/// nonempty but this box is empty.
|
||||
#[inline]
|
||||
pub fn contains_box(&self, other: &Self) -> bool {
|
||||
other.is_empty_or_negative()
|
||||
|| (self.min.x <= other.min.x && other.max.x <= self.max.x
|
||||
&& self.min.y <= other.min.y && other.max.y <= self.max.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
#[inline]
|
||||
pub fn to_non_empty(&self) -> Option<NonEmpty<Self>> {
|
||||
if self.is_empty_or_negative() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(NonEmpty(*self))
|
||||
}
|
||||
/// Computes the intersection of two boxes.
|
||||
///
|
||||
/// The result is a negative box if the boxes do not intersect.
|
||||
@ -177,35 +201,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero,
|
||||
{
|
||||
/// Returns true if this box contains the point. Points are considered
|
||||
/// in the box if they are on the front, left or top faces, but outside if they
|
||||
/// are on the back, right or bottom faces.
|
||||
#[inline]
|
||||
pub fn contains(&self, p: Point2D<T, U>) -> bool {
|
||||
self.min.x <= p.x && p.x < self.max.x
|
||||
&& self.min.y <= p.y && p.y < self.max.y
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero + Sub<T, Output = T>,
|
||||
{
|
||||
/// Returns true if this box contains the interior of the other box. Always
|
||||
/// returns true if other is empty, and always returns false if other is
|
||||
/// nonempty but this box is empty.
|
||||
#[inline]
|
||||
pub fn contains_box(&self, other: &Self) -> bool {
|
||||
other.is_empty_or_negative()
|
||||
|| (self.min.x <= other.min.x && other.max.x <= self.max.x
|
||||
&& self.min.y <= other.min.y && other.max.y <= self.max.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + Sub<T, Output = T>,
|
||||
@ -215,6 +210,16 @@ where
|
||||
(self.max - self.min).to_size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn width(&self) -> T {
|
||||
self.max.x - self.min.x
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn height(&self) -> T {
|
||||
self.max.y - self.min.y
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_rect(&self) -> Rect<T, U> {
|
||||
Rect {
|
||||
@ -278,37 +283,25 @@ where
|
||||
{
|
||||
let mut points = points.into_iter();
|
||||
|
||||
// Need at least 2 different points for a valid box (ie: volume > 0).
|
||||
let (mut min_x, mut min_y) = match points.next() {
|
||||
Some(first) => (first.borrow().x, first.borrow().y),
|
||||
None => return Box2D::zero(),
|
||||
};
|
||||
|
||||
let (mut max_x, mut max_y) = (min_x, min_y);
|
||||
|
||||
{
|
||||
let mut assign_min_max = |point: I::Item| {
|
||||
let p = point.borrow();
|
||||
if p.x < min_x {
|
||||
min_x = p.x
|
||||
}
|
||||
if p.x > max_x {
|
||||
max_x = p.x
|
||||
}
|
||||
if p.y < min_y {
|
||||
min_y = p.y
|
||||
}
|
||||
if p.y > max_y {
|
||||
max_y = p.y
|
||||
}
|
||||
};
|
||||
|
||||
match points.next() {
|
||||
Some(second) => assign_min_max(second),
|
||||
None => return Box2D::zero(),
|
||||
for point in points {
|
||||
let p = point.borrow();
|
||||
if p.x < min_x {
|
||||
min_x = p.x
|
||||
}
|
||||
|
||||
for point in points {
|
||||
assign_min_max(point);
|
||||
if p.x > max_x {
|
||||
max_x = p.x
|
||||
}
|
||||
if p.y < min_y {
|
||||
min_y = p.y
|
||||
}
|
||||
if p.y > max_y {
|
||||
max_y = p.y
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +318,8 @@ where
|
||||
{
|
||||
/// Linearly interpolate between this box and another box.
|
||||
///
|
||||
/// `t` is expected to be between zero and one.
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
Self::new(
|
||||
@ -393,7 +387,7 @@ where
|
||||
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + Zero,
|
||||
T: Zero,
|
||||
{
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
@ -456,34 +450,43 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Unit> Box2D<T, Unit>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Box2D<T, UnknownUnit> {
|
||||
Box2D::new(self.min.to_untyped(), self.max.to_untyped())
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(c: &Box2D<T, UnknownUnit>) -> Box2D<T, Unit> {
|
||||
#[inline]
|
||||
pub fn from_untyped(c: &Box2D<T, UnknownUnit>) -> Box2D<T, U> {
|
||||
Box2D::new(
|
||||
Point2D::from_untyped(c.min),
|
||||
Point2D::from_untyped(c.max),
|
||||
)
|
||||
}
|
||||
|
||||
/// Cast the unit
|
||||
#[inline]
|
||||
pub fn cast_unit<V>(&self) -> Box2D<T, V> {
|
||||
Box2D::new(self.min.cast_unit(), self.max.cast_unit())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0, Unit> Box2D<T0, Unit>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T0: NumCast + Copy,
|
||||
T: NumCast + Copy,
|
||||
{
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Box2D<T1, Unit> {
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Box2D<NewT, U> {
|
||||
Box2D::new(
|
||||
self.min.cast(),
|
||||
self.max.cast(),
|
||||
@ -495,7 +498,7 @@ where
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Box2D<T1, Unit>> {
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Box2D<NewT, U>> {
|
||||
match (self.min.try_cast(), self.max.try_cast()) {
|
||||
(Some(a), Some(b)) => Some(Box2D::new(a, b)),
|
||||
_ => None,
|
||||
@ -546,14 +549,16 @@ where
|
||||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, Unit> Box2D<T, Unit> {
|
||||
impl<T: NumCast + Copy, U> Box2D<T, U> {
|
||||
/// Cast into an `f32` box.
|
||||
pub fn to_f32(&self) -> Box2D<f32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Box2D<f32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` box.
|
||||
pub fn to_f64(&self) -> Box2D<f64, Unit> {
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Box2D<f64, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -562,7 +567,8 @@ impl<T: NumCast + Copy, Unit> Box2D<T, Unit> {
|
||||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> Box2D<usize, Unit> {
|
||||
#[inline]
|
||||
pub fn to_usize(&self) -> Box2D<usize, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -571,7 +577,8 @@ impl<T: NumCast + Copy, Unit> Box2D<T, Unit> {
|
||||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> Box2D<u32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_u32(&self) -> Box2D<u32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -580,7 +587,8 @@ impl<T: NumCast + Copy, Unit> Box2D<T, Unit> {
|
||||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> Box2D<i32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_i32(&self) -> Box2D<i32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -589,7 +597,8 @@ impl<T: NumCast + Copy, Unit> Box2D<T, Unit> {
|
||||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> Box2D<i64, Unit> {
|
||||
#[inline]
|
||||
pub fn to_i64(&self) -> Box2D<i64, U> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
@ -617,6 +626,13 @@ mod tests {
|
||||
assert_eq!(b.size().height, 20.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_width_height() {
|
||||
let b = Box2D::new(point2(-10.0, -10.0), point2(10.0, 10.0));
|
||||
assert!(b.width() == 20.0);
|
||||
assert!(b.height() == 20.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_center() {
|
||||
let b = Box2D::new(point2(-10.0, -10.0), point2(10.0, 10.0));
|
||||
|
218
third_party/rust/euclid/src/box3d.rs
vendored
218
third_party/rust/euclid/src/box3d.rs
vendored
@ -10,7 +10,7 @@
|
||||
use super::UnknownUnit;
|
||||
use scale::Scale;
|
||||
use num::*;
|
||||
use point::Point3D;
|
||||
use point::{Point3D, point3};
|
||||
use vector::Vector3D;
|
||||
use size::Size3D;
|
||||
use approxord::{min, max};
|
||||
@ -32,7 +32,7 @@ use core::ops::{Add, Div, Mul, Sub};
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
|
||||
pub struct Box3D<T, U> {
|
||||
pub min: Point3D<T, U>,
|
||||
pub min: Point3D<T, U>,
|
||||
pub max: Point3D<T, U>,
|
||||
}
|
||||
|
||||
@ -45,9 +45,9 @@ impl<T: Hash, U> Hash for Box3D<T, U> {
|
||||
|
||||
impl<T: Copy, U> Copy for Box3D<T, U> {}
|
||||
|
||||
impl<T: Copy, U> Clone for Box3D<T, U> {
|
||||
impl<T: Clone, U> Clone for Box3D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
Self::new(self.min.clone(), self.max.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,8 @@ impl<T: fmt::Display, U> fmt::Display for Box3D<T, U> {
|
||||
|
||||
impl<T, U> Box3D<T, U> {
|
||||
/// Constructor.
|
||||
pub fn new(min: Point3D<T, U>, max: Point3D<T, U>) -> Self {
|
||||
#[inline]
|
||||
pub const fn new(min: Point3D<T, U>, max: Point3D<T, U>) -> Self {
|
||||
Box3D {
|
||||
min,
|
||||
max,
|
||||
@ -96,7 +97,7 @@ where
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
T: PartialOrd,
|
||||
{
|
||||
/// Returns true if the box has a negative volume.
|
||||
///
|
||||
@ -113,15 +114,6 @@ where
|
||||
self.max.x <= self.min.x || self.max.y <= self.min.y || self.max.z <= self.min.z
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_non_empty(&self) -> Option<NonEmpty<Self>> {
|
||||
if self.is_empty_or_negative() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(NonEmpty(*self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
self.min.x < other.max.x
|
||||
@ -132,6 +124,41 @@ where
|
||||
&& self.max.z > other.min.z
|
||||
}
|
||||
|
||||
/// Returns `true` if this box3d contains the point. Points are considered
|
||||
/// in the box3d if they are on the front, left or top faces, but outside if they
|
||||
/// are on the back, right or bottom faces.
|
||||
#[inline]
|
||||
pub fn contains(&self, other: Point3D<T, U>) -> bool {
|
||||
self.min.x <= other.x && other.x < self.max.x
|
||||
&& self.min.y <= other.y && other.y < self.max.y
|
||||
&& self.min.z <= other.z && other.z < self.max.z
|
||||
}
|
||||
|
||||
/// Returns `true` if this box3d contains the interior of the other box3d. Always
|
||||
/// returns `true` if other is empty, and always returns `false` if other is
|
||||
/// nonempty but this box3d is empty.
|
||||
#[inline]
|
||||
pub fn contains_box(&self, other: &Self) -> bool {
|
||||
other.is_empty_or_negative()
|
||||
|| (self.min.x <= other.min.x && other.max.x <= self.max.x
|
||||
&& self.min.y <= other.min.y && other.max.y <= self.max.y
|
||||
&& self.min.z <= other.min.z && other.max.z <= self.max.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
#[inline]
|
||||
pub fn to_non_empty(&self) -> Option<NonEmpty<Self>> {
|
||||
if self.is_empty_or_negative() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(NonEmpty(*self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_intersection(&self, other: &Self) -> Option<NonEmpty<Self>> {
|
||||
if !self.intersects(other) {
|
||||
@ -155,7 +182,7 @@ where
|
||||
);
|
||||
|
||||
Box3D::new(
|
||||
intersection_min,
|
||||
intersection_min,
|
||||
intersection_max,
|
||||
)
|
||||
}
|
||||
@ -176,37 +203,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero,
|
||||
{
|
||||
/// Returns true if this box3d contains the point. Points are considered
|
||||
/// in the box3d if they are on the front, left or top faces, but outside if they
|
||||
/// are on the back, right or bottom faces.
|
||||
#[inline]
|
||||
pub fn contains(&self, other: Point3D<T, U>) -> bool {
|
||||
self.min.x <= other.x && other.x < self.max.x
|
||||
&& self.min.y <= other.y && other.y < self.max.y
|
||||
&& self.min.z <= other.z && other.z < self.max.z
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero + Sub<T, Output = T>,
|
||||
{
|
||||
/// Returns true if this box3d contains the interior of the other box3d. Always
|
||||
/// returns true if other is empty, and always returns false if other is
|
||||
/// nonempty but this box3d is empty.
|
||||
#[inline]
|
||||
pub fn contains_box(&self, other: &Self) -> bool {
|
||||
other.is_empty_or_negative()
|
||||
|| (self.min.x <= other.min.x && other.max.x <= self.max.x
|
||||
&& self.min.y <= other.min.y && other.max.y <= self.max.y
|
||||
&& self.min.z <= other.min.z && other.max.z <= self.max.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + Sub<T, Output = T>,
|
||||
@ -219,6 +215,21 @@ where
|
||||
self.max.z - self.min.z,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn width(&self) -> T {
|
||||
self.max.x - self.min.x
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn height(&self) -> T {
|
||||
self.max.y - self.min.y
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn depth(&self) -> T {
|
||||
self.max.z - self.min.z
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
@ -248,47 +259,38 @@ where
|
||||
{
|
||||
let mut points = points.into_iter();
|
||||
|
||||
// Need at least 2 different points for a valid box3d (ie: volume > 0).
|
||||
let (mut min_x, mut min_y, mut min_z) = match points.next() {
|
||||
Some(first) => (first.borrow().x, first.borrow().y, first.borrow().z),
|
||||
None => return Box3D::zero(),
|
||||
};
|
||||
let (mut max_x, mut max_y, mut max_z) = (min_x, min_y, min_z);
|
||||
|
||||
{
|
||||
let mut assign_min_max = |point: I::Item| {
|
||||
let p = point.borrow();
|
||||
if p.x < min_x {
|
||||
min_x = p.x
|
||||
}
|
||||
if p.x > max_x {
|
||||
max_x = p.x
|
||||
}
|
||||
if p.y < min_y {
|
||||
min_y = p.y
|
||||
}
|
||||
if p.y > max_y {
|
||||
max_y = p.y
|
||||
}
|
||||
if p.z < min_z {
|
||||
min_z = p.z
|
||||
}
|
||||
if p.z > max_z {
|
||||
max_z = p.z
|
||||
}
|
||||
};
|
||||
|
||||
match points.next() {
|
||||
Some(second) => assign_min_max(second),
|
||||
None => return Box3D::zero(),
|
||||
for point in points {
|
||||
let p = point.borrow();
|
||||
if p.x < min_x {
|
||||
min_x = p.x
|
||||
}
|
||||
|
||||
for point in points {
|
||||
assign_min_max(point);
|
||||
if p.x > max_x {
|
||||
max_x = p.x
|
||||
}
|
||||
if p.y < min_y {
|
||||
min_y = p.y
|
||||
}
|
||||
if p.y > max_y {
|
||||
max_y = p.y
|
||||
}
|
||||
if p.z < min_z {
|
||||
min_z = p.z
|
||||
}
|
||||
if p.z > max_z {
|
||||
max_z = p.z
|
||||
}
|
||||
}
|
||||
|
||||
Self::new(Point3D::new(min_x, min_y, min_z), Point3D::new(max_x, max_y, max_z))
|
||||
Box3D {
|
||||
min: point3(min_x, min_y, min_z),
|
||||
max: point3(max_x, max_y, max_z),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,7 +300,8 @@ where
|
||||
{
|
||||
/// Linearly interpolate between this box3d and another box3d.
|
||||
///
|
||||
/// `t` is expected to be between zero and one.
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
Self::new(
|
||||
@ -320,7 +323,7 @@ where
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + Clone + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
@ -384,9 +387,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + Zero,
|
||||
T: Zero,
|
||||
{
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
@ -449,7 +452,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Unit> Box3D<T, Unit>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
@ -464,24 +467,31 @@ where
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(c: &Box3D<T, UnknownUnit>) -> Box3D<T, Unit> {
|
||||
pub fn from_untyped(c: &Box3D<T, UnknownUnit>) -> Box3D<T, U> {
|
||||
Box3D {
|
||||
min: Point3D::from_untyped(c.min),
|
||||
max: Point3D::from_untyped(c.max),
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast the unit
|
||||
#[inline]
|
||||
pub fn cast_unit<V>(&self) -> Box3D<T, V> {
|
||||
Box3D::new(self.min.cast_unit(), self.max.cast_unit())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0, Unit> Box3D<T0, Unit>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T0: NumCast + Copy,
|
||||
T: NumCast + Copy,
|
||||
{
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Box3D<T1, Unit> {
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Box3D<NewT, U> {
|
||||
Box3D::new(
|
||||
self.min.cast(),
|
||||
self.max.cast(),
|
||||
@ -493,7 +503,7 @@ where
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Box3D<T1, Unit>> {
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Box3D<NewT, U>> {
|
||||
match (self.min.try_cast(), self.max.try_cast()) {
|
||||
(Some(a), Some(b)) => Some(Box3D::new(a, b)),
|
||||
_ => None,
|
||||
@ -546,14 +556,16 @@ where
|
||||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, Unit> Box3D<T, Unit> {
|
||||
impl<T: NumCast + Copy, U> Box3D<T, U> {
|
||||
/// Cast into an `f32` box3d.
|
||||
pub fn to_f32(&self) -> Box3D<f32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Box3D<f32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` box3d.
|
||||
pub fn to_f64(&self) -> Box3D<f64, Unit> {
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Box3D<f64, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -562,7 +574,8 @@ impl<T: NumCast + Copy, Unit> Box3D<T, Unit> {
|
||||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> Box3D<usize, Unit> {
|
||||
#[inline]
|
||||
pub fn to_usize(&self) -> Box3D<usize, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -571,7 +584,8 @@ impl<T: NumCast + Copy, Unit> Box3D<T, Unit> {
|
||||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> Box3D<u32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_u32(&self) -> Box3D<u32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -580,7 +594,8 @@ impl<T: NumCast + Copy, Unit> Box3D<T, Unit> {
|
||||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> Box3D<i32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_i32(&self) -> Box3D<i32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -589,13 +604,14 @@ impl<T: NumCast + Copy, Unit> Box3D<T, Unit> {
|
||||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> Box3D<i64, Unit> {
|
||||
#[inline]
|
||||
pub fn to_i64(&self) -> Box3D<i64, U> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<Size3D<T, U>> for Box3D<T, U>
|
||||
where
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
fn from(b: Size3D<T, U>) -> Self {
|
||||
@ -632,6 +648,14 @@ mod tests {
|
||||
assert!(b.size().depth == 20.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_width_height_depth() {
|
||||
let b = Box3D::new(point3(-10.0, -10.0, -10.0), point3(10.0, 10.0, 10.0));
|
||||
assert!(b.width() == 20.0);
|
||||
assert!(b.height() == 20.0);
|
||||
assert!(b.depth() == 20.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_center() {
|
||||
let b = Box3D::new(point3(-10.0, -10.0, -10.0), point3(10.0, 10.0, 10.0));
|
||||
@ -770,7 +794,7 @@ mod tests {
|
||||
let b1 = Box3D::from_points(&[point3(-15.0, -20.0, -20.0), point3(10.0, 20.0, 20.0)]);
|
||||
let b2 = Box3D::from_points(&[point3(-10.0, 20.0, 20.0), point3(15.0, -20.0, -20.0)]);
|
||||
assert!(b1.try_intersection(&b2).is_some());
|
||||
|
||||
|
||||
let b1 = Box3D::from_points(&[point3(-15.0, -20.0, -20.0), point3(-10.0, 20.0, 20.0)]);
|
||||
let b2 = Box3D::from_points(&[point3(10.0, 20.0, 20.0), point3(15.0, -20.0, -20.0)]);
|
||||
assert!(b1.try_intersection(&b2).is_none());
|
||||
|
4
third_party/rust/euclid/src/homogen.rs
vendored
4
third_party/rust/euclid/src/homogen.rs
vendored
@ -53,7 +53,7 @@ impl<'de, T, U> serde::Deserialize<'de> for HomogeneousVector<T, U>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
{
|
||||
let (x, y, z, w) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
let (x, y, z, w) = serde::Deserialize::deserialize(deserializer)?;
|
||||
Ok(HomogeneousVector { x, y, z, w, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
@ -93,7 +93,7 @@ impl<T, U> Hash for HomogeneousVector<T, U>
|
||||
impl<T, U> HomogeneousVector<T, U> {
|
||||
/// Constructor taking scalar values directly.
|
||||
#[inline]
|
||||
pub fn new(x: T, y: T, z: T, w: T) -> Self {
|
||||
pub const fn new(x: T, y: T, z: T, w: T) -> Self {
|
||||
HomogeneousVector { x, y, z, w, _unit: PhantomData }
|
||||
}
|
||||
}
|
||||
|
124
third_party/rust/euclid/src/length.rs
vendored
124
third_party/rust/euclid/src/length.rs
vendored
@ -18,6 +18,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use core::cmp::Ordering;
|
||||
use core::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::marker::PhantomData;
|
||||
use core::fmt;
|
||||
|
||||
@ -37,16 +38,16 @@ use core::fmt;
|
||||
#[repr(C)]
|
||||
pub struct Length<T, Unit>(pub T, #[doc(hidden)] pub PhantomData<Unit>);
|
||||
|
||||
impl<T: Clone, Unit> Clone for Length<T, Unit> {
|
||||
impl<T: Clone, U> Clone for Length<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
Length(self.0.clone(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Unit> Copy for Length<T, Unit> {}
|
||||
impl<T: Copy, U> Copy for Length<T, U> {}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, Unit, T> Deserialize<'de> for Length<T, Unit>
|
||||
impl<'de, T, U> Deserialize<'de> for Length<T, U>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
@ -55,14 +56,14 @@ where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(Length(
|
||||
try!(Deserialize::deserialize(deserializer)),
|
||||
Deserialize::deserialize(deserializer)?,
|
||||
PhantomData,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T, Unit> Serialize for Length<T, Unit>
|
||||
impl<T, U> Serialize for Length<T, U>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
@ -74,86 +75,108 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Unit> Length<T, Unit> {
|
||||
pub fn new(x: T) -> Self {
|
||||
impl<T, U> Length<T, U> {
|
||||
#[inline]
|
||||
pub const fn new(x: T) -> Self {
|
||||
Length(x, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Unit, T: Clone> Length<T, Unit> {
|
||||
impl<T: Clone, U> Length<T, U> {
|
||||
pub fn get(&self) -> T {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug + Clone, U> fmt::Debug for Length<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.get().fmt(f)
|
||||
/// Cast the unit
|
||||
#[inline]
|
||||
pub fn cast_unit<V>(&self) -> Length<T, V> {
|
||||
Length::new(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display + Clone, U> fmt::Display for Length<T, U> {
|
||||
impl<T: fmt::Debug, U> fmt::Debug for Length<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.get().fmt(f)
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, U> fmt::Display for Length<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for Length<T, U> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Length::new(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Hash for Length<T, U>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: Hasher>(&self, h: &mut H) {
|
||||
self.0.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
// length + length
|
||||
impl<U, T: Clone + Add<T, Output = T>> Add for Length<T, U> {
|
||||
impl<U, T: Add<T, Output = T>> Add for Length<T, U> {
|
||||
type Output = Length<T, U>;
|
||||
fn add(self, other: Length<T, U>) -> Length<T, U> {
|
||||
Length::new(self.get() + other.get())
|
||||
Length::new(self.0 + other.0)
|
||||
}
|
||||
}
|
||||
|
||||
// length += length
|
||||
impl<U, T: Clone + AddAssign<T>> AddAssign for Length<T, U> {
|
||||
impl<U, T: AddAssign<T>> AddAssign for Length<T, U> {
|
||||
fn add_assign(&mut self, other: Length<T, U>) {
|
||||
self.0 += other.get();
|
||||
self.0 += other.0;
|
||||
}
|
||||
}
|
||||
|
||||
// length - length
|
||||
impl<U, T: Clone + Sub<T, Output = T>> Sub<Length<T, U>> for Length<T, U> {
|
||||
impl<U, T: Sub<T, Output = T>> Sub<Length<T, U>> for Length<T, U> {
|
||||
type Output = Length<T, U>;
|
||||
fn sub(self, other: Length<T, U>) -> <Self as Sub>::Output {
|
||||
Length::new(self.get() - other.get())
|
||||
Length::new(self.0 - other.0)
|
||||
}
|
||||
}
|
||||
|
||||
// length -= length
|
||||
impl<U, T: Clone + SubAssign<T>> SubAssign for Length<T, U> {
|
||||
impl<U, T: SubAssign<T>> SubAssign for Length<T, U> {
|
||||
fn sub_assign(&mut self, other: Length<T, U>) {
|
||||
self.0 -= other.get();
|
||||
self.0 -= other.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Saturating length + length and length - length.
|
||||
impl<U, T: Clone + Saturating> Saturating for Length<T, U> {
|
||||
impl<U, T: Saturating> Saturating for Length<T, U> {
|
||||
fn saturating_add(self, other: Length<T, U>) -> Length<T, U> {
|
||||
Length::new(self.get().saturating_add(other.get()))
|
||||
Length::new(self.0.saturating_add(other.0))
|
||||
}
|
||||
|
||||
fn saturating_sub(self, other: Length<T, U>) -> Length<T, U> {
|
||||
Length::new(self.get().saturating_sub(other.get()))
|
||||
Length::new(self.0.saturating_sub(other.0))
|
||||
}
|
||||
}
|
||||
|
||||
// length / length
|
||||
impl<Src, Dst, T: Clone + Div<T, Output = T>> Div<Length<T, Src>> for Length<T, Dst> {
|
||||
impl<Src, Dst, T: Div<T, Output = T>> Div<Length<T, Src>> for Length<T, Dst> {
|
||||
type Output = Scale<T, Src, Dst>;
|
||||
#[inline]
|
||||
fn div(self, other: Length<T, Src>) -> Scale<T, Src, Dst> {
|
||||
Scale::new(self.get() / other.get())
|
||||
Scale::new(self.0 / other.0)
|
||||
}
|
||||
}
|
||||
|
||||
// length * scalar
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for Length<T, U> {
|
||||
impl<T: Mul<T, Output = T>, U> Mul<T> for Length<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, scale: T) -> Self {
|
||||
Length::new(self.get() * scale)
|
||||
Length::new(self.0 * scale)
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,11 +189,11 @@ impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for Length<T, U> {
|
||||
}
|
||||
|
||||
// length / scalar
|
||||
impl<T: Copy + Div<T, Output = T>, U> Div<T> for Length<T, U> {
|
||||
impl<T: Div<T, Output = T>, U> Div<T> for Length<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, scale: T) -> Self {
|
||||
Length::new(self.get() / scale)
|
||||
Length::new(self.0 / scale)
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,65 +206,67 @@ impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for Length<T, U> {
|
||||
}
|
||||
|
||||
// length * scaleFactor
|
||||
impl<Src, Dst, T: Clone + Mul<T, Output = T>> Mul<Scale<T, Src, Dst>> for Length<T, Src> {
|
||||
impl<Src, Dst, T: Mul<T, Output = T>> Mul<Scale<T, Src, Dst>> for Length<T, Src> {
|
||||
type Output = Length<T, Dst>;
|
||||
#[inline]
|
||||
fn mul(self, scale: Scale<T, Src, Dst>) -> Length<T, Dst> {
|
||||
Length::new(self.get() * scale.get())
|
||||
Length::new(self.0 * scale.0)
|
||||
}
|
||||
}
|
||||
|
||||
// length / scaleFactor
|
||||
impl<Src, Dst, T: Clone + Div<T, Output = T>> Div<Scale<T, Src, Dst>> for Length<T, Dst> {
|
||||
impl<Src, Dst, T: Div<T, Output = T>> Div<Scale<T, Src, Dst>> for Length<T, Dst> {
|
||||
type Output = Length<T, Src>;
|
||||
#[inline]
|
||||
fn div(self, scale: Scale<T, Src, Dst>) -> Length<T, Src> {
|
||||
Length::new(self.get() / scale.get())
|
||||
Length::new(self.0 / scale.0)
|
||||
}
|
||||
}
|
||||
|
||||
// -length
|
||||
impl<U, T: Clone + Neg<Output = T>> Neg for Length<T, U> {
|
||||
impl<U, T: Neg<Output = T>> Neg for Length<T, U> {
|
||||
type Output = Length<T, U>;
|
||||
#[inline]
|
||||
fn neg(self) -> Length<T, U> {
|
||||
Length::new(-self.get())
|
||||
Length::new(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Unit, T0: NumCast + Clone> Length<T0, Unit> {
|
||||
impl<T: NumCast + Clone, U> Length<T, U> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
pub fn cast<T1: NumCast + Clone>(&self) -> Length<T1, Unit> {
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Length<NewT, U> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<Length<T1, Unit>> {
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Length<NewT, U>> {
|
||||
NumCast::from(self.get()).map(Length::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Unit, T: Clone + PartialEq> PartialEq for Length<T, Unit> {
|
||||
impl<T: PartialEq, U> PartialEq for Length<T, U> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.get().eq(&other.get())
|
||||
self.0.eq(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Unit, T: Clone + PartialOrd> PartialOrd for Length<T, Unit> {
|
||||
impl<T: PartialOrd, U> PartialOrd for Length<T, U> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
self.get().partial_cmp(&other.get())
|
||||
self.0.partial_cmp(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Unit, T: Clone + Eq> Eq for Length<T, Unit> {}
|
||||
impl<T: Eq, U> Eq for Length<T, U> {}
|
||||
|
||||
impl<Unit, T: Clone + Ord> Ord for Length<T, Unit> {
|
||||
impl<T: Ord, U> Ord for Length<T, U> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.get().cmp(&other.get())
|
||||
self.0.cmp(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Unit, T: Zero> Zero for Length<T, Unit> {
|
||||
impl<T: Zero, U> Zero for Length<T, U> {
|
||||
#[inline]
|
||||
fn zero() -> Self {
|
||||
Length::new(Zero::zero())
|
||||
}
|
||||
@ -253,7 +278,8 @@ where
|
||||
{
|
||||
/// Linearly interpolate between this length and another length.
|
||||
///
|
||||
/// `t` is expected to be between zero and one.
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
let one_t = T::one() - t;
|
||||
|
13
third_party/rust/euclid/src/lib.rs
vendored
13
third_party/rust/euclid/src/lib.rs
vendored
@ -18,9 +18,9 @@
|
||||
//! a screen-space position by a world-space vector and this can be expressed using
|
||||
//! the generic Unit parameter.
|
||||
//!
|
||||
//! This unit system is not mandatory and all * structures have an alias
|
||||
//! This unit system is not mandatory and all structures have an alias
|
||||
//! with the default unit: `UnknownUnit`.
|
||||
//! for example ```Point2D<T>``` is equivalent to ```Point2D<T, UnknownUnit>```.
|
||||
//! for example ```default::Point2D<T>``` is equivalent to ```Point2D<T, UnknownUnit>```.
|
||||
//! Client code typically creates a set of aliases for each type and doesn't need
|
||||
//! to deal with the specifics of typed units further. For example:
|
||||
//!
|
||||
@ -38,6 +38,7 @@
|
||||
//! All euclid types are marked `#[repr(C)]` in order to facilitate exposing them to
|
||||
//! foreign function interfaces (provided the underlying scalar type is also `repr(C)`).
|
||||
//!
|
||||
#![deny(unconditional_recursion)]
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[macro_use]
|
||||
@ -49,6 +50,7 @@ extern crate num_traits;
|
||||
#[cfg(test)]
|
||||
use std as core;
|
||||
|
||||
pub use angle::Angle;
|
||||
pub use box2d::Box2D;
|
||||
pub use length::Length;
|
||||
pub use scale::Scale;
|
||||
@ -64,7 +66,7 @@ pub use rect::{rect, Rect};
|
||||
pub use rigid::{RigidTransform3D};
|
||||
pub use box3d::{box3d, Box3D};
|
||||
pub use translation::{Translation2D, Translation3D};
|
||||
pub use rotation::{Angle, Rotation2D, Rotation3D};
|
||||
pub use rotation::{Rotation2D, Rotation3D};
|
||||
pub use side_offsets::SideOffsets2D;
|
||||
pub use size::{Size2D, Size3D, size2, size3};
|
||||
pub use trig::Trig;
|
||||
@ -72,6 +74,7 @@ pub use trig::Trig;
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
mod angle;
|
||||
pub mod approxeq;
|
||||
pub mod approxord;
|
||||
mod box2d;
|
||||
@ -98,7 +101,10 @@ mod nonempty;
|
||||
pub struct UnknownUnit;
|
||||
|
||||
pub mod default {
|
||||
//! A set of aliases for all types, tagged with the default unknown unit.
|
||||
|
||||
use super::UnknownUnit;
|
||||
pub type Length<T> = super::Length<T, UnknownUnit>;
|
||||
pub type Point2D<T> = super::Point2D<T, UnknownUnit>;
|
||||
pub type Point3D<T> = super::Point3D<T, UnknownUnit>;
|
||||
pub type Vector2D<T> = super::Vector2D<T, UnknownUnit>;
|
||||
@ -114,6 +120,7 @@ pub mod default {
|
||||
pub type Transform3D<T> = super::Transform3D<T, UnknownUnit, UnknownUnit>;
|
||||
pub type Rotation2D<T> = super::Rotation2D<T, UnknownUnit, UnknownUnit>;
|
||||
pub type Rotation3D<T> = super::Rotation3D<T, UnknownUnit, UnknownUnit>;
|
||||
pub type Translation2D<T> = super::Translation2D<T, UnknownUnit, UnknownUnit>;
|
||||
pub type Translation3D<T> = super::Translation3D<T, UnknownUnit, UnknownUnit>;
|
||||
pub type Scale<T> = super::Scale<T, UnknownUnit, UnknownUnit>;
|
||||
pub type RigidTransform3D<T> = super::RigidTransform3D<T, UnknownUnit, UnknownUnit>;
|
||||
|
3
third_party/rust/euclid/src/nonempty.rs
vendored
3
third_party/rust/euclid/src/nonempty.rs
vendored
@ -1,6 +1,5 @@
|
||||
use {Rect, Box2D, Box3D, Vector2D, Vector3D, size2, point2, point3};
|
||||
use approxord::{min, max};
|
||||
use num::Zero;
|
||||
use core::ops::Deref;
|
||||
use core::ops::{Add, Sub};
|
||||
use core::cmp::{PartialEq};
|
||||
@ -27,7 +26,7 @@ impl<T> NonEmpty<T> {
|
||||
|
||||
impl<T, U> NonEmpty<Rect<T, U>>
|
||||
where
|
||||
T: Copy + Clone + Zero + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &NonEmpty<Rect<T, U>>) -> NonEmpty<Rect<T, U>> {
|
||||
|
47
third_party/rust/euclid/src/num.rs
vendored
47
third_party/rust/euclid/src/num.rs
vendored
@ -30,47 +30,74 @@ impl<T: num_traits::One> One for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines the nearest integer value to the original value.
|
||||
pub trait Round: Copy {
|
||||
/// Rounds to the nearest integer value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
#[must_use]
|
||||
fn round(self) -> Self;
|
||||
}
|
||||
/// Defines the biggest integer equal or lower than the original value.
|
||||
pub trait Floor: Copy {
|
||||
/// Rounds to the biggest integer equal or lower than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
#[must_use]
|
||||
fn floor(self) -> Self;
|
||||
}
|
||||
/// Defines the smallest integer equal or greater than the original value.
|
||||
pub trait Ceil: Copy {
|
||||
/// Rounds to the smallest integer equal or greater than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
#[must_use]
|
||||
fn ceil(self) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! num_int {
|
||||
($ty:ty) => (
|
||||
($ty:ty) => {
|
||||
impl Round for $ty {
|
||||
#[inline]
|
||||
fn round(self) -> $ty { self }
|
||||
fn round(self) -> $ty {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl Floor for $ty {
|
||||
#[inline]
|
||||
fn floor(self) -> $ty { self }
|
||||
fn floor(self) -> $ty {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl Ceil for $ty {
|
||||
#[inline]
|
||||
fn ceil(self) -> $ty { self }
|
||||
fn ceil(self) -> $ty {
|
||||
self
|
||||
}
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
macro_rules! num_float {
|
||||
($ty:ty) => (
|
||||
($ty:ty) => {
|
||||
impl Round for $ty {
|
||||
#[inline]
|
||||
fn round(self) -> $ty { self.round() }
|
||||
fn round(self) -> $ty {
|
||||
num_traits::Float::round(self)
|
||||
}
|
||||
}
|
||||
impl Floor for $ty {
|
||||
#[inline]
|
||||
fn floor(self) -> $ty { self.floor() }
|
||||
fn floor(self) -> $ty {
|
||||
num_traits::Float::floor(self)
|
||||
}
|
||||
}
|
||||
impl Ceil for $ty {
|
||||
#[inline]
|
||||
fn ceil(self) -> $ty { self.ceil() }
|
||||
fn ceil(self) -> $ty {
|
||||
num_traits::Float::ceil(self)
|
||||
}
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
num_int!(i16);
|
||||
|
1632
third_party/rust/euclid/src/point.rs
vendored
1632
third_party/rust/euclid/src/point.rs
vendored
File diff suppressed because it is too large
Load Diff
153
third_party/rust/euclid/src/rect.rs
vendored
153
third_party/rust/euclid/src/rect.rs
vendored
@ -47,9 +47,9 @@ impl<T: Hash, U> Hash for Rect<T, U> {
|
||||
|
||||
impl<T: Copy, U> Copy for Rect<T, U> {}
|
||||
|
||||
impl<T: Copy, U> Clone for Rect<T, U> {
|
||||
impl<T: Clone, U> Clone for Rect<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
Self::new(self.origin.clone(), self.size.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,7 +81,8 @@ impl<T: Default, U> Default for Rect<T, U> {
|
||||
|
||||
impl<T, U> Rect<T, U> {
|
||||
/// Constructor.
|
||||
pub fn new(origin: Point2D<T, U>, size: Size2D<T, U>) -> Self {
|
||||
#[inline]
|
||||
pub const fn new(origin: Point2D<T, U>, size: Size2D<T, U>) -> Self {
|
||||
Rect {
|
||||
origin,
|
||||
size,
|
||||
@ -91,9 +92,16 @@ impl<T, U> Rect<T, U> {
|
||||
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + Zero
|
||||
T: Zero
|
||||
{
|
||||
/// Constructor, setting all sides to zero.
|
||||
#[inline]
|
||||
pub fn zero() -> Self {
|
||||
Rect::new(Point2D::origin(), Size2D::zero())
|
||||
}
|
||||
|
||||
/// Creates a rect of the given size, at offset zero.
|
||||
#[inline]
|
||||
pub fn from_size(size: Size2D<T, U>) -> Self {
|
||||
Rect {
|
||||
origin: Point2D::zero(),
|
||||
@ -104,7 +112,7 @@ where
|
||||
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + Clone + Zero + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
@ -144,6 +152,16 @@ where
|
||||
self.origin.y
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn width(&self) -> T {
|
||||
self.size.width
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn height(&self) -> T {
|
||||
self.size.height
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn x_range(&self) -> Range<T> {
|
||||
self.min_x()..self.max_x()
|
||||
@ -189,16 +207,6 @@ where
|
||||
&& self.origin.y <= other.y && other.y < self.origin.y + self.size.height
|
||||
}
|
||||
|
||||
/// Returns true if this rectangle contains the interior of rect. Always
|
||||
/// returns true if rect is empty, and always returns false if rect is
|
||||
/// nonempty but this rectangle is empty.
|
||||
#[inline]
|
||||
pub fn contains_rect(&self, rect: &Self) -> bool {
|
||||
rect.is_empty_or_negative()
|
||||
|| (self.min_x() <= rect.min_x() && rect.max_x() <= self.max_x()
|
||||
&& self.min_y() <= rect.min_y() && rect.max_y() <= self.max_y())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn inflate(&self, width: T, height: T) -> Self {
|
||||
@ -218,6 +226,21 @@ where
|
||||
max: self.max(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
/// Returns true if this rectangle contains the interior of rect. Always
|
||||
/// returns true if rect is empty, and always returns false if rect is
|
||||
/// nonempty but this rectangle is empty.
|
||||
#[inline]
|
||||
pub fn contains_rect(&self, rect: &Self) -> bool {
|
||||
rect.is_empty_or_negative()
|
||||
|| (self.min_x() <= rect.min_x() && rect.max_x() <= self.max_x()
|
||||
&& self.min_y() <= rect.min_y() && rect.max_y() <= self.max_y())
|
||||
}
|
||||
|
||||
/// Calculate the size and position of an inner rectangle.
|
||||
///
|
||||
@ -307,7 +330,8 @@ where
|
||||
{
|
||||
/// Linearly interpolate between this rectangle and another rectangle.
|
||||
///
|
||||
/// `t` is expected to be between zero and one.
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
Self::new(
|
||||
@ -329,7 +353,7 @@ where
|
||||
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + Clone + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
@ -359,7 +383,7 @@ impl<T, U> Rect<T, U> {
|
||||
#[inline]
|
||||
pub fn scale<S: Copy>(&self, x: S, y: S) -> Self
|
||||
where
|
||||
T: Copy + Clone + Mul<S, Output = T>,
|
||||
T: Copy + Mul<S, Output = T>,
|
||||
{
|
||||
Rect::new(
|
||||
Point2D::new(self.origin.x * x, self.origin.y * y),
|
||||
@ -368,32 +392,29 @@ impl<T, U> Rect<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Clone + Mul<T, Output = T>, U> Rect<T, U> {
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Rect<T, U> {
|
||||
#[inline]
|
||||
pub fn area(&self) -> T {
|
||||
self.size.area()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + PartialEq + Zero, U> Rect<T, U> {
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
Rect::new(Point2D::origin(), Size2D::zero())
|
||||
}
|
||||
|
||||
impl<T: Zero + PartialEq, U> Rect<T, U> {
|
||||
/// Returns true if the size is zero, regardless of the origin's value.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.size.width == Zero::zero() || self.size.height == Zero::zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Zero + PartialOrd, U> Rect<T, U> {
|
||||
impl<T: Zero + PartialOrd, U> Rect<T, U> {
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty_or_negative(&self) -> bool {
|
||||
self.size.is_empty_or_negative()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Zero + PartialOrd, U> Rect<T, U> {
|
||||
#[inline]
|
||||
pub fn to_non_empty(&self) -> Option<NonEmpty<Self>> {
|
||||
if self.is_empty_or_negative() {
|
||||
@ -436,7 +457,7 @@ impl<T: Copy + Div<T, Output = T>, U1, U2> Div<Scale<T, U1, U2>> for Rect<T, U2>
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Unit> Rect<T, Unit> {
|
||||
impl<T: Copy, U> Rect<T, U> {
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Rect<T, UnknownUnit> {
|
||||
@ -445,21 +466,28 @@ impl<T: Copy, Unit> Rect<T, Unit> {
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(r: &Rect<T, UnknownUnit>) -> Rect<T, Unit> {
|
||||
pub fn from_untyped(r: &Rect<T, UnknownUnit>) -> Rect<T, U> {
|
||||
Rect::new(
|
||||
Point2D::from_untyped(r.origin),
|
||||
Size2D::from_untyped(r.size),
|
||||
)
|
||||
}
|
||||
|
||||
/// Cast the unit
|
||||
#[inline]
|
||||
pub fn cast_unit<V>(&self) -> Rect<T, V> {
|
||||
Rect::new(self.origin.cast_unit(), self.size.cast_unit())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0: NumCast + Copy, Unit> Rect<T0, Unit> {
|
||||
impl<T: NumCast + Copy, U> Rect<T, U> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Rect<T1, Unit> {
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Rect<NewT, U> {
|
||||
Rect::new(
|
||||
self.origin.cast(),
|
||||
self.size.cast(),
|
||||
@ -471,7 +499,7 @@ impl<T0: NumCast + Copy, Unit> Rect<T0, Unit> {
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Rect<T1, Unit>> {
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Rect<NewT, U>> {
|
||||
match (self.origin.try_cast(), self.size.try_cast()) {
|
||||
(Some(origin), Some(size)) => Some(Rect::new(origin, size)),
|
||||
_ => None,
|
||||
@ -492,7 +520,7 @@ impl<T: Floor + Ceil + Round + Add<T, Output = T> + Sub<T, Output = T>, U> Rect<
|
||||
#[must_use]
|
||||
pub fn round(&self) -> Self {
|
||||
let origin = self.origin.round();
|
||||
let size = self.origin.add_size(&self.size).round() - origin;
|
||||
let size = (self.origin + self.size).round() - origin;
|
||||
Rect::new(origin, Size2D::new(size.x, size.y))
|
||||
}
|
||||
|
||||
@ -501,7 +529,7 @@ impl<T: Floor + Ceil + Round + Add<T, Output = T> + Sub<T, Output = T>, U> Rect<
|
||||
#[must_use]
|
||||
pub fn round_in(&self) -> Self {
|
||||
let origin = self.origin.ceil();
|
||||
let size = self.origin.add_size(&self.size).floor() - origin;
|
||||
let size = (self.origin + self.size).floor() - origin;
|
||||
Rect::new(origin, Size2D::new(size.x, size.y))
|
||||
}
|
||||
|
||||
@ -510,20 +538,22 @@ impl<T: Floor + Ceil + Round + Add<T, Output = T> + Sub<T, Output = T>, U> Rect<
|
||||
#[must_use]
|
||||
pub fn round_out(&self) -> Self {
|
||||
let origin = self.origin.floor();
|
||||
let size = self.origin.add_size(&self.size).ceil() - origin;
|
||||
let size = (self.origin + self.size).ceil() - origin;
|
||||
Rect::new(origin, Size2D::new(size.x, size.y))
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, Unit> Rect<T, Unit> {
|
||||
impl<T: NumCast + Copy, U> Rect<T, U> {
|
||||
/// Cast into an `f32` rectangle.
|
||||
pub fn to_f32(&self) -> Rect<f32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Rect<f32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` rectangle.
|
||||
pub fn to_f64(&self) -> Rect<f64, Unit> {
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Rect<f64, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -532,7 +562,8 @@ impl<T: NumCast + Copy, Unit> Rect<T, Unit> {
|
||||
/// When casting from floating point rectangles, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> Rect<usize, Unit> {
|
||||
#[inline]
|
||||
pub fn to_usize(&self) -> Rect<usize, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -541,7 +572,18 @@ impl<T: NumCast + Copy, Unit> Rect<T, Unit> {
|
||||
/// When casting from floating point rectangles, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> Rect<u32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_u32(&self) -> Rect<u32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `u64` rectangle, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point rectangles, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
#[inline]
|
||||
pub fn to_u64(&self) -> Rect<u64, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -550,7 +592,8 @@ impl<T: NumCast + Copy, Unit> Rect<T, Unit> {
|
||||
/// When casting from floating point rectangles, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> Rect<i32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_i32(&self) -> Rect<i32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -559,13 +602,14 @@ impl<T: NumCast + Copy, Unit> Rect<T, Unit> {
|
||||
/// When casting from floating point rectangles, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> Rect<i64, Unit> {
|
||||
#[inline]
|
||||
pub fn to_i64(&self) -> Rect<i64, U> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<Size2D<T, U>> for Rect<T, U>
|
||||
where T: Copy + Zero
|
||||
where T: Zero
|
||||
{
|
||||
fn from(size: Size2D<T, U>) -> Self {
|
||||
Self::from_size(size)
|
||||
@ -573,7 +617,7 @@ where T: Copy + Zero
|
||||
}
|
||||
|
||||
/// Shorthand for `Rect::new(Point2D::new(x, y), Size2D::new(w, h))`.
|
||||
pub fn rect<T: Copy, U>(x: T, y: T, w: T, h: T) -> Rect<T, U> {
|
||||
pub const fn rect<T, U>(x: T, y: T, w: T, h: T) -> Rect<T, U> {
|
||||
Rect::new(Point2D::new(x, y), Size2D::new(w, h))
|
||||
}
|
||||
|
||||
@ -644,6 +688,22 @@ mod tests {
|
||||
assert!(qr.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_intersection_overflow() {
|
||||
// test some scenarios where the intersection can overflow but
|
||||
// the min_x() and max_x() don't. Gecko currently fails these cases
|
||||
let p = Rect::new(Point2D::new(-2147483648, -2147483648), Size2D::new(0, 0));
|
||||
let q = Rect::new(Point2D::new(2136893440, 2136893440), Size2D::new(279552, 279552));
|
||||
let r = Rect::new(Point2D::new(-2147483648, -2147483648), Size2D::new(1, 1));
|
||||
|
||||
assert!(p.is_empty());
|
||||
let pq = p.intersection(&q);
|
||||
assert!(pq.is_none());
|
||||
|
||||
let qr = q.intersection(&r);
|
||||
assert!(qr.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains() {
|
||||
let r = Rect::new(Point2D::new(-20, 15), Size2D::new(100, 200));
|
||||
@ -752,6 +812,13 @@ mod tests {
|
||||
assert!(r.min_x() == -10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_width_height() {
|
||||
let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40));
|
||||
assert!(r.width() == 50);
|
||||
assert!(r.height() == 40);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_empty() {
|
||||
assert!(Rect::new(Point2D::new(0u32, 0u32), Size2D::new(0u32, 0u32)).is_empty());
|
||||
|
34
third_party/rust/euclid/src/rigid.rs
vendored
34
third_party/rust/euclid/src/rigid.rs
vendored
@ -1,7 +1,11 @@
|
||||
//! All matrix multiplication in this module is in row-vector notation,
|
||||
//! i.e. a vector `v` is transformed with `v * T`, and if you want to apply `T1`
|
||||
//! before `T2` you use `T1 * T2`
|
||||
|
||||
use approxeq::ApproxEq;
|
||||
use num_traits::Float;
|
||||
use trig::Trig;
|
||||
use {Rotation3D, Transform3D, Vector3D};
|
||||
use {Rotation3D, Transform3D, Vector3D, UnknownUnit};
|
||||
|
||||
/// A rigid transformation. All lengths are preserved under such a transformation.
|
||||
///
|
||||
@ -19,20 +23,18 @@ pub struct RigidTransform3D<T, Src, Dst> {
|
||||
pub translation: Vector3D<T, Dst>,
|
||||
}
|
||||
|
||||
// All matrix multiplication in this file is in row-vector notation,
|
||||
// i.e. a vector `v` is transformed with `v * T`, and if you want to apply `T1`
|
||||
// before `T2` you use `T1 * T2`
|
||||
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> RigidTransform3D<T, Src, Dst> {
|
||||
impl<T, Src, Dst> RigidTransform3D<T, Src, Dst> {
|
||||
/// Construct a new rigid transformation, where the `rotation` applies first
|
||||
#[inline]
|
||||
pub fn new(rotation: Rotation3D<T, Src, Dst>, translation: Vector3D<T, Dst>) -> Self {
|
||||
pub const fn new(rotation: Rotation3D<T, Src, Dst>, translation: Vector3D<T, Dst>) -> Self {
|
||||
Self {
|
||||
rotation,
|
||||
translation,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> RigidTransform3D<T, Src, Dst> {
|
||||
/// Construct an identity transform
|
||||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
@ -169,6 +171,24 @@ impl<T: Float + ApproxEq<T>, Src, Dst> RigidTransform3D<T, Src, Dst> {
|
||||
.to_transform()
|
||||
.pre_transform(&self.rotation.to_transform())
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> RigidTransform3D<T, UnknownUnit, UnknownUnit> {
|
||||
RigidTransform3D {
|
||||
rotation: self.rotation.to_untyped(),
|
||||
translation: self.translation.to_untyped(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(transform: &RigidTransform3D<T, UnknownUnit, UnknownUnit>) -> Self {
|
||||
RigidTransform3D {
|
||||
rotation: Rotation3D::from_untyped(&transform.rotation),
|
||||
translation: Vector3D::from_untyped(transform.translation),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> From<Rotation3D<T, Src, Dst>>
|
||||
|
287
third_party/rust/euclid/src/rotation.rs
vendored
287
third_party/rust/euclid/src/rotation.rs
vendored
@ -8,187 +8,18 @@
|
||||
// except according to those terms.
|
||||
|
||||
use approxeq::ApproxEq;
|
||||
use num_traits::{Float, FloatConst, One, Zero, NumCast};
|
||||
use num_traits::{Float, One, Zero, NumCast};
|
||||
use core::fmt;
|
||||
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
|
||||
use core::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use core::marker::PhantomData;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
use trig::Trig;
|
||||
use {Point2D, Point3D, Vector2D, Vector3D, point2, point3, vec3};
|
||||
use {Angle, Point2D, Point3D, Vector2D, Vector3D, point2, point3, vec3};
|
||||
use {Transform2D, Transform3D, UnknownUnit};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
|
||||
/// An angle in radians
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Angle<T> {
|
||||
pub radians: T,
|
||||
}
|
||||
|
||||
impl<T> Angle<T> {
|
||||
#[inline]
|
||||
pub fn radians(radians: T) -> Self {
|
||||
Angle { radians }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(self) -> T {
|
||||
self.radians
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
where
|
||||
T: Trig,
|
||||
{
|
||||
#[inline]
|
||||
pub fn degrees(deg: T) -> Self {
|
||||
Angle {
|
||||
radians: T::degrees_to_radians(deg),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_degrees(self) -> T {
|
||||
T::radians_to_degrees(self.radians)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
where
|
||||
T: Rem<Output = T> + Sub<Output = T> + Add<Output = T> + Zero + FloatConst + PartialOrd + Copy,
|
||||
{
|
||||
/// Returns this angle in the [0..2*PI[ range.
|
||||
pub fn positive(&self) -> Self {
|
||||
let two_pi = T::PI() + T::PI();
|
||||
let mut a = self.radians % two_pi;
|
||||
if a < T::zero() {
|
||||
a = a + two_pi;
|
||||
}
|
||||
Angle::radians(a)
|
||||
}
|
||||
|
||||
/// Returns this angle in the ]-PI..PI] range.
|
||||
pub fn signed(&self) -> Self {
|
||||
Angle::pi() - (Angle::pi() - *self).positive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
where
|
||||
T: Float,
|
||||
{
|
||||
/// Returns (sin(self), cos(self)).
|
||||
pub fn sin_cos(self) -> (T, T) {
|
||||
self.radians.sin_cos()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
where
|
||||
T: Zero,
|
||||
{
|
||||
pub fn zero() -> Self {
|
||||
Angle::radians(T::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
where
|
||||
T: FloatConst + Add<Output = T>,
|
||||
{
|
||||
pub fn pi() -> Self {
|
||||
Angle::radians(T::PI())
|
||||
}
|
||||
|
||||
pub fn two_pi() -> Self {
|
||||
Angle::radians(T::PI() + T::PI())
|
||||
}
|
||||
|
||||
pub fn frac_pi_2() -> Self {
|
||||
Angle::radians(T::FRAC_PI_2())
|
||||
}
|
||||
|
||||
pub fn frac_pi_3() -> Self {
|
||||
Angle::radians(T::FRAC_PI_3())
|
||||
}
|
||||
|
||||
pub fn frac_pi_4() -> Self {
|
||||
Angle::radians(T::FRAC_PI_4())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + Add<T, Output = T>> Add for Angle<T> {
|
||||
type Output = Angle<T>;
|
||||
fn add(self, other: Angle<T>) -> Angle<T> {
|
||||
Angle::radians(self.radians + other.radians)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + AddAssign<T>> AddAssign for Angle<T> {
|
||||
fn add_assign(&mut self, other: Angle<T>) {
|
||||
self.radians += other.radians;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + Sub<T, Output = T>> Sub<Angle<T>> for Angle<T> {
|
||||
type Output = Angle<T>;
|
||||
fn sub(self, other: Angle<T>) -> <Self as Sub>::Output {
|
||||
Angle::radians(self.radians - other.radians)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + SubAssign<T>> SubAssign for Angle<T> {
|
||||
fn sub_assign(&mut self, other: Angle<T>) {
|
||||
self.radians -= other.radians;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + Div<T, Output = T>> Div<Angle<T>> for Angle<T> {
|
||||
type Output = T;
|
||||
#[inline]
|
||||
fn div(self, other: Angle<T>) -> T {
|
||||
self.radians / other.radians
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + Div<T, Output = T>> Div<T> for Angle<T> {
|
||||
type Output = Angle<T>;
|
||||
#[inline]
|
||||
fn div(self, factor: T) -> Angle<T> {
|
||||
Angle::radians(self.radians / factor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + DivAssign<T>> DivAssign<T> for Angle<T> {
|
||||
fn div_assign(&mut self, factor: T) {
|
||||
self.radians /= factor;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + Mul<T, Output = T>> Mul<T> for Angle<T> {
|
||||
type Output = Angle<T>;
|
||||
#[inline]
|
||||
fn mul(self, factor: T) -> Angle<T> {
|
||||
Angle::radians(self.radians * factor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + MulAssign<T>> MulAssign<T> for Angle<T> {
|
||||
fn mul_assign(&mut self, factor: T) {
|
||||
self.radians *= factor;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Neg<Output = T>> Neg for Angle<T> {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self {
|
||||
Angle::radians(-self.radians)
|
||||
}
|
||||
}
|
||||
|
||||
/// A transform that can represent rotations in 2d, represented as an angle in radians.
|
||||
#[repr(C)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
@ -264,9 +95,7 @@ where
|
||||
|
||||
impl<T, Src, Dst> Rotation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
+ Clone
|
||||
+ Add<T, Output = T>
|
||||
T: Add<T, Output = T>
|
||||
+ Sub<T, Output = T>
|
||||
+ Mul<T, Output = T>
|
||||
+ Div<T, Output = T>
|
||||
@ -322,12 +151,29 @@ where
|
||||
pub fn transform_vector(&self, vector: Vector2D<T, Src>) -> Vector2D<T, Dst> {
|
||||
self.transform_point(vector.to_point()).to_vector()
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Rotation2D<T, UnknownUnit, UnknownUnit> {
|
||||
Rotation2D {
|
||||
angle: self.angle,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(r: &Rotation2D<T, UnknownUnit, UnknownUnit>) -> Self {
|
||||
Rotation2D {
|
||||
angle: r.angle,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Rotation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
+ Clone
|
||||
+ Add<T, Output = T>
|
||||
+ Mul<T, Output = T>
|
||||
+ Div<T, Output = T>
|
||||
@ -590,7 +436,8 @@ where
|
||||
|
||||
/// Basic Linear interpolation between this rotation and another rotation.
|
||||
///
|
||||
/// `t` is expected to be between zero and one.
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: &Self, t: T) -> Self {
|
||||
let one_t = T::one() - t;
|
||||
@ -766,6 +613,30 @@ where
|
||||
self.r * factor,
|
||||
)
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Rotation3D<T, UnknownUnit, UnknownUnit> {
|
||||
Rotation3D {
|
||||
i: self.i,
|
||||
j: self.j,
|
||||
k: self.k,
|
||||
r: self.r,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(r: &Rotation3D<T, UnknownUnit, UnknownUnit>) -> Self {
|
||||
Rotation3D {
|
||||
i: r.i,
|
||||
j: r.j,
|
||||
k: r.k,
|
||||
r: r.r,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, Src, Dst> fmt::Debug for Rotation3D<T, Src, Dst> {
|
||||
@ -796,10 +667,6 @@ where
|
||||
T::approx_epsilon()
|
||||
}
|
||||
|
||||
fn approx_eq(&self, other: &Self) -> bool {
|
||||
self.approx_eq_eps(other, &Self::approx_epsilon())
|
||||
}
|
||||
|
||||
fn approx_eq_eps(&self, other: &Self, eps: &T) -> bool {
|
||||
(self.i.approx_eq_eps(&other.i, eps) && self.j.approx_eq_eps(&other.j, eps)
|
||||
&& self.k.approx_eq_eps(&other.k, eps) && self.r.approx_eq_eps(&other.r, eps))
|
||||
@ -1081,61 +948,3 @@ fn from_euler() {
|
||||
|
||||
assert!(ypr_pe.approx_eq(&ypr_pq));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrap_angles() {
|
||||
use core::f32::consts::{FRAC_PI_2, PI};
|
||||
|
||||
assert!(Angle::radians(0.0).positive().radians.approx_eq(&0.0));
|
||||
assert!(
|
||||
Angle::radians(FRAC_PI_2)
|
||||
.positive()
|
||||
.radians
|
||||
.approx_eq(&FRAC_PI_2)
|
||||
);
|
||||
assert!(
|
||||
Angle::radians(-FRAC_PI_2)
|
||||
.positive()
|
||||
.radians
|
||||
.approx_eq(&(3.0 * FRAC_PI_2))
|
||||
);
|
||||
assert!(
|
||||
Angle::radians(3.0 * FRAC_PI_2)
|
||||
.positive()
|
||||
.radians
|
||||
.approx_eq(&(3.0 * FRAC_PI_2))
|
||||
);
|
||||
assert!(
|
||||
Angle::radians(5.0 * FRAC_PI_2)
|
||||
.positive()
|
||||
.radians
|
||||
.approx_eq(&FRAC_PI_2)
|
||||
);
|
||||
assert!(Angle::radians(2.0 * PI).positive().radians.approx_eq(&0.0));
|
||||
assert!(Angle::radians(-2.0 * PI).positive().radians.approx_eq(&0.0));
|
||||
assert!(Angle::radians(PI).positive().radians.approx_eq(&PI));
|
||||
assert!(Angle::radians(-PI).positive().radians.approx_eq(&PI));
|
||||
|
||||
assert!(
|
||||
Angle::radians(FRAC_PI_2)
|
||||
.signed()
|
||||
.radians
|
||||
.approx_eq(&FRAC_PI_2)
|
||||
);
|
||||
assert!(
|
||||
Angle::radians(3.0 * FRAC_PI_2)
|
||||
.signed()
|
||||
.radians
|
||||
.approx_eq(&-FRAC_PI_2)
|
||||
);
|
||||
assert!(
|
||||
Angle::radians(5.0 * FRAC_PI_2)
|
||||
.signed()
|
||||
.radians
|
||||
.approx_eq(&FRAC_PI_2)
|
||||
);
|
||||
assert!(Angle::radians(2.0 * PI).signed().radians.approx_eq(&0.0));
|
||||
assert!(Angle::radians(-2.0 * PI).signed().radians.approx_eq(&0.0));
|
||||
assert!(Angle::radians(-PI).signed().radians.approx_eq(&PI));
|
||||
assert!(Angle::radians(PI).signed().radians.approx_eq(&PI));
|
||||
}
|
||||
|
150
third_party/rust/euclid/src/scale.rs
vendored
150
third_party/rust/euclid/src/scale.rs
vendored
@ -43,12 +43,14 @@ use {Point2D, Rect, Size2D, Vector2D};
|
||||
pub struct Scale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);
|
||||
|
||||
impl<T, Src, Dst> Scale<T, Src, Dst> {
|
||||
pub fn new(x: T) -> Self {
|
||||
#[inline]
|
||||
pub const fn new(x: T) -> Self {
|
||||
Scale(x, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, Src, Dst> Scale<T, Src, Dst> {
|
||||
#[inline]
|
||||
pub fn get(&self) -> T {
|
||||
self.0.clone()
|
||||
}
|
||||
@ -61,6 +63,18 @@ impl<Src, Dst> Scale<f32, Src, Dst> {
|
||||
|
||||
impl<T: Clone + One + Div<T, Output = T>, Src, Dst> Scale<T, Src, Dst> {
|
||||
/// The inverse Scale (1.0 / self).
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::Scale;
|
||||
/// enum Mm {};
|
||||
/// enum Cm {};
|
||||
///
|
||||
/// let cm_per_mm: Scale<f32, Cm, Mm> = Scale::new(0.1);
|
||||
///
|
||||
/// assert_eq!(cm_per_mm.inv(), Scale::new(10.0));
|
||||
/// ```
|
||||
pub fn inv(&self) -> Scale<T, Dst, Src> {
|
||||
let one: T = One::one();
|
||||
Scale::new(one / self.get())
|
||||
@ -68,67 +82,160 @@ impl<T: Clone + One + Div<T, Output = T>, Src, Dst> Scale<T, Src, Dst> {
|
||||
}
|
||||
|
||||
// scale0 * scale1
|
||||
impl<T: Clone + Mul<T, Output = T>, A, B, C> Mul<Scale<T, B, C>> for Scale<T, A, B> {
|
||||
impl<T: Mul<T, Output = T>, A, B, C> Mul<Scale<T, B, C>> for Scale<T, A, B> {
|
||||
type Output = Scale<T, A, C>;
|
||||
#[inline]
|
||||
fn mul(self, other: Scale<T, B, C>) -> Scale<T, A, C> {
|
||||
Scale::new(self.get() * other.get())
|
||||
Scale::new(self.0 * other.0)
|
||||
}
|
||||
}
|
||||
|
||||
// scale0 + scale1
|
||||
impl<T: Clone + Add<T, Output = T>, Src, Dst> Add for Scale<T, Src, Dst> {
|
||||
impl<T: Add<T, Output = T>, Src, Dst> Add for Scale<T, Src, Dst> {
|
||||
type Output = Scale<T, Src, Dst>;
|
||||
#[inline]
|
||||
fn add(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
|
||||
Scale::new(self.get() + other.get())
|
||||
Scale::new(self.0 + other.0)
|
||||
}
|
||||
}
|
||||
|
||||
// scale0 - scale1
|
||||
impl<T: Clone + Sub<T, Output = T>, Src, Dst> Sub for Scale<T, Src, Dst> {
|
||||
impl<T: Sub<T, Output = T>, Src, Dst> Sub for Scale<T, Src, Dst> {
|
||||
type Output = Scale<T, Src, Dst>;
|
||||
#[inline]
|
||||
fn sub(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
|
||||
Scale::new(self.get() - other.get())
|
||||
Scale::new(self.0 - other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Clone, Src, Dst0> Scale<T, Src, Dst0> {
|
||||
impl<T: NumCast + Clone, Src, Dst> Scale<T, Src, Dst> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
pub fn cast<T1: NumCast + Clone>(&self) -> Scale<T1, Src, Dst0> {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If the source value cannot be represented by the target type `NewT`, then
|
||||
/// method panics. Use `try_cast` if that must be case.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::Scale;
|
||||
/// enum Mm {};
|
||||
/// enum Cm {};
|
||||
///
|
||||
/// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
|
||||
///
|
||||
/// assert_eq!(to_mm.cast::<f32>(), Scale::new(10.0));
|
||||
/// ```
|
||||
/// That conversion will panic, because `i32` not enough to store such big numbers:
|
||||
/// ```rust,should_panic
|
||||
/// use euclid::Scale;
|
||||
/// enum Mm {};// millimeter = 10^-2 meters
|
||||
/// enum Em {};// exameter = 10^18 meters
|
||||
///
|
||||
/// // Panics
|
||||
/// let to_em: Scale<i32, Mm, Em> = Scale::new(10e20).cast();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Scale<NewT, Src, Dst> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<Scale<T1, Src, Dst0>> {
|
||||
/// If the source value cannot be represented by the target type `NewT`, then `None`
|
||||
/// is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::Scale;
|
||||
/// enum Mm {};
|
||||
/// enum Cm {};
|
||||
/// enum Em {};// Exameter = 10^18 meters
|
||||
///
|
||||
/// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
|
||||
/// let to_em: Scale<f32, Mm, Em> = Scale::new(10e20);
|
||||
///
|
||||
/// assert_eq!(to_mm.try_cast::<f32>(), Some(Scale::new(10.0)));
|
||||
/// // Integer to small to store that number
|
||||
/// assert_eq!(to_em.try_cast::<i32>(), None);
|
||||
/// ```
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Scale<NewT, Src, Dst>> {
|
||||
NumCast::from(self.get()).map(Scale::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Scale<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Clone + Mul<T, Output = T> + Neg<Output = T> + PartialEq + One,
|
||||
T: Copy + Mul<T, Output = T> + Neg<Output = T> + PartialEq + One,
|
||||
{
|
||||
/// Returns the given point transformed by this scale.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::{Scale, point2};
|
||||
/// enum Mm {};
|
||||
/// enum Cm {};
|
||||
///
|
||||
/// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
|
||||
///
|
||||
/// assert_eq!(to_mm.transform_point(point2(42, -42)), point2(420, -420));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn transform_point(&self, point: Point2D<T, Src>) -> Point2D<T, Dst> {
|
||||
Point2D::new(point.x * self.get(), point.y * self.get())
|
||||
}
|
||||
|
||||
/// Returns the given vector transformed by this scale.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::{Scale, vec2};
|
||||
/// enum Mm {};
|
||||
/// enum Cm {};
|
||||
///
|
||||
/// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
|
||||
///
|
||||
/// assert_eq!(to_mm.transform_vector(vec2(42, -42)), vec2(420, -420));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn transform_vector(&self, vec: Vector2D<T, Src>) -> Vector2D<T, Dst> {
|
||||
Vector2D::new(vec.x * self.get(), vec.y * self.get())
|
||||
}
|
||||
|
||||
/// Returns the given vector transformed by this scale.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::{Scale, size2};
|
||||
/// enum Mm {};
|
||||
/// enum Cm {};
|
||||
///
|
||||
/// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
|
||||
///
|
||||
/// assert_eq!(to_mm.transform_size(size2(42, -42)), size2(420, -420));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn transform_size(&self, size: Size2D<T, Src>) -> Size2D<T, Dst> {
|
||||
Size2D::new(size.width * self.get(), size.height * self.get())
|
||||
}
|
||||
|
||||
/// Returns the given rect transformed by this scale.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::{Scale, rect};
|
||||
/// enum Mm {};
|
||||
/// enum Cm {};
|
||||
///
|
||||
/// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
|
||||
///
|
||||
/// assert_eq!(to_mm.transform_rect(&rect(1, 2, 42, -42)), rect(10, 20, 420, -420));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn transform_rect(&self, rect: &Rect<T, Src>) -> Rect<T, Dst> {
|
||||
Rect::new(
|
||||
@ -143,15 +250,30 @@ where
|
||||
Scale::new(-self.get())
|
||||
}
|
||||
|
||||
/// Returns true if this scale has no effect.
|
||||
/// Returns `true` if this scale has no effect.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::Scale;
|
||||
/// use euclid::num::One;
|
||||
/// enum Mm {};
|
||||
/// enum Cm {};
|
||||
///
|
||||
/// let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
|
||||
/// let mm_per_mm: Scale<f32, Mm, Mm> = Scale::new(1.0);
|
||||
///
|
||||
/// assert_eq!(cm_per_mm.is_identity(), false);
|
||||
/// assert_eq!(mm_per_mm.is_identity(), true);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_identity(&self) -> bool {
|
||||
self.get() == T::one()
|
||||
self.0 == T::one()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Switch to `derive(PartialEq, Clone)` after this Rust issue is fixed:
|
||||
// https://github.com/mozilla/rust/issues/7671
|
||||
// https://github.com/rust-lang/rust/issues/26925
|
||||
|
||||
impl<T: PartialEq, Src, Dst> PartialEq for Scale<T, Src, Dst> {
|
||||
fn eq(&self, other: &Scale<T, Src, Dst>) -> bool {
|
||||
|
74
third_party/rust/euclid/src/side_offsets.rs
vendored
74
third_party/rust/euclid/src/side_offsets.rs
vendored
@ -13,14 +13,15 @@
|
||||
use length::Length;
|
||||
use num::Zero;
|
||||
use core::fmt;
|
||||
use core::ops::Add;
|
||||
use core::ops::{Add, Neg};
|
||||
use core::marker::PhantomData;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::Vector2D;
|
||||
|
||||
/// A group of 2D side offsets, which correspond to top/left/bottom/right for borders, padding,
|
||||
/// A group of 2D side offsets, which correspond to top/right/bottom/left for borders, padding,
|
||||
/// and margins in CSS, optionally tagged with a unit.
|
||||
#[repr(C)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
@ -94,9 +95,12 @@ impl<T: Default, U> Default for SideOffsets2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> SideOffsets2D<T, U> {
|
||||
impl<T, U> SideOffsets2D<T, U> {
|
||||
/// Constructor taking a scalar for each side.
|
||||
pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
|
||||
///
|
||||
/// Sides are specified in top-right-bottom-left order following
|
||||
/// CSS's convention.
|
||||
pub const fn new(top: T, right: T, bottom: T, left: T) -> Self {
|
||||
SideOffsets2D {
|
||||
top,
|
||||
right,
|
||||
@ -107,6 +111,9 @@ impl<T: Copy, U> SideOffsets2D<T, U> {
|
||||
}
|
||||
|
||||
/// Constructor taking a typed Length for each side.
|
||||
///
|
||||
/// Sides are specified in top-right-bottom-left order following
|
||||
/// CSS's convention.
|
||||
pub fn from_lengths(
|
||||
top: Length<T, U>,
|
||||
right: Length<T, U>,
|
||||
@ -116,6 +123,44 @@ impl<T: Copy, U> SideOffsets2D<T, U> {
|
||||
SideOffsets2D::new(top.0, right.0, bottom.0, left.0)
|
||||
}
|
||||
|
||||
/// Construct side offsets from min and a max vector offsets.
|
||||
///
|
||||
/// The outer rect of the resulting side offsets is equivalent to translating
|
||||
/// a rectangle's upper-left corner with the min vector and translating the
|
||||
/// bottom-right corner with the max vector.
|
||||
pub fn from_vectors_outer(min: Vector2D<T, U>, max: Vector2D<T,U>) -> Self
|
||||
where
|
||||
T: Neg<Output = T>
|
||||
{
|
||||
SideOffsets2D {
|
||||
left: -min.x,
|
||||
top: -min.y,
|
||||
right: max.x,
|
||||
bottom: max.y,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct side offsets from min and a max vector offsets.
|
||||
///
|
||||
/// The inner rect of the resulting side offsets is equivalent to translating
|
||||
/// a rectangle's upper-left corner with the min vector and translating the
|
||||
/// bottom-right corner with the max vector.
|
||||
pub fn from_vectors_inner(min: Vector2D<T, U>, max: Vector2D<T,U>) -> Self
|
||||
where
|
||||
T: Neg<Output = T>
|
||||
{
|
||||
SideOffsets2D {
|
||||
left: min.x,
|
||||
top: min.y,
|
||||
right: -max.x,
|
||||
bottom: -max.y,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> SideOffsets2D<T, U> {
|
||||
/// Constructor setting the same value to all sides, taking a scalar value directly.
|
||||
pub fn new_all_same(all: T) -> Self {
|
||||
SideOffsets2D::new(all, all, all, all)
|
||||
@ -142,7 +187,7 @@ where
|
||||
|
||||
impl<T, U> Add for SideOffsets2D<T, U>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>,
|
||||
T: Add<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self {
|
||||
@ -155,9 +200,26 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Zero, U> SideOffsets2D<T, U> {
|
||||
impl<T: Zero, U> SideOffsets2D<T, U> {
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
SideOffsets2D::new(Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_vectors() {
|
||||
use crate::{vec2, point2};
|
||||
type Box2D = crate::default::Box2D<i32>;
|
||||
|
||||
let b = Box2D {
|
||||
min: point2(10, 10),
|
||||
max: point2(20, 20),
|
||||
};
|
||||
|
||||
let outer = b.outer_box(SideOffsets2D::from_vectors_outer(vec2(-1, -2), vec2(3, 4)));
|
||||
let inner = b.inner_box(SideOffsets2D::from_vectors_inner(vec2(1, 2), vec2(-3, -4)));
|
||||
|
||||
assert_eq!(outer, Box2D { min: point2(9, 8), max: point2(23, 24) });
|
||||
assert_eq!(inner, Box2D { min: point2(11, 12), max: point2(17, 16) });
|
||||
}
|
||||
|
297
third_party/rust/euclid/src/size.rs
vendored
297
third_party/rust/euclid/src/size.rs
vendored
@ -8,6 +8,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use super::UnknownUnit;
|
||||
use approxord::{max, min};
|
||||
#[cfg(feature = "mint")]
|
||||
use mint;
|
||||
use length::Length;
|
||||
@ -16,7 +17,7 @@ use vector::{Vector2D, vec2, BoolVector2D};
|
||||
use vector::{Vector3D, vec3, BoolVector3D};
|
||||
use num::*;
|
||||
|
||||
use num_traits::{Float, NumCast, Signed};
|
||||
use num_traits::{NumCast, Signed};
|
||||
use core::fmt;
|
||||
use core::ops::{Add, Div, Mul, Sub};
|
||||
use core::marker::PhantomData;
|
||||
@ -28,7 +29,9 @@ use serde;
|
||||
/// A 2d size tagged with a unit.
|
||||
#[repr(C)]
|
||||
pub struct Size2D<T, U> {
|
||||
/// The extent of the element in the `U` units along the `x` axis (usually horizontal).
|
||||
pub width: T,
|
||||
/// The extent of the element in the `U` units along the `y` axis (usually vertical).
|
||||
pub height: T,
|
||||
#[doc(hidden)]
|
||||
pub _unit: PhantomData<U>,
|
||||
@ -50,10 +53,11 @@ impl<T: Clone, U> Clone for Size2D<T, U> {
|
||||
impl<'de, T, U> serde::Deserialize<'de> for Size2D<T, U>
|
||||
where T: serde::Deserialize<'de>
|
||||
{
|
||||
/// Deserializes 2d size from tuple of width and height.
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
{
|
||||
let (width, height) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
let (width, height) = serde::Deserialize::deserialize(deserializer)?;
|
||||
Ok(Size2D { width, height, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
@ -62,6 +66,7 @@ impl<'de, T, U> serde::Deserialize<'de> for Size2D<T, U>
|
||||
impl<T, U> serde::Serialize for Size2D<T, U>
|
||||
where T: serde::Serialize
|
||||
{
|
||||
/// Serializes 2d size to tuple of width and height.
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: serde::Serializer
|
||||
{
|
||||
@ -108,19 +113,24 @@ impl<T: Default, U> Default for Size2D<T, U> {
|
||||
|
||||
impl<T, U> Size2D<T, U> {
|
||||
/// Constructor taking scalar values.
|
||||
pub fn new(width: T, height: T) -> Self {
|
||||
#[inline]
|
||||
pub const fn new(width: T, height: T) -> Self {
|
||||
Size2D {
|
||||
width,
|
||||
height,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, U> Size2D<T, U> {
|
||||
/// Constructor taking scalar strongly typed lengths.
|
||||
#[inline]
|
||||
pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
|
||||
Size2D::new(width.get(), height.get())
|
||||
Size2D::new(width.0, height.0)
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(p: Size2D<T, UnknownUnit>) -> Self {
|
||||
Size2D::new(p.width, p.height)
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,6 +138,7 @@ impl<T: Round, U> Size2D<T, U> {
|
||||
/// Rounds each component to the nearest integer value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
#[inline]
|
||||
pub fn round(&self) -> Self {
|
||||
Size2D::new(self.width.round(), self.height.round())
|
||||
}
|
||||
@ -137,6 +148,7 @@ impl<T: Ceil, U> Size2D<T, U> {
|
||||
/// Rounds each component to the smallest integer equal or greater than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
#[inline]
|
||||
pub fn ceil(&self) -> Self {
|
||||
Size2D::new(self.width.ceil(), self.height.ceil())
|
||||
}
|
||||
@ -146,26 +158,28 @@ impl<T: Floor, U> Size2D<T, U> {
|
||||
/// Rounds each component to the biggest integer equal or lower than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
#[inline]
|
||||
pub fn floor(&self) -> Self {
|
||||
Size2D::new(self.width.floor(), self.height.floor())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> Add for Size2D<T, U> {
|
||||
impl<T: Add<T, Output = T>, U> Add for Size2D<T, U> {
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self {
|
||||
Size2D::new(self.width + other.width, self.height + other.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Sub<T, Output = T>, U> Sub for Size2D<T, U> {
|
||||
impl<T: Sub<T, Output = T>, U> Sub for Size2D<T, U> {
|
||||
type Output = Self;
|
||||
fn sub(self, other: Self) -> Self {
|
||||
Size2D::new(self.width - other.width, self.height - other.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Clone + Mul<T>, U> Size2D<T, U> {
|
||||
impl<T: Copy + Mul<T>, U> Size2D<T, U> {
|
||||
/// Returns result of multiplication of both components
|
||||
pub fn area(&self) -> T::Output {
|
||||
self.width * self.height
|
||||
}
|
||||
@ -175,9 +189,26 @@ impl<T, U> Size2D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
|
||||
{
|
||||
/// Linearly interpolate between this size and another size.
|
||||
/// Linearly interpolate each component between this size and another size.
|
||||
///
|
||||
/// `t` is expected to be between zero and one.
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::size2;
|
||||
/// use euclid::default::Size2D;
|
||||
///
|
||||
/// let first: Size2D<_> = size2(0.0, 10.0);
|
||||
/// let last: Size2D<_> = size2(8.0, -4.0);
|
||||
///
|
||||
/// assert_eq!(first.lerp(last, -1.0), size2(-8.0, 24.0));
|
||||
/// assert_eq!(first.lerp(last, 0.0), size2( 0.0, 10.0));
|
||||
/// assert_eq!(first.lerp(last, 0.5), size2( 4.0, 3.0));
|
||||
/// assert_eq!(first.lerp(last, 1.0), size2( 8.0, -4.0));
|
||||
/// assert_eq!(first.lerp(last, 2.0), size2(16.0, -18.0));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
let one_t = T::one() - t;
|
||||
@ -189,6 +220,7 @@ where
|
||||
}
|
||||
|
||||
impl<T: Zero + PartialOrd, U> Size2D<T, U> {
|
||||
/// Returns `true` if any component of size is zero or negative.
|
||||
pub fn is_empty_or_negative(&self) -> bool {
|
||||
let zero = T::zero();
|
||||
self.width <= zero || self.height <= zero
|
||||
@ -196,12 +228,17 @@ impl<T: Zero + PartialOrd, U> Size2D<T, U> {
|
||||
}
|
||||
|
||||
impl<T: Zero, U> Size2D<T, U> {
|
||||
/// The same as [`Zero::zero()`] but available without importing trait.
|
||||
///
|
||||
/// [`Zero::zero()`]: ./num/trait.Zero.html#tymethod.zero
|
||||
#[inline]
|
||||
pub fn zero() -> Self {
|
||||
Size2D::new(Zero::zero(), Zero::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> Zero for Size2D<T, U> {
|
||||
#[inline]
|
||||
fn zero() -> Self {
|
||||
Size2D::new(Zero::zero(), Zero::zero())
|
||||
}
|
||||
@ -240,40 +277,45 @@ impl<T: Copy + Div<T, Output = T>, U1, U2> Div<Scale<T, U1, U2>> for Size2D<T, U
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Size2D<T, U> {
|
||||
/// Returns self.width as a Length carrying the unit.
|
||||
/// Return this size as an array of two elements (width, then height).
|
||||
#[inline]
|
||||
pub fn to_array(&self) -> [T; 2] {
|
||||
[self.width, self.height]
|
||||
}
|
||||
|
||||
/// Return this size as a tuple of two elements (width, then height).
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
|
||||
/// Return this size as a vector with width and height.
|
||||
#[inline]
|
||||
pub fn to_vector(&self) -> Vector2D<T, U> {
|
||||
vec2(self.width, self.height)
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Size2D<T, UnknownUnit> {
|
||||
Size2D::new(self.width, self.height)
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(p: Size2D<T, UnknownUnit>) -> Self {
|
||||
Size2D::new(p.width, p.height)
|
||||
/// Cast the unit
|
||||
#[inline]
|
||||
pub fn cast_unit<V>(&self) -> Size2D<T, V> {
|
||||
Size2D::new(self.width, self.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Copy, Unit> Size2D<T, Unit> {
|
||||
impl<T: NumCast + Copy, U> Size2D<T, U> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> Size2D<NewT, Unit> {
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Size2D<NewT, U> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
@ -282,7 +324,7 @@ impl<T: NumCast + Copy, Unit> Size2D<T, Unit> {
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
|
||||
pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<Size2D<NewT, Unit>> {
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Size2D<NewT, U>> {
|
||||
match (NumCast::from(self.width), NumCast::from(self.height)) {
|
||||
(Some(w), Some(h)) => Some(Size2D::new(w, h)),
|
||||
_ => None,
|
||||
@ -292,12 +334,14 @@ impl<T: NumCast + Copy, Unit> Size2D<T, Unit> {
|
||||
// Convenience functions for common casts
|
||||
|
||||
/// Cast into an `f32` size.
|
||||
pub fn to_f32(&self) -> Size2D<f32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Size2D<f32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` size.
|
||||
pub fn to_f64(&self) -> Size2D<f64, Unit> {
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Size2D<f64, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -306,7 +350,8 @@ impl<T: NumCast + Copy, Unit> Size2D<T, Unit> {
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> Size2D<usize, Unit> {
|
||||
#[inline]
|
||||
pub fn to_usize(&self) -> Size2D<usize, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -315,7 +360,18 @@ impl<T: NumCast + Copy, Unit> Size2D<T, Unit> {
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> Size2D<u32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_u32(&self) -> Size2D<u32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `u64` size, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
#[inline]
|
||||
pub fn to_u64(&self) -> Size2D<u64, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -324,7 +380,8 @@ impl<T: NumCast + Copy, Unit> Size2D<T, Unit> {
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> Size2D<i32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_i32(&self) -> Size2D<i32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -333,7 +390,8 @@ impl<T: NumCast + Copy, Unit> Size2D<T, Unit> {
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> Size2D<i64, Unit> {
|
||||
#[inline]
|
||||
pub fn to_i64(&self) -> Size2D<i64, U> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
@ -342,16 +400,23 @@ impl<T, U> Size2D<T, U>
|
||||
where
|
||||
T: Signed,
|
||||
{
|
||||
/// Computes the absolute value of each component.
|
||||
///
|
||||
/// For `f32` and `f64`, `NaN` will be returned for component if the component is `NaN`.
|
||||
///
|
||||
/// For signed integers, `::MIN` will be returned for component if the component is `::MIN`.
|
||||
pub fn abs(&self) -> Self {
|
||||
size2(self.width.abs(), self.height.abs())
|
||||
}
|
||||
|
||||
/// Returns `true` if both components is positive and `false` any component is zero or negative.
|
||||
pub fn is_positive(&self) -> bool {
|
||||
self.width.is_positive() && self.height.is_positive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd, U> Size2D<T, U> {
|
||||
/// Returns vector with results of "greater then" operation on each component.
|
||||
pub fn greater_than(&self, other: Self) -> BoolVector2D {
|
||||
BoolVector2D {
|
||||
x: self.width > other.width,
|
||||
@ -359,6 +424,7 @@ impl<T: PartialOrd, U> Size2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns vector with results of "lower then" operation on each component.
|
||||
pub fn lower_than(&self, other: Self) -> BoolVector2D {
|
||||
BoolVector2D {
|
||||
x: self.width < other.width,
|
||||
@ -369,6 +435,7 @@ impl<T: PartialOrd, U> Size2D<T, U> {
|
||||
|
||||
|
||||
impl<T: PartialEq, U> Size2D<T, U> {
|
||||
/// Returns vector with results of "equal" operation on each component.
|
||||
pub fn equal(&self, other: Self) -> BoolVector2D {
|
||||
BoolVector2D {
|
||||
x: self.width == other.width,
|
||||
@ -376,6 +443,7 @@ impl<T: PartialEq, U> Size2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns vector with results of "not equal" operation on each component.
|
||||
pub fn not_equal(&self, other: Self) -> BoolVector2D {
|
||||
BoolVector2D {
|
||||
x: self.width != other.width,
|
||||
@ -384,37 +452,48 @@ impl<T: PartialEq, U> Size2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> Size2D<T, U> {
|
||||
impl<T: PartialOrd, U> Size2D<T, U> {
|
||||
/// Returns the size each component of which are minimum of this size and another.
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
size2(
|
||||
self.width.min(other.width),
|
||||
self.height.min(other.height),
|
||||
min(self.width, other.width),
|
||||
min(self.height, other.height),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the size each component of which are maximum of this size and another.
|
||||
#[inline]
|
||||
pub fn max(self, other: Self) -> Self {
|
||||
size2(
|
||||
self.width.max(other.width),
|
||||
self.height.max(other.height),
|
||||
max(self.width, other.width),
|
||||
max(self.height, other.height),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the size each component of which clamped by corresponding
|
||||
/// components of `start` and `end`.
|
||||
///
|
||||
/// Shortcut for `self.max(start).min(end)`.
|
||||
#[inline]
|
||||
pub fn clamp(&self, start: Self, end: Self) -> Self {
|
||||
pub fn clamp(&self, start: Self, end: Self) -> Self
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
self.max(start).min(end)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Shorthand for `Size2D::new(w, h)`.
|
||||
pub fn size2<T, U>(w: T, h: T) -> Size2D<T, U> {
|
||||
#[inline]
|
||||
pub const fn size2<T, U>(w: T, h: T) -> Size2D<T, U> {
|
||||
Size2D::new(w, h)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, U> From<mint::Vector2<T>> for Size2D<T, U> {
|
||||
#[inline]
|
||||
fn from(v: mint::Vector2<T>) -> Self {
|
||||
Size2D {
|
||||
width: v.x,
|
||||
@ -425,6 +504,7 @@ impl<T, U> From<mint::Vector2<T>> for Size2D<T, U> {
|
||||
}
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, U> Into<mint::Vector2<T>> for Size2D<T, U> {
|
||||
#[inline]
|
||||
fn into(self) -> mint::Vector2<T> {
|
||||
mint::Vector2 {
|
||||
x: self.width,
|
||||
@ -434,6 +514,7 @@ impl<T, U> Into<mint::Vector2<T>> for Size2D<T, U> {
|
||||
}
|
||||
|
||||
impl<T, U> From<Vector2D<T, U>> for Size2D<T, U> {
|
||||
#[inline]
|
||||
fn from(v: Vector2D<T, U>) -> Self {
|
||||
Size2D {
|
||||
width: v.x,
|
||||
@ -443,25 +524,29 @@ impl<T, U> From<Vector2D<T, U>> for Size2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<[T; 2]> for Size2D<T, U> {
|
||||
impl<T, U> Into<[T; 2]> for Size2D<T, U> {
|
||||
#[inline]
|
||||
fn into(self) -> [T; 2] {
|
||||
self.to_array()
|
||||
[self.width, self.height]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<[T; 2]> for Size2D<T, U> {
|
||||
fn from(array: [T; 2]) -> Self {
|
||||
size2(array[0], array[1])
|
||||
impl<T, U> From<[T; 2]> for Size2D<T, U> {
|
||||
#[inline]
|
||||
fn from([w, h]: [T; 2]) -> Self {
|
||||
size2(w, h)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<(T, T)> for Size2D<T, U> {
|
||||
impl<T, U> Into<(T, T)> for Size2D<T, U> {
|
||||
#[inline]
|
||||
fn into(self) -> (T, T) {
|
||||
self.to_tuple()
|
||||
(self.width, self.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<(T, T)> for Size2D<T, U> {
|
||||
impl<T, U> From<(T, T)> for Size2D<T, U> {
|
||||
#[inline]
|
||||
fn from(tuple: (T, T)) -> Self {
|
||||
size2(tuple.0, tuple.1)
|
||||
}
|
||||
@ -531,8 +616,11 @@ mod size2d {
|
||||
/// A 3d size tagged with a unit.
|
||||
#[repr(C)]
|
||||
pub struct Size3D<T, U> {
|
||||
/// The extent of the element in the `U` units along the `x` axis.
|
||||
pub width: T,
|
||||
/// The extent of the element in the `U` units along the `y` axis.
|
||||
pub height: T,
|
||||
/// The extent of the element in the `U` units along the `z` axis.
|
||||
pub depth: T,
|
||||
#[doc(hidden)]
|
||||
pub _unit: PhantomData<U>,
|
||||
@ -558,7 +646,7 @@ impl<'de, T, U> serde::Deserialize<'de> for Size3D<T, U>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
{
|
||||
let (width, height, depth) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
let (width, height, depth) = serde::Deserialize::deserialize(deserializer)?;
|
||||
Ok(Size3D { width, height, depth, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
@ -614,7 +702,8 @@ impl<T: Default, U> Default for Size3D<T, U> {
|
||||
|
||||
impl<T, U> Size3D<T, U> {
|
||||
/// Constructor taking scalar values.
|
||||
pub fn new(width: T, height: T, depth: T) -> Self {
|
||||
#[inline]
|
||||
pub const fn new(width: T, height: T, depth: T) -> Self {
|
||||
Size3D {
|
||||
width,
|
||||
height,
|
||||
@ -624,10 +713,11 @@ impl<T, U> Size3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, U> Size3D<T, U> {
|
||||
impl<T, U> Size3D<T, U> {
|
||||
/// Constructor taking scalar strongly typed lengths.
|
||||
#[inline]
|
||||
pub fn from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
|
||||
Size3D::new(width.get(), height.get(), depth.get())
|
||||
Size3D::new(width.0, height.0, depth.0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -635,6 +725,7 @@ impl<T: Round, U> Size3D<T, U> {
|
||||
/// Rounds each component to the nearest integer value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
#[inline]
|
||||
pub fn round(&self) -> Self {
|
||||
Size3D::new(self.width.round(), self.height.round(), self.depth.round())
|
||||
}
|
||||
@ -644,6 +735,7 @@ impl<T: Ceil, U> Size3D<T, U> {
|
||||
/// Rounds each component to the smallest integer equal or greater than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
#[inline]
|
||||
pub fn ceil(&self) -> Self {
|
||||
Size3D::new(self.width.ceil(), self.height.ceil(), self.depth.ceil())
|
||||
}
|
||||
@ -653,26 +745,30 @@ impl<T: Floor, U> Size3D<T, U> {
|
||||
/// Rounds each component to the biggest integer equal or lower than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
#[inline]
|
||||
pub fn floor(&self) -> Self {
|
||||
Size3D::new(self.width.floor(), self.height.floor(), self.depth.floor())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> Add for Size3D<T, U> {
|
||||
impl<T: Add<T, Output = T>, U> Add for Size3D<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn add(self, other: Self) -> Self {
|
||||
Size3D::new(self.width + other.width, self.height + other.height, self.depth + other.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Sub<T, Output = T>, U> Sub for Size3D<T, U> {
|
||||
impl<T: Sub<T, Output = T>, U> Sub for Size3D<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn sub(self, other: Self) -> Self {
|
||||
Size3D::new(self.width - other.width, self.height - other.height, self.depth - other.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Clone + Mul<T, Output=T>, U> Size3D<T, U> {
|
||||
impl<T: Copy + Mul<T, Output=T>, U> Size3D<T, U> {
|
||||
/// Returns result of multiplication of all components
|
||||
pub fn volume(&self) -> T {
|
||||
self.width * self.height * self.depth
|
||||
}
|
||||
@ -684,7 +780,24 @@ where
|
||||
{
|
||||
/// Linearly interpolate between this size and another size.
|
||||
///
|
||||
/// `t` is expected to be between zero and one.
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::size3;
|
||||
/// use euclid::default::Size3D;
|
||||
///
|
||||
/// let first: Size3D<_> = size3(0.0, 10.0, -1.0);
|
||||
/// let last: Size3D<_> = size3(8.0, -4.0, 0.0);
|
||||
///
|
||||
/// assert_eq!(first.lerp(last, -1.0), size3(-8.0, 24.0, -2.0));
|
||||
/// assert_eq!(first.lerp(last, 0.0), size3( 0.0, 10.0, -1.0));
|
||||
/// assert_eq!(first.lerp(last, 0.5), size3( 4.0, 3.0, -0.5));
|
||||
/// assert_eq!(first.lerp(last, 1.0), size3( 8.0, -4.0, 0.0));
|
||||
/// assert_eq!(first.lerp(last, 2.0), size3(16.0, -18.0, 1.0));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
let one_t = T::one() - t;
|
||||
@ -697,6 +810,7 @@ where
|
||||
}
|
||||
|
||||
impl<T: Zero + PartialOrd, U> Size3D<T, U> {
|
||||
/// Returns `true` if any component of size is zero or negative.
|
||||
pub fn is_empty_or_negative(&self) -> bool {
|
||||
let zero = T::zero();
|
||||
self.width <= zero || self.height <= zero || self.depth <= zero
|
||||
@ -704,12 +818,17 @@ impl<T: Zero + PartialOrd, U> Size3D<T, U> {
|
||||
}
|
||||
|
||||
impl<T: Zero, U> Size3D<T, U> {
|
||||
/// The same as [`Zero::zero()`] but available without importing trait.
|
||||
///
|
||||
/// [`Zero::zero()`]: ./num/trait.Zero.html#tymethod.zero
|
||||
#[inline]
|
||||
pub fn zero() -> Self {
|
||||
Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> Zero for Size3D<T, U> {
|
||||
#[inline]
|
||||
fn zero() -> Self {
|
||||
Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
|
||||
}
|
||||
@ -748,35 +867,51 @@ impl<T: Copy + Div<T, Output = T>, U1, U2> Div<Scale<T, U1, U2>> for Size3D<T, U
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Size3D<T, U> {
|
||||
/// Returns self.width as a Length carrying the unit.
|
||||
/// Return this size as an array of three elements (width, then height, then depth).
|
||||
#[inline]
|
||||
pub fn to_array(&self) -> [T; 3] {
|
||||
[self.width, self.height, self.depth]
|
||||
}
|
||||
|
||||
/// Return this size as an array of three elements (width, then height, then depth).
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T, T) {
|
||||
(self.width, self.height, self.depth)
|
||||
}
|
||||
|
||||
/// Return this size as a vector with width, height and depth.
|
||||
#[inline]
|
||||
pub fn to_vector(&self) -> Vector3D<T, U> {
|
||||
vec3(self.width, self.height, self.depth)
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Size3D<T, UnknownUnit> {
|
||||
Size3D::new(self.width, self.height, self.depth)
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(p: Size3D<T, UnknownUnit>) -> Self {
|
||||
Size3D::new(p.width, p.height, p.depth)
|
||||
}
|
||||
|
||||
/// Cast the unit
|
||||
#[inline]
|
||||
pub fn cast_unit<V>(&self) -> Size3D<T, V> {
|
||||
Size3D::new(self.width, self.height, self.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Copy, Unit> Size3D<T, Unit> {
|
||||
impl<T: NumCast + Copy, U> Size3D<T, U> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> Size3D<NewT, Unit> {
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> Size3D<NewT, U> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
@ -785,7 +920,7 @@ impl<T: NumCast + Copy, Unit> Size3D<T, Unit> {
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
|
||||
pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<Size3D<NewT, Unit>> {
|
||||
pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<Size3D<NewT, U>> {
|
||||
match (NumCast::from(self.width), NumCast::from(self.height), NumCast::from(self.depth)) {
|
||||
(Some(w), Some(h), Some(d)) => Some(Size3D::new(w, h, d)),
|
||||
_ => None,
|
||||
@ -795,12 +930,14 @@ impl<T: NumCast + Copy, Unit> Size3D<T, Unit> {
|
||||
// Convenience functions for common casts
|
||||
|
||||
/// Cast into an `f32` size.
|
||||
pub fn to_f32(&self) -> Size3D<f32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Size3D<f32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` size.
|
||||
pub fn to_f64(&self) -> Size3D<f64, Unit> {
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Size3D<f64, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -809,7 +946,8 @@ impl<T: NumCast + Copy, Unit> Size3D<T, Unit> {
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> Size3D<usize, Unit> {
|
||||
#[inline]
|
||||
pub fn to_usize(&self) -> Size3D<usize, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -818,7 +956,8 @@ impl<T: NumCast + Copy, Unit> Size3D<T, Unit> {
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> Size3D<u32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_u32(&self) -> Size3D<u32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -827,7 +966,8 @@ impl<T: NumCast + Copy, Unit> Size3D<T, Unit> {
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> Size3D<i32, Unit> {
|
||||
#[inline]
|
||||
pub fn to_i32(&self) -> Size3D<i32, U> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
@ -836,7 +976,8 @@ impl<T: NumCast + Copy, Unit> Size3D<T, Unit> {
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> Size3D<i64, Unit> {
|
||||
#[inline]
|
||||
pub fn to_i64(&self) -> Size3D<i64, U> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
@ -845,16 +986,23 @@ impl<T, U> Size3D<T, U>
|
||||
where
|
||||
T: Signed,
|
||||
{
|
||||
/// Computes the absolute value of each component.
|
||||
///
|
||||
/// For `f32` and `f64`, `NaN` will be returned for component if the component is `NaN`.
|
||||
///
|
||||
/// For signed integers, `::MIN` will be returned for component if the component is `::MIN`.
|
||||
pub fn abs(&self) -> Self {
|
||||
size3(self.width.abs(), self.height.abs(), self.depth.abs())
|
||||
}
|
||||
|
||||
/// Returns `true` if all components is positive and `false` any component is zero or negative.
|
||||
pub fn is_positive(&self) -> bool {
|
||||
self.width.is_positive() && self.height.is_positive() && self.depth.is_positive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd, U> Size3D<T, U> {
|
||||
/// Returns vector with results of "greater than" operation on each component.
|
||||
pub fn greater_than(&self, other: Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width > other.width,
|
||||
@ -863,6 +1011,7 @@ impl<T: PartialOrd, U> Size3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns vector with results of "lower than" operation on each component.
|
||||
pub fn lower_than(&self, other: Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width < other.width,
|
||||
@ -874,6 +1023,7 @@ impl<T: PartialOrd, U> Size3D<T, U> {
|
||||
|
||||
|
||||
impl<T: PartialEq, U> Size3D<T, U> {
|
||||
/// Returns vector with results of "equal" operation on each component.
|
||||
pub fn equal(&self, other: Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width == other.width,
|
||||
@ -882,6 +1032,7 @@ impl<T: PartialEq, U> Size3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns vector with results of "not equal" operation on each component.
|
||||
pub fn not_equal(&self, other: Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width != other.width,
|
||||
@ -891,39 +1042,50 @@ impl<T: PartialEq, U> Size3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> Size3D<T, U> {
|
||||
impl<T: PartialOrd, U> Size3D<T, U> {
|
||||
/// Returns the size each component of which are minimum of this size and another.
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
size3(
|
||||
self.width.min(other.width),
|
||||
self.height.min(other.height),
|
||||
self.depth.min(other.depth),
|
||||
min(self.width, other.width),
|
||||
min(self.height, other.height),
|
||||
min(self.depth, other.depth),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the size each component of which are maximum of this size and another.
|
||||
#[inline]
|
||||
pub fn max(self, other: Self) -> Self {
|
||||
size3(
|
||||
self.width.max(other.width),
|
||||
self.height.max(other.height),
|
||||
self.depth.max(other.depth),
|
||||
max(self.width, other.width),
|
||||
max(self.height, other.height),
|
||||
max(self.depth, other.depth),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the size each component of which clamped by corresponding
|
||||
/// components of `start` and `end`.
|
||||
///
|
||||
/// Shortcut for `self.max(start).min(end)`.
|
||||
#[inline]
|
||||
pub fn clamp(&self, start: Self, end: Self) -> Self {
|
||||
pub fn clamp(&self, start: Self, end: Self) -> Self
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
self.max(start).min(end)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Shorthand for `Size3D::new(w, h, d)`.
|
||||
pub fn size3<T, U>(w: T, h: T, d: T) -> Size3D<T, U> {
|
||||
#[inline]
|
||||
pub const fn size3<T, U>(w: T, h: T, d: T) -> Size3D<T, U> {
|
||||
Size3D::new(w, h, d)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, U> From<mint::Vector3<T>> for Size3D<T, U> {
|
||||
#[inline]
|
||||
fn from(v: mint::Vector3<T>) -> Self {
|
||||
Size3D {
|
||||
width: v.x,
|
||||
@ -935,6 +1097,7 @@ impl<T, U> From<mint::Vector3<T>> for Size3D<T, U> {
|
||||
}
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, U> Into<mint::Vector3<T>> for Size3D<T, U> {
|
||||
#[inline]
|
||||
fn into(self) -> mint::Vector3<T> {
|
||||
mint::Vector3 {
|
||||
x: self.width,
|
||||
|
154
third_party/rust/euclid/src/transform2d.rs
vendored
154
third_party/rust/euclid/src/transform2d.rs
vendored
@ -79,7 +79,7 @@ impl<'de, T, Src, Dst> serde::Deserialize<'de> for Transform2D<T, Src, Dst>
|
||||
m11, m12,
|
||||
m21, m22,
|
||||
m31, m32,
|
||||
) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
) = serde::Deserialize::deserialize(deserializer)?;
|
||||
Ok(Transform2D {
|
||||
m11, m12,
|
||||
m21, m22,
|
||||
@ -132,13 +132,13 @@ impl<T, Src, Dst> Hash for Transform2D<T, Src, Dst>
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
impl<T, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
/// Create a transform specifying its matrix elements in row-major order.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `column_major`
|
||||
pub fn row_major(m11: T, m12: T, m21: T, m22: T, m31: T, m32: T) -> Self {
|
||||
pub const fn row_major(m11: T, m12: T, m21: T, m22: T, m31: T, m32: T) -> Self {
|
||||
Transform2D {
|
||||
m11, m12,
|
||||
m21, m22,
|
||||
@ -152,7 +152,7 @@ impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `row_major`
|
||||
pub fn column_major(m11: T, m21: T, m31: T, m12: T, m22: T, m32: T) -> Self {
|
||||
pub const fn column_major(m11: T, m21: T, m31: T, m12: T, m22: T, m32: T) -> Self {
|
||||
Transform2D {
|
||||
m11, m12,
|
||||
m21, m22,
|
||||
@ -161,12 +161,40 @@ impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Returns true is this transform is approximately equal to the other one, using
|
||||
/// T's default epsilon value.
|
||||
///
|
||||
/// The same as [`ApproxEq::approx_eq()`] but available without importing trait.
|
||||
///
|
||||
/// [`ApproxEq::approx_eq()`]: ./approxeq/trait.ApproxEq.html#method.approx_eq
|
||||
#[inline]
|
||||
pub fn approx_eq(&self, other: &Self) -> bool
|
||||
where T : ApproxEq<T> {
|
||||
<Self as ApproxEq<T>>::approx_eq(&self, &other)
|
||||
}
|
||||
|
||||
/// Returns true is this transform is approximately equal to the other one, using
|
||||
/// a provided epsilon value.
|
||||
///
|
||||
/// The same as [`ApproxEq::approx_eq_eps()`] but available without importing trait.
|
||||
///
|
||||
/// [`ApproxEq::approx_eq_eps()`]: ./approxeq/trait.ApproxEq.html#method.approx_eq_eps
|
||||
#[inline]
|
||||
pub fn approx_eq_eps(&self, other: &Self, eps: &T) -> bool
|
||||
where T : ApproxEq<T> {
|
||||
<Self as ApproxEq<T>>::approx_eq_eps(&self, &other, &eps)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
/// Returns an array containing this transform's terms in row-major order (the order
|
||||
/// in which the transform is actually laid out in memory).
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_column_major_array`
|
||||
#[inline]
|
||||
pub fn to_row_major_array(&self) -> [T; 6] {
|
||||
[
|
||||
self.m11, self.m12,
|
||||
@ -180,6 +208,7 @@ impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_row_major_array`
|
||||
#[inline]
|
||||
pub fn to_column_major_array(&self) -> [T; 6] {
|
||||
[
|
||||
self.m11, self.m21, self.m31,
|
||||
@ -195,6 +224,7 @@ impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), this will return column major arrays.
|
||||
#[inline]
|
||||
pub fn to_row_arrays(&self) -> [[T; 2]; 3] {
|
||||
[
|
||||
[self.m11, self.m12],
|
||||
@ -208,6 +238,7 @@ impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), please provide a column major array.
|
||||
#[inline]
|
||||
pub fn from_row_major_array(array: [T; 6]) -> Self {
|
||||
Self::row_major(
|
||||
array[0], array[1],
|
||||
@ -221,6 +252,7 @@ impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), please provide a column major array.
|
||||
#[inline]
|
||||
pub fn from_row_arrays(array: [[T; 2]; 3]) -> Self {
|
||||
Self::row_major(
|
||||
array[0][0], array[0][1],
|
||||
@ -230,6 +262,7 @@ impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Transform2D<T, UnknownUnit, UnknownUnit> {
|
||||
Transform2D::row_major(
|
||||
self.m11, self.m12,
|
||||
@ -239,6 +272,7 @@ impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(p: &Transform2D<T, UnknownUnit, UnknownUnit>) -> Self {
|
||||
Transform2D::row_major(
|
||||
p.m11, p.m12,
|
||||
@ -248,14 +282,15 @@ impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0: NumCast + Copy, Src, Dst> Transform2D<T0, Src, Dst> {
|
||||
impl<T: NumCast + Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Transform2D<T1, Src, Dst> {
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Transform2D<NewT, Src, Dst> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Transform2D<T1, Src, Dst>> {
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Transform2D<NewT, Src, Dst>> {
|
||||
match (NumCast::from(self.m11), NumCast::from(self.m12),
|
||||
NumCast::from(self.m21), NumCast::from(self.m22),
|
||||
NumCast::from(self.m31), NumCast::from(self.m32)) {
|
||||
@ -295,12 +330,11 @@ where T: Copy +
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Transform2D<T, Src, Dst>
|
||||
where T: Copy + Clone +
|
||||
where T: Copy +
|
||||
Add<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
Div<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Trig +
|
||||
PartialOrd +
|
||||
One + Zero {
|
||||
|
||||
@ -377,39 +411,12 @@ where T: Copy + Clone +
|
||||
#[must_use]
|
||||
pub fn pre_scale(&self, x: T, y: T) -> Self {
|
||||
Transform2D::row_major(
|
||||
self.m11 * x, self.m12,
|
||||
self.m21, self.m22 * y,
|
||||
self.m11 * x, self.m12 * x,
|
||||
self.m21 * y, self.m22 * y,
|
||||
self.m31, self.m32
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a rotation transform.
|
||||
#[inline]
|
||||
pub fn create_rotation(theta: Angle<T>) -> Self {
|
||||
let _0 = Zero::zero();
|
||||
let cos = theta.get().cos();
|
||||
let sin = theta.get().sin();
|
||||
Transform2D::row_major(
|
||||
cos, _0 - sin,
|
||||
sin, cos,
|
||||
_0, _0
|
||||
)
|
||||
}
|
||||
|
||||
/// Applies a rotation after self's transformation and returns the resulting transform.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn post_rotate(&self, theta: Angle<T>) -> Self {
|
||||
self.post_transform(&Transform2D::create_rotation(theta))
|
||||
}
|
||||
|
||||
/// Applies a rotation before self's transformation and returns the resulting transform.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn pre_rotate(&self, theta: Angle<T>) -> Self {
|
||||
self.pre_transform(&Transform2D::create_rotation(theta))
|
||||
}
|
||||
|
||||
/// Returns the given point transformed by this transform.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
@ -452,6 +459,12 @@ where T: Copy + Clone +
|
||||
self.m11 * self.m22 - self.m12 * self.m21
|
||||
}
|
||||
|
||||
/// Returns whether it is possible to compute the inverse transform.
|
||||
#[inline]
|
||||
pub fn is_invertible(&self) -> bool {
|
||||
self.determinant() != Zero::zero()
|
||||
}
|
||||
|
||||
/// Returns the inverse transform if possible.
|
||||
#[must_use]
|
||||
pub fn inverse(&self) -> Option<Transform2D<T, Dst, Src>> {
|
||||
@ -496,8 +509,45 @@ where T: Copy + Clone +
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Transform2D<T, Src, Dst>
|
||||
where T: Copy +
|
||||
Add<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
Div<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Trig +
|
||||
PartialOrd +
|
||||
One + Zero {
|
||||
/// Returns a rotation transform.
|
||||
#[inline]
|
||||
pub fn create_rotation(theta: Angle<T>) -> Self {
|
||||
let _0 = Zero::zero();
|
||||
let cos = theta.get().cos();
|
||||
let sin = theta.get().sin();
|
||||
Transform2D::row_major(
|
||||
cos, _0 - sin,
|
||||
sin, cos,
|
||||
_0, _0
|
||||
)
|
||||
}
|
||||
|
||||
/// Applies a rotation after self's transformation and returns the resulting transform.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn post_rotate(&self, theta: Angle<T>) -> Self {
|
||||
self.post_transform(&Transform2D::create_rotation(theta))
|
||||
}
|
||||
|
||||
/// Applies a rotation before self's transformation and returns the resulting transform.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn pre_rotate(&self, theta: Angle<T>) -> Self {
|
||||
self.pre_transform(&Transform2D::create_rotation(theta))
|
||||
}
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> Transform2D<T, Src, Dst>
|
||||
where T: Copy + Clone +
|
||||
where T: Copy +
|
||||
Add<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
@ -521,15 +571,20 @@ impl <T, Src, Dst> Default for Transform2D<T, Src, Dst>
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ApproxEq<T>, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
pub fn approx_eq(&self, other: &Self) -> bool {
|
||||
self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) &&
|
||||
self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) &&
|
||||
self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32)
|
||||
impl<T: ApproxEq<T>, Src, Dst> ApproxEq<T> for Transform2D<T, Src, Dst> {
|
||||
#[inline]
|
||||
fn approx_epsilon() -> T { T::approx_epsilon() }
|
||||
|
||||
/// Returns true is this transform is approximately equal to the other one, using
|
||||
/// a provided epsilon value.
|
||||
fn approx_eq_eps(&self, other: &Self, eps: &T) -> bool {
|
||||
self.m11.approx_eq_eps(&other.m11, eps) && self.m12.approx_eq_eps(&other.m12, eps) &&
|
||||
self.m21.approx_eq_eps(&other.m21, eps) && self.m22.approx_eq_eps(&other.m22, eps) &&
|
||||
self.m31.approx_eq_eps(&other.m31, eps) && self.m32.approx_eq_eps(&other.m32, eps)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + fmt::Debug, Src, Dst> fmt::Debug for Transform2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> fmt::Debug for Transform2D<T, Src, Dst>
|
||||
where T: Copy + fmt::Debug +
|
||||
PartialEq +
|
||||
One + Zero {
|
||||
@ -616,6 +671,15 @@ mod test {
|
||||
assert!(s1.transform_point(Point2D::new(2.0, 2.0)).approx_eq(&Point2D::new(4.0, 6.0)));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
pub fn test_pre_post_scale() {
|
||||
let m = Mat::create_rotation(rad(FRAC_PI_2)).post_translate(vec2(6.0, 7.0));
|
||||
let s = Mat::create_scale(2.0, 3.0);
|
||||
assert_eq!(m.post_transform(&s), m.post_scale(2.0, 3.0));
|
||||
assert_eq!(m.pre_transform(&s), m.pre_scale(2.0, 3.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_column_major() {
|
||||
assert_eq!(
|
||||
|
89
third_party/rust/euclid/src/transform3d.rs
vendored
89
third_party/rust/euclid/src/transform3d.rs
vendored
@ -93,7 +93,7 @@ impl<'de, T, Src, Dst> serde::Deserialize<'de> for Transform3D<T, Src, Dst>
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44,
|
||||
) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
) = serde::Deserialize::deserialize(deserializer)?;
|
||||
Ok(Transform3D {
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
@ -179,7 +179,7 @@ impl<T, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// is `T * v`), then please use `column_major`
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
pub fn row_major(
|
||||
pub const fn row_major(
|
||||
m11: T, m12: T, m13: T, m14: T,
|
||||
m21: T, m22: T, m23: T, m24: T,
|
||||
m31: T, m32: T, m33: T, m34: T,
|
||||
@ -204,7 +204,7 @@ impl<T, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// is `T * v`), then please use `row_major`
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
pub fn column_major(
|
||||
pub const fn column_major(
|
||||
m11: T, m21: T, m31: T, m41: T,
|
||||
m12: T, m22: T, m32: T, m42: T,
|
||||
m13: T, m23: T, m33: T, m43: T,
|
||||
@ -221,7 +221,7 @@ impl<T, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> Transform3D<T, Src, Dst>
|
||||
where T: Copy + Clone +
|
||||
where T: Copy +
|
||||
PartialEq +
|
||||
One + Zero {
|
||||
#[inline]
|
||||
@ -245,7 +245,7 @@ where T: Copy + Clone +
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> Transform3D<T, Src, Dst>
|
||||
where T: Copy + Clone +
|
||||
where T: Copy +
|
||||
Add<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
@ -323,16 +323,28 @@ where T: Copy + Clone +
|
||||
(m33 * det) < _0
|
||||
}
|
||||
|
||||
/// Returns true is this transform is approximately equal to the other one, using
|
||||
/// T's default epsilon value.
|
||||
///
|
||||
/// The same as [`ApproxEq::approx_eq()`] but available without importing trait.
|
||||
///
|
||||
/// [`ApproxEq::approx_eq()`]: ./approxeq/trait.ApproxEq.html#method.approx_eq
|
||||
#[inline]
|
||||
pub fn approx_eq(&self, other: &Self) -> bool
|
||||
where T : ApproxEq<T> {
|
||||
self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) &&
|
||||
self.m13.approx_eq(&other.m13) && self.m14.approx_eq(&other.m14) &&
|
||||
self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) &&
|
||||
self.m23.approx_eq(&other.m23) && self.m24.approx_eq(&other.m24) &&
|
||||
self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32) &&
|
||||
self.m33.approx_eq(&other.m33) && self.m34.approx_eq(&other.m34) &&
|
||||
self.m41.approx_eq(&other.m41) && self.m42.approx_eq(&other.m42) &&
|
||||
self.m43.approx_eq(&other.m43) && self.m44.approx_eq(&other.m44)
|
||||
<Self as ApproxEq<T>>::approx_eq(&self, &other)
|
||||
}
|
||||
|
||||
/// Returns true is this transform is approximately equal to the other one, using
|
||||
/// a provided epsilon value.
|
||||
///
|
||||
/// The same as [`ApproxEq::approx_eq_eps()`] but available without importing trait.
|
||||
///
|
||||
/// [`ApproxEq::approx_eq_eps()`]: ./approxeq/trait.ApproxEq.html#method.approx_eq_eps
|
||||
#[inline]
|
||||
pub fn approx_eq_eps(&self, other: &Self, eps: &T) -> bool
|
||||
where T : ApproxEq<T> {
|
||||
<Self as ApproxEq<T>>::approx_eq_eps(&self, &other, &eps)
|
||||
}
|
||||
|
||||
/// Returns the same transform with a different destination unit.
|
||||
@ -415,6 +427,12 @@ where T: Copy + Clone +
|
||||
mat.post_transform(self)
|
||||
}
|
||||
|
||||
/// Returns whether it is possible to compute the inverse transform.
|
||||
#[inline]
|
||||
pub fn is_invertible(&self) -> bool {
|
||||
self.determinant() != Zero::zero()
|
||||
}
|
||||
|
||||
/// Returns the inverse transform if possible.
|
||||
pub fn inverse(&self) -> Option<Transform3D<T, Dst, Src>> {
|
||||
let det = self.determinant();
|
||||
@ -718,9 +736,9 @@ where T: Copy + Clone +
|
||||
#[must_use]
|
||||
pub fn pre_scale(&self, x: T, y: T, z: T) -> Self {
|
||||
Transform3D::row_major(
|
||||
self.m11 * x, self.m12, self.m13, self.m14,
|
||||
self.m21 , self.m22 * y, self.m23, self.m24,
|
||||
self.m31 , self.m32, self.m33 * z, self.m34,
|
||||
self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x,
|
||||
self.m21 * y, self.m22 * y, self.m23 * y, self.m24 * y,
|
||||
self.m31 * z, self.m32 * z, self.m33 * z, self.m34 * z,
|
||||
self.m41 , self.m42, self.m43, self.m44
|
||||
)
|
||||
}
|
||||
@ -813,6 +831,7 @@ impl<T: Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_column_major_array`
|
||||
#[inline]
|
||||
pub fn to_row_major_array(&self) -> [T; 16] {
|
||||
[
|
||||
self.m11, self.m12, self.m13, self.m14,
|
||||
@ -827,6 +846,7 @@ impl<T: Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_row_major_array`
|
||||
#[inline]
|
||||
pub fn to_column_major_array(&self) -> [T; 16] {
|
||||
[
|
||||
self.m11, self.m21, self.m31, self.m41,
|
||||
@ -844,6 +864,7 @@ impl<T: Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_column_arrays`
|
||||
#[inline]
|
||||
pub fn to_row_arrays(&self) -> [[T; 4]; 4] {
|
||||
[
|
||||
[self.m11, self.m12, self.m13, self.m14],
|
||||
@ -861,6 +882,7 @@ impl<T: Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_row_arrays`
|
||||
#[inline]
|
||||
pub fn to_column_arrays(&self) -> [[T; 4]; 4] {
|
||||
[
|
||||
[self.m11, self.m21, self.m31, self.m41],
|
||||
@ -875,6 +897,7 @@ impl<T: Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), please provide column-major data to this function.
|
||||
#[inline]
|
||||
pub fn from_array(array: [T; 16]) -> Self {
|
||||
Self::row_major(
|
||||
array[0], array[1], array[2], array[3],
|
||||
@ -889,6 +912,7 @@ impl<T: Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), please provide column-major data to tis function.
|
||||
#[inline]
|
||||
pub fn from_row_arrays(array: [[T; 4]; 4]) -> Self {
|
||||
Self::row_major(
|
||||
array[0][0], array[0][1], array[0][2], array[0][3],
|
||||
@ -899,14 +923,15 @@ impl<T: Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0: NumCast + Copy, Src, Dst> Transform3D<T0, Src, Dst> {
|
||||
impl<T: NumCast + Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Transform3D<T1, Src, Dst> {
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Transform3D<NewT, Src, Dst> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Transform3D<T1, Src, Dst>> {
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Transform3D<NewT, Src, Dst>> {
|
||||
match (NumCast::from(self.m11), NumCast::from(self.m12),
|
||||
NumCast::from(self.m13), NumCast::from(self.m14),
|
||||
NumCast::from(self.m21), NumCast::from(self.m22),
|
||||
@ -929,6 +954,22 @@ impl<T0: NumCast + Copy, Src, Dst> Transform3D<T0, Src, Dst> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ApproxEq<T>, Src, Dst> ApproxEq<T> for Transform3D<T, Src, Dst> {
|
||||
#[inline]
|
||||
fn approx_epsilon() -> T { T::approx_epsilon() }
|
||||
|
||||
fn approx_eq_eps(&self, other: &Self, eps: &T) -> bool {
|
||||
self.m11.approx_eq_eps(&other.m11, eps) && self.m12.approx_eq_eps(&other.m12, eps) &&
|
||||
self.m13.approx_eq_eps(&other.m13, eps) && self.m14.approx_eq_eps(&other.m14, eps) &&
|
||||
self.m21.approx_eq_eps(&other.m21, eps) && self.m22.approx_eq_eps(&other.m22, eps) &&
|
||||
self.m23.approx_eq_eps(&other.m23, eps) && self.m24.approx_eq_eps(&other.m24, eps) &&
|
||||
self.m31.approx_eq_eps(&other.m31, eps) && self.m32.approx_eq_eps(&other.m32, eps) &&
|
||||
self.m33.approx_eq_eps(&other.m33, eps) && self.m34.approx_eq_eps(&other.m34, eps) &&
|
||||
self.m41.approx_eq_eps(&other.m41, eps) && self.m42.approx_eq_eps(&other.m42, eps) &&
|
||||
self.m43.approx_eq_eps(&other.m43, eps) && self.m44.approx_eq_eps(&other.m44, eps)
|
||||
}
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> Default for Transform3D<T, Src, Dst>
|
||||
where T: Copy + PartialEq + One + Zero
|
||||
{
|
||||
@ -1040,6 +1081,16 @@ mod tests {
|
||||
assert_eq!(Mf32::create_scale(2.0, 3.0, 0.0).to_2d(), Transform2D::create_scale(2.0, 3.0));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
pub fn test_pre_post_scale() {
|
||||
let m = Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2)).post_translate(vec3(6.0, 7.0, 8.0));
|
||||
let s = Mf32::create_scale(2.0, 3.0, 4.0);
|
||||
assert_eq!(m.post_transform(&s), m.post_scale(2.0, 3.0, 4.0));
|
||||
assert_eq!(m.pre_transform(&s), m.pre_scale(2.0, 3.0, 4.0));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
pub fn test_ortho() {
|
||||
let (left, right, bottom, top) = (0.0f32, 1.0f32, 0.1f32, 1.0f32);
|
||||
|
162
third_party/rust/euclid/src/translation.rs
vendored
162
third_party/rust/euclid/src/translation.rs
vendored
@ -9,6 +9,7 @@
|
||||
|
||||
use {Vector2D, Point2D, Vector3D, Point3D, Transform2D, Transform3D};
|
||||
use {Size2D, Rect, vec2, point2, vec3, point3};
|
||||
use UnknownUnit;
|
||||
use num::*;
|
||||
use trig::Trig;
|
||||
use core::ops::{Add, Sub, Neg, Mul, Div};
|
||||
@ -82,38 +83,71 @@ impl<T, Src, Dst> Hash for Translation2D<T, Src, Dst>
|
||||
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst> {
|
||||
#[inline]
|
||||
pub fn new(x: T, y: T) -> Self {
|
||||
pub const fn new(x: T, y: T) -> Self {
|
||||
Translation2D {
|
||||
x,
|
||||
y,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// No-op, just cast the unit.
|
||||
#[inline]
|
||||
pub fn transform_size(&self, s: Size2D<T, Src>) -> Size2D<T, Dst> {
|
||||
Size2D::new(s.width, s.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst>
|
||||
where
|
||||
T : Copy
|
||||
{
|
||||
/// Cast into a 2D vector.
|
||||
#[inline]
|
||||
pub fn to_vector(&self) -> Vector2D<T, Src> {
|
||||
vec2(self.x, self.y)
|
||||
}
|
||||
|
||||
/// Cast into an array with x and y.
|
||||
#[inline]
|
||||
pub fn to_array(&self) -> [T; 2] {
|
||||
[self.x, self.y]
|
||||
}
|
||||
|
||||
/// Cast into a tuple with x and y.
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Translation2D<T, UnknownUnit, UnknownUnit> {
|
||||
Translation2D {
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(t: &Translation2D<T, UnknownUnit, UnknownUnit>) -> Self {
|
||||
Translation2D {
|
||||
x: t.x,
|
||||
y: t.y,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst>
|
||||
where
|
||||
T : Copy + Zero
|
||||
T: Zero
|
||||
{
|
||||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
let _0 = T::zero();
|
||||
Translation2D::new(_0, _0)
|
||||
Translation2D::new(T::zero(), T::zero())
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +157,8 @@ where
|
||||
{
|
||||
#[inline]
|
||||
pub fn is_identity(&self) -> bool {
|
||||
self.x == T::zero() && self.y == T::zero()
|
||||
let _0 = T::zero();
|
||||
self.x == _0 && self.y == _0
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,17 +180,6 @@ where
|
||||
size: self.transform_size(r.size),
|
||||
}
|
||||
}
|
||||
|
||||
/// No-op, just cast the unit.
|
||||
#[inline]
|
||||
pub fn transform_size(&self, s: Size2D<T, Src>) -> Size2D<T, Dst> {
|
||||
Size2D::new(s.width, s.height)
|
||||
}
|
||||
|
||||
/// Cast into a 2D vector.
|
||||
pub fn to_vector(&self) -> Vector2D<T, Src> {
|
||||
vec2(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst>
|
||||
@ -172,7 +196,7 @@ where
|
||||
impl<T, Src, Dst1, Dst2> Add<Translation2D<T, Dst1, Dst2>>
|
||||
for Translation2D<T, Src, Dst1>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>
|
||||
T: Add<T, Output = T>
|
||||
{
|
||||
type Output = Translation2D<T, Src, Dst2>;
|
||||
fn add(self, other: Translation2D<T, Dst1, Dst2>) -> Translation2D<T, Src, Dst2> {
|
||||
@ -187,7 +211,7 @@ impl<T, Src, Dst1, Dst2>
|
||||
Sub<Translation2D<T, Dst1, Dst2>>
|
||||
for Translation2D<T, Src, Dst2>
|
||||
where
|
||||
T: Copy + Sub<T, Output = T>
|
||||
T: Sub<T, Output = T>
|
||||
{
|
||||
type Output = Translation2D<T, Src, Dst1>;
|
||||
fn sub(self, other: Translation2D<T, Dst1, Dst2>) -> Translation2D<T, Src, Dst1> {
|
||||
@ -201,7 +225,6 @@ where
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
+ Clone
|
||||
+ Add<T, Output = T>
|
||||
+ Mul<T, Output = T>
|
||||
+ Div<T, Output = T>
|
||||
@ -219,8 +242,6 @@ where
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> From<Vector2D<T, Src>> for Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
{
|
||||
fn from(v: Vector2D<T, Src>) -> Self {
|
||||
Translation2D::new(v.x, v.y)
|
||||
@ -228,8 +249,6 @@ where
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Into<Vector2D<T, Src>> for Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
{
|
||||
fn into(self) -> Vector2D<T, Src> {
|
||||
vec2(self.x, self.y)
|
||||
@ -239,7 +258,6 @@ where
|
||||
impl<T, Src, Dst> Into<Transform2D<T, Src, Dst>> for Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
+ Clone
|
||||
+ Add<T, Output = T>
|
||||
+ Mul<T, Output = T>
|
||||
+ Div<T, Output = T>
|
||||
@ -255,20 +273,24 @@ where
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> Default for Translation2D<T, Src, Dst>
|
||||
where T: Copy + Zero
|
||||
where T: Zero
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> fmt::Debug for Translation2D<T, Src, Dst>
|
||||
where T: Copy + fmt::Debug {
|
||||
impl<T: fmt::Debug, Src, Dst> fmt::Debug for Translation2D<T, Src, Dst> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.to_array().fmt(f)
|
||||
write!(f, "Translation({:?},{:?})", self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, Src, Dst> fmt::Display for Translation2D<T, Src, Dst> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "({},{})", self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A 3d transformation from a space to another that can only express translations.
|
||||
@ -304,7 +326,7 @@ impl<'de, T, Src, Dst> serde::Deserialize<'de> for Translation3D<T, Src, Dst>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
{
|
||||
let (x, y, z) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
let (x, y, z) = serde::Deserialize::deserialize(deserializer)?;
|
||||
Ok(Translation3D { x, y, z, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
@ -342,7 +364,7 @@ impl<T, Src, Dst> Hash for Translation3D<T, Src, Dst>
|
||||
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst> {
|
||||
#[inline]
|
||||
pub fn new(x: T, y: T, z: T) -> Self {
|
||||
pub const fn new(x: T, y: T, z: T) -> Self {
|
||||
Translation3D {
|
||||
x,
|
||||
y,
|
||||
@ -350,31 +372,66 @@ impl<T, Src, Dst> Translation3D<T, Src, Dst> {
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// No-op, just cast the unit.
|
||||
#[inline]
|
||||
pub fn transform_size(self, s: Size2D<T, Src>) -> Size2D<T, Dst> {
|
||||
Size2D::new(s.width, s.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
{
|
||||
/// Cast into a 3D vector.
|
||||
#[inline]
|
||||
pub fn to_vector(&self) -> Vector3D<T, Src> {
|
||||
vec3(self.x, self.y, self.z)
|
||||
}
|
||||
|
||||
/// Cast into an array with x, y and z.
|
||||
#[inline]
|
||||
pub fn to_array(&self) -> [T; 3] {
|
||||
[self.x, self.y, self.z]
|
||||
}
|
||||
|
||||
/// Cast into a tuple with x, y and z.
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T, T) {
|
||||
(self.x, self.y, self.z)
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Translation3D<T, UnknownUnit, UnknownUnit> {
|
||||
Translation3D {
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
z: self.z,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(t: &Translation3D<T, UnknownUnit, UnknownUnit>) -> Self {
|
||||
Translation3D {
|
||||
x: t.x,
|
||||
y: t.y,
|
||||
z: t.z,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Zero
|
||||
T: Zero
|
||||
{
|
||||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
let _0 = T::zero();
|
||||
Translation3D::new(_0, _0, _0)
|
||||
Translation3D::new(T::zero(), T::zero(), T::zero())
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,7 +441,8 @@ where
|
||||
{
|
||||
#[inline]
|
||||
pub fn is_identity(&self) -> bool {
|
||||
self.x == T::zero() && self.y == T::zero() && self.z == T::zero()
|
||||
let _0 = T::zero();
|
||||
self.x == _0 && self.y == _0 && self.z == _0
|
||||
}
|
||||
}
|
||||
|
||||
@ -412,17 +470,6 @@ where
|
||||
size: self.transform_size(r.size),
|
||||
}
|
||||
}
|
||||
|
||||
/// No-op, just cast the unit.
|
||||
#[inline]
|
||||
pub fn transform_size(self, s: Size2D<T, Src>) -> Size2D<T, Dst> {
|
||||
Size2D::new(s.width, s.height)
|
||||
}
|
||||
|
||||
/// Cast into a 3D vector.
|
||||
pub fn to_vector(&self) -> Vector3D<T, Src> {
|
||||
vec3(self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
@ -439,7 +486,7 @@ where
|
||||
impl<T, Src, Dst1, Dst2> Add<Translation3D<T, Dst1, Dst2>>
|
||||
for Translation3D<T, Src, Dst1>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>
|
||||
T: Add<T, Output = T>
|
||||
{
|
||||
type Output = Translation3D<T, Src, Dst2>;
|
||||
fn add(self, other: Translation3D<T, Dst1, Dst2>) -> Translation3D<T, Src, Dst2> {
|
||||
@ -455,7 +502,7 @@ impl<T, Src, Dst1, Dst2>
|
||||
Sub<Translation3D<T, Dst1, Dst2>>
|
||||
for Translation3D<T, Src, Dst2>
|
||||
where
|
||||
T: Copy + Sub<T, Output = T>
|
||||
T: Sub<T, Output = T>
|
||||
{
|
||||
type Output = Translation3D<T, Src, Dst1>;
|
||||
fn sub(self, other: Translation3D<T, Dst1, Dst2>) -> Translation3D<T, Src, Dst1> {
|
||||
@ -469,7 +516,7 @@ where
|
||||
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Clone +
|
||||
T: Copy +
|
||||
Add<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
@ -487,8 +534,6 @@ where
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> From<Vector3D<T, Src>> for Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
{
|
||||
fn from(v: Vector3D<T, Src>) -> Self {
|
||||
Translation3D::new(v.x, v.y, v.z)
|
||||
@ -496,8 +541,6 @@ where
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Into<Vector3D<T, Src>> for Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
{
|
||||
fn into(self) -> Vector3D<T, Src> {
|
||||
vec3(self.x, self.y, self.z)
|
||||
@ -506,7 +549,7 @@ where
|
||||
|
||||
impl<T, Src, Dst> Into<Transform3D<T, Src, Dst>> for Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Clone +
|
||||
T: Copy +
|
||||
Add<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
@ -522,17 +565,22 @@ where
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> Default for Translation3D<T, Src, Dst>
|
||||
where T: Copy + Zero
|
||||
where T: Zero
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> fmt::Debug for Translation3D<T, Src, Dst>
|
||||
where T: Copy + fmt::Debug {
|
||||
impl<T: fmt::Debug, Src, Dst> fmt::Debug for Translation3D<T, Src, Dst> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.to_array().fmt(f)
|
||||
write!(f, "Translation({:?},{:?},{:?})", self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, Src, Dst> fmt::Display for Translation3D<T, Src, Dst> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "({},{},{})", self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
|
23
third_party/rust/euclid/src/trig.rs
vendored
23
third_party/rust/euclid/src/trig.rs
vendored
@ -18,14 +18,20 @@ pub trait Trig {
|
||||
}
|
||||
|
||||
macro_rules! trig {
|
||||
($ty:ident) => (
|
||||
($ty:ident) => {
|
||||
impl Trig for $ty {
|
||||
#[inline]
|
||||
fn sin(self) -> $ty { self.sin() }
|
||||
fn sin(self) -> $ty {
|
||||
num_traits::Float::sin(self)
|
||||
}
|
||||
#[inline]
|
||||
fn cos(self) -> $ty { self.cos() }
|
||||
fn cos(self) -> $ty {
|
||||
num_traits::Float::cos(self)
|
||||
}
|
||||
#[inline]
|
||||
fn tan(self) -> $ty { self.tan() }
|
||||
fn tan(self) -> $ty {
|
||||
num_traits::Float::tan(self)
|
||||
}
|
||||
|
||||
/// A slightly faster approximation of `atan2`.
|
||||
///
|
||||
@ -38,11 +44,12 @@ macro_rules! trig {
|
||||
|
||||
// See https://math.stackexchange.com/questions/1098487/atan2-faster-approximation#1105038
|
||||
use core::$ty::consts;
|
||||
let x_abs = x.abs();
|
||||
let y_abs = y.abs();
|
||||
let x_abs = num_traits::Float::abs(x);
|
||||
let y_abs = num_traits::Float::abs(y);
|
||||
let a = x_abs.min(y_abs) / x_abs.max(y_abs);
|
||||
let s = a * a;
|
||||
let mut result = ((-0.046_496_474_9 * s + 0.159_314_22) * s - 0.327_622_764) * s * a + a;
|
||||
let mut result =
|
||||
((-0.046_496_474_9 * s + 0.159_314_22) * s - 0.327_622_764) * s * a + a;
|
||||
if y_abs > x_abs {
|
||||
result = consts::FRAC_PI_2 - result;
|
||||
}
|
||||
@ -66,7 +73,7 @@ macro_rules! trig {
|
||||
rad.to_degrees()
|
||||
}
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
trig!(f32);
|
||||
|
622
third_party/rust/euclid/src/vector.rs
vendored
622
third_party/rust/euclid/src/vector.rs
vendored
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user