Skip to content

Commit

Permalink
Port fill logic from cpp lib (#5)
Browse files Browse the repository at this point in the history
* Port filling behavior to match original lib

* update test case
  • Loading branch information
shuoli84 authored Mar 20, 2023
1 parent 816ba16 commit 7e2187d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 8 deletions.
24 changes: 19 additions & 5 deletions src/sweeper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::advancing_front::{AdvancingFront, NodeId, NodeRef};
use crate::points::{Points, PointsBuilder};
use crate::triangles::TriangleId;
use crate::triangles::TriangleStore;
use crate::utils::{in_circle, in_scan_area, orient_2d, Orientation};
use crate::utils::{in_circle, in_scan_area, orient_2d, Angle, Orientation};
use crate::{shape::*, Context, PointId, Triangle};

/// Observer for sweeper, used to monitor how sweeper works, quite useful
Expand Down Expand Up @@ -627,10 +627,10 @@ impl Sweeper {
}

fn should_fill(node: &NodeRef) -> bool {
let next_node = node.next().unwrap();
let next = node.next().unwrap();
let prev_node = node.prev().unwrap();

let angle = crate::utils::Angle::new(node.point(), next_node.point(), prev_node.point());
let angle = crate::utils::Angle::new(node.point(), next.point(), prev_node.point());

if angle.is_negative() {
// negative means next -> node -> prev is cw, then it is not a hole
Expand All @@ -642,6 +642,20 @@ impl Sweeper {
return false;
}

if let Some(next_next) = next.next() {
if Angle::new(node.point(), next_next.point(), prev_node.point())
.between_0_to_90_degree()
{
return false;
}
}

if let Some(prev_prev) = prev_node.prev() {
if Angle::new(node.point(), next.point(), prev_prev.point()).between_0_to_90_degree() {
return false;
}
}

true
}
}
Expand Down Expand Up @@ -1589,7 +1603,7 @@ mod tests {
.collect::<Vec<_>>();
assert_eq!(triangles.len(), 273);
assert!(cache_hit.hit_rate() > 0.63);
assert!(cache_hit.rotate_count <= 331);
assert!(cache_hit.rotate_count == 272);
}

#[test]
Expand All @@ -1604,7 +1618,7 @@ mod tests {
.collect::<Vec<_>>();
assert_eq!(triangles.len(), 1034);
assert!(cache_hit.hit_rate() > 0.71);
assert!(cache_hit.rotate_count <= 665);
assert!(cache_hit.rotate_count == 671);
}

#[test]
Expand Down
27 changes: 24 additions & 3 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ impl Angle {
Angle { dy: y, dx: x }
}

/// Check angle between 0 and 90, all exclusive
pub fn between_0_to_90_degree(&self) -> bool {
// * `x = 0`, `y = 0`: `0`
// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
if self.dx == 0. && self.dy == 0. {
true
} else if self.dx > 0. {
self.dy > 0.
} else {
false
}
}

/// whether the angle exceeds PI / 2
pub fn exceeds_90_degree(&self) -> bool {
// * `x = 0`, `y = 0`: `0`
Expand Down Expand Up @@ -161,16 +176,19 @@ mod tests {
#[test]
fn test_angle() {
let angle = Angle::new(Point::new(0., 0.), Point::new(1., 0.), Point::new(1., 1.));
assert!(!dbg!(angle).exceeds_90_degree());
assert!(!angle.exceeds_90_degree());
assert!(!angle.is_negative());
assert!(angle.between_0_to_90_degree());

let angle = Angle::new(Point::new(0., 0.), Point::new(0.1, 1.), Point::new(1., 0.));
assert!(!dbg!(angle).exceeds_90_degree());
assert!(angle.is_negative());
assert!(!angle.between_0_to_90_degree());

let angle = Angle::new(Point::new(0., 0.), Point::new(0., -1.), Point::new(1., 0.));
let angle = Angle::new(Point::new(0., 0.), Point::new(0.1, -1.), Point::new(1., 0.));
assert!(!angle.exceeds_90_degree());
assert!(!angle.is_negative());
assert!(angle.between_0_to_90_degree());

let angle = Angle::new(
Point::new(0., 0.),
Expand All @@ -179,6 +197,7 @@ mod tests {
);
assert!(angle.exceeds_90_degree());
assert!(!angle.is_negative());
assert!(!angle.between_0_to_90_degree());

let angle = Angle::new(
Point::new(0., 0.),
Expand All @@ -187,13 +206,15 @@ mod tests {
);
assert!(angle.is_negative());
assert!(!angle.exceeds_90_degree());
assert!(!angle.between_0_to_90_degree());

let angle = Angle::new(
Point::new(0., 0.),
Point::new(1.0, 0.),
Point::new(-1., 0.1),
);
assert!(!dbg!(angle).is_negative());
assert!(!angle.is_negative());
assert!(angle.exceeds_90_degree());
assert!(!angle.between_0_to_90_degree());
}
}

0 comments on commit 7e2187d

Please sign in to comment.