rust/integral-geometry/src/lib.rs
changeset 15850 44b49f255e31
parent 15773 a4558e2be08c
child 15948 9bd828451d77
child 16010 5ba4d3a0c3eb
equal deleted inserted replaced
15849:64b0a5cead86 15850:44b49f255e31
   139     pub const fn is_power_of_two(&self) -> bool {
   139     pub const fn is_power_of_two(&self) -> bool {
   140         self.width.is_power_of_two() && self.height.is_power_of_two()
   140         self.width.is_power_of_two() && self.height.is_power_of_two()
   141     }
   141     }
   142 
   142 
   143     #[inline]
   143     #[inline]
   144     pub fn next_power_of_two(&self) -> Self {
   144     pub const fn as_power_of_two(&self) -> Option<PotSize> {
   145         Self {
   145         PotSize::new(self.width, self.height)
   146             width: self.width.next_power_of_two(),
   146     }
   147             height: self.height.next_power_of_two(),
   147 
   148         }
   148     #[inline]
       
   149     pub const fn next_power_of_two(&self) -> PotSize {
       
   150         PotSize::new_impl(
       
   151             self.width.next_power_of_two(),
       
   152             self.height.next_power_of_two(),
       
   153         )
   149     }
   154     }
   150 
   155 
   151     #[inline]
   156     #[inline]
   152     pub const fn transpose(&self) -> Self {
   157     pub const fn transpose(&self) -> Self {
   153         Self::new(self.height, self.width)
   158         Self::new(self.height, self.width)
   154     }
   159     }
   155 
   160 
   156     #[inline]
   161     #[inline]
   157     pub fn to_mask(&self) -> SizeMask {
       
   158         SizeMask::new(*self)
       
   159     }
       
   160 
       
   161     #[inline]
       
   162     pub fn to_square(&self) -> Self {
   162     pub fn to_square(&self) -> Self {
   163         Self::square(max(self.width, self.height))
   163         Self::square(max(self.width, self.height))
   164     }
   164     }
   165 
   165 
   166     pub fn to_grid_index(&self) -> GridIndex {
       
   167         GridIndex::new(*self)
       
   168     }
       
   169 
       
   170     #[inline]
   166     #[inline]
   171     pub const fn contains(&self, other: Self) -> bool {
   167     pub const fn contains(&self, other: Self) -> bool {
   172         self.width >= other.width && self.height >= other.height
   168         self.width >= other.width && self.height >= other.height
   173     }
   169     }
   174 
   170 
   175     #[inline]
   171     #[inline]
   176     pub fn join(&self, other: Self) -> Self {
   172     pub fn join(&self, other: Self) -> Self {
       
   173         Self::new(max(self.width, other.width), max(self.height, other.height))
       
   174     }
       
   175 }
       
   176 
       
   177 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
       
   178 pub struct PotSize {
       
   179     size: Size,
       
   180 }
       
   181 
       
   182 impl PotSize {
       
   183     #[inline]
       
   184     const fn new_impl(width: usize, height: usize) -> Self {
       
   185         debug_assert!(width.is_power_of_two() && height.is_power_of_two());
   177         Self {
   186         Self {
   178             width: max(self.width, other.width),
   187             size: Size::new(width, height),
   179             height: max(self.height, other.height)
   188         }
   180         }
   189     }
       
   190 
       
   191     #[inline]
       
   192     pub const fn new(width: usize, height: usize) -> Option<Self> {
       
   193         if width.is_power_of_two() && height.is_power_of_two() {
       
   194             Some(Self::new_impl(width, height))
       
   195         } else {
       
   196             None
       
   197         }
       
   198     }
       
   199 
       
   200     pub const fn size(&self) -> Size {
       
   201         self.size
       
   202     }
       
   203 
       
   204     pub const fn width(&self) -> usize {
       
   205         self.size.width
       
   206     }
       
   207 
       
   208     pub const fn height(&self) -> usize {
       
   209         self.size.height
       
   210     }
       
   211 
       
   212     #[inline]
       
   213     pub const fn square(size: usize) -> Option<Self> {
       
   214         if size.is_power_of_two() {
       
   215             Some(Self::new_impl(size, size))
       
   216         } else {
       
   217             None
       
   218         }
       
   219     }
       
   220 
       
   221     #[inline]
       
   222     pub const fn area(&self) -> usize {
       
   223         self.size.area()
       
   224     }
       
   225 
       
   226     #[inline]
       
   227     pub const fn linear_index(&self, x: usize, y: usize) -> usize {
       
   228         self.size.linear_index(x, y)
       
   229     }
       
   230 
       
   231     #[inline]
       
   232     pub const fn transpose(&self) -> Self {
       
   233         Self::new_impl(self.height(), self.width())
       
   234     }
       
   235 
       
   236     #[inline]
       
   237     pub fn to_square(&self) -> Self {
       
   238         let size = max(self.width(), self.height());
       
   239         Self::new_impl(size, size)
       
   240     }
       
   241 
       
   242     #[inline]
       
   243     pub const fn to_mask(&self) -> SizeMask {
       
   244         SizeMask::new(*self)
       
   245     }
       
   246 
       
   247     pub const fn to_grid_index(&self) -> GridIndex {
       
   248         GridIndex::new(*self)
       
   249     }
       
   250 
       
   251     #[inline]
       
   252     pub const fn contains(&self, other: Self) -> bool {
       
   253         self.size.contains(other.size)
       
   254     }
       
   255 
       
   256     #[inline]
       
   257     pub fn join(&self, other: Self) -> Self {
       
   258         Self::new_impl(
       
   259             max(self.width(), other.width()),
       
   260             max(self.height(), other.height()),
       
   261         )
   181     }
   262     }
   182 }
   263 }
   183 
   264 
   184 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
   265 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
   185 pub struct SizeMask {
   266 pub struct SizeMask {
   186     size: Size,
   267     size: Size,
   187 }
   268 }
   188 
   269 
   189 impl SizeMask {
   270 impl SizeMask {
   190     #[inline]
   271     #[inline]
   191     pub fn new(size: Size) -> Self {
   272     pub const fn new(size: PotSize) -> Self {
   192         debug_assert!(size.is_power_of_two());
   273         Self {
   193         let size = Size {
   274             size: Size::new(!(size.width() - 1), !(size.height() - 1)),
   194             width: !(size.width - 1),
   275         }
   195             height: !(size.height - 1),
       
   196         };
       
   197         Self { size }
       
   198     }
   276     }
   199 
   277 
   200     #[inline]
   278     #[inline]
   201     pub fn contains_x<T: Into<usize>>(&self, x: T) -> bool {
   279     pub fn contains_x<T: Into<usize>>(&self, x: T) -> bool {
   202         (self.size.width & x.into()) == 0
   280         (self.size.width & x.into()) == 0
   209 
   287 
   210     #[inline]
   288     #[inline]
   211     pub fn contains(&self, point: Point) -> bool {
   289     pub fn contains(&self, point: Point) -> bool {
   212         self.contains_x(point.x as usize) && self.contains_y(point.y as usize)
   290         self.contains_x(point.x as usize) && self.contains_y(point.y as usize)
   213     }
   291     }
       
   292 
       
   293     #[inline]
       
   294     pub const fn to_size(&self) -> PotSize {
       
   295         PotSize::new_impl(!self.size.width + 1, !self.size.height + 1)
       
   296     }
   214 }
   297 }
   215 
   298 
   216 pub struct GridIndex {
   299 pub struct GridIndex {
   217     shift: Point,
   300     shift: Point,
   218 }
   301 }
   219 
   302 
   220 impl GridIndex {
   303 impl GridIndex {
   221     pub fn new(size: Size) -> Self {
   304     pub const fn new(size: PotSize) -> Self {
   222         debug_assert!(size.is_power_of_two());
       
   223         let shift = Point::new(
   305         let shift = Point::new(
   224             size.width.trailing_zeros() as i32,
   306             size.width().trailing_zeros() as i32,
   225             size.height.trailing_zeros() as i32,
   307             size.height().trailing_zeros() as i32,
   226         );
   308         );
   227         Self { shift }
   309         Self { shift }
   228     }
   310     }
   229 
   311 
   230     pub const fn map(&self, position: Point) -> Point {
   312     pub const fn map(&self, position: Point) -> Point {
   322         top_left: Point::ZERO,
   404         top_left: Point::ZERO,
   323         bottom_right: Point::diag(-1),
   405         bottom_right: Point::diag(-1),
   324     };
   406     };
   325 
   407 
   326     #[inline]
   408     #[inline]
   327     pub fn new(top_left: Point, bottom_right: Point) -> Self {
   409     pub const fn new(top_left: Point, bottom_right: Point) -> Self {
   328         debug_assert!(top_left.x <= bottom_right.x + 1);
   410         debug_assert!(top_left.x <= bottom_right.x + 1);
   329         debug_assert!(top_left.y <= bottom_right.y + 1);
   411         debug_assert!(top_left.y <= bottom_right.y + 1);
   330         Self {
   412         Self {
   331             top_left,
   413             top_left,
   332             bottom_right,
   414             bottom_right,
   333         }
   415         }
   334     }
   416     }
   335 
   417 
   336     pub fn from_box(left: i32, right: i32, top: i32, bottom: i32) -> Self {
   418     pub const fn from_box(left: i32, right: i32, top: i32, bottom: i32) -> Self {
   337         Self::new(Point::new(left, top), Point::new(right, bottom))
   419         Self::new(Point::new(left, top), Point::new(right, bottom))
   338     }
   420     }
   339 
   421 
   340     pub fn from_size(top_left: Point, size: Size) -> Self {
   422     pub fn from_size(top_left: Point, size: Size) -> Self {
   341         Self::new(
   423         Self::new(
   448             && self.top() <= other.bottom()
   530             && self.top() <= other.bottom()
   449             && self.bottom() >= other.top()
   531             && self.bottom() >= other.top()
   450     }
   532     }
   451 
   533 
   452     #[inline]
   534     #[inline]
   453     pub fn split_at(&self, point: Point) -> [Rect; 4] {
   535     pub const fn split_at(&self, point: Point) -> [Rect; 4] {
   454         debug_assert!(self.contains_inside(point));
   536         debug_assert!(self.contains_inside(point));
   455         [
   537         [
   456             Self::from_box(self.left(), point.x, self.top(), point.y),
   538             Self::from_box(self.left(), point.x, self.top(), point.y),
   457             Self::from_box(point.x, self.right(), self.top(), point.y),
   539             Self::from_box(point.x, self.right(), self.top(), point.y),
   458             Self::from_box(point.x, self.right(), point.y, self.bottom()),
   540             Self::from_box(point.x, self.right(), point.y, self.bottom()),
   459             Self::from_box(self.left(), point.x, point.y, self.bottom()),
   541             Self::from_box(self.left(), point.x, point.y, self.bottom()),
   460         ]
   542         ]
   461     }
   543     }
   462 
   544 
   463     #[inline]
   545     #[inline]
   464     pub fn with_margins(&self, left: i32, right: i32, top: i32, bottom: i32) -> Self {
   546     pub const fn with_margins(&self, left: i32, right: i32, top: i32, bottom: i32) -> Self {
   465         Self::from_box(
   547         Self::from_box(
   466             self.left() - left,
   548             self.left() - left,
   467             self.right() + right,
   549             self.right() + right,
   468             self.top() - top,
   550             self.top() - top,
   469             self.bottom() + bottom,
   551             self.bottom() + bottom,