pub struct BoundingBox { /* private fields */ }Expand description
A rectilinear, 2-dimensional bounding box.
A 2-dimensional rectilinear bounding box is described by four values: minimum
x-value, maximum x-value, minimum y-value and and maximum y-value. This struct
can be created either from any type which implements Into<BoundingBox> or
from the constructors new or
try_new. The values defining a bounding box (xmin,
xmax, ymin, ymax) are called “extremas”.
Since a bounding box only consists of four f64 values (32 bytes), it is cheap to
copy, hence it implements the
Copy trait.
§Features
This struct can be serialized / deserialized if the serde feature is enabled.
Implementations§
Source§impl BoundingBox
impl BoundingBox
Sourcepub fn new(xmin: f64, xmax: f64, ymin: f64, ymax: f64) -> Self
pub fn new(xmin: f64, xmax: f64, ymin: f64, ymax: f64) -> Self
Generates a bounding box from minimum and maximum x- and y-values.
§Panics
Panics if xmin > xmax or if ymin > ymax.
§Examples
use bounding_box::BoundingBox;
let _ = BoundingBox::new(0.0, 1.0, 0.0, 1.0);This example panics because xmin > xmax.
use bounding_box::BoundingBox;
let _ = BoundingBox::new(2.0, 1.0, 0.0, 1.0);Sourcepub fn try_new(xmin: f64, xmax: f64, ymin: f64, ymax: f64) -> Option<Self>
pub fn try_new(xmin: f64, xmax: f64, ymin: f64, ymax: f64) -> Option<Self>
Like BoundingBox::new, but returns None instead of panicking if xmin > xmax or if ymin > ymax.
§Examples
use bounding_box::BoundingBox;
assert!(BoundingBox::try_new(0.0, 1.0, 0.0, 1.0).is_some());
assert!(BoundingBox::try_new(2.0, 1.0, 0.0, 1.0).is_none());Sourcepub fn try_set_xmin(&mut self, val: f64) -> bool
pub fn try_set_xmin(&mut self, val: f64) -> bool
Fallible sets a new value for xmin. If the new value is bigger than xmax, the old value is left unchanged
and this function returns false. Otherwise, it returns true and the old value is replaced by the new value.
§Examples
use bounding_box::BoundingBox;
let mut bb = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
assert_eq!(bb.xmin(), 0.0);
assert!(bb.try_set_xmin(0.5));
assert_eq!(bb.xmin(), 0.5);
assert!(!bb.try_set_xmin(1.5));
assert_eq!(bb.xmin(), 0.5);Sourcepub fn try_set_xmax(&mut self, val: f64) -> bool
pub fn try_set_xmax(&mut self, val: f64) -> bool
Fallible sets a new value for xmax. If the new value is smaller than xmin, the old value is left unchanged
and this function returns false. Otherwise, it returns true and the old value is replaced by the new value.
§Examples
use bounding_box::BoundingBox;
let mut bb = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
assert_eq!(bb.xmax(), 1.0);
assert!(bb.try_set_xmax(0.5));
assert_eq!(bb.xmax(), 0.5);
assert!(!bb.try_set_xmax(-0.5));
assert_eq!(bb.xmax(), 0.5);Sourcepub fn try_set_ymin(&mut self, val: f64) -> bool
pub fn try_set_ymin(&mut self, val: f64) -> bool
Fallible sets a new value for ymin. If the new value is bigger than ymax, the old value is left unchanged
and this function returns false. Otherwise, it returns true and the old value is replaced by the new value.
§Examples
use bounding_box::BoundingBox;
let mut bb = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
assert_eq!(bb.ymin(), 0.0);
assert!(bb.try_set_ymin(0.5));
assert_eq!(bb.ymin(), 0.5);
assert!(!bb.try_set_ymin(1.5));
assert_eq!(bb.ymin(), 0.5);Sourcepub fn try_set_ymax(&mut self, val: f64) -> bool
pub fn try_set_ymax(&mut self, val: f64) -> bool
Fallible sets a new value for ymax. If the new value is smaller than ymin, the old value is left unchanged
and this function returns false. Otherwise, it returns true and the old value is replaced by the new value.
§Examples
use bounding_box::BoundingBox;
let mut bb = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
assert_eq!(bb.ymax(), 1.0);
assert!(bb.try_set_ymax(0.5));
assert_eq!(bb.ymax(), 0.5);
assert!(!bb.try_set_ymax(-0.5));
assert_eq!(bb.ymax(), 0.5);Sourcepub fn from_points<'a, T: Into<[f64; 2]>, I: Iterator<Item = T>>(
verts: I,
) -> Option<Self>
pub fn from_points<'a, T: Into<[f64; 2]>, I: Iterator<Item = T>>( verts: I, ) -> Option<Self>
Creates a bounding box from an iterator over vertices.
If the iterator is empty, this function returns None.
use bounding_box::BoundingBox;
let verts = vec![
[1.0, 0.0],
[-5.0, 2.0],
[3.0, -12.3],
[7.0, 0.0],
[2.0, 11.0],
[1.0, -6.0],
];
let bb = BoundingBox::from_points(verts.into_iter()).expect("iterator yields at least one elment");
assert_eq!(bb.xmin(), -5.0);
assert_eq!(bb.xmax(), 7.0);
assert_eq!(bb.ymin(), -12.3);
assert_eq!(bb.ymax(), 11.0);Sourcepub fn from_bounded_entities<T: Into<BoundingBox>, I: Iterator<Item = T>>(
entities: I,
) -> Option<Self>
pub fn from_bounded_entities<T: Into<BoundingBox>, I: Iterator<Item = T>>( entities: I, ) -> Option<Self>
Creates a bounding box from an iterator over any types implementing
Into<BoundingBox>.
If the iterator is empty, this function returns None.
use bounding_box::BoundingBox;
struct Circle {
center: [f64; 2],
radius: f64
}
impl From<&Circle> for BoundingBox {
fn from(c: &Circle) -> BoundingBox {
return BoundingBox::new(c.center[0] - c.radius,
c.center[0] + c.radius,
c.center[1] - c.radius,
c.center[1] + c.radius);
}
}
let c1 = Circle {center: [0.0, 0.0], radius: 1.0};
let c2 = Circle {center: [0.0, 2.0], radius: 1.0};
let c3 = Circle {center: [0.0, 2.0], radius: 2.0};
let bb = BoundingBox::from_bounded_entities([&c1, &c2, &c3].into_iter()).expect("iterator has at least one element");
assert_eq!(bb.xmin(), -2.0);
assert_eq!(bb.xmax(), 2.0);
assert_eq!(bb.ymin(), -1.0);
assert_eq!(bb.ymax(), 4.0);Sourcepub fn union(&self, other: &BoundingBox) -> BoundingBox
pub fn union(&self, other: &BoundingBox) -> BoundingBox
Creates the union of two bounding boxes.
The union of two bounding boxes is the minimum bounding box which covers both bounding boxes.
§Examples
use bounding_box::BoundingBox;
let bb1 = BoundingBox::new(-1.0, 3.5, 2.0, 3.0);
let bb2 = BoundingBox::new(-5.0, 2.5, -1.0, 5.0);
let bb = bb1.union(&bb2);
assert_eq!(bb.xmin(), -5.0);
assert_eq!(bb.xmax(), 3.5);
assert_eq!(bb.ymin(), -1.0);
assert_eq!(bb.ymax(), 5.0);Sourcepub fn covers_point<T: Into<[f64; 2]>>(&self, point: T) -> bool
pub fn covers_point<T: Into<[f64; 2]>>(&self, point: T) -> bool
Returns true if self covers a given point.
A point is “covered” by the bounding box if it is either within or on the
boundaries of self. Mathematically speaking, the following two
inequalities must be true:
self.xmin() <= point[0] <= self.xmax()
self.ymin() <= point[1] <= self.ymax()
If the boundaries should be excluded, use BoundingBox::contains_point
instead.
If the feature flag approx is enabled, the method
BoundingBox::approx_covers_point is made available, which allows
providing tolerances for the aforementioned inequalities.
§Examples
use bounding_box::BoundingBox;
let bb = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
assert!(bb.covers_point([0.5, 0.5]));
assert!(bb.covers_point([0.0, 0.0])); // On boundary
assert!(!bb.covers_point([-1.0, 0.0]));
assert!(!bb.covers_point([0.0, 2.0]));
Sourcepub fn approx_covers_point<T: Into<[f64; 2]>>(
&self,
point: T,
epsilon: f64,
max_ulps: u32,
) -> bool
pub fn approx_covers_point<T: Into<[f64; 2]>>( &self, point: T, epsilon: f64, max_ulps: u32, ) -> bool
Like BoundingBox::covers_point, but with absolute and ULPs tolerances.
This variant of BoundingBox::covers_point allows specifying an absolute
and an ULP
tolerance. These tolerances are used to check if the given point lies
“approximately” on an edge of the bounding box.
§Examples
use bounding_box::BoundingBox;
let bb = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
// Exact check: Point is outside the bounding box
assert!(!bb.covers_point([1.0001, 1.0]));
// Check using tolerances: Point is inside bounding box
assert!(bb.approx_covers_point([1.0001, 1.0], 1e-3, 0));
// Check using a finer tolerance: Point is outside the bounding box
assert!(!bb.approx_covers_point([1.0001, 1.0], 1e-6, 0));§Features
This function uses the ulps_eq macro of the approx crate, therefore
the approx feature needs to be enabled.
Sourcepub fn contains_point<T: Into<[f64; 2]>>(&self, point: T) -> bool
pub fn contains_point<T: Into<[f64; 2]>>(&self, point: T) -> bool
Returns true if self contains a given point.
A point is “contained” by the bounding box if it is within the boundaries of
self. Mathematically speaking, the following two inequalities must be true:
self.xmin() < point[0] < self.xmax()
self.ymin() < point[1] < self.ymax()
If the boundaries should be included, use BoundingBox::covers_point
instead.
§Examples
use bounding_box::BoundingBox;
let bb = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
assert!(bb.contains_point([0.5, 0.5]));
assert!(!bb.contains_point([0.0, 0.0])); // On boundary
assert!(!bb.contains_point([-1.0, 0.0]));
assert!(!bb.contains_point([0.0, 2.0]));
Sourcepub fn covers(&self, other: &Self) -> bool
pub fn covers(&self, other: &Self) -> bool
Returns true if self covers other.
A bounding box “covers” another bounding box, if every point covered by the
second box is also covered by the first one according to the definition
given in BoundingBox::covers_point:
self.xmin() <= other.xmin() <= other.xmax() <= self.xmax()
self.ymin() <= other.ymin() <= other.ymax() <= self.ymax()
If the boundaries of self should be excluded, use BoundingBox::covers
instead.
If the feature flag approx is enabled, the method
`BoundingBox::approx_covers is made available, which allows
providing tolerances for the aforementioned inequalities.
§Examples
use bounding_box::BoundingBox;
// bb1 covers bb2, but not the other way around
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.2, 0.8, 0.2, 0.8);
assert!(bb1.covers(&bb2));
assert!(!bb2.covers(&bb1));
// bb1 covers itself
assert!(bb1.covers(&bb1));
// bb1 and bb2 share a border
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.2, 1.0, 0.2, 0.8);
assert!(bb1.covers(&bb2));
// bb1 and bb2 are separated from each other, and therefore neither one covers the other
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(2.0, 3.0, 2.0, 3.0);
assert!(!bb1.covers(&bb2));
assert!(!bb2.covers(&bb1));Sourcepub fn approx_covers(&self, other: &Self, epsilon: f64, max_ulps: u32) -> bool
pub fn approx_covers(&self, other: &Self, epsilon: f64, max_ulps: u32) -> bool
Like BoundingBox::covers, but with absolute and ULPs tolerances.
This variant of BoundingBox::covers allows specifying an absolute and
an ULP tolerance.
These tolerances are used to check if the extremas of the boxes are
“approximately” equal.
use bounding_box::BoundingBox;
// bb1 covers bb2 depending on the selected tolerances
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.0, 1.0001, 0.0, 0.5);
assert!(!bb1.covers(&bb2));
assert!(bb1.approx_covers(&bb2, 1e-3, 0));
assert!(!bb1.approx_covers(&bb2, 1e-6, 0));§Features
This function uses the ulps_eq macro of the approx crate, therefore
the approx feature needs to be enabled.
Sourcepub fn contains(&self, other: &Self) -> bool
pub fn contains(&self, other: &Self) -> bool
Returns true if self contains other.
A bounding box “contains” another bounding box, if every point covered by
the second box is also contained within the first one according to the
definitions given in BoundingBox::covers_point and
BoundingBox::contains_point:
self.xmin() < other.xmin() <= other.xmax() < self.xmax()
self.ymin() < other.ymin() <= other.ymax() < self.ymax()
If the boundaries of self should be excluded, use BoundingBox::covers
instead.
If the feature flag approx is enabled, the method
`BoundingBox::approx_covers is made available, which allows
providing tolerances for the aforementioned inequalities.
§Examples
use bounding_box::BoundingBox;
// bb1 contains bb2, but not the other way around
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.2, 0.8, 0.2, 0.8);
assert!(bb1.contains(&bb2));
assert!(!bb2.contains(&bb1));
// bb1 does not contain itself
assert!(!bb1.contains(&bb1));
// bb1 and bb2 share a border
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.2, 1.0, 0.2, 0.8);
assert!(!bb1.contains(&bb2));
// bb1 and bb2 are separated from each other, and therefore neither one contains the other
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(2.0, 3.0, 2.0, 3.0);
assert!(!bb1.contains(&bb2));
assert!(!bb2.contains(&bb1));Sourcepub fn approx_eq(&self, other: &Self, epsilon: f64, max_ulps: u32) -> bool
pub fn approx_eq(&self, other: &Self, epsilon: f64, max_ulps: u32) -> bool
Check if the two bounding boxes are approximately equal.
This check is performed using the ulps_eq macro of the approx crate.
use bounding_box::BoundingBox;
// bb1 covers bb2 depending on the selected tolerances
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.0, 1.0001, 0.0, 1.0);
assert!(!bb1.eq(&bb2));
assert!(bb1.approx_eq(&bb2, 1e-3, 0));
assert!(!bb1.approx_eq(&bb2, 1e-6, 0));§Features
This function uses the ulps_eq
macro of the approx crate, therefore the approx feature needs to be enabled.
Sourcepub fn intersects(&self, other: &Self) -> bool
pub fn intersects(&self, other: &Self) -> bool
Returns true if the bounding boxes intersect, i.e. if they both cover at least one common point.
The boxes are intersecting if they are just touching.
§Examples
use bounding_box::BoundingBox;
// bb1 and bb2 intersect
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(-1.0, 1.0, 0.2, 0.8);
assert!(bb1.intersects(&bb2));
// bb1 and bb2 do not intersect
let bb1 = BoundingBox::new(-1.0, 3.5, 2.0, 3.0);
let bb2 = BoundingBox::new(-5.0, 2.5, -1.0, 1.0);
assert!(!bb1.intersects(&bb2));
// bb2 is contained in bb1
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.2, 1.0, 0.2, 0.8);
assert!(bb1.intersects(&bb2));
// bb1 is contained in bb2
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.2, 1.0, 0.2, 0.8);
assert!(bb2.intersects(&bb1));
// bb1 touches bb2 => intersection
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(1.0, 2.0, 0.0, 1.0);
assert!(bb2.intersects(&bb1));Sourcepub fn overlaps(&self, other: &Self) -> bool
pub fn overlaps(&self, other: &Self) -> bool
Returns true if the bounding boxes overlap, i.e. if they both contain at least one common point.
The boxes are NOT intersecting if they are just touching.
§Examples
use bounding_box::BoundingBox;
// bb1 and bb2 overlap
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(-1.0, 1.0, 0.2, 0.8);
assert!(bb1.overlaps(&bb2));
// bb1 and bb2 do not overlap
let bb1 = BoundingBox::new(-1.0, 3.5, 2.0, 3.0);
let bb2 = BoundingBox::new(-5.0, 2.5, -1.0, 1.0);
assert!(!bb1.overlaps(&bb2));
// bb2 is contained in bb1
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.2, 1.0, 0.2, 0.8);
assert!(bb1.overlaps(&bb2));
// bb1 is contained in bb2
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.2, 1.0, 0.2, 0.8);
assert!(bb2.overlaps(&bb1));
// bb1 touches bb2 => no overlapping
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(1.0, 2.0, 0.0, 1.0);
assert!(!bb2.overlaps(&bb1));Sourcepub fn touches(&self, other: &Self) -> bool
pub fn touches(&self, other: &Self) -> bool
Check if the bounding boxes are touching.
The bounding boxes are touching if they share at least one extremum and are not intersecting each other.
§Examples
use bounding_box::BoundingBox;
// bb1 touches bb2 => no intersection
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(1.0, 2.0, 0.0, 1.0);
assert!(bb2.touches(&bb1));
// bb1 is included in bb2 and two edges are touching
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(0.0, 2.0, 0.0, 1.0);
assert!(!bb2.touches(&bb1));
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(1.0001, 2.0, 0.0, 1.0);
assert!(!bb2.touches(&bb1));Sourcepub fn approx_touches(&self, other: &Self, epsilon: f64, max_ulps: u32) -> bool
pub fn approx_touches(&self, other: &Self, epsilon: f64, max_ulps: u32) -> bool
Like BoundingBox::touches, but with absolute and ULPs tolerances.
This variant of BoundingBox::touches allows specifying an absolute and
an ULP tolerance. These tolerances
are used to check if the boxes share at least one extremas “approximately”.
This check is performed using the ulps_eq
macro of the approx crate. Please see its documentation.
§Examples
use bounding_box::BoundingBox;
let bb1 = BoundingBox::new(0.0, 1.0, 0.0, 1.0);
let bb2 = BoundingBox::new(1.0001, 2.0, 0.0, 1.0);
assert!(!bb1.touches(&bb2));
assert!(bb1.approx_touches(&bb2, 1e-3, 0));
assert!(!bb1.approx_touches(&bb2, 1e-6, 0));§Features
This function uses the ulps_eq
macro of the approx crate, therefore the approx feature needs to be enabled.
Sourcepub fn width(&self) -> f64
pub fn width(&self) -> f64
Returns the width of the bounding box.
§Examples
use bounding_box::BoundingBox;
let bb = BoundingBox::new(-1.0, 1.0, 2.0, 7.0);
assert_eq!(bb.width(), 2.0);Sourcepub fn height(&self) -> f64
pub fn height(&self) -> f64
Returns the height of the bounding box.
§Examples
use bounding_box::BoundingBox;
let bb = BoundingBox::new(-1.0, 1.0, 2.0, 7.0);
assert_eq!(bb.height(), 5.0);Sourcepub fn center(&self) -> [f64; 2]
pub fn center(&self) -> [f64; 2]
Returns the center of the bounding box.
§Examples
use bounding_box::BoundingBox;
let bb = BoundingBox::new(-1.0, 1.0, 2.0, 7.0);
assert_eq!(bb.center(), [0.0, 4.5]);Sourcepub fn translate<T: Into<[f64; 2]>>(&mut self, shift: T)
pub fn translate<T: Into<[f64; 2]>>(&mut self, shift: T)
Translates the bounding box by the given shift.
§Examples
use bounding_box::BoundingBox;
let mut bb = BoundingBox::new(0.0, 1.0, 1.0, 2.0);
bb.translate([1.0, -1.0]);
assert_eq!(bb.xmin(), 1.0);
assert_eq!(bb.xmax(), 2.0);
assert_eq!(bb.ymin(), 0.0);
assert_eq!(bb.ymax(), 1.0);Sourcepub fn scale(&mut self, factor: f64)
pub fn scale(&mut self, factor: f64)
Scales the width and height of self while keeping the center fixed.
The bounding box is scaled by multiplying its width and height by the factor and then recalculating the extremas by adding / subtracting half the width / height from the center.
§Examples
use bounding_box::BoundingBox;
let mut bb = BoundingBox::new(0.0, 1.0, 2.0, 4.0);
assert_eq!(bb.center(), [0.5, 3.0]);
assert_eq!(bb.width(), 1.0);
assert_eq!(bb.height(), 2.0);
bb.scale(2.0);
assert_eq!(bb.center(), [0.5, 3.0]);
assert_eq!(bb.width(), 2.0);
assert_eq!(bb.height(), 4.0);
assert_eq!(bb.xmin(), -0.5);
assert_eq!(bb.xmax(), 1.5);
assert_eq!(bb.ymin(), 1.0);
assert_eq!(bb.ymax(), 5.0);Sourcepub fn remove_singular_dimensions(&mut self, add_to_extr: f64)
pub fn remove_singular_dimensions(&mut self, add_to_extr: f64)
Remove any singular dimensions by “buffering” them with add_to_extr.
The value add_to_extr is applied to both the minimum and the maximum value of a singular dimension.
For example, if the bounding box width is 0 (xmin = xmax) and add_to_extr = 1.0, the new width will be 2.0.
§Examples
use bounding_box::BoundingBox;
let mut bb = BoundingBox::new(0.0, 0.0, -1.0, 1.0);
assert_eq!(bb.width(), 0.0);
bb.remove_singular_dimensions(1.0);
assert_eq!(bb.width(), 2.0);
assert_eq!(bb.xmin(), -1.0);
assert_eq!(bb.xmax(), 1.0);
// =================================================
let mut bb = BoundingBox::new(-1.0, 1.0, 2.0, 2.0);
assert_eq!(bb.height(), 0.0);
bb.remove_singular_dimensions(3.0);
assert_eq!(bb.height(), 6.0);
assert_eq!(bb.ymin(), -1.0);
assert_eq!(bb.ymax(), 5.0);Trait Implementations§
Source§impl Clone for BoundingBox
impl Clone for BoundingBox
Source§fn clone(&self) -> BoundingBox
fn clone(&self) -> BoundingBox
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more