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

[BUG] Out-of-range data is deformed (line slopes changed) #689

Open
werner291 opened this issue Mar 27, 2025 · 2 comments
Open

[BUG] Out-of-range data is deformed (line slopes changed) #689

werner291 opened this issue Mar 27, 2025 · 2 comments
Labels
bug Something isn't working

Comments

@werner291
Copy link

werner291 commented Mar 27, 2025

Describe the bug

I'm plotting a simple test plot of the equation y = x^2.

// Simple chart setup for testing
    let root = SVGBackend::new("test.svg", (640, 480)).into_drawing_area();
    root.fill(&WHITE).unwrap();

    let mut chart = ChartBuilder::on(&root)
        .caption("Test Chart", ("sans-serif", 50).into_font())
        .x_label_area_size(30)
        .y_label_area_size(30)
        .margin(5)
        .build_cartesian_2d(0..10, 0..10)
        .unwrap();

    chart.configure_mesh().draw().unwrap();

    chart
        .draw_series(LineSeries::new(
            (0..10).map(|x| (x, x * x)),
            &RED,
        ))
        .unwrap();

    root.present().expect("Unable to write result to file");

This produces the following plot:

Image

As you can see, the data goes out of range. What I would expect is that either:

  • The line crosses outside the chart rectangle.
  • The line is clipped off at the boundary
  • The code produces an error/panic

However, with the current implementation, the slope of the line is instead adjusted between x=3 and x=4, and for x > 4, it just goes flat against the top boundary. I consider this a severe deformation of the input data.

Sure, in this example I artificially created some data that goes out-of-bounds, but with datasets in the wild, you might accidentally create artifacts in the plot that may lead to incorrect conclusions being drawn.

The root cause is this:

/// Used for 2d coordinate transformations.
pub struct BackendCoordOnly;

impl CoordMapper for BackendCoordOnly {
    type Output = BackendCoord;
    fn map<CT: CoordTranslate>(coord_trans: &CT, from: &CT::From, rect: &Rect) -> BackendCoord {
        rect.truncate(coord_trans.translate(from))
    }
}

Unfortunately, the truncation behavior here is a bit naïve, as this also applies to the endpoints of lines.

Version Information

plotters = { version = "0.3.7", default-features = false, features = ["svg_backend", "all_series","colormaps","full_palette","histogram"] }

@werner291 werner291 added the bug Something isn't working label Mar 27, 2025
@werner291
Copy link
Author

Personally, I'd actually prefer to just not truncate the coordinates at all, something like:

/// Used for 2d coordinate transformations.
pub struct BackendCoordOnly;

impl CoordMapper for BackendCoordOnly {
    type Output = BackendCoord;
    fn map<CT: CoordTranslate>(coord_trans: &CT, from: &CT::From, rect: &Rect) -> BackendCoord {
        coord_trans.translate(from) // note removed call to "truncate"
    }
}

The whole way I discovered this bug in the first place was because I was trying to draw some text outside the bounds of the chart (underneath the X-axis) and was very confused as to why the text would not go further down. (Only the text anchor is clipped to the rectangle btw, the text itself happily crosses outside.)

@werner291
Copy link
Author

Alternatively, perhaps consider letting the backend handle clipping?

SVG, for instance, offers the <clipPath> and <mask> elements

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant