rust/integral-geometry/src/lib.rs
changeset 16073 5d302b12d837
parent 16052 6633961698ad
equal deleted inserted replaced
16072:a4cbc6926439 16073:5d302b12d837
   111     }
   111     }
   112 }
   112 }
   113 
   113 
   114 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
   114 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
   115 pub struct Size {
   115 pub struct Size {
   116     pub width: usize,
   116     pub width: u32,
   117     pub height: usize,
   117     pub height: u32,
   118 }
   118 }
   119 
   119 
   120 impl Size {
   120 impl Size {
   121     pub const EMPTY: Self = Self::square(0);
   121     pub const EMPTY: Self = Self::square(0);
   122 
   122 
   123     #[inline]
   123     #[inline]
   124     pub const fn new(width: usize, height: usize) -> Self {
   124     pub const fn new(width: u32, height: u32) -> Self {
   125         Self { width, height }
   125         Self { width, height }
   126     }
   126     }
   127 
   127 
   128     #[inline]
   128     #[inline]
   129     pub const fn square(size: usize) -> Self {
   129     pub const fn square(size: u32) -> Self {
   130         Self {
   130         Self {
   131             width: size,
   131             width: size,
   132             height: size,
   132             height: size,
   133         }
   133         }
   134     }
   134     }
   135 
   135 
   136     #[inline]
   136     #[inline]
   137     pub const fn area(&self) -> usize {
   137     pub const fn area(&self) -> u32 {
   138         self.width * self.height
   138         self.width * self.height
   139     }
   139     }
   140 
   140 
   141     #[inline]
   141     #[inline]
   142     pub const fn linear_index(&self, x: usize, y: usize) -> usize {
   142     pub const fn linear_index(&self, x: u32, y: u32) -> u32 {
   143         y * self.width + x
   143         y * self.width + x
   144     }
   144     }
   145 
   145 
   146     #[inline]
   146     #[inline]
   147     pub const fn is_power_of_two(&self) -> bool {
   147     pub const fn is_power_of_two(&self) -> bool {
   192     size: Size,
   192     size: Size,
   193 }
   193 }
   194 
   194 
   195 impl PotSize {
   195 impl PotSize {
   196     #[inline]
   196     #[inline]
   197     const fn new_impl(width: usize, height: usize) -> Self {
   197     const fn new_impl(width: u32, height: u32) -> Self {
   198         debug_assert!(width.is_power_of_two() && height.is_power_of_two());
   198         debug_assert!(width.is_power_of_two() && height.is_power_of_two());
   199         Self {
   199         Self {
   200             size: Size::new(width, height),
   200             size: Size::new(width, height),
   201         }
   201         }
   202     }
   202     }
   203 
   203 
   204     #[inline]
   204     #[inline]
   205     pub const fn new(width: usize, height: usize) -> Option<Self> {
   205     pub const fn new(width: u32, height: u32) -> Option<Self> {
   206         if width.is_power_of_two() && height.is_power_of_two() {
   206         if width.is_power_of_two() && height.is_power_of_two() {
   207             Some(Self::new_impl(width, height))
   207             Some(Self::new_impl(width, height))
   208         } else {
   208         } else {
   209             None
   209             None
   210         }
   210         }
   212 
   212 
   213     pub const fn size(&self) -> Size {
   213     pub const fn size(&self) -> Size {
   214         self.size
   214         self.size
   215     }
   215     }
   216 
   216 
   217     pub const fn width(&self) -> usize {
   217     pub const fn width(&self) -> u32 {
   218         self.size.width
   218         self.size.width
   219     }
   219     }
   220 
   220 
   221     pub const fn height(&self) -> usize {
   221     pub const fn height(&self) -> u32 {
   222         self.size.height
   222         self.size.height
   223     }
   223     }
   224 
   224 
   225     #[inline]
   225     #[inline]
   226     pub const fn square(size: usize) -> Option<Self> {
   226     pub const fn square(size: u32) -> Option<Self> {
   227         if size.is_power_of_two() {
   227         if size.is_power_of_two() {
   228             Some(Self::new_impl(size, size))
   228             Some(Self::new_impl(size, size))
   229         } else {
   229         } else {
   230             None
   230             None
   231         }
   231         }
   232     }
   232     }
   233 
   233 
   234     #[inline]
   234     #[inline]
   235     pub const fn area(&self) -> usize {
   235     pub const fn area(&self) -> u32 {
   236         self.size.area()
   236         self.size.area()
   237     }
   237     }
   238 
   238 
   239     #[inline]
   239     #[inline]
   240     pub const fn linear_index(&self, x: usize, y: usize) -> usize {
   240     pub const fn linear_index(&self, x: u32, y: u32) -> u32 {
   241         self.size.linear_index(x, y)
   241         self.size.linear_index(x, y)
   242     }
   242     }
   243 
   243 
   244     #[inline]
   244     #[inline]
   245     pub const fn transpose(&self) -> Self {
   245     pub const fn transpose(&self) -> Self {
   287             size: Size::new(!(size.width() - 1), !(size.height() - 1)),
   287             size: Size::new(!(size.width() - 1), !(size.height() - 1)),
   288         }
   288         }
   289     }
   289     }
   290 
   290 
   291     #[inline]
   291     #[inline]
   292     pub fn contains_x<T: Into<usize>>(&self, x: T) -> bool {
   292     pub fn contains_x<T: Into<u32>>(&self, x: T) -> bool {
   293         (self.size.width & x.into()) == 0
   293         (self.size.width & x.into()) == 0
   294     }
   294     }
   295 
   295 
   296     #[inline]
   296     #[inline]
   297     pub fn contains_y<T: Into<usize>>(&self, y: T) -> bool {
   297     pub fn contains_y<T: Into<u32>>(&self, y: T) -> bool {
   298         (self.size.height & y.into()) == 0
   298         (self.size.height & y.into()) == 0
   299     }
   299     }
   300 
   300 
   301     #[inline]
   301     #[inline]
   302     pub fn contains(&self, point: Point) -> bool {
   302     pub fn contains(&self, point: Point) -> bool {
   303         self.contains_x(point.x as usize) && self.contains_y(point.y as usize)
   303         self.contains_x(point.x as u32) && self.contains_y(point.y as u32)
   304     }
   304     }
   305 
   305 
   306     #[inline]
   306     #[inline]
   307     pub const fn to_size(&self) -> PotSize {
   307     pub const fn to_size(&self) -> PotSize {
   308         PotSize::new_impl(!self.size.width + 1, !self.size.height + 1)
   308         PotSize::new_impl(!self.size.width + 1, !self.size.height + 1)
   437             top_left,
   437             top_left,
   438             top_left + Point::new(size.width as i32 - 1, size.height as i32 - 1),
   438             top_left + Point::new(size.width as i32 - 1, size.height as i32 - 1),
   439         )
   439         )
   440     }
   440     }
   441 
   441 
   442     pub fn from_size_coords(x: i32, y: i32, width: usize, height: usize) -> Self {
   442     pub fn from_size_coords(x: i32, y: i32, width: u32, height: u32) -> Self {
   443         Self::from_size(Point::new(x, y), Size::new(width, height))
   443         Self::from_size(Point::new(x, y), Size::new(width, height))
   444     }
   444     }
   445 
   445 
   446     pub fn at_origin(size: Size) -> Self {
   446     pub fn at_origin(size: Size) -> Self {
   447         Self::from_size(Point::ZERO, size)
   447         Self::from_size(Point::ZERO, size)
   448     }
   448     }
   449 
   449 
   450     #[inline]
   450     #[inline]
   451     pub const fn width(&self) -> usize {
   451     pub const fn width(&self) -> u32 {
   452         (self.right() - self.left() + 1) as usize
   452         (self.right() - self.left() + 1) as u32
   453     }
   453     }
   454 
   454 
   455     #[inline]
   455     #[inline]
   456     pub const fn height(&self) -> usize {
   456     pub const fn height(&self) -> u32 {
   457         (self.bottom() - self.top() + 1) as usize
   457         (self.bottom() - self.top() + 1) as u32
   458     }
   458     }
   459 
   459 
   460     #[inline]
   460     #[inline]
   461     pub const fn size(&self) -> Size {
   461     pub const fn size(&self) -> Size {
   462         Size::new(self.width(), self.height())
   462         Size::new(self.width(), self.height())
   463     }
   463     }
   464 
   464 
   465     #[inline]
   465     #[inline]
   466     pub const fn area(&self) -> usize {
   466     pub const fn area(&self) -> u32 {
   467         self.size().area()
   467         self.size().area()
   468     }
   468     }
   469 
   469 
   470     #[inline]
   470     #[inline]
   471     pub const fn left(&self) -> i32 {
   471     pub const fn left(&self) -> i32 {
   502         (self.top_left() + self.bottom_right()) / 2
   502         (self.top_left() + self.bottom_right()) / 2
   503     }
   503     }
   504 
   504 
   505     #[inline]
   505     #[inline]
   506     pub fn with_margin(&self, margin: i32) -> Self {
   506     pub fn with_margin(&self, margin: i32) -> Self {
   507         let offset = Point::new(min(margin, self.width() as i32 / 2), min(margin, self.height() as i32 / 2));
   507         let offset = Point::new(
       
   508             min(margin, self.width() as i32 / 2),
       
   509             min(margin, self.height() as i32 / 2),
       
   510         );
   508         Self::new(self.top_left() + offset, self.bottom_right() - offset)
   511         Self::new(self.top_left() + offset, self.bottom_right() - offset)
   509     }
   512     }
   510 
   513 
   511     #[inline]
   514     #[inline]
   512     pub const fn x_range(&self) -> RangeInclusive<i32> {
   515     pub const fn x_range(&self) -> RangeInclusive<i32> {
   564             self.bottom() + bottom,
   567             self.bottom() + bottom,
   565         )
   568         )
   566     }
   569     }
   567 
   570 
   568     #[inline]
   571     #[inline]
   569     pub fn quotient(self, x: usize, y: usize) -> Point {
   572     pub fn quotient(self, x: u32, y: u32) -> Point {
   570         self.top_left() + Point::new((x % self.width()) as i32, (y % self.height()) as i32)
   573         self.top_left() + Point::new((x % self.width()) as i32, (y % self.height()) as i32)
   571     }
   574     }
   572 }
   575 }
   573 
   576 
   574 trait RangeClamp<T> {
   577 trait RangeClamp<T> {