diff options
author | Jovansonlee Cesar <ivanceras@gmail.com> | 2021-07-12 20:37:56 +0800 |
---|---|---|
committer | Jovansonlee Cesar <ivanceras@gmail.com> | 2021-07-12 20:37:56 +0800 |
commit | 039c74fefaab4c7226de57f258072fb6a5974722 (patch) | |
tree | 81c8d55990f7da6ea9c6398f247f767fce119845 | |
parent | d379b7fe9ae6fa79d553715329d638301600319f (diff) |
Initial migration from ncollide2d to parry2d
-rw-r--r-- | svgbob/Cargo.toml | 2 | ||||
-rw-r--r-- | svgbob/src/buffer/cell_buffer/cell.rs | 13 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment.rs | 50 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment/circle.rs | 58 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment/line.rs | 22 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment/polygon.rs | 6 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment/rect.rs | 20 | ||||
-rw-r--r-- | svgbob/src/util.rs | 8 |
8 files changed, 109 insertions, 70 deletions
diff --git a/svgbob/Cargo.toml b/svgbob/Cargo.toml index 794c21b..d4da08e 100644 --- a/svgbob/Cargo.toml +++ b/svgbob/Cargo.toml @@ -11,7 +11,7 @@ license = "Apache-2.0" [dependencies] nalgebra = "0.28" -ncollide2d = "0.31" +ncollide2d = { version = "0.6", package = "parry2d"} lazy_static = "1.3.0" sauron = { version = "0.34" } unicode-width = "0.1.5" diff --git a/svgbob/src/buffer/cell_buffer/cell.rs b/svgbob/src/buffer/cell_buffer/cell.rs index 098e6d5..079a7f7 100644 --- a/svgbob/src/buffer/cell_buffer/cell.rs +++ b/svgbob/src/buffer/cell_buffer/cell.rs @@ -3,7 +3,7 @@ use ncollide2d::query::PointQuery; use ncollide2d::{ bounding_volume::AABB, math::Isometry, - query::{proximity, Proximity}, + query::intersection_test, shape::{Polyline, Segment}, }; use std::{cmp, cmp::Ordering, fmt}; @@ -125,7 +125,7 @@ impl Cell { /// the bounding box of this cell #[inline] - fn bounding_box(&self) -> AABB<f32> { + fn bounding_box(&self) -> AABB { let start = Point::new( self.x as f32 * Self::width(), self.y as f32 * Self::height(), @@ -140,7 +140,7 @@ impl Cell { /// Convert the bounding box aabb to polyline segment /// the dots from top-left, top-right, bottom-right, bottom-left then closing to top-left /// The polyline is then used to testing for intersection with the line segment - fn polyline(&self) -> Polyline<f32> { + fn polyline(&self) -> Polyline { let aabb = self.bounding_box(); let min = aabb.mins; let max = aabb.maxs; @@ -172,14 +172,13 @@ impl Cell { pub fn is_intersected(&self, start: Point, end: Point) -> bool { let pl = self.polyline(); let segment = Segment::new(*start, *end); - let prox = proximity( + intersection_test( &Isometry::identity(), &pl, &Isometry::identity(), &segment, - 0.0, - ); - prox == Proximity::Intersecting + ) + .expect("must pass intersection test") } /// check if this cell is bounded by the lower bound and upper bound diff --git a/svgbob/src/buffer/fragment_buffer/fragment.rs b/svgbob/src/buffer/fragment_buffer/fragment.rs index 95e31e5..ae0b2b4 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment.rs @@ -6,10 +6,11 @@ pub use line::Line; pub use marker_line::{Marker, MarkerLine}; use ncollide2d::bounding_volume::BoundingVolume; use ncollide2d::query::PointQuery; +use ncollide2d::shape::ConvexPolygon; use ncollide2d::{ bounding_volume::AABB, math::Isometry, - query::{proximity, Proximity}, + query::intersection_test, shape::{Polyline, Segment, Shape}, }; pub use polygon::{Polygon, PolygonTag}; @@ -298,40 +299,42 @@ impl Fragment { } /// check if this fragment is intersecting with this bounding box - pub fn is_intersecting(&self, bbox: &AABB<f32>) -> bool { - let bbox: Polyline<f32> = Polyline::new( - vec![ - *Point::new(bbox.mins.x, bbox.mins.y), - *Point::new(bbox.maxs.x, bbox.mins.y), - *Point::new(bbox.maxs.x, bbox.maxs.y), - *Point::new(bbox.mins.x, bbox.maxs.y), - ], - None, - ); + /// Note: if intersection logic requires testing the solid shape inside the polygon + /// use the ConvexPolygon of each shape instead of Polyline + pub fn is_intersecting(&self, bbox: &AABB) -> bool { + let points = vec![ + *Point::new(bbox.mins.x, bbox.mins.y), + *Point::new(bbox.maxs.x, bbox.mins.y), + *Point::new(bbox.maxs.x, bbox.maxs.y), + *Point::new(bbox.mins.x, bbox.maxs.y), + ]; + let bbox = Polyline::new(points, None); let identity = Isometry::identity(); match self { Fragment::Line(line) => { - let segment: Segment<f32> = line.clone().into(); - proximity(&identity, &segment, &identity, &bbox, 0.0) - == Proximity::Intersecting + let segment: Segment = line.clone().into(); + let res = + intersection_test(&identity, &segment, &identity, &bbox) + .expect("must pass"); + println!("res: {}", res); + res } Fragment::Rect(rect) => { - let polyline: Polyline<f32> = rect.clone().into(); - proximity(&identity, &polyline, &identity, &bbox, 0.0) - == Proximity::Intersecting + let polyline: Polyline = rect.clone().into(); + intersection_test(&identity, &polyline, &identity, &bbox) + .expect("must pass") } Fragment::Circle(circle) => { - // do not include the small circles - let polyline: Polyline<f32> = circle.clone().into(); - proximity(&identity, &polyline, &identity, &bbox, 0.0) - == Proximity::Intersecting + let polyline: Polyline = circle.clone().into(); + intersection_test(&identity, &polyline, &identity, &bbox) + .expect("must pass") } _ => false, } } /// check if this fragment can be contain in the specified bounding box `bbox` - pub fn is_inside(&self, bbox: &AABB<f32>) -> bool { + pub fn is_inside(&self, bbox: &AABB) -> bool { let (start, end) = self.bounds(); let frag_bound = AABB::new(*start, *end); bbox.contains(&frag_bound) @@ -939,6 +942,9 @@ mod tests { let line1 = line(CellGrid::a(), CellGrid::y()); assert!(line1.hit(CellGrid::g(), CellGrid::s())); + let rect_gs = rect(CellGrid::g(), CellGrid::s(), false, false); + assert!(!rect_gs.hit(CellGrid::a(), CellGrid::y())); + let rect1 = rect(CellGrid::a(), CellGrid::y(), false, false); assert!(!rect1.hit(CellGrid::g(), CellGrid::s())); } 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 } diff --git a/svgbob/src/buffer/fragment_buffer/fragment/line.rs b/svgbob/src/buffer/fragment_buffer/fragment/line.rs index 2360bb7..54c135b 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment/line.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment/line.rs @@ -4,11 +4,7 @@ use crate::{ util, Direction, Point, }; use ncollide2d::query::PointQuery; -use ncollide2d::{ - bounding_volume::AABB, - query::{proximity, Proximity}, - shape::Polyline, -}; +use ncollide2d::{bounding_volume::AABB, shape::Polyline}; use ncollide2d::{ math::Isometry, shape::{Segment, Shape}, @@ -535,8 +531,8 @@ impl<MSG> Into<Node<MSG>> for Line { } } -impl Into<Segment<f32>> for Line { - fn into(self) -> Segment<f32> { +impl Into<Segment> for Line { + fn into(self) -> Segment { Segment::new(*self.start, *self.end) } } @@ -638,18 +634,6 @@ mod tests { assert!(line2.is_touching(&line1)); assert!(util::is_collinear(&line1.start, &line1.end, &line2.start)); assert!(util::is_collinear(&line2.start, &line2.end, &line1.end)); - let area1 = ncollide2d::utils::triangle_area( - &line1.start, - &line1.end, - &line2.start, - ); - println!("area1: {}", area1); - let area2 = ncollide2d::utils::triangle_area( - &line1.start, - &line1.end, - &line2.end, - ); - println!("area2: {}", area2); assert!(line1.can_merge(&line2)); } diff --git a/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs b/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs index f61e53c..d2d0815 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs @@ -175,7 +175,7 @@ impl Polygon { impl Bounds for Polygon { fn bounds(&self) -> (Point, Point) { - let pl: Polyline<f32> = self.clone().into(); + let pl: Polyline = self.clone().into(); let aabb = pl.local_aabb(); (Point::from(*aabb.mins), Point::from(*aabb.maxs)) } @@ -195,8 +195,8 @@ impl fmt::Display for Polygon { } } -impl Into<Polyline<f32>> for Polygon { - fn into(self) -> Polyline<f32> { +impl Into<Polyline> for Polygon { + fn into(self) -> Polyline { let points: Vec<Point2<f32>> = self.points.iter().map(|p| **p).collect(); Polyline::new(points, None) diff --git a/svgbob/src/buffer/fragment_buffer/fragment/rect.rs b/svgbob/src/buffer/fragment_buffer/fragment/rect.rs index 27264a8..0978bf4 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment/rect.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment/rect.rs @@ -1,6 +1,5 @@ use crate::{fragment::Bounds, util, Cell, Point}; -use std::fmt; - +use ncollide2d::shape::ConvexPolygon; use ncollide2d::shape::{Polyline, Segment, Shape}; use sauron::{ html::attributes::*, @@ -8,6 +7,7 @@ use sauron::{ Node, }; use std::cmp::Ordering; +use std::fmt; #[derive(Debug, Clone)] pub struct Rect { @@ -120,8 +120,8 @@ impl fmt::Display for Rect { } } -impl Into<Polyline<f32>> for Rect { - fn into(self) -> Polyline<f32> { +impl Into<Polyline> for Rect { + fn into(self) -> Polyline { Polyline::new( vec![ *self.start, @@ -135,6 +135,18 @@ impl Into<Polyline<f32>> for Rect { } } +impl Into<ConvexPolygon> for Rect { + fn into(self) -> ConvexPolygon { + ConvexPolygon::from_convex_polyline(vec![ + *self.start, + *Point::new(self.end.x, self.start.y), + *self.end, + *Point::new(self.start.x, self.end.y), + ]) + .expect("must create a convex polygon") + } +} + impl<MSG> Into<Node<MSG>> for Rect { fn into(self) -> Node<MSG> { rect( diff --git a/svgbob/src/util.rs b/svgbob/src/util.rs index 4253c5f..499bf9f 100644 --- a/svgbob/src/util.rs +++ b/svgbob/src/util.rs @@ -1,4 +1,5 @@ use crate::Point; +use ncollide2d::shape::Triangle; use ncollide2d::{bounding_volume::AABB, math::Isometry, query::PointQuery}; use std::cmp::Ordering; @@ -27,7 +28,7 @@ pub fn ord(f1: f32, f2: f32) -> Ordering { /// clips a line to the bounding box of this whole grid /// and approximate each point to the closes intersection fn clip_line_internal( - aabb: &AABB<f32>, + aabb: &AABB, start: Point, end: Point, ) -> Option<(Point, Point)> { @@ -45,7 +46,7 @@ fn clip_line_internal( /// clip a line but do not extend the points pub fn clip_line( - aabb: &AABB<f32>, + aabb: &AABB, start: Point, end: Point, ) -> Option<(Point, Point)> { @@ -74,7 +75,8 @@ pub fn clip_line( /// the threshold are of 0.01 is used since /// lines may not be very aligned. pub fn is_collinear(a: &Point, b: &Point, c: &Point) -> bool { - ncollide2d::utils::triangle_area(a, b, c) < 0.01 + use std::ops::Deref; + Triangle::new(*a.deref(), *b.deref(), *c.deref()).area() < 0.01 } pub fn pad(v: f32) -> f32 { |