Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plot: Line styles #482

Merged
Prev Previous commit
Next Next commit
apply suggestions
  • Loading branch information
EmbersArc committed Jul 3, 2021
commit 80936ba876da11bd2dd0881eade0d85fa25ae10e
86 changes: 18 additions & 68 deletions egui/src/widgets/plot/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,25 @@ impl Value {
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum LineStyle {
Solid,
Dotted { px: f32 },
Dashed { px: f32 },
Dotted { spacing: f32 },
Dashed { length: f32 },
}

impl LineStyle {
pub fn dashed_loose() -> Self {
Self::Dashed { px: 10.0 }
Self::Dashed { length: 10.0 }
}

pub fn dashed_dense() -> Self {
Self::Dashed { px: 5.0 }
Self::Dashed { length: 5.0 }
}

pub fn dotted_loose() -> Self {
Self::Dotted { px: 10.0 }
Self::Dotted { spacing: 10.0 }
}

pub fn dotted_dense() -> Self {
Self::Dotted { px: 5.0 }
Self::Dotted { spacing: 5.0 }
}

fn style_line(
Expand All @@ -82,20 +82,26 @@ impl LineStyle {
}
shapes.push(Shape::line(line, stroke));
}
LineStyle::Dotted { px } => {
LineStyle::Dotted { spacing } => {
// Take the stroke width for the radius even though it's not "correct", otherwise
// the dots would become too small.
let mut radius = stroke.width;
if highlight {
radius *= 2f32.sqrt();
}
points_from_line(&line, *px, radius, stroke.color, shapes)
shapes.extend(Shape::dotted_line(&line, stroke.color, *spacing, radius))
}
LineStyle::Dashed { px } => {
LineStyle::Dashed { length } => {
if highlight {
stroke.width *= 2.0;
}
dashes_from_line(&line, *px, stroke, shapes);
let golden_ratio = (5.0_f32.sqrt() - 1.0) / 2.0; // 0.61803398875
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hint: let golden_ratio = (5.0_f32.sqrt() + 1.0) / 2.0; // 1.61803398875 to avoid the division later :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but made redundant by the other change :)

shapes.extend(Shape::dashed_line(
&line,
stroke,
*length,
1.0 / golden_ratio,
))
}
}
}
Expand All @@ -107,68 +113,12 @@ impl ToString for LineStyle {
fn to_string(&self) -> String {
match self {
LineStyle::Solid => "Solid".into(),
LineStyle::Dotted { px } => format!("Dotted{}Px", px),
LineStyle::Dashed { px } => format!("Dashed{}Px", px),
LineStyle::Dotted { spacing } => format!("Dotted{}Px", spacing),
LineStyle::Dashed { length } => format!("Dashed{}Px", length),
}
}
}

fn points_from_line(
line: &[Pos2],
spacing: f32,
radius: f32,
color: Color32,
shapes: &mut Vec<Shape>,
) {
let mut position_on_segment = 0.0;
line.windows(2).for_each(|window| {
let start = window[0];
let end = window[1];
let vector = end - start;
let segment_length = vector.length();
while position_on_segment < segment_length {
let new_point = start + vector * (position_on_segment / segment_length);
shapes.push(Shape::circle_filled(new_point, radius, color));
position_on_segment += spacing;
}
position_on_segment -= segment_length;
});
}

fn dashes_from_line(line: &[Pos2], dash_length: f32, stroke: Stroke, shapes: &mut Vec<Shape>) {
let gap_length = 0.5 * dash_length;
let mut position_on_segment = 0.0;
let mut drawing_dash = false;
line.windows(2).for_each(|window| {
let start = window[0];
let end = window[1];
let vector = end - start;
let segment_length = vector.length();
while position_on_segment < segment_length {
let new_point = start + vector * (position_on_segment / segment_length);
if drawing_dash {
// This is the end point.
if let Shape::Path { points, .. } = shapes.last_mut().unwrap() {
points.push(new_point);
}
position_on_segment += gap_length;
} else {
// Start a new dash.
shapes.push(Shape::line(vec![new_point], stroke));
position_on_segment += dash_length;
}
drawing_dash = !drawing_dash;
}
// If the segment ends and the dash is not finished, add the segment's end point.
if drawing_dash {
if let Shape::Path { points, .. } = shapes.last_mut().unwrap() {
points.push(end);
}
}
position_on_segment -= segment_length;
});
}

// ----------------------------------------------------------------------------

/// A horizontal line in a plot, filling the full width
Expand Down
2 changes: 2 additions & 0 deletions epaint/src/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ impl Shape {
}
}

/// Creates equally spaced filled circles from a line.
fn points_from_line(
line: &[Pos2],
spacing: f32,
Expand All @@ -213,6 +214,7 @@ fn points_from_line(
});
}

/// Creates dashes from a line.
fn dashes_from_line(
line: &[Pos2],
stroke: Stroke,
Expand Down