Skip to content

Commit 32cb020

Browse files
authored
Clean up fill polygon impl (#136)
1 parent 62b79da commit 32cb020

5 files changed

Lines changed: 461 additions & 169 deletions

File tree

‎star/src/turtle/elements/clip.rs‎

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use std::iter;
22

3-
use lyon_geom::{LineSegment, Point};
3+
use lyon_geom::Point;
44

55
use super::intersect::{Intersections, PARAM_EPSILON};
6-
use crate::turtle::elements::{DrawCommand, FillPolygon, Stroke};
6+
use crate::turtle::elements::{DrawCommand, FillPolygon, PointLocation, Stroke};
77

88
#[derive(Debug, Clone)]
99
struct ActiveClip {
@@ -25,17 +25,7 @@ impl ClipStack {
2525
.flat_map(|polygon| {
2626
iter::once(&polygon.outer)
2727
.chain(&polygon.holes)
28-
.flat_map(|stroke| {
29-
stroke
30-
.commands()
31-
.copied()
32-
.chain((!stroke.is_closed()).then_some(DrawCommand::LineTo(
33-
LineSegment {
34-
from: stroke.end_point(),
35-
to: stroke.start_point(),
36-
},
37-
)))
38-
})
28+
.flat_map(Stroke::closed_commands)
3929
})
4030
.collect(),
4131
clip_polygons,
@@ -85,7 +75,12 @@ impl ClipStack {
8575
ts.dedup_by(|a, b| (*a - *b).abs() < PARAM_EPSILON);
8676

8777
// Draw ranges that are active within some clipping polygon
88-
let is_inside = |pt: Point<f64>| active.clip_polygons.iter().any(|p| p.contains_point(pt));
78+
let is_inside = |pt: Point<f64>| {
79+
active
80+
.clip_polygons
81+
.iter()
82+
.any(|p| p.contains_point(pt) == PointLocation::Interior)
83+
};
8984
for (&t_a, &t_b) in ts.iter().zip(ts.iter().skip(1)) {
9085
let t_mid = f64::midpoint(t_a, t_b);
9186
if is_inside(cmd.sample(t_mid)) {
@@ -107,18 +102,17 @@ fn group_commands_into_strokes(cmds: Vec<DrawCommand>) -> Vec<Stroke> {
107102
let cmd_start = cmd.start_point();
108103
let cmd_end = cmd.end_point();
109104

110-
if let (Some(prev), Some(start)) = (prev_end, cmd_start) {
111-
// If the next command does not start where the previous command ended,
112-
// emit the current stroke and start a new one across the rapid-travel gap.
113-
if (prev - start).square_length() > f64::EPSILON
105+
if let Some(prev) = prev_end {
106+
// Start a new stroke if there is a jump.
107+
if (prev - cmd_start).square_length() > f64::EPSILON
114108
&& let Some(s) = current_start.take()
115109
{
116110
strokes.push(Stroke::new(s, std::mem::take(&mut current_cmds), None));
117111
}
118112
}
119113

120114
if current_start.is_none() {
121-
current_start = cmd_start;
115+
current_start = Some(cmd_start);
122116
}
123117
prev_end = Some(cmd_end);
124118
current_cmds.push(cmd);

0 commit comments

Comments
 (0)