Faster dashed line generation (#1027)
* Faster dashed lines generation * Add dashed_line benchmark
This commit is contained in:
parent
79cfdaa1f9
commit
d31f7d6522
|
|
@ -950,6 +950,7 @@ dependencies = [
|
||||||
"atomic_refcell",
|
"atomic_refcell",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cint",
|
"cint",
|
||||||
|
"criterion",
|
||||||
"emath",
|
"emath",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ All notable changes to the epaint crate will be documented in this file.
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
* Added `Shape::dashed_line_many` ([#1027](https://github.com/emilk/egui/pull/1027)).
|
||||||
|
|
||||||
## 0.16.0 - 2021-12-29
|
## 0.16.0 - 2021-12-29
|
||||||
* Anti-alias path ends ([#893](https://github.com/emilk/egui/pull/893)).
|
* Anti-alias path ends ([#893](https://github.com/emilk/egui/pull/893)).
|
||||||
|
|
|
||||||
|
|
@ -63,3 +63,10 @@ single_threaded = ["atomic_refcell"]
|
||||||
# Only needed if you plan to use the same fonts from multiple threads.
|
# Only needed if you plan to use the same fonts from multiple threads.
|
||||||
# It comes with a minor performance impact.
|
# It comes with a minor performance impact.
|
||||||
multi_threaded = ["parking_lot"]
|
multi_threaded = ["parking_lot"]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
criterion = { version = "0.3", default-features = false }
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "benchmark"
|
||||||
|
harness = false
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
|
||||||
|
use epaint::{pos2, Color32, Shape, Stroke};
|
||||||
|
|
||||||
|
fn single_dashed_lines(c: &mut Criterion) {
|
||||||
|
c.bench_function("single_dashed_lines", move |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
|
||||||
|
let line = [pos2(0.0, 0.0), pos2(50.0, 0.0), pos2(100.0, 1.0)];
|
||||||
|
|
||||||
|
for _ in 0..100 {
|
||||||
|
v.extend(Shape::dashed_line(
|
||||||
|
&line,
|
||||||
|
Stroke::new(1.5, Color32::RED),
|
||||||
|
10.0,
|
||||||
|
2.5,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
black_box(v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn many_dashed_lines(c: &mut Criterion) {
|
||||||
|
c.bench_function("many_dashed_lines", move |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
|
||||||
|
let line = [pos2(0.0, 0.0), pos2(50.0, 0.0), pos2(100.0, 1.0)];
|
||||||
|
|
||||||
|
for _ in 0..100 {
|
||||||
|
Shape::dashed_line_many(&line, Stroke::new(1.5, Color32::RED), 10.0, 2.5, &mut v);
|
||||||
|
}
|
||||||
|
|
||||||
|
black_box(v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(benches, single_dashed_lines, many_dashed_lines);
|
||||||
|
criterion_main!(benches);
|
||||||
|
|
@ -75,6 +75,18 @@ impl Shape {
|
||||||
shapes
|
shapes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Turn a line into dashes. If you need to create many dashed lines use this instead of
|
||||||
|
/// [`Self::dashed_line`]
|
||||||
|
pub fn dashed_line_many(
|
||||||
|
points: &[Pos2],
|
||||||
|
stroke: impl Into<Stroke>,
|
||||||
|
dash_length: f32,
|
||||||
|
gap_length: f32,
|
||||||
|
shapes: &mut Vec<Shape>,
|
||||||
|
) {
|
||||||
|
dashes_from_line(points, stroke.into(), dash_length, gap_length, shapes);
|
||||||
|
}
|
||||||
|
|
||||||
/// A convex polygon with a fill and optional stroke.
|
/// A convex polygon with a fill and optional stroke.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn convex_polygon(
|
pub fn convex_polygon(
|
||||||
|
|
@ -425,27 +437,27 @@ fn dashes_from_line(
|
||||||
let end = window[1];
|
let end = window[1];
|
||||||
let vector = end - start;
|
let vector = end - start;
|
||||||
let segment_length = vector.length();
|
let segment_length = vector.length();
|
||||||
|
|
||||||
|
let mut start_point = start;
|
||||||
while position_on_segment < segment_length {
|
while position_on_segment < segment_length {
|
||||||
let new_point = start + vector * (position_on_segment / segment_length);
|
let new_point = start + vector * (position_on_segment / segment_length);
|
||||||
if drawing_dash {
|
if drawing_dash {
|
||||||
// This is the end point.
|
// This is the end point.
|
||||||
if let Shape::Path(PathShape { points, .. }) = shapes.last_mut().unwrap() {
|
shapes.push(Shape::line_segment([start_point, new_point], stroke));
|
||||||
points.push(new_point);
|
|
||||||
}
|
|
||||||
position_on_segment += gap_length;
|
position_on_segment += gap_length;
|
||||||
} else {
|
} else {
|
||||||
// Start a new dash.
|
// Start a new dash.
|
||||||
shapes.push(Shape::line(vec![new_point], stroke));
|
start_point = new_point;
|
||||||
position_on_segment += dash_length;
|
position_on_segment += dash_length;
|
||||||
}
|
}
|
||||||
drawing_dash = !drawing_dash;
|
drawing_dash = !drawing_dash;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the segment ends and the dash is not finished, add the segment's end point.
|
// If the segment ends and the dash is not finished, add the segment's end point.
|
||||||
if drawing_dash {
|
if drawing_dash {
|
||||||
if let Shape::Path(PathShape { points, .. }) = shapes.last_mut().unwrap() {
|
shapes.push(Shape::line_segment([start_point, end], stroke));
|
||||||
points.push(end);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
position_on_segment -= segment_length;
|
position_on_segment -= segment_length;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue