Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6bd4b8d

Browse files
committed
Correctly draw scanlines
1 parent 6a3a8f8 commit 6bd4b8d

File tree

1 file changed

+110
-14
lines changed

1 file changed

+110
-14
lines changed

examples/thick-triangles.rs

Lines changed: 110 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,49 +15,137 @@ use embedded_graphics::{
1515
prelude::*,
1616
primitives::line::StrokeOffset,
1717
primitives::*,
18+
style::StrokeAlignment,
1819
style::{PrimitiveStyle, TextStyle},
1920
};
2021
use embedded_graphics_simulator::{
2122
OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window,
2223
};
2324
use sdl2::keyboard::Keycode;
2425

26+
/// Calculate squared distance from midpoint of an outside (left) edge to the center of the triangle
27+
fn calc_dist(center: Point, start: LineJoin, end: LineJoin) -> u32 {
28+
let start = start.second_edge_start.left;
29+
let end = end.first_edge_end.left;
30+
31+
Line::new(start, end).distance_to_point_squared(center)
32+
}
33+
2534
fn draw(
2635
display: &mut SimulatorDisplay<Rgb888>,
2736
mouse_pos: Point,
2837
position: Point,
2938
stroke_width: u32,
39+
stroke_alignment: StrokeAlignment,
3040
) -> Result<(), core::convert::Infallible> {
3141
display.clear(Rgb888::BLACK)?;
3242

43+
// {
44+
// let l1 = Line::new(Point::new(150, 50), Point::new(100, 100));
45+
// let l2 = Line::new(Point::new(100, 100), position);
46+
47+
// l1.into_styled(PrimitiveStyle::with_stroke(Rgb888::RED, 1))
48+
// .draw(display)?;
49+
// l2.into_styled(PrimitiveStyle::with_stroke(Rgb888::GREEN, 1))
50+
// .draw(display)?;
51+
52+
// let (e_l1_l, e_l1_r) = l1.extents(stroke_width, stroke_alignment.as_offset());
53+
// let (e_l2_l, e_l2_r) = l2.extents(stroke_width, stroke_alignment.as_offset());
54+
55+
// let first_segment_start_edge = Line::new(e_l1_l.start, e_l1_r.start);
56+
// let second_segment_end_edge = Line::new(e_l2_l.end, e_l2_r.end);
57+
58+
// e_l1_l
59+
// .into_styled(PrimitiveStyle::with_stroke(Rgb888::RED, 1))
60+
// .draw(display)?;
61+
// e_l1_r
62+
// .into_styled(PrimitiveStyle::with_stroke(Rgb888::RED, 1))
63+
// .draw(display)?;
64+
// first_segment_start_edge
65+
// .into_styled(PrimitiveStyle::with_stroke(Rgb888::CSS_ORANGE, 1))
66+
// .draw(display)?;
67+
68+
// e_l2_l
69+
// .into_styled(PrimitiveStyle::with_stroke(Rgb888::GREEN, 1))
70+
// .draw(display)?;
71+
// e_l2_r
72+
// .into_styled(PrimitiveStyle::with_stroke(Rgb888::GREEN, 1))
73+
// .draw(display)?;
74+
// second_segment_end_edge
75+
// .into_styled(PrimitiveStyle::with_stroke(Rgb888::CSS_GREEN, 1))
76+
// .draw(display)?;
77+
78+
// dbg!(
79+
// first_segment_start_edge.segment_intersection(&e_l2_l),
80+
// second_segment_end_edge.segment_intersection(&e_l1_r)
81+
// );
82+
// // dbg!(l1.line_intersection(&l2));
83+
// }
84+
3385
let scanline = Line::new(
3486
Point::new(0, mouse_pos.y),
3587
Point::new(display.size().width as i32, mouse_pos.y),
3688
);
3789
let scanline_y = scanline.start.y;
3890

91+
Text::new(&format!("{:?}", stroke_alignment), Point::zero())
92+
.into_styled(TextStyle::new(Font6x8, Rgb888::GREEN))
93+
.draw(display)?;
94+
3995
scanline
4096
.into_styled(PrimitiveStyle::with_stroke(Rgb888::BLUE, 1))
4197
.draw(display)?;
4298

43-
let offset = StrokeOffset::None;
4499
let p1 = Point::new(80, 150);
45100
let p2 = Point::new(120, 80);
46101
let p3 = position;
47102

103+
let points = [p1, p2, p3];
104+
48105
let t = Triangle::new(p1, p2, p3).sorted_clockwise();
49106

50107
let joins = [
51-
LineJoin::from_points(t.p3, t.p1, t.p2, stroke_width, offset),
52-
LineJoin::from_points(t.p1, t.p2, t.p3, stroke_width, offset),
53-
LineJoin::from_points(t.p2, t.p3, t.p1, stroke_width, offset),
108+
LineJoin::from_points(t.p3, t.p1, t.p2, stroke_width, stroke_alignment.as_offset()),
109+
LineJoin::from_points(t.p1, t.p2, t.p3, stroke_width, stroke_alignment.as_offset()),
110+
LineJoin::from_points(t.p2, t.p3, t.p1, stroke_width, stroke_alignment.as_offset()),
54111
];
55112

56-
let is_degenerate = joins.iter().any(|j| j.is_degenerate());
113+
let is_collapsed = joins.iter().any(|j| j.is_degenerate());
114+
115+
Text::new(&format!("{:?}", is_collapsed), Point::new(0, 8))
116+
.into_styled(TextStyle::new(Font6x8, Rgb888::GREEN))
117+
.draw(display)?;
57118

58119
let points = [t.p1, t.p2, t.p3];
59120

60-
let mut it = ClosedThickSegmentIter::new(&points, stroke_width, StrokeOffset::None);
121+
let it = ClosedThickSegmentIter::new(&points, stroke_width, stroke_alignment.as_offset());
122+
123+
println!("---");
124+
125+
// let inner_t = Triangle::new(
126+
// joins[0].first_edge_end.right,
127+
// joins[1].first_edge_end.right,
128+
// joins[2].first_edge_end.right,
129+
// );
130+
131+
// inner_t
132+
// .into_styled(PrimitiveStyle::with_stroke(Rgb888::YELLOW, 1))
133+
// .draw(display)?;
134+
135+
// Text::new(&format!("{:?}", inner_t.area_doubled()), Point::new(0, 16))
136+
// .into_styled(TextStyle::new(Font6x8, Rgb888::GREEN))
137+
// .draw(display)?;
138+
139+
// let centroid = t.centroid();
140+
141+
// let dist1 = calc_dist(centroid, joins[0], joins[1]);
142+
// let dist2 = calc_dist(centroid, joins[1], joins[2]);
143+
// let dist3 = calc_dist(centroid, joins[2], joins[0]);
144+
145+
// // Flag denoting whether the inside of the triangle is completely filled by the edge strokes
146+
// // or not.
147+
// let is_collapsed =
148+
// dist1 < stroke_width.pow(2) || dist2 < stroke_width.pow(2) || dist3 < stroke_width.pow(2);
61149

62150
it.clone().enumerate().try_for_each(|(idx, side)| {
63151
// Outside is always left side of line due to clockwise sorting.
@@ -72,7 +160,7 @@ fn draw(
72160

73161
outside
74162
.into_styled(PrimitiveStyle::with_stroke(
75-
if !is_degenerate {
163+
if !is_collapsed {
76164
Rgb888::CSS_CORAL
77165
} else {
78166
Rgb888::CSS_DARK_ORANGE
@@ -81,13 +169,13 @@ fn draw(
81169
))
82170
.draw(display)?;
83171

84-
if !is_degenerate {
172+
if !is_collapsed {
85173
inside
86174
.into_styled(PrimitiveStyle::with_stroke(Rgb888::CSS_DEEP_SKY_BLUE, 1))
87175
.draw(display)?;
88176
}
89177

90-
Text::new(&format!("P{}", idx + 1), outside.start)
178+
Text::new(&format!("P{}", idx + 1), points[idx])
91179
.into_styled(TextStyle::new(Font6x8, Rgb888::CSS_YELLOW_GREEN))
92180
.draw(display)
93181
})?;
@@ -119,8 +207,9 @@ fn main() -> Result<(), core::convert::Infallible> {
119207
let mut position = Point::new(150, 120);
120208
let mut stroke_width = 5;
121209
let mut mouse_down = false;
210+
let mut alignment = StrokeAlignment::Center;
122211

123-
draw(&mut display, position, position, stroke_width)?;
212+
draw(&mut display, position, position, stroke_width, alignment)?;
124213

125214
'running: loop {
126215
window.update(&display);
@@ -131,25 +220,32 @@ fn main() -> Result<(), core::convert::Infallible> {
131220
SimulatorEvent::KeyDown { keycode, .. } => {
132221
match keycode {
133222
Keycode::Up => stroke_width += 1,
134-
Keycode::Down => stroke_width = (stroke_width as i32 - 1).max(0) as u32,
223+
Keycode::Down => stroke_width = stroke_width.saturating_sub(1),
224+
Keycode::Space => {
225+
alignment = match alignment {
226+
StrokeAlignment::Inside => StrokeAlignment::Center,
227+
StrokeAlignment::Center => StrokeAlignment::Outside,
228+
StrokeAlignment::Outside => StrokeAlignment::Inside,
229+
}
230+
}
135231
_ => (),
136232
}
137233

138-
draw(&mut display, position, position, stroke_width)?;
234+
draw(&mut display, position, position, stroke_width, alignment)?;
139235
}
140236
SimulatorEvent::MouseButtonDown { point, .. } => {
141237
mouse_down = true;
142238
position = point;
143239

144-
draw(&mut display, point, position, stroke_width)?;
240+
draw(&mut display, point, position, stroke_width, alignment)?;
145241
}
146242
SimulatorEvent::MouseButtonUp { .. } => mouse_down = false,
147243
SimulatorEvent::MouseMove { point, .. } => {
148244
if mouse_down {
149245
position = point;
150246
}
151247

152-
draw(&mut display, point, position, stroke_width)?;
248+
draw(&mut display, point, position, stroke_width, alignment)?;
153249
}
154250
_ => {}
155251
}

0 commit comments

Comments
 (0)