rust/integral-geometry/src/lib.rs
changeset 14140 3078123e84ea
parent 14139 37c99587825d
child 14141 477faa7b8a48
equal deleted inserted replaced
14139:37c99587825d 14140:3078123e84ea
     1 #[macro_use]
     1 #[macro_use]
     2 extern crate fpnum;
     2 extern crate fpnum;
     3 
     3 
     4 use fpnum::{distance, FPNum, FPPoint};
     4 use fpnum::{distance, FPNum, FPPoint};
     5 use std::{
     5 use std::{
     6     cmp::max,
     6     cmp::{max, min},
     7     ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign}
     7     ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign},
     8 };
     8 };
     9 
     9 
    10 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
    10 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
    11 pub struct Point {
    11 pub struct Point {
    12     pub x: i32,
    12     pub x: i32,
    72         self.dot(other.rotate90())
    72         self.dot(other.rotate90())
    73     }
    73     }
    74 
    74 
    75     #[inline]
    75     #[inline]
    76     pub fn clamp(self, rect: &Rect) -> Point {
    76     pub fn clamp(self, rect: &Rect) -> Point {
    77         Point::new(
    77         Point::new(rect.x_range().clamp(self.x), rect.y_range().clamp(self.y))
    78             rect.x_range().clamp(self.x),
       
    79             rect.y_range().clamp(self.y)
       
    80         )
       
    81     }
    78     }
    82 
    79 
    83     #[inline]
    80     #[inline]
    84     pub fn line_to(self, end: Point) -> Line {
    81     pub fn line_to(self, end: Point) -> Line {
    85         Line::new(self, end)
    82         Line::new(self, end)
   272 impl Rect {
   269 impl Rect {
   273     #[inline]
   270     #[inline]
   274     pub fn new(top_left: Point, bottom_right: Point) -> Self {
   271     pub fn new(top_left: Point, bottom_right: Point) -> Self {
   275         assert!(top_left.x <= bottom_right.x + 1);
   272         assert!(top_left.x <= bottom_right.x + 1);
   276         assert!(top_left.y <= bottom_right.y + 1);
   273         assert!(top_left.y <= bottom_right.y + 1);
   277         Self { top_left, bottom_right }
   274         Self {
       
   275             top_left,
       
   276             bottom_right,
       
   277         }
   278     }
   278     }
   279 
   279 
   280     pub fn from_box(left: i32, right: i32, top: i32, bottom: i32) -> Self {
   280     pub fn from_box(left: i32, right: i32, top: i32, bottom: i32) -> Self {
   281         Self::new(Point::new(left, top), Point::new(right, bottom))
   281         Self::new(Point::new(left, top), Point::new(right, bottom))
   282     }
   282     }
   283 
   283 
   284     pub fn from_size(top_left: Point, size: Size) -> Self {
   284     pub fn from_size(top_left: Point, size: Size) -> Self {
   285         Self::new(
   285         Self::new(
   286             top_left,
   286             top_left,
   287             top_left + Point::new(size.width as i32 - 1, size.height as i32 - 1)
   287             top_left + Point::new(size.width as i32 - 1, size.height as i32 - 1),
   288         )
   288         )
   289     }
   289     }
   290 
   290 
   291     pub fn from_size_coords(x: i32, y: i32, width: usize, height: usize) -> Self {
   291     pub fn from_size_coords(x: i32, y: i32, width: usize, height: usize) -> Self {
   292         Self::from_size(Point::new(x, y), Size::new(width, height))
   292         Self::from_size(Point::new(x, y), Size::new(width, height))
   352     }
   352     }
   353 
   353 
   354     #[inline]
   354     #[inline]
   355     pub fn with_margin(&self, margin: i32) -> Self {
   355     pub fn with_margin(&self, margin: i32) -> Self {
   356         let offset = Point::diag(margin);
   356         let offset = Point::diag(margin);
   357         Self::new(
   357         Self::new(self.top_left() + offset, self.bottom_right() - offset)
   358             self.top_left() + offset,
       
   359             self.bottom_right() - offset
       
   360         )
       
   361     }
   358     }
   362 
   359 
   363     #[inline]
   360     #[inline]
   364     pub fn x_range(&self) -> RangeInclusive<i32> {
   361     pub fn x_range(&self) -> RangeInclusive<i32> {
   365         self.left()..=self.right()
   362         self.left()..=self.right()
   402         ]
   399         ]
   403     }
   400     }
   404 
   401 
   405     #[inline]
   402     #[inline]
   406     pub fn quotient(self, x: usize, y: usize) -> Point {
   403     pub fn quotient(self, x: usize, y: usize) -> Point {
   407         self.top_left() +
   404         self.top_left() + Point::new((x % self.width()) as i32, (y % self.height()) as i32)
   408             Point::new(
       
   409                 (x % self.width()) as i32,
       
   410                 (y % self.height()) as i32
       
   411             )
       
   412     }
   405     }
   413 }
   406 }
   414 
   407 
   415 trait RangeContains<T> {
   408 trait RangeContains<T> {
   416     fn contains(&self, value: T) -> bool;
   409     fn contains(&self, value: T) -> bool;
   417 }
   410 }
   418 
   411 
   419 impl <T: Ord> RangeContains<T> for Range<T> {
   412 impl<T: Ord> RangeContains<T> for Range<T> {
   420     fn contains(&self, value: T) -> bool {
   413     fn contains(&self, value: T) -> bool {
   421         value >= self.start && value < self.end
   414         value >= self.start && value < self.end
   422     }
   415     }
   423 }
   416 }
   424 
   417 
   425 impl <T: Ord> RangeContains<T> for RangeInclusive<T> {
   418 impl<T: Ord> RangeContains<T> for RangeInclusive<T> {
   426     fn contains(&self, value: T) -> bool {
   419     fn contains(&self, value: T) -> bool {
   427         value >= *self.start() && value <= *self.end()
   420         value >= *self.start() && value <= *self.end()
   428     }
   421     }
   429 }
   422 }
   430 
   423 
   431 trait RangeClamp<T> {
   424 trait RangeClamp<T> {
   432     fn clamp(&self, value: T) -> T;
   425     fn clamp(&self, value: T) -> T;
   433 }
   426 }
   434 
   427 
   435 impl <T: Ord + Copy> RangeClamp<T> for RangeInclusive<T> {
   428 impl<T: Ord + Copy> RangeClamp<T> for RangeInclusive<T> {
   436     fn clamp(&self, value: T) -> T {
   429     fn clamp(&self, value: T) -> T {
   437         if value < *self.start() {
   430         if value < *self.start() {
   438             *self.start()
   431             *self.start()
   439         } else if value > *self.end() {
   432         } else if value > *self.end() {
   440             *self.end()
   433             *self.end()
   477 
   470 
   478     pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &mut Point> + 'a {
   471     pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &mut Point> + 'a {
   479         let edges_count = self.edges_count();
   472         let edges_count = self.edges_count();
   480         let start = self.vertices.as_mut_ptr();
   473         let start = self.vertices.as_mut_ptr();
   481         let end = unsafe { start.add(self.vertices.len()) };
   474         let end = unsafe { start.add(self.vertices.len()) };
   482         PolygonPointsIteratorMut { source: self, start, end }
   475         PolygonPointsIteratorMut {
       
   476             source: self,
       
   477             start,
       
   478             end,
       
   479         }
   483     }
   480     }
   484 
   481 
   485     fn force_close(&mut self) {
   482     fn force_close(&mut self) {
   486         if !self.vertices.is_empty() {
   483         if !self.vertices.is_empty() {
   487             self.vertices[0] = self.vertices[self.vertices.len() - 1];
   484             self.vertices[0] = self.vertices[self.vertices.len() - 1];
   492         (&self.vertices[0..self.edges_count()])
   489         (&self.vertices[0..self.edges_count()])
   493             .iter()
   490             .iter()
   494             .zip(&self.vertices[1..])
   491             .zip(&self.vertices[1..])
   495             .map(|(s, e)| Line::new(*s, *e))
   492             .map(|(s, e)| Line::new(*s, *e))
   496     }
   493     }
       
   494 
       
   495     pub fn bezierize(&mut self, segments_number: u32) {
       
   496         fn calc_point(p1: Point, p2: Point, p3: Point) -> FPPoint {
       
   497             let diff13 = (p1 - p3).to_fppoint();
       
   498             let diff13_norm = diff13.distance();
       
   499 
       
   500             if diff13_norm.is_zero() {
       
   501                 diff13
       
   502             } else {
       
   503                 let diff12_norm = (p1 - p2).to_fppoint().distance();
       
   504                 let diff23_norm = (p2 - p3).to_fppoint().distance();
       
   505                 let min_distance = min(diff13_norm, min(diff12_norm, diff23_norm));
       
   506 
       
   507                 diff13 * min_distance / diff13_norm / 3
       
   508             }
       
   509         }
       
   510 
       
   511         if self.vertices.len() < 4 {
       
   512             return;
       
   513         }
       
   514 
       
   515         let delta = fp!(1 / segments_number);
       
   516         let mut bezierized_vertices = Vec::new();
       
   517         let mut pi = 0;
       
   518         let mut i = 1;
       
   519         let mut ni = 2;
       
   520         let mut right_point = calc_point(self.vertices[pi], self.vertices[i], self.vertices[ni]);
       
   521         let mut left_point;
       
   522 
       
   523         pi += 1;
       
   524         while pi != 0 {
       
   525             pi = i;
       
   526             i = ni;
       
   527             ni += 1;
       
   528             if ni >= self.vertices.len() {
       
   529                 ni = 0;
       
   530             }
       
   531 
       
   532             left_point = right_point;
       
   533             right_point = calc_point(self.vertices[pi], self.vertices[i], self.vertices[ni]);
       
   534 
       
   535             bezierized_vertices.extend(BezierCurveSegments::new(
       
   536                 Line::new(self.vertices[pi], self.vertices[i]),
       
   537                 left_point,
       
   538                 -right_point,
       
   539                 delta,
       
   540             ));
       
   541         }
       
   542 
       
   543         self.vertices = bezierized_vertices;
       
   544     }
   497 }
   545 }
   498 
   546 
   499 struct PolygonPointsIteratorMut<'a> {
   547 struct PolygonPointsIteratorMut<'a> {
   500     source: &'a mut Polygon,
   548     source: &'a mut Polygon,
   501     start: *mut Point,
   549     start: *mut Point,
   502     end: *mut Point
   550     end: *mut Point,
   503 }
   551 }
   504 
   552 
   505 impl <'a> Iterator for PolygonPointsIteratorMut<'a> {
   553 impl<'a> Iterator for PolygonPointsIteratorMut<'a> {
   506     type Item = &'a mut Point;
   554     type Item = &'a mut Point;
   507 
   555 
   508     fn next(&mut self) -> Option<<Self as Iterator>::Item> {
   556     fn next(&mut self) -> Option<<Self as Iterator>::Item> {
   509         if self.start == self.end {
   557         if self.start == self.end {
   510             None
   558             None
   516             }
   564             }
   517         }
   565         }
   518     }
   566     }
   519 }
   567 }
   520 
   568 
   521 impl <'a> Drop for PolygonPointsIteratorMut<'a> {
   569 impl<'a> Drop for PolygonPointsIteratorMut<'a> {
   522     fn drop(&mut self) {
   570     fn drop(&mut self) {
   523         self.source.force_close();
   571         self.source.force_close();
   524     }
   572     }
   525 }
   573 }
   526 
   574 
   535 }
   583 }
   536 
   584 
   537 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
   585 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
   538 pub struct Ray {
   586 pub struct Ray {
   539     pub start: Point,
   587     pub start: Point,
   540     pub direction: Point
   588     pub direction: Point,
   541 }
   589 }
   542 
   590 
   543 impl Ray {
   591 impl Ray {
   544     #[inline]
   592     #[inline]
   545     pub fn new(start: Point, direction: Point) -> Ray {
   593     pub fn new(start: Point, direction: Point) -> Ray {
   739 pub struct BezierCurveSegments {
   787 pub struct BezierCurveSegments {
   740     segment: Line,
   788     segment: Line,
   741     c1: FPPoint,
   789     c1: FPPoint,
   742     c2: FPPoint,
   790     c2: FPPoint,
   743     offset: FPNum,
   791     offset: FPNum,
       
   792     max_offset: FPNum,
   744     delta: FPNum,
   793     delta: FPNum,
       
   794     have_finished: bool,
   745 }
   795 }
   746 
   796 
   747 impl BezierCurveSegments {
   797 impl BezierCurveSegments {
   748     pub fn new(segment: Line, p1: Point, p2: Point, delta: FPNum) -> Self {
   798     pub fn new(segment: Line, p1: FPPoint, p2: FPPoint, delta: FPNum) -> Self {
   749         Self {
   799         Self {
   750             segment,
   800             segment,
   751             c1: (segment.start - p1).to_fppoint(),
   801             c1: segment.start.to_fppoint() - p1,
   752             c2: (segment.end - p2).to_fppoint(),
   802             c2: segment.end.to_fppoint() - p2,
   753             offset: fp!(0),
   803             offset: fp!(0),
       
   804             max_offset: fp!(4095 / 4096),
   754             delta,
   805             delta,
       
   806             have_finished: false,
   755         }
   807         }
   756     }
   808     }
   757 }
   809 }
   758 
   810 
   759 impl Iterator for BezierCurveSegments {
   811 impl Iterator for BezierCurveSegments {
   760     type Item = Point;
   812     type Item = Point;
   761 
   813 
   762     fn next(&mut self) -> Option<Self::Item> {
   814     fn next(&mut self) -> Option<Self::Item> {
   763         if self.offset < fp!(1) {
   815         if self.offset < self.max_offset {
   764             let offset_sq = self.offset * self.offset;
   816             let offset_sq = self.offset * self.offset;
   765             let offset_cub = offset_sq * self.offset;
   817             let offset_cub = offset_sq * self.offset;
   766 
   818 
   767             let r1 = fp!(1) - self.offset * 3 + offset_sq * 3 - offset_cub;
   819             let r1 = fp!(1) - self.offset * 3 + offset_sq * 3 - offset_cub;
   768             let r2 = self.offset * 3 - offset_sq * 6 + offset_cub * 3;
   820             let r2 = self.offset * 3 - offset_sq * 6 + offset_cub * 3;
   778                 + offset_cub * self.segment.end.y;
   830                 + offset_cub * self.segment.end.y;
   779 
   831 
   780             self.offset += self.delta;
   832             self.offset += self.delta;
   781 
   833 
   782             Some(Point::new(x.round(), y.round()))
   834             Some(Point::new(x.round(), y.round()))
       
   835         } else if !self.have_finished {
       
   836             self.have_finished = true;
       
   837 
       
   838             Some(self.segment.end)
   783         } else {
   839         } else {
   784             None
   840             None
   785         }
   841         }
   786     }
   842     }
   787 }
   843 }