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
ToBoundingBox
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.
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_vertices<'a, T: Into<[f64; 2]>, I: Iterator<Item = T>>(
verts: I,
) -> Option<Self>
pub fn from_vertices<'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_vertices(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<'a, T: ToBoundingBox + ?Sized + 'a, I: Iterator<Item = &'a T>>(
entities: I,
) -> Option<Self>
pub fn from_bounded_entities<'a, T: ToBoundingBox + ?Sized + 'a, I: Iterator<Item = &'a T>>( entities: I, ) -> Option<Self>
Creates a bounding box from an iterator over any types implementing ToBoundingBox
.
If the iterator is empty, this function returns None
.
use bounding_box::{BoundingBox, ToBoundingBox};
struct Circle {
center: [f64; 2],
radius: f64
}
impl ToBoundingBox for Circle {
fn bounding_box(&self) -> BoundingBox {
return BoundingBox::new(self.center[0] - self.radius,
self.center[0] + self.radius,
self.center[1] - self.radius,
self.center[1] + self.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 contains 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 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 also seen as included if it is located on the edge of a bounding box.
§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]));
assert!(bb.contains_point([0.0, 0.0]));
assert!(!bb.contains_point([-1.0, 0.0]));
assert!(!bb.contains_point([0.0, 2.0]));
Sourcepub fn approx_contains_point<T: Into<[f64; 2]>>(
&self,
point: T,
epsilon: f64,
max_ulps: u32,
) -> bool
pub fn approx_contains_point<T: Into<[f64; 2]>>( &self, point: T, epsilon: f64, max_ulps: u32, ) -> bool
Like BoundingBox::contains_point
, but with absolute and ULPs tolerances.
This variant of BoundingBox::contains_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.
This check is performed using the ulps_eq
macro of the approx crate. Please see its documentation.
§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.contains_point([1.0001, 1.0]));
// Check using tolerances: Point is inside bounding box
assert!(bb.approx_contains_point([1.0001, 1.0], 1e-3, 0));
// Check using a finer tolerance: Point is outside the bounding box
assert!(!bb.approx_contains_point([1.0001, 1.0], 1e-6, 0));
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 the latter can be placed inside the former. This is true even if the boxes share some extremums. This also means that a bounding box always contains itself (see examples).
§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 contains 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 of 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_contains(&self, other: &Self, epsilon: f64, max_ulps: u32) -> bool
pub fn approx_contains(&self, other: &Self, epsilon: f64, max_ulps: u32) -> bool
Like BoundingBox::contains
, but with absolute and ULPs tolerances.
This variant of BoundingBox::contains
allows specifying an absolute and
an ULP tolerance. These tolerances
are used to check if the extremas of the boxes are “approximately” equal.
This check is performed using the ulps_eq
macro of the approx crate. Please see its documentation.
use bounding_box::BoundingBox;
// bb1 contains 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.contains(&bb2));
assert!(bb1.approx_contains(&bb2, 1e-3, 0));
assert!(!bb1.approx_contains(&bb2, 1e-6, 0));
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. Please see its documentation.
use bounding_box::BoundingBox;
// bb1 contains 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));
Sourcepub fn intersects(&self, other: &Self) -> bool
pub fn intersects(&self, other: &Self) -> bool
Returns true if the bounding boxes intersect.
The boxes are NOT 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 => 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.intersects(&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));
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