зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 3 changesets (bug 1625220) for causing wrench bustages CLOSED TREE
Backed out changeset fbeb908b3513 (bug 1625220) Backed out changeset 793808082134 (bug 1625220) Backed out changeset 17bf8121665a (bug 1625220)
This commit is contained in:
Родитель
aa2f460364
Коммит
73e4464101
|
@ -1197,9 +1197,9 @@ checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
|||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.20.8"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57d9ae79e19d69ffb5b47b0a744c4215c115dfed4039314c9ca1b8ddc6c333be"
|
||||
checksum = "2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"
|
||||
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.8", features = ["serde"] }
|
||||
euclid = { version = "0.20.0", features = ["serde"] }
|
||||
app_units = "0.7"
|
||||
gleam = "0.10.0"
|
||||
log = "0.4"
|
||||
|
|
|
@ -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.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (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.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -79,11 +79,6 @@ 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"
|
||||
|
@ -433,7 +428,7 @@ dependencies = [
|
|||
name = "direct-composition"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (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",
|
||||
|
@ -490,10 +485,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.20.8"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -750,7 +745,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.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"png 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -827,7 +822,7 @@ name = "line_drawing"
|
|||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1001,7 +996,7 @@ name = "num-integer"
|
|||
version = "0.1.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1010,7 +1005,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.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1019,16 +1014,13 @@ 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.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.11"
|
||||
version = "0.2.4"
|
||||
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"
|
||||
|
@ -1056,7 +1048,7 @@ name = "ordered-float"
|
|||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1105,7 +1097,7 @@ dependencies = [
|
|||
name = "peek-poke"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke-derive 0.2.1",
|
||||
]
|
||||
|
||||
|
@ -1141,9 +1133,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.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (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.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1641,7 +1633,7 @@ dependencies = [
|
|||
name = "tileview"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"euclid 0.20.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (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",
|
||||
|
@ -1829,7 +1821,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.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (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)",
|
||||
|
@ -1839,7 +1831,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.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (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)",
|
||||
|
@ -1864,7 +1856,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.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.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)",
|
||||
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1882,7 +1874,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.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (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)",
|
||||
|
@ -1973,7 +1965,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.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1991,7 +1983,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.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (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)",
|
||||
|
@ -2082,7 +2074,6 @@ 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"
|
||||
|
@ -2127,7 +2118,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.8 (registry+https://github.com/rust-lang/crates.io-index)" = "57d9ae79e19d69ffb5b47b0a744c4215c115dfed4039314c9ca1b8ddc6c333be"
|
||||
"checksum euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"
|
||||
"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"
|
||||
|
@ -2189,7 +2180,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.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||
"checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28"
|
||||
"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"
|
||||
|
|
|
@ -6,7 +6,6 @@ check-alphabetical-order = false
|
|||
[ignore]
|
||||
# Ignored packages with duplicated versions
|
||||
packages = [
|
||||
"autocfg",
|
||||
"core-graphics",
|
||||
"core-text",
|
||||
"gl_generator",
|
||||
|
|
|
@ -1171,7 +1171,7 @@ pub enum DrawTarget {
|
|||
|
||||
impl DrawTarget {
|
||||
pub fn new_default(size: DeviceIntSize, surface_origin_is_top_left: bool) -> Self {
|
||||
let total_size = device_size_as_framebuffer_size(size);
|
||||
let total_size = FramebufferIntSize::from_untyped(size.to_untyped());
|
||||
DrawTarget::Default {
|
||||
rect: total_size.into(),
|
||||
total_size,
|
||||
|
@ -1212,15 +1212,15 @@ impl DrawTarget {
|
|||
/// Returns the dimensions of this draw-target.
|
||||
pub fn dimensions(&self) -> DeviceIntSize {
|
||||
match *self {
|
||||
DrawTarget::Default { total_size, .. } => total_size.cast_unit(),
|
||||
DrawTarget::Default { total_size, .. } => DeviceIntSize::from_untyped(total_size.to_untyped()),
|
||||
DrawTarget::Texture { dimensions, .. } => dimensions,
|
||||
DrawTarget::External { size, .. } => size.cast_unit(),
|
||||
DrawTarget::External { size, .. } => DeviceIntSize::from_untyped(size.to_untyped()),
|
||||
DrawTarget::NativeSurface { dimensions, .. } => dimensions,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_framebuffer_rect(&self, device_rect: DeviceIntRect) -> FramebufferIntRect {
|
||||
let mut fb_rect = device_rect_as_framebuffer_rect(&device_rect);
|
||||
let mut fb_rect = FramebufferIntRect::from_untyped(&device_rect.to_untyped());
|
||||
match *self {
|
||||
DrawTarget::Default { ref rect, surface_origin_is_top_left, .. } => {
|
||||
// perform a Y-flip here
|
||||
|
@ -1255,16 +1255,16 @@ impl DrawTarget {
|
|||
.unwrap_or_else(FramebufferIntRect::zero)
|
||||
}
|
||||
DrawTarget::NativeSurface { offset, .. } => {
|
||||
device_rect_as_framebuffer_rect(&scissor_rect.translate(offset.to_vector()))
|
||||
FramebufferIntRect::from_untyped(&scissor_rect.translate(offset.to_vector()).to_untyped())
|
||||
}
|
||||
DrawTarget::Texture { .. } | DrawTarget::External { .. } => {
|
||||
device_rect_as_framebuffer_rect(&scissor_rect)
|
||||
FramebufferIntRect::from_untyped(&scissor_rect.to_untyped())
|
||||
}
|
||||
}
|
||||
None => {
|
||||
FramebufferIntRect::new(
|
||||
FramebufferIntPoint::zero(),
|
||||
device_size_as_framebuffer_size(dimensions),
|
||||
FramebufferIntSize::from_untyped(dimensions.to_untyped()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1891,7 +1891,7 @@ impl Device {
|
|||
DrawTarget::Texture { dimensions, fbo_id, with_depth, .. } => {
|
||||
let rect = FramebufferIntRect::new(
|
||||
FramebufferIntPoint::zero(),
|
||||
device_size_as_framebuffer_size(dimensions),
|
||||
FramebufferIntSize::from_untyped(dimensions.to_untyped()),
|
||||
);
|
||||
(fbo_id, rect, with_depth)
|
||||
},
|
||||
|
@ -1901,7 +1901,10 @@ impl Device {
|
|||
DrawTarget::NativeSurface { external_fbo_id, offset, dimensions, .. } => {
|
||||
(
|
||||
FBOId(external_fbo_id),
|
||||
device_rect_as_framebuffer_rect(&DeviceIntRect::new(offset, dimensions)),
|
||||
FramebufferIntRect::new(
|
||||
FramebufferIntPoint::from_untyped(offset.to_untyped()),
|
||||
FramebufferIntSize::from_untyped(dimensions.to_untyped()),
|
||||
),
|
||||
true
|
||||
)
|
||||
}
|
||||
|
@ -2329,7 +2332,7 @@ impl Device {
|
|||
} else {
|
||||
let rect = FramebufferIntRect::new(
|
||||
FramebufferIntPoint::zero(),
|
||||
device_size_as_framebuffer_size(src.get_dimensions()),
|
||||
FramebufferIntSize::from_untyped(src.get_dimensions().to_untyped()),
|
||||
);
|
||||
for layer in 0..src.layer_count.min(dst.layer_count) as LayerIndex {
|
||||
self.blit_render_target(
|
||||
|
|
|
@ -2395,11 +2395,11 @@ impl TileCacheInstance {
|
|||
|
||||
self.map_local_to_surface = SpaceMapper::new(
|
||||
self.spatial_node_index,
|
||||
pic_rect,
|
||||
PictureRect::from_untyped(&pic_rect.to_untyped()),
|
||||
);
|
||||
self.map_child_pic_to_surface = SpaceMapper::new(
|
||||
self.spatial_node_index,
|
||||
pic_rect,
|
||||
PictureRect::from_untyped(&pic_rect.to_untyped()),
|
||||
);
|
||||
|
||||
let pic_to_world_mapper = SpaceMapper::new_with_target(
|
||||
|
@ -2430,7 +2430,7 @@ impl TileCacheInstance {
|
|||
);
|
||||
|
||||
let clip_chain_instance = frame_state.clip_store.build_clip_chain_instance(
|
||||
pic_rect.cast_unit(),
|
||||
LayoutRect::from_untyped(&pic_rect.to_untyped()),
|
||||
&self.map_local_to_surface,
|
||||
&pic_to_world_mapper,
|
||||
frame_context.spatial_tree,
|
||||
|
@ -4562,7 +4562,7 @@ impl PicturePrimitive {
|
|||
|
||||
match self.raster_config {
|
||||
Some(ref mut raster_config) => {
|
||||
let pic_rect = self.precise_local_rect.cast_unit();
|
||||
let pic_rect = PictureRect::from_untyped(&self.precise_local_rect.to_untyped());
|
||||
|
||||
let mut device_pixel_scale = frame_state
|
||||
.surfaces[raster_config.surface_index.0]
|
||||
|
@ -4579,7 +4579,7 @@ impl PicturePrimitive {
|
|||
let mut max_offset = vec2(0.0, 0.0);
|
||||
let mut min_offset = vec2(0.0, 0.0);
|
||||
for shadow in shadows {
|
||||
let offset = layout_vector_as_picture_vector(shadow.offset);
|
||||
let offset = shadow.offset.cast_unit();
|
||||
max_offset = max_offset.max(offset);
|
||||
min_offset = min_offset.min(offset);
|
||||
}
|
||||
|
@ -4590,10 +4590,15 @@ 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::from_vectors_outer(
|
||||
-world_max.max(vec2(0.0, 0.0)),
|
||||
-world_min.min(vec2(0.0, 0.0)),
|
||||
SideOffsets2D::new(
|
||||
-top_left.y,
|
||||
bottom_right.x,
|
||||
bottom_right.y,
|
||||
-top_left.x,
|
||||
)
|
||||
}
|
||||
_ => SideOffsets2D::zero(),
|
||||
|
|
|
@ -312,7 +312,7 @@ impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
|
|||
pub fn unmap(&self, rect: &Rect<f32, T>) -> Option<Rect<f32, F>> {
|
||||
match self.kind {
|
||||
CoordinateSpaceMapping::Local => {
|
||||
Some(rect.cast_unit())
|
||||
Some(Rect::from_untyped(&rect.to_untyped()))
|
||||
}
|
||||
CoordinateSpaceMapping::ScaleOffset(ref scale_offset) => {
|
||||
Some(scale_offset.unmap_rect(rect))
|
||||
|
@ -326,7 +326,7 @@ impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
|
|||
pub fn map(&self, rect: &Rect<f32, F>) -> Option<Rect<f32, T>> {
|
||||
match self.kind {
|
||||
CoordinateSpaceMapping::Local => {
|
||||
Some(rect.cast_unit())
|
||||
Some(Rect::from_untyped(&rect.to_untyped()))
|
||||
}
|
||||
CoordinateSpaceMapping::ScaleOffset(ref scale_offset) => {
|
||||
Some(scale_offset.map_rect(rect))
|
||||
|
@ -1962,7 +1962,7 @@ impl PrimitiveStore {
|
|||
// relative transforms have changed, which means we need to
|
||||
// re-map the dependencies of any child primitives.
|
||||
world_culling_rect = tile_cache.pre_update(
|
||||
layout_rect_as_picture_rect(&pic.estimated_local_rect),
|
||||
PictureRect::from_untyped(&pic.estimated_local_rect.to_untyped()),
|
||||
surface_index,
|
||||
frame_context,
|
||||
frame_state,
|
||||
|
@ -4230,8 +4230,7 @@ fn get_clipped_device_rect(
|
|||
let unclipped_raster_rect = {
|
||||
let world_rect = *unclipped * Scale::new(1.0);
|
||||
let raster_rect = world_rect * device_pixel_scale.inv();
|
||||
|
||||
raster_rect.cast_unit()
|
||||
Rect::from_untyped(&raster_rect.to_untyped())
|
||||
};
|
||||
|
||||
let unclipped_world_rect = map_to_world.map(&unclipped_raster_rect)?;
|
||||
|
|
|
@ -6054,7 +6054,7 @@ impl Renderer {
|
|||
|
||||
let texture_rect = FramebufferIntRect::new(
|
||||
FramebufferIntPoint::zero(),
|
||||
source_rect.size.cast_unit(),
|
||||
FramebufferIntSize::from_untyped(source_rect.size.to_untyped()),
|
||||
);
|
||||
|
||||
debug_renderer.add_rect(
|
||||
|
@ -6193,7 +6193,7 @@ impl Renderer {
|
|||
device.clear_target(
|
||||
Some(tag_color),
|
||||
None,
|
||||
Some(tag_rect.cast_unit()),
|
||||
Some(FramebufferIntRect::from_untyped(&tag_rect.to_untyped())),
|
||||
);
|
||||
|
||||
// Draw the dimensions onto the tag.
|
||||
|
@ -6321,7 +6321,7 @@ impl Renderer {
|
|||
|
||||
pub fn read_gpu_cache(&mut self) -> (DeviceIntSize, Vec<u8>) {
|
||||
let texture = self.gpu_cache_texture.texture.as_ref().unwrap();
|
||||
let size = device_size_as_framebuffer_size(texture.get_dimensions());
|
||||
let size = FramebufferIntSize::from_untyped(texture.get_dimensions().to_untyped());
|
||||
let mut texels = vec![0; (size.width * size.height * 16) as usize];
|
||||
self.device.begin_frame();
|
||||
self.device.bind_read_target(ReadTarget::from_texture(texture, 0));
|
||||
|
@ -6858,7 +6858,7 @@ impl Renderer {
|
|||
// read from textures directly with `get_tex_image*`.
|
||||
|
||||
for layer_id in 0 .. texture.get_layer_count() {
|
||||
let rect = device_size_as_framebuffer_size(rect_size).into();
|
||||
let rect = FramebufferIntSize::from_untyped(rect_size.to_untyped()).into();
|
||||
|
||||
device.attach_read_texture(texture, layer_id);
|
||||
#[cfg(feature = "png")]
|
||||
|
|
|
@ -290,7 +290,7 @@ impl AsyncScreenshotGrabber {
|
|||
let draw_target_rect = draw_target
|
||||
.to_framebuffer_rect(DeviceIntRect::new(DeviceIntPoint::new(0, 0), dest_size));
|
||||
|
||||
let read_target_rect = device_rect_as_framebuffer_rect(&read_target_rect);
|
||||
let read_target_rect = FramebufferIntRect::from_untyped(&read_target_rect.to_untyped());
|
||||
|
||||
if level == 0 && !device.surface_origin_is_top_left() {
|
||||
device.blit_render_target_invert_y(
|
||||
|
|
|
@ -299,25 +299,3 @@ impl<U> RectExt for Rect<f32, U> {
|
|||
self.max()
|
||||
}
|
||||
}
|
||||
|
||||
// A few helpers to convert to cast between coordinate spaces that are often equivalent.
|
||||
|
||||
#[inline]
|
||||
pub fn layout_rect_as_picture_rect(layout_rect: &LayoutRect) -> PictureRect {
|
||||
layout_rect.cast_unit()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn layout_vector_as_picture_vector(layout_vector: LayoutVector2D) -> PictureVector2D {
|
||||
layout_vector.cast_unit()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn device_size_as_framebuffer_size(framebuffer_size: DeviceIntSize) -> FramebufferIntSize {
|
||||
framebuffer_size.cast_unit()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn device_rect_as_framebuffer_rect(framebuffer_rect: &DeviceIntRect) -> FramebufferIntRect {
|
||||
framebuffer_rect.cast_unit()
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"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"}
|
||||
{"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"}
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "euclid"
|
||||
version = "0.20.8"
|
||||
version = "0.20.0"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "Geometry primitives"
|
||||
documentation = "https://docs.rs/euclid/"
|
||||
|
@ -25,19 +25,14 @@ version = "0.5.1"
|
|||
optional = true
|
||||
|
||||
[dependencies.num-traits]
|
||||
version = "0.2.10"
|
||||
default-features = false
|
||||
version = "0.2"
|
||||
|
||||
[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 = []
|
||||
|
|
|
@ -1,244 +0,0 @@
|
|||
// 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));
|
||||
}
|
|
@ -9,33 +9,26 @@
|
|||
|
||||
/// Trait for testing approximate equality
|
||||
pub trait ApproxEq<Eps> {
|
||||
/// Default epsilon value
|
||||
fn approx_epsilon() -> Eps;
|
||||
|
||||
/// Returns `true` is this object is approximately equal to the other one, using
|
||||
/// a provided epsilon value.
|
||||
fn approx_eq(&self, other: &Self) -> bool;
|
||||
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
|
||||
fn approx_epsilon() -> $ty { $eps }
|
||||
#[inline]
|
||||
fn approx_eq(&self, other: &$ty) -> bool {
|
||||
self.approx_eq_eps(other, &$eps)
|
||||
}
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$ty, approx_epsilon: &$ty) -> bool {
|
||||
num_traits::Float::abs(*self - *other) < *approx_epsilon
|
||||
(*self - *other).abs() < *approx_epsilon
|
||||
}
|
||||
}
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
approx_eq!(f32, 1.0e-6);
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
// 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
|
||||
|
|
|
@ -47,9 +47,9 @@ impl<T: Hash, U> Hash for Box2D<T, U> {
|
|||
|
||||
impl<T: Copy, U> Copy for Box2D<T, U> {}
|
||||
|
||||
impl<T: Clone, U> Clone for Box2D<T, U> {
|
||||
impl<T: Copy, U> Clone for Box2D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
Self::new(self.min.clone(), self.max.clone())
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,8 +75,7 @@ impl<T: fmt::Display, U> fmt::Display for Box2D<T, U> {
|
|||
|
||||
impl<T, U> Box2D<T, U> {
|
||||
/// Constructor.
|
||||
#[inline]
|
||||
pub const fn new(min: Point2D<T, U>, max: Point2D<T, U>) -> Self {
|
||||
pub fn new(min: Point2D<T, U>, max: Point2D<T, U>) -> Self {
|
||||
Box2D {
|
||||
min,
|
||||
max,
|
||||
|
@ -99,7 +98,7 @@ where
|
|||
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: PartialOrd,
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
/// Returns true if the box has a negative area.
|
||||
///
|
||||
|
@ -116,39 +115,6 @@ where
|
|||
self.max.x <= self.min.x || self.max.y <= self.min.y
|
||||
}
|
||||
|
||||
/// Returns `true` if the two boxes intersect.
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
self.min.x < other.max.x
|
||||
&& self.max.x > other.min.x
|
||||
&& self.min.y < other.max.y
|
||||
&& 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() {
|
||||
|
@ -157,6 +123,16 @@ where
|
|||
|
||||
Some(NonEmpty(*self))
|
||||
}
|
||||
|
||||
/// Returns true if the two boxes intersect.
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
self.min.x < other.max.x
|
||||
&& self.max.x > other.min.x
|
||||
&& self.min.y < other.max.y
|
||||
&& self.max.y > other.min.y
|
||||
}
|
||||
|
||||
/// Computes the intersection of two boxes.
|
||||
///
|
||||
/// The result is a negative box if the boxes do not intersect.
|
||||
|
@ -201,6 +177,35 @@ 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>,
|
||||
|
@ -210,16 +215,6 @@ 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 {
|
||||
|
@ -283,25 +278,37 @@ 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);
|
||||
for point in points {
|
||||
let p = point.borrow();
|
||||
if p.x < min_x {
|
||||
min_x = p.x
|
||||
|
||||
{
|
||||
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(),
|
||||
}
|
||||
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
|
||||
|
||||
for point in points {
|
||||
assign_min_max(point);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,8 +325,7 @@ where
|
|||
{
|
||||
/// Linearly interpolate between this box and another box.
|
||||
///
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
/// `t` is expected to be between zero and one.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
Self::new(
|
||||
|
@ -387,7 +393,7 @@ where
|
|||
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Zero,
|
||||
T: Copy + Zero,
|
||||
{
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
|
@ -450,43 +456,34 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box2D<T, U>
|
||||
impl<T, Unit> Box2D<T, Unit>
|
||||
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.
|
||||
#[inline]
|
||||
pub fn from_untyped(c: &Box2D<T, UnknownUnit>) -> Box2D<T, U> {
|
||||
pub fn from_untyped(c: &Box2D<T, UnknownUnit>) -> Box2D<T, Unit> {
|
||||
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<T, U> Box2D<T, U>
|
||||
impl<T0, Unit> Box2D<T0, Unit>
|
||||
where
|
||||
T: NumCast + Copy,
|
||||
T0: 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.
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Box2D<NewT, U> {
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Box2D<T1, Unit> {
|
||||
Box2D::new(
|
||||
self.min.cast(),
|
||||
self.max.cast(),
|
||||
|
@ -498,7 +495,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<NewT: NumCast>(&self) -> Option<Box2D<NewT, U>> {
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Box2D<T1, Unit>> {
|
||||
match (self.min.try_cast(), self.max.try_cast()) {
|
||||
(Some(a), Some(b)) => Some(Box2D::new(a, b)),
|
||||
_ => None,
|
||||
|
@ -549,16 +546,14 @@ where
|
|||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, U> Box2D<T, U> {
|
||||
impl<T: NumCast + Copy, Unit> Box2D<T, Unit> {
|
||||
/// Cast into an `f32` box.
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Box2D<f32, U> {
|
||||
pub fn to_f32(&self) -> Box2D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` box.
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Box2D<f64, U> {
|
||||
pub fn to_f64(&self) -> Box2D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -567,8 +562,7 @@ impl<T: NumCast + Copy, U> Box2D<T, U> {
|
|||
/// 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.
|
||||
#[inline]
|
||||
pub fn to_usize(&self) -> Box2D<usize, U> {
|
||||
pub fn to_usize(&self) -> Box2D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -577,8 +571,7 @@ impl<T: NumCast + Copy, U> Box2D<T, U> {
|
|||
/// 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.
|
||||
#[inline]
|
||||
pub fn to_u32(&self) -> Box2D<u32, U> {
|
||||
pub fn to_u32(&self) -> Box2D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -587,8 +580,7 @@ impl<T: NumCast + Copy, U> Box2D<T, U> {
|
|||
/// 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.
|
||||
#[inline]
|
||||
pub fn to_i32(&self) -> Box2D<i32, U> {
|
||||
pub fn to_i32(&self) -> Box2D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -597,8 +589,7 @@ impl<T: NumCast + Copy, U> Box2D<T, U> {
|
|||
/// 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.
|
||||
#[inline]
|
||||
pub fn to_i64(&self) -> Box2D<i64, U> {
|
||||
pub fn to_i64(&self) -> Box2D<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
@ -626,13 +617,6 @@ 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));
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
use super::UnknownUnit;
|
||||
use scale::Scale;
|
||||
use num::*;
|
||||
use point::{Point3D, point3};
|
||||
use point::Point3D;
|
||||
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: Clone, U> Clone for Box3D<T, U> {
|
||||
impl<T: Copy, U> Clone for Box3D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
Self::new(self.min.clone(), self.max.clone())
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,8 +73,7 @@ impl<T: fmt::Display, U> fmt::Display for Box3D<T, U> {
|
|||
|
||||
impl<T, U> Box3D<T, U> {
|
||||
/// Constructor.
|
||||
#[inline]
|
||||
pub const fn new(min: Point3D<T, U>, max: Point3D<T, U>) -> Self {
|
||||
pub fn new(min: Point3D<T, U>, max: Point3D<T, U>) -> Self {
|
||||
Box3D {
|
||||
min,
|
||||
max,
|
||||
|
@ -97,7 +96,7 @@ where
|
|||
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: PartialOrd,
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
/// Returns true if the box has a negative volume.
|
||||
///
|
||||
|
@ -114,6 +113,15 @@ 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
|
||||
|
@ -124,41 +132,6 @@ 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) {
|
||||
|
@ -182,7 +155,7 @@ where
|
|||
);
|
||||
|
||||
Box3D::new(
|
||||
intersection_min,
|
||||
intersection_min,
|
||||
intersection_max,
|
||||
)
|
||||
}
|
||||
|
@ -203,6 +176,37 @@ 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>,
|
||||
|
@ -215,21 +219,6 @@ 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>
|
||||
|
@ -259,38 +248,47 @@ 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);
|
||||
|
||||
for point in points {
|
||||
let p = point.borrow();
|
||||
if p.x < min_x {
|
||||
min_x = p.x
|
||||
{
|
||||
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(),
|
||||
}
|
||||
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
|
||||
|
||||
for point in points {
|
||||
assign_min_max(point);
|
||||
}
|
||||
}
|
||||
|
||||
Box3D {
|
||||
min: point3(min_x, min_y, min_z),
|
||||
max: point3(max_x, max_y, max_z),
|
||||
}
|
||||
Self::new(Point3D::new(min_x, min_y, min_z), Point3D::new(max_x, max_y, max_z))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,8 +298,7 @@ where
|
|||
{
|
||||
/// Linearly interpolate between this box3d and another box3d.
|
||||
///
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
/// `t` is expected to be between zero and one.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
Self::new(
|
||||
|
@ -323,7 +320,7 @@ where
|
|||
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
T: Copy + Clone + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
|
@ -387,9 +384,9 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Zero,
|
||||
T: Copy + Zero,
|
||||
{
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
|
@ -452,7 +449,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
impl<T, Unit> Box3D<T, Unit>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
|
@ -467,31 +464,24 @@ where
|
|||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(c: &Box3D<T, UnknownUnit>) -> Box3D<T, U> {
|
||||
pub fn from_untyped(c: &Box3D<T, UnknownUnit>) -> Box3D<T, Unit> {
|
||||
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<T, U> Box3D<T, U>
|
||||
impl<T0, Unit> Box3D<T0, Unit>
|
||||
where
|
||||
T: NumCast + Copy,
|
||||
T0: 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.
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Box3D<NewT, U> {
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Box3D<T1, Unit> {
|
||||
Box3D::new(
|
||||
self.min.cast(),
|
||||
self.max.cast(),
|
||||
|
@ -503,7 +493,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<NewT: NumCast>(&self) -> Option<Box3D<NewT, U>> {
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Box3D<T1, Unit>> {
|
||||
match (self.min.try_cast(), self.max.try_cast()) {
|
||||
(Some(a), Some(b)) => Some(Box3D::new(a, b)),
|
||||
_ => None,
|
||||
|
@ -556,16 +546,14 @@ where
|
|||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, U> Box3D<T, U> {
|
||||
impl<T: NumCast + Copy, Unit> Box3D<T, Unit> {
|
||||
/// Cast into an `f32` box3d.
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Box3D<f32, U> {
|
||||
pub fn to_f32(&self) -> Box3D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` box3d.
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Box3D<f64, U> {
|
||||
pub fn to_f64(&self) -> Box3D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -574,8 +562,7 @@ impl<T: NumCast + Copy, U> Box3D<T, U> {
|
|||
/// 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.
|
||||
#[inline]
|
||||
pub fn to_usize(&self) -> Box3D<usize, U> {
|
||||
pub fn to_usize(&self) -> Box3D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -584,8 +571,7 @@ impl<T: NumCast + Copy, U> Box3D<T, U> {
|
|||
/// 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.
|
||||
#[inline]
|
||||
pub fn to_u32(&self) -> Box3D<u32, U> {
|
||||
pub fn to_u32(&self) -> Box3D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -594,8 +580,7 @@ impl<T: NumCast + Copy, U> Box3D<T, U> {
|
|||
/// 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.
|
||||
#[inline]
|
||||
pub fn to_i32(&self) -> Box3D<i32, U> {
|
||||
pub fn to_i32(&self) -> Box3D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -604,14 +589,13 @@ impl<T: NumCast + Copy, U> Box3D<T, U> {
|
|||
/// 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.
|
||||
#[inline]
|
||||
pub fn to_i64(&self) -> Box3D<i64, U> {
|
||||
pub fn to_i64(&self) -> Box3D<i64, Unit> {
|
||||
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 {
|
||||
|
@ -648,14 +632,6 @@ 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));
|
||||
|
@ -794,7 +770,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());
|
||||
|
|
|
@ -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) = serde::Deserialize::deserialize(deserializer)?;
|
||||
let (x, y, z, w) = try!(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 const fn new(x: T, y: T, z: T, w: T) -> Self {
|
||||
pub fn new(x: T, y: T, z: T, w: T) -> Self {
|
||||
HomogeneousVector { x, y, z, w, _unit: PhantomData }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ 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;
|
||||
|
||||
|
@ -38,16 +37,16 @@ use core::fmt;
|
|||
#[repr(C)]
|
||||
pub struct Length<T, Unit>(pub T, #[doc(hidden)] pub PhantomData<Unit>);
|
||||
|
||||
impl<T: Clone, U> Clone for Length<T, U> {
|
||||
impl<T: Clone, Unit> Clone for Length<T, Unit> {
|
||||
fn clone(&self) -> Self {
|
||||
Length(self.0.clone(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Copy for Length<T, U> {}
|
||||
impl<T: Copy, Unit> Copy for Length<T, Unit> {}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, T, U> Deserialize<'de> for Length<T, U>
|
||||
impl<'de, Unit, T> Deserialize<'de> for Length<T, Unit>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
|
@ -56,14 +55,14 @@ where
|
|||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(Length(
|
||||
Deserialize::deserialize(deserializer)?,
|
||||
try!(Deserialize::deserialize(deserializer)),
|
||||
PhantomData,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T, U> Serialize for Length<T, U>
|
||||
impl<T, Unit> Serialize for Length<T, Unit>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
|
@ -75,108 +74,86 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> Length<T, U> {
|
||||
#[inline]
|
||||
pub const fn new(x: T) -> Self {
|
||||
impl<T, Unit> Length<T, Unit> {
|
||||
pub fn new(x: T) -> Self {
|
||||
Length(x, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, U> Length<T, U> {
|
||||
impl<Unit, T: Clone> Length<T, Unit> {
|
||||
pub fn get(&self) -> T {
|
||||
self.0.clone()
|
||||
}
|
||||
|
||||
/// Cast the unit
|
||||
#[inline]
|
||||
pub fn cast_unit<V>(&self) -> Length<T, V> {
|
||||
Length::new(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for Length<T, U> {
|
||||
impl<T: fmt::Debug + Clone, U> fmt::Debug for Length<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
self.get().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, U> fmt::Display for Length<T, U> {
|
||||
impl<T: fmt::Display + Clone, 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);
|
||||
self.get().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// length + length
|
||||
impl<U, T: Add<T, Output = T>> Add for Length<T, U> {
|
||||
impl<U, T: Clone + 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.0 + other.0)
|
||||
Length::new(self.get() + other.get())
|
||||
}
|
||||
}
|
||||
|
||||
// length += length
|
||||
impl<U, T: AddAssign<T>> AddAssign for Length<T, U> {
|
||||
impl<U, T: Clone + AddAssign<T>> AddAssign for Length<T, U> {
|
||||
fn add_assign(&mut self, other: Length<T, U>) {
|
||||
self.0 += other.0;
|
||||
self.0 += other.get();
|
||||
}
|
||||
}
|
||||
|
||||
// length - length
|
||||
impl<U, T: Sub<T, Output = T>> Sub<Length<T, U>> for Length<T, U> {
|
||||
impl<U, T: Clone + 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.0 - other.0)
|
||||
Length::new(self.get() - other.get())
|
||||
}
|
||||
}
|
||||
|
||||
// length -= length
|
||||
impl<U, T: SubAssign<T>> SubAssign for Length<T, U> {
|
||||
impl<U, T: Clone + SubAssign<T>> SubAssign for Length<T, U> {
|
||||
fn sub_assign(&mut self, other: Length<T, U>) {
|
||||
self.0 -= other.0;
|
||||
self.0 -= other.get();
|
||||
}
|
||||
}
|
||||
|
||||
// Saturating length + length and length - length.
|
||||
impl<U, T: Saturating> Saturating for Length<T, U> {
|
||||
impl<U, T: Clone + Saturating> Saturating for Length<T, U> {
|
||||
fn saturating_add(self, other: Length<T, U>) -> Length<T, U> {
|
||||
Length::new(self.0.saturating_add(other.0))
|
||||
Length::new(self.get().saturating_add(other.get()))
|
||||
}
|
||||
|
||||
fn saturating_sub(self, other: Length<T, U>) -> Length<T, U> {
|
||||
Length::new(self.0.saturating_sub(other.0))
|
||||
Length::new(self.get().saturating_sub(other.get()))
|
||||
}
|
||||
}
|
||||
|
||||
// length / length
|
||||
impl<Src, Dst, T: Div<T, Output = T>> Div<Length<T, Src>> for Length<T, Dst> {
|
||||
impl<Src, Dst, T: Clone + 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.0 / other.0)
|
||||
Scale::new(self.get() / other.get())
|
||||
}
|
||||
}
|
||||
|
||||
// length * scalar
|
||||
impl<T: Mul<T, Output = T>, U> Mul<T> for Length<T, U> {
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for Length<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, scale: T) -> Self {
|
||||
Length::new(self.0 * scale)
|
||||
Length::new(self.get() * scale)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,11 +166,11 @@ impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for Length<T, U> {
|
|||
}
|
||||
|
||||
// length / scalar
|
||||
impl<T: Div<T, Output = T>, U> Div<T> for Length<T, U> {
|
||||
impl<T: Copy + Div<T, Output = T>, U> Div<T> for Length<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, scale: T) -> Self {
|
||||
Length::new(self.0 / scale)
|
||||
Length::new(self.get() / scale)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,67 +183,65 @@ impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for Length<T, U> {
|
|||
}
|
||||
|
||||
// length * scaleFactor
|
||||
impl<Src, Dst, T: Mul<T, Output = T>> Mul<Scale<T, Src, Dst>> for Length<T, Src> {
|
||||
impl<Src, Dst, T: Clone + 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.0 * scale.0)
|
||||
Length::new(self.get() * scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
// length / scaleFactor
|
||||
impl<Src, Dst, T: Div<T, Output = T>> Div<Scale<T, Src, Dst>> for Length<T, Dst> {
|
||||
impl<Src, Dst, T: Clone + 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.0 / scale.0)
|
||||
Length::new(self.get() / scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
// -length
|
||||
impl<U, T: Neg<Output = T>> Neg for Length<T, U> {
|
||||
impl<U, T: Clone + Neg<Output = T>> Neg for Length<T, U> {
|
||||
type Output = Length<T, U>;
|
||||
#[inline]
|
||||
fn neg(self) -> Length<T, U> {
|
||||
Length::new(-self.0)
|
||||
Length::new(-self.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Clone, U> Length<T, U> {
|
||||
impl<Unit, T0: NumCast + Clone> Length<T0, Unit> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Length<NewT, U> {
|
||||
pub fn cast<T1: NumCast + Clone>(&self) -> Length<T1, Unit> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Length<NewT, U>> {
|
||||
pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<Length<T1, Unit>> {
|
||||
NumCast::from(self.get()).map(Length::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, U> PartialEq for Length<T, U> {
|
||||
impl<Unit, T: Clone + PartialEq> PartialEq for Length<T, Unit> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.eq(&other.0)
|
||||
self.get().eq(&other.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd, U> PartialOrd for Length<T, U> {
|
||||
impl<Unit, T: Clone + PartialOrd> PartialOrd for Length<T, Unit> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
self.0.partial_cmp(&other.0)
|
||||
self.get().partial_cmp(&other.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq, U> Eq for Length<T, U> {}
|
||||
impl<Unit, T: Clone + Eq> Eq for Length<T, Unit> {}
|
||||
|
||||
impl<T: Ord, U> Ord for Length<T, U> {
|
||||
impl<Unit, T: Clone + Ord> Ord for Length<T, Unit> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.0.cmp(&other.0)
|
||||
self.get().cmp(&other.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> Zero for Length<T, U> {
|
||||
#[inline]
|
||||
impl<Unit, T: Zero> Zero for Length<T, Unit> {
|
||||
fn zero() -> Self {
|
||||
Length::new(Zero::zero())
|
||||
}
|
||||
|
@ -278,8 +253,7 @@ where
|
|||
{
|
||||
/// Linearly interpolate between this length and another length.
|
||||
///
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
/// `t` is expected to be between zero and one.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
let one_t = T::one() - t;
|
||||
|
|
|
@ -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 ```default::Point2D<T>``` is equivalent to ```Point2D<T, UnknownUnit>```.
|
||||
//! for example ```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,7 +38,6 @@
|
|||
//! 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]
|
||||
|
@ -50,7 +49,6 @@ 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;
|
||||
|
@ -66,7 +64,7 @@ pub use rect::{rect, Rect};
|
|||
pub use rigid::{RigidTransform3D};
|
||||
pub use box3d::{box3d, Box3D};
|
||||
pub use translation::{Translation2D, Translation3D};
|
||||
pub use rotation::{Rotation2D, Rotation3D};
|
||||
pub use rotation::{Angle, Rotation2D, Rotation3D};
|
||||
pub use side_offsets::SideOffsets2D;
|
||||
pub use size::{Size2D, Size3D, size2, size3};
|
||||
pub use trig::Trig;
|
||||
|
@ -74,7 +72,6 @@ pub use trig::Trig;
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
mod angle;
|
||||
pub mod approxeq;
|
||||
pub mod approxord;
|
||||
mod box2d;
|
||||
|
@ -101,10 +98,7 @@ 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>;
|
||||
|
@ -120,7 +114,6 @@ 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>;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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};
|
||||
|
@ -26,7 +27,7 @@ impl<T> NonEmpty<T> {
|
|||
|
||||
impl<T, U> NonEmpty<Rect<T, U>>
|
||||
where
|
||||
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
T: Copy + Clone + Zero + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &NonEmpty<Rect<T, U>>) -> NonEmpty<Rect<T, U>> {
|
||||
|
|
|
@ -30,74 +30,47 @@ 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 {
|
||||
num_traits::Float::round(self)
|
||||
}
|
||||
fn round(self) -> $ty { self.round() }
|
||||
}
|
||||
impl Floor for $ty {
|
||||
#[inline]
|
||||
fn floor(self) -> $ty {
|
||||
num_traits::Float::floor(self)
|
||||
}
|
||||
fn floor(self) -> $ty { self.floor() }
|
||||
}
|
||||
impl Ceil for $ty {
|
||||
#[inline]
|
||||
fn ceil(self) -> $ty {
|
||||
num_traits::Float::ceil(self)
|
||||
}
|
||||
fn ceil(self) -> $ty { self.ceil() }
|
||||
}
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
num_int!(i16);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -47,9 +47,9 @@ impl<T: Hash, U> Hash for Rect<T, U> {
|
|||
|
||||
impl<T: Copy, U> Copy for Rect<T, U> {}
|
||||
|
||||
impl<T: Clone, U> Clone for Rect<T, U> {
|
||||
impl<T: Copy, U> Clone for Rect<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
Self::new(self.origin.clone(), self.size.clone())
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,8 +81,7 @@ impl<T: Default, U> Default for Rect<T, U> {
|
|||
|
||||
impl<T, U> Rect<T, U> {
|
||||
/// Constructor.
|
||||
#[inline]
|
||||
pub const fn new(origin: Point2D<T, U>, size: Size2D<T, U>) -> Self {
|
||||
pub fn new(origin: Point2D<T, U>, size: Size2D<T, U>) -> Self {
|
||||
Rect {
|
||||
origin,
|
||||
size,
|
||||
|
@ -92,16 +91,9 @@ impl<T, U> Rect<T, U> {
|
|||
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Zero
|
||||
T: Copy + 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(),
|
||||
|
@ -112,7 +104,7 @@ where
|
|||
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
T: Copy + Clone + Zero + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
|
@ -152,16 +144,6 @@ 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()
|
||||
|
@ -207,6 +189,16 @@ 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 {
|
||||
|
@ -226,21 +218,6 @@ 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.
|
||||
///
|
||||
|
@ -330,8 +307,7 @@ where
|
|||
{
|
||||
/// Linearly interpolate between this rectangle and another rectangle.
|
||||
///
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
/// `t` is expected to be between zero and one.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
Self::new(
|
||||
|
@ -353,7 +329,7 @@ where
|
|||
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
T: Copy + Clone + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
|
@ -383,7 +359,7 @@ impl<T, U> Rect<T, U> {
|
|||
#[inline]
|
||||
pub fn scale<S: Copy>(&self, x: S, y: S) -> Self
|
||||
where
|
||||
T: Copy + Mul<S, Output = T>,
|
||||
T: Copy + Clone + Mul<S, Output = T>,
|
||||
{
|
||||
Rect::new(
|
||||
Point2D::new(self.origin.x * x, self.origin.y * y),
|
||||
|
@ -392,29 +368,32 @@ impl<T, U> Rect<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Rect<T, U> {
|
||||
impl<T: Copy + Clone + Mul<T, Output = T>, U> Rect<T, U> {
|
||||
#[inline]
|
||||
pub fn area(&self) -> T {
|
||||
self.size.area()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero + PartialEq, U> Rect<T, U> {
|
||||
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())
|
||||
}
|
||||
|
||||
/// 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: Zero + PartialOrd, U> Rect<T, U> {
|
||||
impl<T: Copy + 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() {
|
||||
|
@ -457,7 +436,7 @@ impl<T: Copy + Div<T, Output = T>, U1, U2> Div<Scale<T, U1, U2>> for Rect<T, U2>
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Rect<T, U> {
|
||||
impl<T: Copy, Unit> Rect<T, Unit> {
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Rect<T, UnknownUnit> {
|
||||
|
@ -466,28 +445,21 @@ impl<T: Copy, U> Rect<T, U> {
|
|||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(r: &Rect<T, UnknownUnit>) -> Rect<T, U> {
|
||||
pub fn from_untyped(r: &Rect<T, UnknownUnit>) -> Rect<T, Unit> {
|
||||
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<T: NumCast + Copy, U> Rect<T, U> {
|
||||
impl<T0: NumCast + Copy, Unit> Rect<T0, Unit> {
|
||||
/// 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.
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Rect<NewT, U> {
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Rect<T1, Unit> {
|
||||
Rect::new(
|
||||
self.origin.cast(),
|
||||
self.size.cast(),
|
||||
|
@ -499,7 +471,7 @@ impl<T: NumCast + Copy, U> Rect<T, U> {
|
|||
/// 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<NewT: NumCast>(&self) -> Option<Rect<NewT, U>> {
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Rect<T1, Unit>> {
|
||||
match (self.origin.try_cast(), self.size.try_cast()) {
|
||||
(Some(origin), Some(size)) => Some(Rect::new(origin, size)),
|
||||
_ => None,
|
||||
|
@ -520,7 +492,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 + self.size).round() - origin;
|
||||
let size = self.origin.add_size(&self.size).round() - origin;
|
||||
Rect::new(origin, Size2D::new(size.x, size.y))
|
||||
}
|
||||
|
||||
|
@ -529,7 +501,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 + self.size).floor() - origin;
|
||||
let size = self.origin.add_size(&self.size).floor() - origin;
|
||||
Rect::new(origin, Size2D::new(size.x, size.y))
|
||||
}
|
||||
|
||||
|
@ -538,22 +510,20 @@ 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 + self.size).ceil() - origin;
|
||||
let size = self.origin.add_size(&self.size).ceil() - origin;
|
||||
Rect::new(origin, Size2D::new(size.x, size.y))
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, U> Rect<T, U> {
|
||||
impl<T: NumCast + Copy, Unit> Rect<T, Unit> {
|
||||
/// Cast into an `f32` rectangle.
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Rect<f32, U> {
|
||||
pub fn to_f32(&self) -> Rect<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` rectangle.
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Rect<f64, U> {
|
||||
pub fn to_f64(&self) -> Rect<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -562,8 +532,7 @@ impl<T: NumCast + Copy, U> Rect<T, U> {
|
|||
/// 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_usize(&self) -> Rect<usize, U> {
|
||||
pub fn to_usize(&self) -> Rect<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -572,18 +541,7 @@ impl<T: NumCast + Copy, U> Rect<T, U> {
|
|||
/// 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_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> {
|
||||
pub fn to_u32(&self) -> Rect<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -592,8 +550,7 @@ impl<T: NumCast + Copy, U> Rect<T, U> {
|
|||
/// 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_i32(&self) -> Rect<i32, U> {
|
||||
pub fn to_i32(&self) -> Rect<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -602,14 +559,13 @@ impl<T: NumCast + Copy, U> Rect<T, U> {
|
|||
/// 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_i64(&self) -> Rect<i64, U> {
|
||||
pub fn to_i64(&self) -> Rect<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<Size2D<T, U>> for Rect<T, U>
|
||||
where T: Zero
|
||||
where T: Copy + Zero
|
||||
{
|
||||
fn from(size: Size2D<T, U>) -> Self {
|
||||
Self::from_size(size)
|
||||
|
@ -617,7 +573,7 @@ where T: Zero
|
|||
}
|
||||
|
||||
/// Shorthand for `Rect::new(Point2D::new(x, y), Size2D::new(w, h))`.
|
||||
pub const fn rect<T, U>(x: T, y: T, w: T, h: T) -> Rect<T, U> {
|
||||
pub fn rect<T: Copy, U>(x: T, y: T, w: T, h: T) -> Rect<T, U> {
|
||||
Rect::new(Point2D::new(x, y), Size2D::new(w, h))
|
||||
}
|
||||
|
||||
|
@ -688,22 +644,6 @@ 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));
|
||||
|
@ -812,13 +752,6 @@ 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());
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
//! 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, UnknownUnit};
|
||||
use {Rotation3D, Transform3D, Vector3D};
|
||||
|
||||
/// A rigid transformation. All lengths are preserved under such a transformation.
|
||||
///
|
||||
|
@ -23,18 +19,20 @@ pub struct RigidTransform3D<T, Src, Dst> {
|
|||
pub translation: Vector3D<T, Dst>,
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> RigidTransform3D<T, Src, 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> {
|
||||
/// Construct a new rigid transformation, where the `rotation` applies first
|
||||
#[inline]
|
||||
pub const fn new(rotation: Rotation3D<T, Src, Dst>, translation: Vector3D<T, Dst>) -> Self {
|
||||
pub 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 {
|
||||
|
@ -171,24 +169,6 @@ 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>>
|
||||
|
|
|
@ -8,18 +8,187 @@
|
|||
// except according to those terms.
|
||||
|
||||
use approxeq::ApproxEq;
|
||||
use num_traits::{Float, One, Zero, NumCast};
|
||||
use num_traits::{Float, FloatConst, One, Zero, NumCast};
|
||||
use core::fmt;
|
||||
use core::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
|
||||
use core::marker::PhantomData;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
use trig::Trig;
|
||||
use {Angle, Point2D, Point3D, Vector2D, Vector3D, point2, point3, vec3};
|
||||
use {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))]
|
||||
|
@ -95,7 +264,9 @@ where
|
|||
|
||||
impl<T, Src, Dst> Rotation2D<T, Src, Dst>
|
||||
where
|
||||
T: Add<T, Output = T>
|
||||
T: Copy
|
||||
+ Clone
|
||||
+ Add<T, Output = T>
|
||||
+ Sub<T, Output = T>
|
||||
+ Mul<T, Output = T>
|
||||
+ Div<T, Output = T>
|
||||
|
@ -151,29 +322,12 @@ 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>
|
||||
|
@ -436,8 +590,7 @@ where
|
|||
|
||||
/// Basic Linear interpolation between this rotation and another rotation.
|
||||
///
|
||||
/// When `t` is `One::one()`, returned value equals to `other`,
|
||||
/// otherwise equals to `self`.
|
||||
/// `t` is expected to be between zero and one.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: &Self, t: T) -> Self {
|
||||
let one_t = T::one() - t;
|
||||
|
@ -613,30 +766,6 @@ 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> {
|
||||
|
@ -667,6 +796,10 @@ 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))
|
||||
|
@ -948,3 +1081,61 @@ 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));
|
||||
}
|
||||
|
|
|
@ -43,14 +43,12 @@ 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> {
|
||||
#[inline]
|
||||
pub const fn new(x: T) -> Self {
|
||||
pub 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()
|
||||
}
|
||||
|
@ -63,18 +61,6 @@ 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())
|
||||
|
@ -82,160 +68,67 @@ impl<T: Clone + One + Div<T, Output = T>, Src, Dst> Scale<T, Src, Dst> {
|
|||
}
|
||||
|
||||
// scale0 * scale1
|
||||
impl<T: Mul<T, Output = T>, A, B, C> Mul<Scale<T, B, C>> for Scale<T, A, B> {
|
||||
impl<T: Clone + 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.0 * other.0)
|
||||
Scale::new(self.get() * other.get())
|
||||
}
|
||||
}
|
||||
|
||||
// scale0 + scale1
|
||||
impl<T: Add<T, Output = T>, Src, Dst> Add for Scale<T, Src, Dst> {
|
||||
impl<T: Clone + 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.0 + other.0)
|
||||
Scale::new(self.get() + other.get())
|
||||
}
|
||||
}
|
||||
|
||||
// scale0 - scale1
|
||||
impl<T: Sub<T, Output = T>, Src, Dst> Sub for Scale<T, Src, Dst> {
|
||||
impl<T: Clone + 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.0 - other.0)
|
||||
Scale::new(self.get() - other.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Clone, Src, Dst> Scale<T, Src, Dst> {
|
||||
impl<T: NumCast + Clone, Src, Dst0> Scale<T, Src, Dst0> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// # 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> {
|
||||
pub fn cast<T1: NumCast + Clone>(&self) -> Scale<T1, Src, Dst0> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
/// 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>> {
|
||||
pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<Scale<T1, Src, Dst0>> {
|
||||
NumCast::from(self.get()).map(Scale::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Scale<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T> + Neg<Output = T> + PartialEq + One,
|
||||
T: Copy + Clone + 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(
|
||||
|
@ -250,30 +143,15 @@ where
|
|||
Scale::new(-self.get())
|
||||
}
|
||||
|
||||
/// 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);
|
||||
/// ```
|
||||
/// Returns true if this scale has no effect.
|
||||
#[inline]
|
||||
pub fn is_identity(&self) -> bool {
|
||||
self.0 == T::one()
|
||||
self.get() == T::one()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Switch to `derive(PartialEq, Clone)` after this Rust issue is fixed:
|
||||
// https://github.com/rust-lang/rust/issues/26925
|
||||
// https://github.com/mozilla/rust/issues/7671
|
||||
|
||||
impl<T: PartialEq, Src, Dst> PartialEq for Scale<T, Src, Dst> {
|
||||
fn eq(&self, other: &Scale<T, Src, Dst>) -> bool {
|
||||
|
|
|
@ -13,15 +13,14 @@
|
|||
use length::Length;
|
||||
use num::Zero;
|
||||
use core::fmt;
|
||||
use core::ops::{Add, Neg};
|
||||
use core::ops::Add;
|
||||
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/right/bottom/left for borders, padding,
|
||||
/// A group of 2D side offsets, which correspond to top/left/bottom/right for borders, padding,
|
||||
/// and margins in CSS, optionally tagged with a unit.
|
||||
#[repr(C)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
|
@ -95,12 +94,9 @@ impl<T: Default, U> Default for SideOffsets2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> SideOffsets2D<T, U> {
|
||||
impl<T: Copy, U> SideOffsets2D<T, U> {
|
||||
/// Constructor taking a scalar for each side.
|
||||
///
|
||||
/// 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 {
|
||||
pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
|
||||
SideOffsets2D {
|
||||
top,
|
||||
right,
|
||||
|
@ -111,9 +107,6 @@ impl<T, 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>,
|
||||
|
@ -123,44 +116,6 @@ impl<T, 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)
|
||||
|
@ -187,7 +142,7 @@ where
|
|||
|
||||
impl<T, U> Add for SideOffsets2D<T, U>
|
||||
where
|
||||
T: Add<T, Output = T>,
|
||||
T: Copy + Add<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self {
|
||||
|
@ -200,26 +155,9 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> SideOffsets2D<T, U> {
|
||||
impl<T: Copy + 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) });
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
use super::UnknownUnit;
|
||||
use approxord::{max, min};
|
||||
#[cfg(feature = "mint")]
|
||||
use mint;
|
||||
use length::Length;
|
||||
|
@ -17,7 +16,7 @@ use vector::{Vector2D, vec2, BoolVector2D};
|
|||
use vector::{Vector3D, vec3, BoolVector3D};
|
||||
use num::*;
|
||||
|
||||
use num_traits::{NumCast, Signed};
|
||||
use num_traits::{Float, NumCast, Signed};
|
||||
use core::fmt;
|
||||
use core::ops::{Add, Div, Mul, Sub};
|
||||
use core::marker::PhantomData;
|
||||
|
@ -29,9 +28,7 @@ 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>,
|
||||
|
@ -53,11 +50,10 @@ 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) = serde::Deserialize::deserialize(deserializer)?;
|
||||
let (width, height) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
Ok(Size2D { width, height, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +62,6 @@ 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
|
||||
{
|
||||
|
@ -113,24 +108,19 @@ impl<T: Default, U> Default for Size2D<T, U> {
|
|||
|
||||
impl<T, U> Size2D<T, U> {
|
||||
/// Constructor taking scalar values.
|
||||
#[inline]
|
||||
pub const fn new(width: T, height: T) -> Self {
|
||||
pub fn new(width: T, height: T) -> Self {
|
||||
Size2D {
|
||||
width,
|
||||
height,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
/// Constructor taking scalar strongly typed lengths.
|
||||
#[inline]
|
||||
pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
|
||||
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)
|
||||
impl<T: Clone, U> Size2D<T, U> {
|
||||
/// Constructor taking scalar strongly typed lengths.
|
||||
pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
|
||||
Size2D::new(width.get(), height.get())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +128,6 @@ 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())
|
||||
}
|
||||
|
@ -148,7 +137,6 @@ 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())
|
||||
}
|
||||
|
@ -158,28 +146,26 @@ 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: Add<T, Output = T>, U> Add for Size2D<T, U> {
|
||||
impl<T: Copy + 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: Sub<T, Output = T>, U> Sub for Size2D<T, U> {
|
||||
impl<T: Copy + 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 + Mul<T>, U> Size2D<T, U> {
|
||||
/// Returns result of multiplication of both components
|
||||
impl<T: Copy + Clone + Mul<T>, U> Size2D<T, U> {
|
||||
pub fn area(&self) -> T::Output {
|
||||
self.width * self.height
|
||||
}
|
||||
|
@ -189,26 +175,9 @@ impl<T, U> Size2D<T, U>
|
|||
where
|
||||
T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
|
||||
{
|
||||
/// Linearly interpolate each component between this size and another size.
|
||||
/// Linearly interpolate between this size and another size.
|
||||
///
|
||||
/// 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));
|
||||
/// ```
|
||||
/// `t` is expected to be between zero and one.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
let one_t = T::one() - t;
|
||||
|
@ -220,7 +189,6 @@ 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
|
||||
|
@ -228,17 +196,12 @@ 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())
|
||||
}
|
||||
|
@ -277,45 +240,40 @@ 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> {
|
||||
/// Return this size as an array of two elements (width, then height).
|
||||
/// Returns self.width as a Length carrying the unit.
|
||||
#[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)
|
||||
}
|
||||
|
||||
/// Cast the unit
|
||||
#[inline]
|
||||
pub fn cast_unit<V>(&self) -> Size2D<T, V> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Copy, U> Size2D<T, U> {
|
||||
impl<T: NumCast + Copy, Unit> Size2D<T, Unit> {
|
||||
/// 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.
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Size2D<NewT, U> {
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> Size2D<NewT, Unit> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
|
@ -324,7 +282,7 @@ impl<T: NumCast + Copy, U> Size2D<T, U> {
|
|||
/// 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>(&self) -> Option<Size2D<NewT, U>> {
|
||||
pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<Size2D<NewT, Unit>> {
|
||||
match (NumCast::from(self.width), NumCast::from(self.height)) {
|
||||
(Some(w), Some(h)) => Some(Size2D::new(w, h)),
|
||||
_ => None,
|
||||
|
@ -334,14 +292,12 @@ impl<T: NumCast + Copy, U> Size2D<T, U> {
|
|||
// Convenience functions for common casts
|
||||
|
||||
/// Cast into an `f32` size.
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Size2D<f32, U> {
|
||||
pub fn to_f32(&self) -> Size2D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` size.
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Size2D<f64, U> {
|
||||
pub fn to_f64(&self) -> Size2D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -350,8 +306,7 @@ impl<T: NumCast + Copy, U> Size2D<T, U> {
|
|||
/// 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_usize(&self) -> Size2D<usize, U> {
|
||||
pub fn to_usize(&self) -> Size2D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -360,18 +315,7 @@ impl<T: NumCast + Copy, U> Size2D<T, U> {
|
|||
/// 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_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> {
|
||||
pub fn to_u32(&self) -> Size2D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -380,8 +324,7 @@ impl<T: NumCast + Copy, U> Size2D<T, U> {
|
|||
/// 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_i32(&self) -> Size2D<i32, U> {
|
||||
pub fn to_i32(&self) -> Size2D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -390,8 +333,7 @@ impl<T: NumCast + Copy, U> Size2D<T, U> {
|
|||
/// 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_i64(&self) -> Size2D<i64, U> {
|
||||
pub fn to_i64(&self) -> Size2D<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
@ -400,23 +342,16 @@ 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,
|
||||
|
@ -424,7 +359,6 @@ 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,
|
||||
|
@ -435,7 +369,6 @@ 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,
|
||||
|
@ -443,7 +376,6 @@ 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,
|
||||
|
@ -452,48 +384,37 @@ impl<T: PartialEq, 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.
|
||||
impl<T: Float, U> Size2D<T, U> {
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
size2(
|
||||
min(self.width, other.width),
|
||||
min(self.height, other.height),
|
||||
self.width.min(other.width),
|
||||
self.height.min(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(
|
||||
max(self.width, other.width),
|
||||
max(self.height, other.height),
|
||||
self.width.max(other.width),
|
||||
self.height.max(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
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
pub fn clamp(&self, start: Self, end: Self) -> Self {
|
||||
self.max(start).min(end)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Shorthand for `Size2D::new(w, h)`.
|
||||
#[inline]
|
||||
pub const fn size2<T, U>(w: T, h: T) -> Size2D<T, U> {
|
||||
pub 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,
|
||||
|
@ -504,7 +425,6 @@ 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,
|
||||
|
@ -514,7 +434,6 @@ 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,
|
||||
|
@ -524,29 +443,25 @@ impl<T, U> From<Vector2D<T, U>> for Size2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> Into<[T; 2]> for Size2D<T, U> {
|
||||
#[inline]
|
||||
impl<T: Copy, U> Into<[T; 2]> for Size2D<T, U> {
|
||||
fn into(self) -> [T; 2] {
|
||||
[self.width, self.height]
|
||||
self.to_array()
|
||||
}
|
||||
}
|
||||
|
||||
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> From<[T; 2]> for Size2D<T, U> {
|
||||
fn from(array: [T; 2]) -> Self {
|
||||
size2(array[0], array[1])
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Into<(T, T)> for Size2D<T, U> {
|
||||
#[inline]
|
||||
impl<T: Copy, U> Into<(T, T)> for Size2D<T, U> {
|
||||
fn into(self) -> (T, T) {
|
||||
(self.width, self.height)
|
||||
self.to_tuple()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<(T, T)> for Size2D<T, U> {
|
||||
#[inline]
|
||||
impl<T: Copy, U> From<(T, T)> for Size2D<T, U> {
|
||||
fn from(tuple: (T, T)) -> Self {
|
||||
size2(tuple.0, tuple.1)
|
||||
}
|
||||
|
@ -616,11 +531,8 @@ 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>,
|
||||
|
@ -646,7 +558,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) = serde::Deserialize::deserialize(deserializer)?;
|
||||
let (width, height, depth) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
Ok(Size3D { width, height, depth, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
|
@ -702,8 +614,7 @@ impl<T: Default, U> Default for Size3D<T, U> {
|
|||
|
||||
impl<T, U> Size3D<T, U> {
|
||||
/// Constructor taking scalar values.
|
||||
#[inline]
|
||||
pub const fn new(width: T, height: T, depth: T) -> Self {
|
||||
pub fn new(width: T, height: T, depth: T) -> Self {
|
||||
Size3D {
|
||||
width,
|
||||
height,
|
||||
|
@ -713,11 +624,10 @@ impl<T, U> Size3D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> Size3D<T, U> {
|
||||
impl<T: Clone, 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.0, height.0, depth.0)
|
||||
Size3D::new(width.get(), height.get(), depth.get())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -725,7 +635,6 @@ 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())
|
||||
}
|
||||
|
@ -735,7 +644,6 @@ 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())
|
||||
}
|
||||
|
@ -745,30 +653,26 @@ 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: Add<T, Output = T>, U> Add for Size3D<T, U> {
|
||||
impl<T: Copy + 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: Sub<T, Output = T>, U> Sub for Size3D<T, U> {
|
||||
impl<T: Copy + 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 + Mul<T, Output=T>, U> Size3D<T, U> {
|
||||
/// Returns result of multiplication of all components
|
||||
impl<T: Copy + Clone + Mul<T, Output=T>, U> Size3D<T, U> {
|
||||
pub fn volume(&self) -> T {
|
||||
self.width * self.height * self.depth
|
||||
}
|
||||
|
@ -780,24 +684,7 @@ where
|
|||
{
|
||||
/// Linearly interpolate between this size and another size.
|
||||
///
|
||||
/// 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));
|
||||
/// ```
|
||||
/// `t` is expected to be between zero and one.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
let one_t = T::one() - t;
|
||||
|
@ -810,7 +697,6 @@ 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
|
||||
|
@ -818,17 +704,12 @@ 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())
|
||||
}
|
||||
|
@ -867,51 +748,35 @@ 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> {
|
||||
/// Return this size as an array of three elements (width, then height, then depth).
|
||||
/// Returns self.width as a Length carrying the unit.
|
||||
#[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, U> Size3D<T, U> {
|
||||
impl<T: NumCast + Copy, Unit> Size3D<T, Unit> {
|
||||
/// 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.
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> Size3D<NewT, U> {
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> Size3D<NewT, Unit> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
|
@ -920,7 +785,7 @@ impl<T: NumCast + Copy, U> Size3D<T, U> {
|
|||
/// 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, U>> {
|
||||
pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<Size3D<NewT, Unit>> {
|
||||
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,
|
||||
|
@ -930,14 +795,12 @@ impl<T: NumCast + Copy, U> Size3D<T, U> {
|
|||
// Convenience functions for common casts
|
||||
|
||||
/// Cast into an `f32` size.
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Size3D<f32, U> {
|
||||
pub fn to_f32(&self) -> Size3D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` size.
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Size3D<f64, U> {
|
||||
pub fn to_f64(&self) -> Size3D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -946,8 +809,7 @@ impl<T: NumCast + Copy, U> Size3D<T, U> {
|
|||
/// 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_usize(&self) -> Size3D<usize, U> {
|
||||
pub fn to_usize(&self) -> Size3D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -956,8 +818,7 @@ impl<T: NumCast + Copy, U> Size3D<T, U> {
|
|||
/// 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_u32(&self) -> Size3D<u32, U> {
|
||||
pub fn to_u32(&self) -> Size3D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -966,8 +827,7 @@ impl<T: NumCast + Copy, U> Size3D<T, U> {
|
|||
/// 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_i32(&self) -> Size3D<i32, U> {
|
||||
pub fn to_i32(&self) -> Size3D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -976,8 +836,7 @@ impl<T: NumCast + Copy, U> Size3D<T, U> {
|
|||
/// 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_i64(&self) -> Size3D<i64, U> {
|
||||
pub fn to_i64(&self) -> Size3D<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
@ -986,23 +845,16 @@ 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,
|
||||
|
@ -1011,7 +863,6 @@ 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,
|
||||
|
@ -1023,7 +874,6 @@ 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,
|
||||
|
@ -1032,7 +882,6 @@ 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,
|
||||
|
@ -1042,50 +891,39 @@ impl<T: PartialEq, 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.
|
||||
impl<T: Float, U> Size3D<T, U> {
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
size3(
|
||||
min(self.width, other.width),
|
||||
min(self.height, other.height),
|
||||
min(self.depth, other.depth),
|
||||
self.width.min(other.width),
|
||||
self.height.min(other.height),
|
||||
self.depth.min(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(
|
||||
max(self.width, other.width),
|
||||
max(self.height, other.height),
|
||||
max(self.depth, other.depth),
|
||||
self.width.max(other.width),
|
||||
self.height.max(other.height),
|
||||
self.depth.max(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
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
pub fn clamp(&self, start: Self, end: Self) -> Self {
|
||||
self.max(start).min(end)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Shorthand for `Size3D::new(w, h, d)`.
|
||||
#[inline]
|
||||
pub const fn size3<T, U>(w: T, h: T, d: T) -> Size3D<T, U> {
|
||||
pub 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,
|
||||
|
@ -1097,7 +935,6 @@ 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,
|
||||
|
|
|
@ -79,7 +79,7 @@ impl<'de, T, Src, Dst> serde::Deserialize<'de> for Transform2D<T, Src, Dst>
|
|||
m11, m12,
|
||||
m21, m22,
|
||||
m31, m32,
|
||||
) = serde::Deserialize::deserialize(deserializer)?;
|
||||
) = try!(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, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
impl<T: Copy, 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 const fn row_major(m11: T, m12: T, m21: T, m22: T, m31: T, m32: T) -> Self {
|
||||
pub 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, 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 const fn column_major(m11: T, m21: T, m31: T, m12: T, m22: T, m32: T) -> Self {
|
||||
pub fn column_major(m11: T, m21: T, m31: T, m12: T, m22: T, m32: T) -> Self {
|
||||
Transform2D {
|
||||
m11, m12,
|
||||
m21, m22,
|
||||
|
@ -161,40 +161,12 @@ impl<T, 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,
|
||||
|
@ -208,7 +180,6 @@ 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,
|
||||
|
@ -224,7 +195,6 @@ 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],
|
||||
|
@ -238,7 +208,6 @@ 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],
|
||||
|
@ -252,7 +221,6 @@ 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],
|
||||
|
@ -262,7 +230,6 @@ 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,
|
||||
|
@ -272,7 +239,6 @@ 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,
|
||||
|
@ -282,15 +248,14 @@ impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
impl<T0: NumCast + Copy, Src, Dst> Transform2D<T0, Src, Dst> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Transform2D<NewT, Src, Dst> {
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Transform2D<T1, Src, Dst> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Transform2D<NewT, Src, Dst>> {
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Transform2D<T1, 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)) {
|
||||
|
@ -330,11 +295,12 @@ where T: Copy +
|
|||
}
|
||||
|
||||
impl<T, Src, Dst> Transform2D<T, Src, Dst>
|
||||
where T: Copy +
|
||||
where T: Copy + Clone +
|
||||
Add<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
Div<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Trig +
|
||||
PartialOrd +
|
||||
One + Zero {
|
||||
|
||||
|
@ -411,12 +377,39 @@ where T: Copy +
|
|||
#[must_use]
|
||||
pub fn pre_scale(&self, x: T, y: T) -> Self {
|
||||
Transform2D::row_major(
|
||||
self.m11 * x, self.m12 * x,
|
||||
self.m21 * y, self.m22 * y,
|
||||
self.m11 * x, self.m12,
|
||||
self.m21, 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`
|
||||
|
@ -459,12 +452,6 @@ where T: Copy +
|
|||
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>> {
|
||||
|
@ -509,45 +496,8 @@ where T: Copy +
|
|||
}
|
||||
}
|
||||
|
||||
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 +
|
||||
where T: Copy + Clone +
|
||||
Add<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
|
@ -571,20 +521,15 @@ impl <T, Src, Dst> Default for Transform2D<T, Src, Dst>
|
|||
}
|
||||
}
|
||||
|
||||
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: 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, Src, Dst> fmt::Debug for Transform2D<T, Src, Dst>
|
||||
impl<T: Copy + fmt::Debug, Src, Dst> fmt::Debug for Transform2D<T, Src, Dst>
|
||||
where T: Copy + fmt::Debug +
|
||||
PartialEq +
|
||||
One + Zero {
|
||||
|
@ -671,15 +616,6 @@ 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!(
|
||||
|
|
|
@ -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,
|
||||
) = serde::Deserialize::deserialize(deserializer)?;
|
||||
) = try!(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 const fn row_major(
|
||||
pub 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 const fn column_major(
|
||||
pub 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 +
|
||||
where T: Copy + Clone +
|
||||
PartialEq +
|
||||
One + Zero {
|
||||
#[inline]
|
||||
|
@ -245,7 +245,7 @@ where T: Copy +
|
|||
}
|
||||
|
||||
impl <T, Src, Dst> Transform3D<T, Src, Dst>
|
||||
where T: Copy +
|
||||
where T: Copy + Clone +
|
||||
Add<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
|
@ -323,28 +323,16 @@ where T: Copy +
|
|||
(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 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)
|
||||
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)
|
||||
}
|
||||
|
||||
/// Returns the same transform with a different destination unit.
|
||||
|
@ -427,12 +415,6 @@ where T: Copy +
|
|||
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();
|
||||
|
@ -736,9 +718,9 @@ where T: Copy +
|
|||
#[must_use]
|
||||
pub fn pre_scale(&self, x: T, y: T, z: T) -> Self {
|
||||
Transform3D::row_major(
|
||||
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.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.m41 , self.m42, self.m43, self.m44
|
||||
)
|
||||
}
|
||||
|
@ -831,7 +813,6 @@ 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,
|
||||
|
@ -846,7 +827,6 @@ 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,
|
||||
|
@ -864,7 +844,6 @@ 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],
|
||||
|
@ -882,7 +861,6 @@ 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],
|
||||
|
@ -897,7 +875,6 @@ 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],
|
||||
|
@ -912,7 +889,6 @@ 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],
|
||||
|
@ -923,15 +899,14 @@ impl<T: Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
impl<T0: NumCast + Copy, Src, Dst> Transform3D<T0, Src, Dst> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
#[inline]
|
||||
pub fn cast<NewT: NumCast>(&self) -> Transform3D<NewT, Src, Dst> {
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Transform3D<T1, Src, Dst> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
pub fn try_cast<NewT: NumCast>(&self) -> Option<Transform3D<NewT, Src, Dst>> {
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Transform3D<T1, 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),
|
||||
|
@ -954,22 +929,6 @@ impl<T: NumCast + Copy, Src, Dst> Transform3D<T, 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
|
||||
{
|
||||
|
@ -1081,16 +1040,6 @@ 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);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
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};
|
||||
|
@ -83,71 +82,38 @@ impl<T, Src, Dst> Hash for Translation2D<T, Src, Dst>
|
|||
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst> {
|
||||
#[inline]
|
||||
pub const fn new(x: T, y: T) -> Self {
|
||||
pub 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: Zero
|
||||
T : Copy + Zero
|
||||
{
|
||||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
Translation2D::new(T::zero(), T::zero())
|
||||
let _0 = T::zero();
|
||||
Translation2D::new(_0, _0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,8 +123,7 @@ where
|
|||
{
|
||||
#[inline]
|
||||
pub fn is_identity(&self) -> bool {
|
||||
let _0 = T::zero();
|
||||
self.x == _0 && self.y == _0
|
||||
self.x == T::zero() && self.y == T::zero()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,6 +145,17 @@ 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>
|
||||
|
@ -196,7 +172,7 @@ where
|
|||
impl<T, Src, Dst1, Dst2> Add<Translation2D<T, Dst1, Dst2>>
|
||||
for Translation2D<T, Src, Dst1>
|
||||
where
|
||||
T: Add<T, Output = T>
|
||||
T: Copy + Add<T, Output = T>
|
||||
{
|
||||
type Output = Translation2D<T, Src, Dst2>;
|
||||
fn add(self, other: Translation2D<T, Dst1, Dst2>) -> Translation2D<T, Src, Dst2> {
|
||||
|
@ -211,7 +187,7 @@ impl<T, Src, Dst1, Dst2>
|
|||
Sub<Translation2D<T, Dst1, Dst2>>
|
||||
for Translation2D<T, Src, Dst2>
|
||||
where
|
||||
T: Sub<T, Output = T>
|
||||
T: Copy + Sub<T, Output = T>
|
||||
{
|
||||
type Output = Translation2D<T, Src, Dst1>;
|
||||
fn sub(self, other: Translation2D<T, Dst1, Dst2>) -> Translation2D<T, Src, Dst1> {
|
||||
|
@ -225,6 +201,7 @@ 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>
|
||||
|
@ -242,6 +219,8 @@ 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)
|
||||
|
@ -249,6 +228,8 @@ impl<T, Src, Dst> From<Vector2D<T, Src>> for Translation2D<T, Src, Dst>
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -258,6 +239,7 @@ impl<T, Src, Dst> Into<Vector2D<T, Src>> for Translation2D<T, Src, Dst>
|
|||
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>
|
||||
|
@ -273,24 +255,20 @@ where
|
|||
}
|
||||
|
||||
impl <T, Src, Dst> Default for Translation2D<T, Src, Dst>
|
||||
where T: Zero
|
||||
where T: Copy + Zero
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, Src, Dst> fmt::Debug for Translation2D<T, Src, Dst> {
|
||||
impl<T, Src, Dst> fmt::Debug for Translation2D<T, Src, Dst>
|
||||
where T: Copy + fmt::Debug {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Translation({:?},{:?})", self.x, self.y)
|
||||
self.to_array().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -326,7 +304,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) = serde::Deserialize::deserialize(deserializer)?;
|
||||
let (x, y, z) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
Ok(Translation3D { x, y, z, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
|
@ -364,7 +342,7 @@ impl<T, Src, Dst> Hash for Translation3D<T, Src, Dst>
|
|||
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst> {
|
||||
#[inline]
|
||||
pub const fn new(x: T, y: T, z: T) -> Self {
|
||||
pub fn new(x: T, y: T, z: T) -> Self {
|
||||
Translation3D {
|
||||
x,
|
||||
y,
|
||||
|
@ -372,66 +350,31 @@ 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: Zero
|
||||
T: Copy + Zero
|
||||
{
|
||||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
Translation3D::new(T::zero(), T::zero(), T::zero())
|
||||
let _0 = T::zero();
|
||||
Translation3D::new(_0, _0, _0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,8 +384,7 @@ where
|
|||
{
|
||||
#[inline]
|
||||
pub fn is_identity(&self) -> bool {
|
||||
let _0 = T::zero();
|
||||
self.x == _0 && self.y == _0 && self.z == _0
|
||||
self.x == T::zero() && self.y == T::zero() && self.z == T::zero()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,6 +412,17 @@ 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>
|
||||
|
@ -486,7 +439,7 @@ where
|
|||
impl<T, Src, Dst1, Dst2> Add<Translation3D<T, Dst1, Dst2>>
|
||||
for Translation3D<T, Src, Dst1>
|
||||
where
|
||||
T: Add<T, Output = T>
|
||||
T: Copy + Add<T, Output = T>
|
||||
{
|
||||
type Output = Translation3D<T, Src, Dst2>;
|
||||
fn add(self, other: Translation3D<T, Dst1, Dst2>) -> Translation3D<T, Src, Dst2> {
|
||||
|
@ -502,7 +455,7 @@ impl<T, Src, Dst1, Dst2>
|
|||
Sub<Translation3D<T, Dst1, Dst2>>
|
||||
for Translation3D<T, Src, Dst2>
|
||||
where
|
||||
T: Sub<T, Output = T>
|
||||
T: Copy + Sub<T, Output = T>
|
||||
{
|
||||
type Output = Translation3D<T, Src, Dst1>;
|
||||
fn sub(self, other: Translation3D<T, Dst1, Dst2>) -> Translation3D<T, Src, Dst1> {
|
||||
|
@ -516,7 +469,7 @@ where
|
|||
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy +
|
||||
T: Copy + Clone +
|
||||
Add<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
|
@ -534,6 +487,8 @@ 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)
|
||||
|
@ -541,6 +496,8 @@ impl<T, Src, Dst> From<Vector3D<T, Src>> for Translation3D<T, Src, Dst>
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -549,7 +506,7 @@ impl<T, Src, Dst> Into<Vector3D<T, Src>> for Translation3D<T, Src, Dst>
|
|||
|
||||
impl<T, Src, Dst> Into<Transform3D<T, Src, Dst>> for Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy +
|
||||
T: Copy + Clone +
|
||||
Add<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
|
@ -565,22 +522,17 @@ where
|
|||
}
|
||||
|
||||
impl <T, Src, Dst> Default for Translation3D<T, Src, Dst>
|
||||
where T: Zero
|
||||
where T: Copy + Zero
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, Src, Dst> fmt::Debug for Translation3D<T, Src, Dst> {
|
||||
impl<T, Src, Dst> fmt::Debug for Translation3D<T, Src, Dst>
|
||||
where T: Copy + fmt::Debug {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
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)
|
||||
self.to_array().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,20 +18,14 @@ pub trait Trig {
|
|||
}
|
||||
|
||||
macro_rules! trig {
|
||||
($ty:ident) => {
|
||||
($ty:ident) => (
|
||||
impl Trig for $ty {
|
||||
#[inline]
|
||||
fn sin(self) -> $ty {
|
||||
num_traits::Float::sin(self)
|
||||
}
|
||||
fn sin(self) -> $ty { self.sin() }
|
||||
#[inline]
|
||||
fn cos(self) -> $ty {
|
||||
num_traits::Float::cos(self)
|
||||
}
|
||||
fn cos(self) -> $ty { self.cos() }
|
||||
#[inline]
|
||||
fn tan(self) -> $ty {
|
||||
num_traits::Float::tan(self)
|
||||
}
|
||||
fn tan(self) -> $ty { self.tan() }
|
||||
|
||||
/// A slightly faster approximation of `atan2`.
|
||||
///
|
||||
|
@ -44,12 +38,11 @@ macro_rules! trig {
|
|||
|
||||
// See https://math.stackexchange.com/questions/1098487/atan2-faster-approximation#1105038
|
||||
use core::$ty::consts;
|
||||
let x_abs = num_traits::Float::abs(x);
|
||||
let y_abs = num_traits::Float::abs(y);
|
||||
let x_abs = x.abs();
|
||||
let y_abs = y.abs();
|
||||
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;
|
||||
}
|
||||
|
@ -73,7 +66,7 @@ macro_rules! trig {
|
|||
rad.to_degrees()
|
||||
}
|
||||
}
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
trig!(f32);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче