--- a/rust/fpnum/src/lib.rs Mon Nov 05 23:15:56 2018 +0300
+++ b/rust/fpnum/src/lib.rs Mon Nov 05 21:36:28 2018 +0100
@@ -47,11 +47,11 @@
}
#[inline]
- pub fn round(&self) -> i64 {
+ pub fn round(&self) -> i32 {
if self.is_negative {
- -((self.value >> 32) as i64)
+ -((self.value >> 32) as i32)
} else {
- (self.value >> 32) as i64
+ (self.value >> 32) as i32
}
}
--- a/rust/integral-geometry/src/lib.rs Mon Nov 05 23:15:56 2018 +0300
+++ b/rust/integral-geometry/src/lib.rs Mon Nov 05 21:36:28 2018 +0100
@@ -1,12 +1,12 @@
+#[macro_use]
extern crate fpnum;
-use fpnum::distance;
+use fpnum::{distance, FPNum, FPPoint};
use std::{
cmp::max,
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign}
};
-
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct Point {
pub x: i32,
@@ -99,6 +99,11 @@
pub fn cotangent(self) -> i32 {
self.x / self.y
}
+
+ #[inline]
+ pub fn to_fppoint(&self) -> FPPoint {
+ FPPoint::new(self.x.into(), self.y.into())
+ }
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
@@ -731,6 +736,56 @@
}
}
+pub struct BezierCurveSegments {
+ segment: Line,
+ c1: FPPoint,
+ c2: FPPoint,
+ offset: FPNum,
+ delta: FPNum,
+}
+
+impl BezierCurveSegments {
+ pub fn new(segment: Line, p1: Point, p2: Point, delta: FPNum) -> Self {
+ Self {
+ segment,
+ c1: (segment.start - p1).to_fppoint(),
+ c2: (segment.end - p2).to_fppoint(),
+ offset: fp!(0),
+ delta,
+ }
+ }
+}
+
+impl Iterator for BezierCurveSegments {
+ type Item = Point;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.offset < fp!(1) {
+ let offset_sq = self.offset * self.offset;
+ let offset_cub = offset_sq * self.offset;
+
+ let r1 = fp!(1) - self.offset * 3 + offset_sq * 3 - offset_cub;
+ let r2 = self.offset * 3 - offset_sq * 6 + offset_cub * 3;
+ let r3 = offset_sq * 3 - offset_cub * 3;
+
+ let x = r1 * self.segment.start.x
+ + r2 * self.c1.x()
+ + r3 * self.c2.x()
+ + offset_cub * self.segment.end.x;
+ let y = r1 * self.segment.start.y
+ + r2 * self.c1.y()
+ + r3 * self.c2.y()
+ + offset_cub * self.segment.end.y;
+
+ self.offset += self.delta;
+
+ Some(Point::new(x.round(), y.round()))
+ } else {
+ None
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;