rust/integral-geometry/src/lib.rs
changeset 14627 2e2b31cf0871
parent 14208 87f1054c2333
child 14717 16024046d458
equal deleted inserted replaced
14626:ab6be7d200b0 14627:2e2b31cf0871
     1 use fpnum::{distance, FPNum, FPPoint, fp};
     1 use fpnum::{distance, fp, FPNum, FPPoint};
     2 use std::{
     2 use std::{
     3     cmp::{max, min},
     3     cmp::{max, min},
     4     ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign},
     4     ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign},
     5 };
     5 };
     6 
     6 
     9     pub x: i32,
     9     pub x: i32,
    10     pub y: i32,
    10     pub y: i32,
    11 }
    11 }
    12 
    12 
    13 impl Point {
    13 impl Point {
    14     #[inline]
    14     pub const ZERO: Self = Self::new(0, 0);
    15     pub fn new(x: i32, y: i32) -> Self {
    15 
       
    16     #[inline]
       
    17     pub const fn new(x: i32, y: i32) -> Self {
    16         Self { x, y }
    18         Self { x, y }
    17     }
    19     }
    18 
    20 
    19     #[inline]
    21     #[inline]
    20     pub fn diag(v: i32) -> Self {
    22     pub const fn diag(v: i32) -> Self {
    21         Self::new(v, v)
    23         Self::new(v, v)
    22     }
       
    23 
       
    24     #[inline]
       
    25     pub fn zero() -> Self {
       
    26         Self::new(0, 0)
       
    27     }
    24     }
    28 
    25 
    29     #[inline]
    26     #[inline]
    30     pub fn signum(self) -> Self {
    27     pub fn signum(self) -> Self {
    31         Self::new(self.x.signum(), self.y.signum())
    28         Self::new(self.x.signum(), self.y.signum())
    35     pub fn abs(self) -> Self {
    32     pub fn abs(self) -> Self {
    36         Self::new(self.x.abs(), self.y.abs())
    33         Self::new(self.x.abs(), self.y.abs())
    37     }
    34     }
    38 
    35 
    39     #[inline]
    36     #[inline]
    40     pub fn dot(self, other: Point) -> i32 {
    37     pub const fn dot(self, other: Point) -> i32 {
    41         self.x * other.x + self.y * other.y
    38         self.x * other.x + self.y * other.y
    42     }
    39     }
    43 
    40 
    44     #[inline]
    41     #[inline]
    45     pub fn max_norm(self) -> i32 {
    42     pub fn max_norm(self) -> i32 {
    50     pub fn integral_norm(self) -> u32 {
    47     pub fn integral_norm(self) -> u32 {
    51         distance(self.x, self.y).abs_round()
    48         distance(self.x, self.y).abs_round()
    52     }
    49     }
    53 
    50 
    54     #[inline]
    51     #[inline]
    55     pub fn transform(self, matrix: &[i32; 4]) -> Self {
    52     pub const fn transform(self, matrix: &[i32; 4]) -> Self {
    56         Point::new(
    53         Point::new(
    57             matrix[0] * self.x + matrix[1] * self.y,
    54             matrix[0] * self.x + matrix[1] * self.y,
    58             matrix[2] * self.x + matrix[3] * self.y,
    55             matrix[2] * self.x + matrix[3] * self.y,
    59         )
    56         )
    60     }
    57     }
    61 
    58 
    62     #[inline]
    59     #[inline]
    63     pub fn rotate90(self) -> Self {
    60     pub const fn rotate90(self) -> Self {
    64         Point::new(self.y, -self.x)
    61         Point::new(self.y, -self.x)
    65     }
    62     }
    66 
    63 
    67     #[inline]
    64     #[inline]
    68     pub fn cross(self, other: Point) -> i32 {
    65     pub const fn cross(self, other: Point) -> i32 {
    69         self.dot(other.rotate90())
    66         self.dot(other.rotate90())
    70     }
    67     }
    71 
    68 
    72     #[inline]
    69     #[inline]
    73     pub fn clamp(self, rect: &Rect) -> Point {
    70     pub fn clamp(self, rect: &Rect) -> Point {
    74         Point::new(rect.x_range().clamp(self.x), rect.y_range().clamp(self.y))
    71         Point::new(rect.x_range().clamp(self.x), rect.y_range().clamp(self.y))
    75     }
    72     }
    76 
    73 
    77     #[inline]
    74     #[inline]
    78     pub fn line_to(self, end: Point) -> Line {
    75     pub const fn line_to(self, end: Point) -> Line {
    79         Line::new(self, end)
    76         Line::new(self, end)
    80     }
    77     }
    81 
    78 
    82     #[inline]
    79     #[inline]
    83     pub fn ray_with_dir(self, direction: Point) -> Ray {
    80     pub const fn ray_with_dir(self, direction: Point) -> Ray {
    84         Ray::new(self, direction)
    81         Ray::new(self, direction)
    85     }
    82     }
    86 
    83 
    87     #[inline]
    84     #[inline]
    88     pub fn tangent_mul(self, x: i32) -> i32 {
    85     pub const fn tangent_mul(self, x: i32) -> i32 {
    89         x * self.y / self.x
    86         x * self.y / self.x
    90     }
    87     }
    91 
    88 
    92     #[inline]
    89     #[inline]
    93     pub fn cotangent_mul(self, y: i32) -> i32 {
    90     pub const fn cotangent_mul(self, y: i32) -> i32 {
    94         y * self.x / self.y
    91         y * self.x / self.y
    95     }
    92     }
    96 
    93 
    97     #[inline]
    94     #[inline]
    98     pub fn to_fppoint(self) -> FPPoint {
    95     pub fn to_fppoint(self) -> FPPoint {
   111     pub height: usize,
   108     pub height: usize,
   112 }
   109 }
   113 
   110 
   114 impl Size {
   111 impl Size {
   115     #[inline]
   112     #[inline]
   116     pub fn new(width: usize, height: usize) -> Self {
   113     pub const fn new(width: usize, height: usize) -> Self {
   117         Size { width, height }
   114         Self { width, height }
   118     }
   115     }
   119 
   116 
   120     #[inline]
   117     #[inline]
   121     pub fn square(size: usize) -> Self {
   118     pub const fn square(size: usize) -> Self {
   122         Size {
   119         Self {
   123             width: size,
   120             width: size,
   124             height: size,
   121             height: size,
   125         }
   122         }
   126     }
   123     }
   127 
   124 
   128     #[inline]
   125     #[inline]
   129     pub fn area(&self) -> usize {
   126     pub const fn area(&self) -> usize {
   130         self.width * self.height
   127         self.width * self.height
   131     }
   128     }
   132 
   129 
   133     #[inline]
   130     #[inline]
   134     pub fn linear_index(&self, x: usize, y: usize) -> usize {
   131     pub const fn linear_index(&self, x: usize, y: usize) -> usize {
   135         y * self.width + x
   132         y * self.width + x
   136     }
   133     }
   137 
   134 
   138     #[inline]
   135     #[inline]
   139     pub fn is_power_of_two(&self) -> bool {
   136     pub fn is_power_of_two(&self) -> bool {
   147             height: self.height.next_power_of_two(),
   144             height: self.height.next_power_of_two(),
   148         }
   145         }
   149     }
   146     }
   150 
   147 
   151     #[inline]
   148     #[inline]
   152     pub fn transpose(&self) -> Self {
   149     pub const fn transpose(&self) -> Self {
   153         Self::new(self.height, self.width)
   150         Self::new(self.height, self.width)
   154     }
   151     }
   155 
   152 
   156     #[inline]
   153     #[inline]
   157     pub fn to_mask(&self) -> SizeMask {
   154     pub fn to_mask(&self) -> SizeMask {
   158         SizeMask::new(*self)
   155         SizeMask::new(*self)
   159     }
   156     }
   160 
   157 
   161     #[inline]
   158     #[inline]
   162     pub fn to_square(&self) -> Size {
   159     pub fn to_square(&self) -> Self {
   163         Size::square(max(self.width, self.height))
   160         Self::square(max(self.width, self.height))
   164     }
   161     }
   165 
   162 
   166     pub fn to_grid_index(&self) -> GridIndex {
   163     pub fn to_grid_index(&self) -> GridIndex {
   167         GridIndex::new(*self)
   164         GridIndex::new(*self)
   168     }
   165     }
   174 }
   171 }
   175 
   172 
   176 impl SizeMask {
   173 impl SizeMask {
   177     #[inline]
   174     #[inline]
   178     pub fn new(size: Size) -> Self {
   175     pub fn new(size: Size) -> Self {
   179         assert!(size.is_power_of_two());
   176         debug_assert!(size.is_power_of_two());
   180         let size = Size {
   177         let size = Size {
   181             width: !(size.width - 1),
   178             width: !(size.width - 1),
   182             height: !(size.height - 1),
   179             height: !(size.height - 1),
   183         };
   180         };
   184         Self { size }
   181         Self { size }
   305 }
   302 }
   306 
   303 
   307 impl Rect {
   304 impl Rect {
   308     #[inline]
   305     #[inline]
   309     pub fn new(top_left: Point, bottom_right: Point) -> Self {
   306     pub fn new(top_left: Point, bottom_right: Point) -> Self {
   310         assert!(top_left.x <= bottom_right.x + 1);
   307         debug_assert!(top_left.x <= bottom_right.x + 1);
   311         assert!(top_left.y <= bottom_right.y + 1);
   308         debug_assert!(top_left.y <= bottom_right.y + 1);
   312         Self {
   309         Self {
   313             top_left,
   310             top_left,
   314             bottom_right,
   311             bottom_right,
   315         }
   312         }
   316     }
   313     }
   329     pub fn from_size_coords(x: i32, y: i32, width: usize, height: usize) -> Self {
   326     pub fn from_size_coords(x: i32, y: i32, width: usize, height: usize) -> Self {
   330         Self::from_size(Point::new(x, y), Size::new(width, height))
   327         Self::from_size(Point::new(x, y), Size::new(width, height))
   331     }
   328     }
   332 
   329 
   333     pub fn at_origin(size: Size) -> Self {
   330     pub fn at_origin(size: Size) -> Self {
   334         Self::from_size(Point::zero(), size)
   331         Self::from_size(Point::ZERO, size)
   335     }
   332     }
   336 
   333 
   337     #[inline]
   334     #[inline]
   338     pub fn width(&self) -> usize {
   335     pub const fn width(&self) -> usize {
   339         (self.right() - self.left() + 1) as usize
   336         (self.right() - self.left() + 1) as usize
   340     }
   337     }
   341 
   338 
   342     #[inline]
   339     #[inline]
   343     pub fn height(&self) -> usize {
   340     pub const fn height(&self) -> usize {
   344         (self.bottom() - self.top() + 1) as usize
   341         (self.bottom() - self.top() + 1) as usize
   345     }
   342     }
   346 
   343 
   347     #[inline]
   344     #[inline]
   348     pub fn size(&self) -> Size {
   345     pub const fn size(&self) -> Size {
   349         Size::new(self.width(), self.height())
   346         Size::new(self.width(), self.height())
   350     }
   347     }
   351 
   348 
   352     #[inline]
   349     #[inline]
   353     pub fn area(&self) -> usize {
   350     pub const fn area(&self) -> usize {
   354         self.size().area()
   351         self.size().area()
   355     }
   352     }
   356 
   353 
   357     #[inline]
   354     #[inline]
   358     pub fn left(&self) -> i32 {
   355     pub const fn left(&self) -> i32 {
   359         self.top_left().x
   356         self.top_left().x
   360     }
   357     }
   361 
   358 
   362     #[inline]
   359     #[inline]
   363     pub fn top(&self) -> i32 {
   360     pub const fn top(&self) -> i32 {
   364         self.top_left().y
   361         self.top_left().y
   365     }
   362     }
   366 
   363 
   367     #[inline]
   364     #[inline]
   368     pub fn right(&self) -> i32 {
   365     pub const fn right(&self) -> i32 {
   369         self.bottom_right().x
   366         self.bottom_right().x
   370     }
   367     }
   371 
   368 
   372     #[inline]
   369     #[inline]
   373     pub fn bottom(&self) -> i32 {
   370     pub const fn bottom(&self) -> i32 {
   374         self.bottom_right().y
   371         self.bottom_right().y
   375     }
   372     }
   376 
   373 
   377     #[inline]
   374     #[inline]
   378     pub fn top_left(&self) -> Point {
   375     pub const fn top_left(&self) -> Point {
   379         self.top_left
   376         self.top_left
   380     }
   377     }
   381 
   378 
   382     #[inline]
   379     #[inline]
   383     pub fn bottom_right(&self) -> Point {
   380     pub const fn bottom_right(&self) -> Point {
   384         self.bottom_right
   381         self.bottom_right
   385     }
   382     }
   386 
   383 
   387     #[inline]
   384     #[inline]
   388     pub fn center(&self) -> Point {
   385     pub fn center(&self) -> Point {
   627     pub direction: Point,
   624     pub direction: Point,
   628 }
   625 }
   629 
   626 
   630 impl Ray {
   627 impl Ray {
   631     #[inline]
   628     #[inline]
   632     pub fn new(start: Point, direction: Point) -> Ray {
   629     pub const fn new(start: Point, direction: Point) -> Ray {
   633         Self { start, direction }
   630         Self { start, direction }
   634     }
   631     }
   635 
   632 
   636     #[inline]
   633     #[inline]
   637     pub fn tangent_mul(&self, x: i32) -> i32 {
   634     pub const fn tangent_mul(&self, x: i32) -> i32 {
   638         self.direction.tangent_mul(x)
   635         self.direction.tangent_mul(x)
   639     }
   636     }
   640 
   637 
   641     #[inline]
   638     #[inline]
   642     pub fn cotangent_mul(&self, y: i32) -> i32 {
   639     pub const fn cotangent_mul(&self, y: i32) -> i32 {
   643         self.direction.cotangent_mul(y)
   640         self.direction.cotangent_mul(y)
   644     }
   641     }
   645 
   642 
   646     #[inline]
   643     #[inline]
   647     pub fn orientation(&self, point: Point) -> i32 {
   644     pub fn orientation(&self, point: Point) -> i32 {
   654     pub start: Point,
   651     pub start: Point,
   655     pub end: Point,
   652     pub end: Point,
   656 }
   653 }
   657 
   654 
   658 impl Line {
   655 impl Line {
   659     #[inline]
   656     pub const ZERO: Self = Self::new(Point::ZERO, Point::ZERO);
   660     pub fn new(start: Point, end: Point) -> Self {
   657 
       
   658     #[inline]
       
   659     pub const fn new(start: Point, end: Point) -> Self {
   661         Self { start, end }
   660         Self { start, end }
   662     }
       
   663 
       
   664     #[inline]
       
   665     pub fn zero() -> Self {
       
   666         Self::new(Point::zero(), Point::zero())
       
   667     }
   661     }
   668 
   662 
   669     #[inline]
   663     #[inline]
   670     pub fn center(&self) -> Point {
   664     pub fn center(&self) -> Point {
   671         (self.start + self.end) / 2
   665         (self.start + self.end) / 2
   708 impl LinePoints {
   702 impl LinePoints {
   709     pub fn new(line: Line) -> Self {
   703     pub fn new(line: Line) -> Self {
   710         let dir = line.end - line.start;
   704         let dir = line.end - line.start;
   711 
   705 
   712         Self {
   706         Self {
   713             accumulator: Point::zero(),
   707             accumulator: Point::ZERO,
   714             direction: dir.abs(),
   708             direction: dir.abs(),
   715             sign: dir.signum(),
   709             sign: dir.signum(),
   716             current: line.start,
   710             current: line.start,
   717             total_steps: dir.max_norm(),
   711             total_steps: dir.max_norm(),
   718             step: 0,
   712             step: 0,
   749     point: Point,
   743     point: Point,
   750     step: i32,
   744     step: i32,
   751 }
   745 }
   752 
   746 
   753 impl ArcPoints {
   747 impl ArcPoints {
   754     pub fn new(radius: i32) -> Self {
   748     pub const fn new(radius: i32) -> Self {
   755         Self {
   749         Self {
   756             point: Point::new(0, radius),
   750             point: Point::new(0, radius),
   757             step: 3 - 2 * radius,
   751             step: 3 - 2 * radius,
   758         }
   752         }
   759     }
   753     }