summaryrefslogtreecommitdiffstats
path: root/svgbob/src/buffer/fragment_buffer/fragment/circle.rs
diff options
context:
space:
mode:
Diffstat (limited to 'svgbob/src/buffer/fragment_buffer/fragment/circle.rs')
-rw-r--r--svgbob/src/buffer/fragment_buffer/fragment/circle.rs58
1 files changed, 47 insertions, 11 deletions
diff --git a/svgbob/src/buffer/fragment_buffer/fragment/circle.rs b/svgbob/src/buffer/fragment_buffer/fragment/circle.rs
index f43428a..058b738 100644
--- a/svgbob/src/buffer/fragment_buffer/fragment/circle.rs
+++ b/svgbob/src/buffer/fragment_buffer/fragment/circle.rs
@@ -1,5 +1,6 @@
use crate::{fragment::Bounds, util, Cell, Point};
-use ncollide2d::procedural;
+use nalgebra::Point2;
+use ncollide2d::shape::ConvexPolygon;
use ncollide2d::shape::Polyline;
use std::{cmp::Ordering, fmt};
@@ -30,11 +31,18 @@ impl Circle {
fn top_left_bound(&self) -> Point {
Point::new(self.center.x - self.radius, self.center.y - self.radius)
}
+ fn top_right_bound(&self) -> Point {
+ Point::new(self.center.x + self.radius, self.center.y - self.radius)
+ }
fn bottom_right_bound(&self) -> Point {
Point::new(self.center.x + self.radius, self.center.y + self.radius)
}
+ fn bottom_left_bound(&self) -> Point {
+ Point::new(self.center.x - self.radius, self.center.y + self.radius)
+ }
+
/// offset the circles parameter from the arg cell
pub(in crate) fn absolute_position(&self, cell: Cell) -> Self {
Circle {
@@ -107,19 +115,47 @@ impl PartialEq for Circle {
}
}
-impl Into<Polyline<f32>> for Circle {
- fn into(self) -> Polyline<f32> {
- use nalgebra::Point2;
- let pl = procedural::circle(&(self.radius * 2.0), 64);
- let mut points = pl.coords().to_vec();
- let orig_len = points.len();
- points.dedup();
+impl Into<Polyline> for Circle {
+ fn into(self) -> Polyline {
+ let points: Vec<Point2<f32>> = extract_circle_points(self.radius, 64)
+ .into_iter()
+ .map(|p| Point2::new(p.x + self.center.x, p.y + self.center.y))
+ .collect();
+
+ Polyline::new(points, None)
+ }
+}
- let adjusted: Vec<Point2<f32>> = points
+impl Into<ConvexPolygon> for Circle {
+ fn into(self) -> ConvexPolygon {
+ let points: Vec<Point2<f32>> = extract_circle_points(self.radius, 64)
.into_iter()
- .map(|p| *Point::new(p.x + self.center.x, p.y + self.center.y))
+ .map(|p| Point2::new(p.x + self.center.x, p.y + self.center.y))
.collect();
- Polyline::new(adjusted, None)
+ ConvexPolygon::from_convex_polyline(points)
+ .expect("must create a convex polygon")
+ }
+}
+
+fn extract_circle_points(radius: f32, nsubdivs: u32) -> Vec<Point> {
+ let two_pi = std::f32::consts::TAU;
+ let dtheta = two_pi / nsubdivs as f32;
+ push_xy_arc(radius, nsubdivs, dtheta)
+}
+
+/// Pushes a discretized counterclockwise circle to a buffer.
+/// The circle is contained on the plane spanned by the `x` and `y` axis.
+fn push_xy_arc(radius: f32, nsubdiv: u32, dtheta: f32) -> Vec<Point> {
+ let mut out: Vec<Point> = vec![];
+ let mut curr_theta: f32 = 0.0;
+
+ for _ in 0..nsubdiv {
+ let x = curr_theta.cos() * radius;
+ let y = curr_theta.sin() * radius;
+ out.push(Point::new(x, y));
+
+ curr_theta = curr_theta + dtheta;
}
+ out
}