rust/integral-geometry/src/lib.rs
changeset 14131 c416d32764b7
parent 14126 32383b888309
child 14133 a65b60f36b96
equal deleted inserted replaced
14129:703242ade2c1 14131:c416d32764b7
     1 extern crate fpnum;
     1 extern crate fpnum;
     2 
     2 
     3 use fpnum::distance;
     3 use fpnum::distance;
     4 use std::cmp::max;
     4 use std::cmp::max;
     5 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, RangeInclusive, Sub, SubAssign};
     5 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign};
     6 
     6 
     7 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
     7 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
     8 pub struct Point {
     8 pub struct Point {
     9     pub x: i32,
     9     pub x: i32,
    10     pub y: i32,
    10     pub y: i32,
    12 
    12 
    13 impl Point {
    13 impl Point {
    14     #[inline]
    14     #[inline]
    15     pub fn new(x: i32, y: i32) -> Self {
    15     pub fn new(x: i32, y: i32) -> Self {
    16         Self { x, y }
    16         Self { x, y }
       
    17     }
       
    18 
       
    19     #[inline]
       
    20     pub fn diag(v: i32) -> Self {
       
    21         Self::new(v, v)
    17     }
    22     }
    18 
    23 
    19     #[inline]
    24     #[inline]
    20     pub fn zero() -> Self {
    25     pub fn zero() -> Self {
    21         Self::new(0, 0)
    26         Self::new(0, 0)
    63     pub fn cross(self, other: Point) -> i32 {
    68     pub fn cross(self, other: Point) -> i32 {
    64         self.dot(other.rotate90())
    69         self.dot(other.rotate90())
    65     }
    70     }
    66 
    71 
    67     #[inline]
    72     #[inline]
    68     pub fn fit(self, rect: &Rect) -> Point {
    73     pub fn clamp(self, rect: &Rect) -> Point {
    69         let x = if self.x > rect.right() {
    74         Point::new(
    70             rect.right()
    75             rect.x_range().clamp(self.x),
    71         } else if self.x < rect.left() {
    76             rect.y_range().clamp(self.y)
    72             rect.left()
    77         )
    73         } else {
    78     }
    74             self.x
    79 
    75         };
    80     #[inline]
    76         let y = if self.y > rect.bottom() {
    81     pub fn line_to(self, end: Point) -> Line {
    77             rect.bottom()
    82         Line::new(self, end)
    78         } else if self.y < rect.top() {
    83     }
    79             rect.top()
    84 
    80         } else {
    85     #[inline]
    81             self.y
    86     pub fn ray_to(self, end: Point) -> Ray {
    82         };
    87         self.line_to(end).to_ray()
    83 
    88     }
    84         Point::new(x, y)
    89 
       
    90     #[inline]
       
    91     pub fn tangent(self) -> i32 {
       
    92         self.y / self.x
       
    93     }
       
    94 
       
    95     #[inline]
       
    96     pub fn cotangent(self) -> i32 {
       
    97         self.x / self.y
    85     }
    98     }
    86 }
    99 }
    87 
   100 
    88 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
   101 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
    89 pub struct Size {
   102 pub struct Size {
   344     #[inline]
   357     #[inline]
   345     pub fn y_range(&self) -> RangeInclusive<i32> {
   358     pub fn y_range(&self) -> RangeInclusive<i32> {
   346         self.y..=self.y + self.height as i32
   359         self.y..=self.y + self.height as i32
   347     }
   360     }
   348 
   361 
   349     /* requires #[feature(range_contains)]
       
   350     #[inline]
   362     #[inline]
   351     pub fn contains(&self, point: Point) -> bool {
   363     pub fn contains(&self, point: Point) -> bool {
   352         x_range().contains(point.x) && y_range.contains(point.y)
   364         self.x_range().contains(point.x) && self.y_range().contains(point.y)
   353     }*/
   365     }
   354 
   366 
   355     #[inline]
   367     #[inline]
   356     pub fn contains_inside(&self, point: Point) -> bool {
   368     pub fn contains_inside(&self, point: Point) -> bool {
   357         point.x > self.left()
   369         point.x > self.left()
   358             && point.x < self.right()
   370             && point.x < self.right()
   376             Rect::from_box(point.x, self.right(), self.top(), point.y),
   388             Rect::from_box(point.x, self.right(), self.top(), point.y),
   377             Rect::from_box(point.x, self.right(), point.y, self.bottom()),
   389             Rect::from_box(point.x, self.right(), point.y, self.bottom()),
   378             Rect::from_box(self.left(), point.x, point.y, self.bottom()),
   390             Rect::from_box(self.left(), point.x, point.y, self.bottom()),
   379         ]
   391         ]
   380     }
   392     }
       
   393 
       
   394     #[inline]
       
   395     pub fn quotient(self, x: u32, y: u32) -> Point {
       
   396         self.top_left() +
       
   397             Point::new(
       
   398                 (x % self.width) as i32,
       
   399                 (y % self.height) as i32
       
   400             )
       
   401     }
       
   402 }
       
   403 
       
   404 trait RangeContains<T> {
       
   405     fn contains(&self, value: T) -> bool;
       
   406 }
       
   407 
       
   408 impl <T: Ord> RangeContains<T> for Range<T> {
       
   409     fn contains(&self, value: T) -> bool {
       
   410         value >= self.start && value < self.end
       
   411     }
       
   412 }
       
   413 
       
   414 impl <T: Ord> RangeContains<T> for RangeInclusive<T> {
       
   415     fn contains(&self, value: T) -> bool {
       
   416         value >= *self.start() && value <= *self.end()
       
   417     }
       
   418 }
       
   419 
       
   420 trait RangeClamp<T> {
       
   421     fn clamp(&self, value: T) -> T;
       
   422 }
       
   423 
       
   424 impl <T: Ord + Copy> RangeClamp<T> for RangeInclusive<T> {
       
   425     fn clamp(&self, value: T) -> T {
       
   426         if value < *self.start() {
       
   427             *self.start()
       
   428         } else if value > *self.end() {
       
   429             *self.end()
       
   430         } else {
       
   431             value
       
   432         }
       
   433     }
   381 }
   434 }
   382 
   435 
   383 pub struct Polygon {
   436 pub struct Polygon {
   384     vertices: Vec<Point>,
   437     vertices: Vec<Point>,
   385 }
   438 }
   433         Self { vertices: v }
   486         Self { vertices: v }
   434     }
   487     }
   435 }
   488 }
   436 
   489 
   437 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
   490 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
       
   491 pub struct Ray {
       
   492     pub start: Point,
       
   493     pub direction: Point
       
   494 }
       
   495 
       
   496 impl Ray {
       
   497     #[inline]
       
   498     pub fn new(start: Point, direction: Point) -> Ray {
       
   499         Self { start, direction }
       
   500     }
       
   501 
       
   502     #[inline]
       
   503     pub fn tangent(&self) -> i32 {
       
   504         self.direction.tangent()
       
   505     }
       
   506 
       
   507     #[inline]
       
   508     pub fn cotangent(&self) -> i32 {
       
   509         self.direction.cotangent()
       
   510     }
       
   511 
       
   512     #[inline]
       
   513     pub fn orientation(&self, point: Point) -> i32 {
       
   514         (point - self.start).cross(self.direction).signum()
       
   515     }
       
   516 }
       
   517 
       
   518 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
   438 pub struct Line {
   519 pub struct Line {
   439     pub start: Point,
   520     pub start: Point,
   440     pub end: Point,
   521     pub end: Point,
   441 }
   522 }
   442 
   523 
   455     pub fn center(&self) -> Point {
   536     pub fn center(&self) -> Point {
   456         (self.start + self.end) / 2
   537         (self.start + self.end) / 2
   457     }
   538     }
   458 
   539 
   459     #[inline]
   540     #[inline]
       
   541     pub fn scaled_direction(&self) -> Point {
       
   542         self.end - self.start
       
   543     }
       
   544 
       
   545     #[inline]
   460     pub fn scaled_normal(&self) -> Point {
   546     pub fn scaled_normal(&self) -> Point {
   461         (self.end - self.start).rotate90()
   547         self.scaled_direction().rotate90()
       
   548     }
       
   549 
       
   550     #[inline]
       
   551     pub fn to_ray(&self) -> Ray {
       
   552         Ray::new(self.start, self.scaled_direction())
   462     }
   553     }
   463 }
   554 }
   464 
   555 
   465 impl IntoIterator for Line {
   556 impl IntoIterator for Line {
   466     type Item = Point;
   557     type Item = Point;