rust/integral-geometry/src/lib.rs
branchui-scaling
changeset 15288 c4fd2813b127
parent 15220 13041ae61ac5
child 15291 16bd389fc735
equal deleted inserted replaced
13395:0135e64c6c66 15288:c4fd2813b127
       
     1 use fpnum::{fp, integral_sqrt, FPNum, FPPoint};
       
     2 use std::{
       
     3     cmp::{max, min},
       
     4     ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, RangeInclusive, Sub, SubAssign},
       
     5 };
       
     6 
       
     7 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
       
     8 pub struct Point {
       
     9     pub x: i32,
       
    10     pub y: i32,
       
    11 }
       
    12 
       
    13 impl Point {
       
    14     pub const ZERO: Self = Self::new(0, 0);
       
    15 
       
    16     #[inline]
       
    17     pub const fn new(x: i32, y: i32) -> Self {
       
    18         Self { x, y }
       
    19     }
       
    20 
       
    21     #[inline]
       
    22     pub const fn diag(v: i32) -> Self {
       
    23         Self::new(v, v)
       
    24     }
       
    25 
       
    26     #[inline]
       
    27     pub fn signum(self) -> Self {
       
    28         Self::new(self.x.signum(), self.y.signum())
       
    29     }
       
    30 
       
    31     #[inline]
       
    32     pub fn abs(self) -> Self {
       
    33         Self::new(self.x.abs(), self.y.abs())
       
    34     }
       
    35 
       
    36     #[inline]
       
    37     pub const fn dot(self, other: Point) -> i32 {
       
    38         self.x * other.x + self.y * other.y
       
    39     }
       
    40 
       
    41     #[inline]
       
    42     pub fn max_norm(self) -> i32 {
       
    43         std::cmp::max(self.x.abs(), self.y.abs())
       
    44     }
       
    45 
       
    46     #[inline]
       
    47     pub fn integral_norm(self) -> u32 {
       
    48         let sqr = (self.x as u64).pow(2) + (self.y as u64).pow(2);
       
    49         integral_sqrt(sqr) as u32
       
    50     }
       
    51 
       
    52     #[inline]
       
    53     pub const fn transform(self, matrix: &[i32; 4]) -> Self {
       
    54         Point::new(
       
    55             matrix[0] * self.x + matrix[1] * self.y,
       
    56             matrix[2] * self.x + matrix[3] * self.y,
       
    57         )
       
    58     }
       
    59 
       
    60     #[inline]
       
    61     pub const fn rotate90(self) -> Self {
       
    62         Point::new(self.y, -self.x)
       
    63     }
       
    64 
       
    65     #[inline]
       
    66     pub const fn cross(self, other: Point) -> i32 {
       
    67         self.dot(other.rotate90())
       
    68     }
       
    69 
       
    70     #[inline]
       
    71     pub fn clamp(self, rect: &Rect) -> Point {
       
    72         Point::new(rect.x_range().clamp(self.x), rect.y_range().clamp(self.y))
       
    73     }
       
    74 
       
    75     #[inline]
       
    76     pub const fn line_to(self, end: Point) -> Line {
       
    77         Line::new(self, end)
       
    78     }
       
    79 
       
    80     #[inline]
       
    81     pub const fn ray_with_dir(self, direction: Point) -> Ray {
       
    82         Ray::new(self, direction)
       
    83     }
       
    84 
       
    85     #[inline]
       
    86     pub const fn tangent_mul(self, x: i32) -> i32 {
       
    87         x * self.y / self.x
       
    88     }
       
    89 
       
    90     #[inline]
       
    91     pub const fn cotangent_mul(self, y: i32) -> i32 {
       
    92         y * self.x / self.y
       
    93     }
       
    94 
       
    95     #[inline]
       
    96     pub fn to_fppoint(self) -> FPPoint {
       
    97         FPPoint::new(self.x.into(), self.y.into())
       
    98     }
       
    99 
       
   100     #[inline]
       
   101     pub fn from_fppoint(p: &FPPoint) -> Self {
       
   102         Self::new(p.x().round(), p.y().round())
       
   103     }
       
   104 }
       
   105 
       
   106 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
       
   107 pub struct Size {
       
   108     pub width: usize,
       
   109     pub height: usize,
       
   110 }
       
   111 
       
   112 impl Size {
       
   113     pub const EMPTY: Self = Self::square(0);
       
   114 
       
   115     #[inline]
       
   116     pub const fn new(width: usize, height: usize) -> Self {
       
   117         Self { width, height }
       
   118     }
       
   119 
       
   120     #[inline]
       
   121     pub const fn square(size: usize) -> Self {
       
   122         Self {
       
   123             width: size,
       
   124             height: size,
       
   125         }
       
   126     }
       
   127 
       
   128     #[inline]
       
   129     pub const fn area(&self) -> usize {
       
   130         self.width * self.height
       
   131     }
       
   132 
       
   133     #[inline]
       
   134     pub const fn linear_index(&self, x: usize, y: usize) -> usize {
       
   135         y * self.width + x
       
   136     }
       
   137 
       
   138     #[inline]
       
   139     pub fn is_power_of_two(&self) -> bool {
       
   140         self.width.is_power_of_two() && self.height.is_power_of_two()
       
   141     }
       
   142 
       
   143     #[inline]
       
   144     pub fn next_power_of_two(&self) -> Self {
       
   145         Self {
       
   146             width: self.width.next_power_of_two(),
       
   147             height: self.height.next_power_of_two(),
       
   148         }
       
   149     }
       
   150 
       
   151     #[inline]
       
   152     pub const fn transpose(&self) -> Self {
       
   153         Self::new(self.height, self.width)
       
   154     }
       
   155 
       
   156     #[inline]
       
   157     pub fn to_mask(&self) -> SizeMask {
       
   158         SizeMask::new(*self)
       
   159     }
       
   160 
       
   161     #[inline]
       
   162     pub fn to_square(&self) -> Self {
       
   163         Self::square(max(self.width, self.height))
       
   164     }
       
   165 
       
   166     pub fn to_grid_index(&self) -> GridIndex {
       
   167         GridIndex::new(*self)
       
   168     }
       
   169 
       
   170     #[inline]
       
   171     pub fn contains(&self, other: Self) -> bool {
       
   172         self.width >= other.width && self.height >= other.height
       
   173     }
       
   174 }
       
   175 
       
   176 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
       
   177 pub struct SizeMask {
       
   178     size: Size,
       
   179 }
       
   180 
       
   181 impl SizeMask {
       
   182     #[inline]
       
   183     pub fn new(size: Size) -> Self {
       
   184         debug_assert!(size.is_power_of_two());
       
   185         let size = Size {
       
   186             width: !(size.width - 1),
       
   187             height: !(size.height - 1),
       
   188         };
       
   189         Self { size }
       
   190     }
       
   191 
       
   192     #[inline]
       
   193     pub fn contains_x<T: Into<usize>>(&self, x: T) -> bool {
       
   194         (self.size.width & x.into()) == 0
       
   195     }
       
   196 
       
   197     #[inline]
       
   198     pub fn contains_y<T: Into<usize>>(&self, y: T) -> bool {
       
   199         (self.size.height & y.into()) == 0
       
   200     }
       
   201 
       
   202     #[inline]
       
   203     pub fn contains(&self, point: Point) -> bool {
       
   204         self.contains_x(point.x as usize) && self.contains_y(point.y as usize)
       
   205     }
       
   206 }
       
   207 
       
   208 pub struct GridIndex {
       
   209     shift: Point,
       
   210 }
       
   211 
       
   212 impl GridIndex {
       
   213     pub fn new(size: Size) -> Self {
       
   214         assert!(size.is_power_of_two());
       
   215         let shift = Point::new(
       
   216             size.width.trailing_zeros() as i32,
       
   217             size.height.trailing_zeros() as i32,
       
   218         );
       
   219         Self { shift }
       
   220     }
       
   221 
       
   222     pub fn map(&self, position: Point) -> Point {
       
   223         Point::new(position.x >> self.shift.x, position.y >> self.shift.y)
       
   224     }
       
   225 }
       
   226 
       
   227 macro_rules! bin_op_impl {
       
   228     ($op: ty, $name: tt) => {
       
   229         impl $op for Point {
       
   230             type Output = Self;
       
   231 
       
   232             #[inline]
       
   233             fn $name(self, rhs: Self) -> Self::Output {
       
   234                 Self::new(self.x.$name(rhs.x), self.y.$name(rhs.y))
       
   235             }
       
   236         }
       
   237     };
       
   238 }
       
   239 
       
   240 macro_rules! scalar_bin_op_impl {
       
   241     ($($op: tt)::+, $name: tt) => {
       
   242         impl $($op)::+<i32> for Point {
       
   243             type Output = Self;
       
   244 
       
   245             #[inline]
       
   246             fn $name(self, rhs: i32) -> Self::Output {
       
   247                 Self::new(self.x.$name(rhs), self.y.$name(rhs))
       
   248             }
       
   249         }
       
   250     };
       
   251 }
       
   252 
       
   253 macro_rules! bin_assign_op_impl {
       
   254     ($op: ty, $name: tt) => {
       
   255         impl $op for Point {
       
   256             #[inline]
       
   257             fn $name(&mut self, rhs: Self) {
       
   258                 self.x.$name(rhs.x);
       
   259                 self.y.$name(rhs.y);
       
   260             }
       
   261         }
       
   262     };
       
   263 }
       
   264 
       
   265 macro_rules! fp_scalar_bin_op_impl {
       
   266     ($($op: tt)::+, $name: tt) => {
       
   267         impl $($op)::+<FPNum> for Point {
       
   268             type Output = FPPoint;
       
   269 
       
   270             #[inline]
       
   271             fn $name(self, rhs: FPNum) -> Self::Output {
       
   272                 FPPoint::new(rhs.$name(self.x), rhs.$name(self.y))
       
   273             }
       
   274         }
       
   275     };
       
   276 }
       
   277 
       
   278 macro_rules! left_fp_scalar_bin_op_impl {
       
   279     ($($op: tt)::+, $name: tt) => {
       
   280         impl $($op)::+<Point> for FPNum {
       
   281             type Output = FPPoint;
       
   282 
       
   283             #[inline]
       
   284             fn $name(self, rhs: Point) -> Self::Output {
       
   285                 FPPoint::new(self.$name(rhs.x), self.$name(rhs.y))
       
   286             }
       
   287         }
       
   288     };
       
   289 }
       
   290 
       
   291 bin_op_impl!(Add, add);
       
   292 bin_op_impl!(Sub, sub);
       
   293 bin_op_impl!(Mul, mul);
       
   294 bin_op_impl!(Div, div);
       
   295 scalar_bin_op_impl!(Mul, mul);
       
   296 scalar_bin_op_impl!(Div, div);
       
   297 fp_scalar_bin_op_impl!(Mul, mul);
       
   298 fp_scalar_bin_op_impl!(Div, div);
       
   299 left_fp_scalar_bin_op_impl!(Mul, mul);
       
   300 left_fp_scalar_bin_op_impl!(Div, div);
       
   301 bin_assign_op_impl!(AddAssign, add_assign);
       
   302 bin_assign_op_impl!(SubAssign, sub_assign);
       
   303 bin_assign_op_impl!(MulAssign, mul_assign);
       
   304 bin_assign_op_impl!(DivAssign, div_assign);
       
   305 
       
   306 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
       
   307 pub struct Rect {
       
   308     top_left: Point,
       
   309     bottom_right: Point,
       
   310 }
       
   311 
       
   312 impl Rect {
       
   313     pub const EMPTY: Self = Self {
       
   314         top_left: Point::ZERO,
       
   315         bottom_right: Point::diag(-1),
       
   316     };
       
   317 
       
   318     #[inline]
       
   319     pub fn new(top_left: Point, bottom_right: Point) -> Self {
       
   320         debug_assert!(top_left.x <= bottom_right.x + 1);
       
   321         debug_assert!(top_left.y <= bottom_right.y + 1);
       
   322         Self {
       
   323             top_left,
       
   324             bottom_right,
       
   325         }
       
   326     }
       
   327 
       
   328     pub fn from_box(left: i32, right: i32, top: i32, bottom: i32) -> Self {
       
   329         Self::new(Point::new(left, top), Point::new(right, bottom))
       
   330     }
       
   331 
       
   332     pub fn from_size(top_left: Point, size: Size) -> Self {
       
   333         Self::new(
       
   334             top_left,
       
   335             top_left + Point::new(size.width as i32 - 1, size.height as i32 - 1),
       
   336         )
       
   337     }
       
   338 
       
   339     pub fn from_size_coords(x: i32, y: i32, width: usize, height: usize) -> Self {
       
   340         Self::from_size(Point::new(x, y), Size::new(width, height))
       
   341     }
       
   342 
       
   343     pub fn at_origin(size: Size) -> Self {
       
   344         Self::from_size(Point::ZERO, size)
       
   345     }
       
   346 
       
   347     #[inline]
       
   348     pub const fn width(&self) -> usize {
       
   349         (self.right() - self.left() + 1) as usize
       
   350     }
       
   351 
       
   352     #[inline]
       
   353     pub const fn height(&self) -> usize {
       
   354         (self.bottom() - self.top() + 1) as usize
       
   355     }
       
   356 
       
   357     #[inline]
       
   358     pub const fn size(&self) -> Size {
       
   359         Size::new(self.width(), self.height())
       
   360     }
       
   361 
       
   362     #[inline]
       
   363     pub const fn area(&self) -> usize {
       
   364         self.size().area()
       
   365     }
       
   366 
       
   367     #[inline]
       
   368     pub const fn left(&self) -> i32 {
       
   369         self.top_left().x
       
   370     }
       
   371 
       
   372     #[inline]
       
   373     pub const fn top(&self) -> i32 {
       
   374         self.top_left().y
       
   375     }
       
   376 
       
   377     #[inline]
       
   378     pub const fn right(&self) -> i32 {
       
   379         self.bottom_right().x
       
   380     }
       
   381 
       
   382     #[inline]
       
   383     pub const fn bottom(&self) -> i32 {
       
   384         self.bottom_right().y
       
   385     }
       
   386 
       
   387     #[inline]
       
   388     pub const fn top_left(&self) -> Point {
       
   389         self.top_left
       
   390     }
       
   391 
       
   392     #[inline]
       
   393     pub const fn bottom_right(&self) -> Point {
       
   394         self.bottom_right
       
   395     }
       
   396 
       
   397     #[inline]
       
   398     pub fn center(&self) -> Point {
       
   399         (self.top_left() + self.bottom_right()) / 2
       
   400     }
       
   401 
       
   402     #[inline]
       
   403     pub fn with_margin(&self, margin: i32) -> Self {
       
   404         let offset = Point::diag(margin);
       
   405         Self::new(self.top_left() + offset, self.bottom_right() - offset)
       
   406     }
       
   407 
       
   408     #[inline]
       
   409     pub fn x_range(&self) -> RangeInclusive<i32> {
       
   410         self.left()..=self.right()
       
   411     }
       
   412 
       
   413     #[inline]
       
   414     pub fn y_range(&self) -> RangeInclusive<i32> {
       
   415         self.top()..=self.bottom()
       
   416     }
       
   417 
       
   418     #[inline]
       
   419     pub fn contains(&self, point: Point) -> bool {
       
   420         self.x_range().contains(&point.x) && self.y_range().contains(&point.y)
       
   421     }
       
   422 
       
   423     #[inline]
       
   424     pub fn contains_inside(&self, point: Point) -> bool {
       
   425         point.x > self.left()
       
   426             && point.x < self.right()
       
   427             && point.y > self.top()
       
   428             && point.y < self.bottom()
       
   429     }
       
   430 
       
   431     #[inline]
       
   432     pub fn contains_rect(&self, other: &Self) -> bool {
       
   433         self.contains(other.top_left()) && self.contains(other.bottom_right())
       
   434     }
       
   435 
       
   436     #[inline]
       
   437     pub fn intersects(&self, other: &Rect) -> bool {
       
   438         self.left() <= other.right()
       
   439             && self.right() >= other.left()
       
   440             && self.top() <= other.bottom()
       
   441             && self.bottom() >= other.top()
       
   442     }
       
   443 
       
   444     #[inline]
       
   445     pub fn split_at(&self, point: Point) -> [Rect; 4] {
       
   446         assert!(self.contains_inside(point));
       
   447         [
       
   448             Self::from_box(self.left(), point.x, self.top(), point.y),
       
   449             Self::from_box(point.x, self.right(), self.top(), point.y),
       
   450             Self::from_box(point.x, self.right(), point.y, self.bottom()),
       
   451             Self::from_box(self.left(), point.x, point.y, self.bottom()),
       
   452         ]
       
   453     }
       
   454 
       
   455     #[inline]
       
   456     pub fn with_margins(&self, left: i32, right: i32, top: i32, bottom: i32) -> Self {
       
   457         Self::from_box(
       
   458             self.left() - left,
       
   459             self.right() + right,
       
   460             self.top() - top,
       
   461             self.bottom() + bottom,
       
   462         )
       
   463     }
       
   464 
       
   465     #[inline]
       
   466     pub fn quotient(self, x: usize, y: usize) -> Point {
       
   467         self.top_left() + Point::new((x % self.width()) as i32, (y % self.height()) as i32)
       
   468     }
       
   469 }
       
   470 
       
   471 trait RangeClamp<T> {
       
   472     fn clamp(&self, value: T) -> T;
       
   473 }
       
   474 
       
   475 impl<T: Ord + Copy> RangeClamp<T> for RangeInclusive<T> {
       
   476     fn clamp(&self, value: T) -> T {
       
   477         if value < *self.start() {
       
   478             *self.start()
       
   479         } else if value > *self.end() {
       
   480             *self.end()
       
   481         } else {
       
   482             value
       
   483         }
       
   484     }
       
   485 }
       
   486 
       
   487 pub struct Polygon {
       
   488     vertices: Vec<Point>,
       
   489 }
       
   490 
       
   491 impl Polygon {
       
   492     pub fn new(vertices: &[Point]) -> Self {
       
   493         let mut v = Vec::with_capacity(vertices.len() + 1);
       
   494         v.extend_from_slice(vertices);
       
   495         if !v.is_empty() {
       
   496             let start = v[0];
       
   497             v.push(start);
       
   498         }
       
   499         Self { vertices: v }
       
   500     }
       
   501 
       
   502     pub fn edges_count(&self) -> usize {
       
   503         self.vertices.len().saturating_sub(1)
       
   504     }
       
   505 
       
   506     pub fn get_edge(&self, index: usize) -> Line {
       
   507         Line::new(self.vertices[index], self.vertices[index + 1])
       
   508     }
       
   509 
       
   510     pub fn split_edge(&mut self, edge_index: usize, vertex: Point) {
       
   511         self.vertices.insert(edge_index + 1, vertex);
       
   512     }
       
   513 
       
   514     pub fn iter<'a>(&'a self) -> impl Iterator<Item = &Point> + 'a {
       
   515         (&self.vertices[..self.edges_count()]).iter()
       
   516     }
       
   517 
       
   518     pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &mut Point> + 'a {
       
   519         let edges_count = self.edges_count();
       
   520         let start = self.vertices.as_mut_ptr();
       
   521         let end = unsafe { start.add(edges_count) };
       
   522         PolygonPointsIteratorMut {
       
   523             source: self,
       
   524             start,
       
   525             end,
       
   526         }
       
   527     }
       
   528 
       
   529     fn force_close(&mut self) {
       
   530         if !self.vertices.is_empty() {
       
   531             let edges_count = self.edges_count();
       
   532             self.vertices[edges_count] = self.vertices[0];
       
   533         }
       
   534     }
       
   535 
       
   536     pub fn iter_edges<'a>(&'a self) -> impl Iterator<Item = Line> + 'a {
       
   537         (&self.vertices[0..self.edges_count()])
       
   538             .iter()
       
   539             .zip(&self.vertices[1..])
       
   540             .map(|(s, e)| Line::new(*s, *e))
       
   541     }
       
   542 
       
   543     pub fn bezierize(&mut self, segments_number: u32) {
       
   544         fn calc_point(p1: Point, p2: Point, p3: Point) -> FPPoint {
       
   545             let diff13 = (p1 - p3).to_fppoint();
       
   546             let diff13_norm = diff13.distance();
       
   547 
       
   548             if diff13_norm.is_zero() {
       
   549                 diff13
       
   550             } else {
       
   551                 let diff12_norm = (p1 - p2).to_fppoint().distance();
       
   552                 let diff23_norm = (p2 - p3).to_fppoint().distance();
       
   553                 let min_distance = min(diff13_norm, min(diff12_norm, diff23_norm));
       
   554 
       
   555                 diff13 * min_distance / diff13_norm / 3
       
   556             }
       
   557         }
       
   558 
       
   559         if self.vertices.len() < 4 {
       
   560             return;
       
   561         }
       
   562 
       
   563         let delta = fp!(1 / segments_number);
       
   564         let mut bezierized_vertices = Vec::new();
       
   565         let mut pi = 0;
       
   566         let mut i = 1;
       
   567         let mut ni = 2;
       
   568         let mut right_point = calc_point(self.vertices[pi], self.vertices[i], self.vertices[ni]);
       
   569         let mut left_point;
       
   570 
       
   571         pi += 1;
       
   572         while pi != 0 {
       
   573             pi = i;
       
   574             i = ni;
       
   575             ni += 1;
       
   576             if ni >= self.vertices.len() {
       
   577                 ni = 0;
       
   578             }
       
   579 
       
   580             left_point = right_point;
       
   581             right_point = calc_point(self.vertices[pi], self.vertices[i], self.vertices[ni]);
       
   582 
       
   583             bezierized_vertices.extend(BezierCurveSegments::new(
       
   584                 Line::new(self.vertices[pi], self.vertices[i]),
       
   585                 left_point,
       
   586                 -right_point,
       
   587                 delta,
       
   588             ));
       
   589         }
       
   590 
       
   591         self.vertices = bezierized_vertices;
       
   592     }
       
   593 }
       
   594 
       
   595 struct PolygonPointsIteratorMut<'a> {
       
   596     source: &'a mut Polygon,
       
   597     start: *mut Point,
       
   598     end: *mut Point,
       
   599 }
       
   600 
       
   601 impl<'a> Iterator for PolygonPointsIteratorMut<'a> {
       
   602     type Item = &'a mut Point;
       
   603 
       
   604     fn next(&mut self) -> Option<<Self as Iterator>::Item> {
       
   605         if self.start == self.end {
       
   606             None
       
   607         } else {
       
   608             unsafe {
       
   609                 let result = &mut *self.start;
       
   610                 self.start = self.start.add(1);
       
   611                 Some(result)
       
   612             }
       
   613         }
       
   614     }
       
   615 }
       
   616 
       
   617 impl<'a> Drop for PolygonPointsIteratorMut<'a> {
       
   618     fn drop(&mut self) {
       
   619         self.source.force_close();
       
   620     }
       
   621 }
       
   622 
       
   623 impl From<Vec<Point>> for Polygon {
       
   624     fn from(mut v: Vec<Point>) -> Self {
       
   625         if !v.is_empty() && v[0] != v[v.len() - 1] {
       
   626             let start = v[0];
       
   627             v.push(start)
       
   628         }
       
   629         Self { vertices: v }
       
   630     }
       
   631 }
       
   632 
       
   633 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
       
   634 pub struct Ray {
       
   635     pub start: Point,
       
   636     pub direction: Point,
       
   637 }
       
   638 
       
   639 impl Ray {
       
   640     #[inline]
       
   641     pub const fn new(start: Point, direction: Point) -> Ray {
       
   642         Self { start, direction }
       
   643     }
       
   644 
       
   645     #[inline]
       
   646     pub const fn tangent_mul(&self, x: i32) -> i32 {
       
   647         self.direction.tangent_mul(x)
       
   648     }
       
   649 
       
   650     #[inline]
       
   651     pub const fn cotangent_mul(&self, y: i32) -> i32 {
       
   652         self.direction.cotangent_mul(y)
       
   653     }
       
   654 
       
   655     #[inline]
       
   656     pub fn orientation(&self, point: Point) -> i32 {
       
   657         (point - self.start).cross(self.direction).signum()
       
   658     }
       
   659 }
       
   660 
       
   661 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
       
   662 pub struct Line {
       
   663     pub start: Point,
       
   664     pub end: Point,
       
   665 }
       
   666 
       
   667 impl Line {
       
   668     pub const ZERO: Self = Self::new(Point::ZERO, Point::ZERO);
       
   669 
       
   670     #[inline]
       
   671     pub const fn new(start: Point, end: Point) -> Self {
       
   672         Self { start, end }
       
   673     }
       
   674 
       
   675     #[inline]
       
   676     pub fn center(&self) -> Point {
       
   677         (self.start + self.end) / 2
       
   678     }
       
   679 
       
   680     #[inline]
       
   681     pub fn scaled_direction(&self) -> Point {
       
   682         self.end - self.start
       
   683     }
       
   684 
       
   685     #[inline]
       
   686     pub fn scaled_normal(&self) -> Point {
       
   687         self.scaled_direction().rotate90()
       
   688     }
       
   689 
       
   690     #[inline]
       
   691     pub fn to_ray(&self) -> Ray {
       
   692         Ray::new(self.start, self.scaled_direction())
       
   693     }
       
   694 }
       
   695 
       
   696 impl IntoIterator for Line {
       
   697     type Item = Point;
       
   698     type IntoIter = LinePoints;
       
   699 
       
   700     fn into_iter(self) -> Self::IntoIter {
       
   701         LinePoints::new(self)
       
   702     }
       
   703 }
       
   704 
       
   705 pub struct LinePoints {
       
   706     accumulator: Point,
       
   707     direction: Point,
       
   708     sign: Point,
       
   709     current: Point,
       
   710     total_steps: i32,
       
   711     step: i32,
       
   712 }
       
   713 
       
   714 impl LinePoints {
       
   715     pub fn new(line: Line) -> Self {
       
   716         let dir = line.end - line.start;
       
   717 
       
   718         Self {
       
   719             accumulator: Point::ZERO,
       
   720             direction: dir.abs(),
       
   721             sign: dir.signum(),
       
   722             current: line.start,
       
   723             total_steps: dir.max_norm(),
       
   724             step: 0,
       
   725         }
       
   726     }
       
   727 }
       
   728 
       
   729 impl Iterator for LinePoints {
       
   730     type Item = Point;
       
   731 
       
   732     fn next(&mut self) -> Option<Self::Item> {
       
   733         if self.step <= self.total_steps {
       
   734             self.accumulator += self.direction;
       
   735 
       
   736             if self.accumulator.x > self.total_steps {
       
   737                 self.accumulator.x -= self.total_steps;
       
   738                 self.current.x += self.sign.x;
       
   739             }
       
   740             if self.accumulator.y > self.total_steps {
       
   741                 self.accumulator.y -= self.total_steps;
       
   742                 self.current.y += self.sign.y;
       
   743             }
       
   744 
       
   745             self.step += 1;
       
   746 
       
   747             Some(self.current)
       
   748         } else {
       
   749             None
       
   750         }
       
   751     }
       
   752 }
       
   753 
       
   754 pub struct ArcPoints {
       
   755     point: Point,
       
   756     step: i32,
       
   757 }
       
   758 
       
   759 impl ArcPoints {
       
   760     pub const fn new(radius: i32) -> Self {
       
   761         Self {
       
   762             point: Point::new(0, radius),
       
   763             step: 3 - 2 * radius,
       
   764         }
       
   765     }
       
   766 }
       
   767 
       
   768 impl Iterator for ArcPoints {
       
   769     type Item = Point;
       
   770 
       
   771     fn next(&mut self) -> Option<Self::Item> {
       
   772         if self.point.x < self.point.y {
       
   773             let result = self.point;
       
   774 
       
   775             if self.step < 0 {
       
   776                 self.step += self.point.x * 4 + 6;
       
   777             } else {
       
   778                 self.step += (self.point.x - self.point.y) * 4 + 10;
       
   779                 self.point.y -= 1;
       
   780             }
       
   781 
       
   782             self.point.x += 1;
       
   783 
       
   784             Some(result)
       
   785         } else if self.point.x == self.point.y {
       
   786             self.point.x += 1;
       
   787 
       
   788             Some(self.point)
       
   789         } else {
       
   790             None
       
   791         }
       
   792     }
       
   793 }
       
   794 
       
   795 pub struct EquidistantPoints {
       
   796     vector: Vec<Point>,
       
   797 }
       
   798 
       
   799 impl EquidistantPoints {
       
   800     pub fn new(vector: Point) -> Self {
       
   801         Self {
       
   802             vector: if vector.x == vector.y {
       
   803                 vec![
       
   804                     Point::new(vector.x, vector.x),
       
   805                     Point::new(vector.x, -vector.x),
       
   806                     Point::new(-vector.x, -vector.x),
       
   807                     Point::new(-vector.x, vector.x),
       
   808                 ]
       
   809             } else {
       
   810                 vec![
       
   811                     Point::new(vector.x, vector.y),
       
   812                     Point::new(vector.x, -vector.y),
       
   813                     Point::new(-vector.x, -vector.y),
       
   814                     Point::new(-vector.x, vector.y),
       
   815                     Point::new(vector.y, vector.x),
       
   816                     Point::new(vector.y, -vector.x),
       
   817                     Point::new(-vector.y, -vector.x),
       
   818                     Point::new(-vector.y, vector.x),
       
   819                 ]
       
   820             },
       
   821         }
       
   822     }
       
   823 }
       
   824 
       
   825 impl IntoIterator for EquidistantPoints {
       
   826     type Item = Point;
       
   827     type IntoIter = std::vec::IntoIter<Point>;
       
   828 
       
   829     fn into_iter(self) -> Self::IntoIter {
       
   830         self.vector.into_iter()
       
   831     }
       
   832 }
       
   833 
       
   834 pub struct BezierCurveSegments {
       
   835     segment: Line,
       
   836     control_point1: FPPoint,
       
   837     control_point2: FPPoint,
       
   838     offset: FPNum,
       
   839     max_offset: FPNum,
       
   840     delta: FPNum,
       
   841     have_finished: bool,
       
   842 }
       
   843 
       
   844 impl BezierCurveSegments {
       
   845     pub fn new(segment: Line, p1: FPPoint, p2: FPPoint, delta: FPNum) -> Self {
       
   846         Self {
       
   847             segment,
       
   848             control_point1: segment.start.to_fppoint() - p1,
       
   849             control_point2: segment.end.to_fppoint() - p2,
       
   850             offset: fp!(0),
       
   851             max_offset: fp!(4095 / 4096),
       
   852             delta,
       
   853             have_finished: false,
       
   854         }
       
   855     }
       
   856 }
       
   857 
       
   858 impl Iterator for BezierCurveSegments {
       
   859     type Item = Point;
       
   860 
       
   861     fn next(&mut self) -> Option<Self::Item> {
       
   862         if self.offset < self.max_offset {
       
   863             let offset_sq = self.offset * self.offset;
       
   864             let offset_cub = offset_sq * self.offset;
       
   865 
       
   866             let r1 = fp!(1) - self.offset * 3 + offset_sq * 3 - offset_cub;
       
   867             let r2 = self.offset * 3 - offset_sq * 6 + offset_cub * 3;
       
   868             let r3 = offset_sq * 3 - offset_cub * 3;
       
   869 
       
   870             let p = r1 * self.segment.start
       
   871                 + r2 * self.control_point1
       
   872                 + r3 * self.control_point2
       
   873                 + offset_cub * self.segment.end;
       
   874 
       
   875             self.offset += self.delta;
       
   876 
       
   877             Some(Point::from_fppoint(&p))
       
   878         } else if !self.have_finished {
       
   879             self.have_finished = true;
       
   880 
       
   881             Some(self.segment.end)
       
   882         } else {
       
   883             None
       
   884         }
       
   885     }
       
   886 }
       
   887 
       
   888 #[cfg(test)]
       
   889 mod tests {
       
   890     use super::*;
       
   891 
       
   892     fn get_points(coords: &[(i32, i32)]) -> Vec<Point> {
       
   893         coords.iter().map(|(x, y)| Point::new(*x, *y)).collect()
       
   894     }
       
   895 
       
   896     #[test]
       
   897     fn line_basic() {
       
   898         let line: Vec<Point> = Line::new(Point::new(0, 0), Point::new(3, 3))
       
   899             .into_iter()
       
   900             .collect();
       
   901         let v = get_points(&[(0, 0), (1, 1), (2, 2), (3, 3)]);
       
   902 
       
   903         assert_eq!(line, v);
       
   904     }
       
   905 
       
   906     #[test]
       
   907     fn line_skewed() {
       
   908         let line: Vec<Point> = Line::new(Point::new(0, 0), Point::new(5, -7))
       
   909             .into_iter()
       
   910             .collect();
       
   911         let v = get_points(&[
       
   912             (0, 0),
       
   913             (1, -1),
       
   914             (2, -2),
       
   915             (2, -3),
       
   916             (3, -4),
       
   917             (4, -5),
       
   918             (4, -6),
       
   919             (5, -7),
       
   920         ]);
       
   921 
       
   922         assert_eq!(line, v);
       
   923     }
       
   924 
       
   925     #[test]
       
   926     fn equidistant_full() {
       
   927         let n: Vec<Point> = EquidistantPoints::new(Point::new(1, 3))
       
   928             .into_iter()
       
   929             .collect();
       
   930         let v = get_points(&[
       
   931             (1, 3),
       
   932             (1, -3),
       
   933             (-1, -3),
       
   934             (-1, 3),
       
   935             (3, 1),
       
   936             (3, -1),
       
   937             (-3, -1),
       
   938             (-3, 1),
       
   939         ]);
       
   940 
       
   941         assert_eq!(n, v);
       
   942     }
       
   943 
       
   944     #[test]
       
   945     fn equidistant_half() {
       
   946         let n: Vec<Point> = EquidistantPoints::new(Point::new(2, 2))
       
   947             .into_iter()
       
   948             .collect();
       
   949         let v = get_points(&[(2, 2), (2, -2), (-2, -2), (-2, 2)]);
       
   950 
       
   951         assert_eq!(n, v);
       
   952     }
       
   953 
       
   954     #[test]
       
   955     fn line() {
       
   956         let l = Line::new(Point::new(1, 1), Point::new(5, 6));
       
   957 
       
   958         assert_eq!(l.center(), Point::new(3, 3));
       
   959     }
       
   960 
       
   961     #[test]
       
   962     fn rect() {
       
   963         let r = Rect::from_box(10, 100, 0, 70);
       
   964 
       
   965         assert!(r.contains_inside(Point::new(99, 69)));
       
   966         assert!(!r.contains_inside(Point::new(100, 70)));
       
   967 
       
   968         assert_eq!(r.top_left(), Point::new(10, 0));
       
   969         assert_eq!(r.with_margin(12), Rect::from_box(22, 88, 12, 58));
       
   970     }
       
   971 
       
   972     #[test]
       
   973     fn fit() {
       
   974         let r = Rect::from_box(10, 100, 0, 70);
       
   975 
       
   976         assert_eq!(Point::new(0, -10).clamp(&r), Point::new(10, 0));
       
   977         assert_eq!(Point::new(1000, 1000).clamp(&r), Point::new(100, 70));
       
   978     }
       
   979 }