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] "attempt to subtract with overflow" When plotting polygons out of bounds #405

Open
egordm opened this issue Aug 13, 2022 · 1 comment
Labels
bug Something isn't working

Comments

@egordm
Copy link
Contributor

egordm commented Aug 13, 2022

Describe the bug

The issue I am having is that while plotting polygons out of bounds, I get the following error:

thread 'main' panicked at 'attempt to subtract with overflow', .../plotters/plotters-backend/src/rasterizer/polygon.rs:98:54
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I have looked a bit into the issue, and while the error happens in polygon.rs:98:54, the actual problem is in the path.rs:38.

What seems to be happening is that as the polygon goes out of bounds, it is clipped to stay within the axes.
This clipping introduces a lot of colinear points. The check for colinearity does not seem to catch all these cases.

If we the example listed in the reproduction section and look what compute_polygon_vertex does with the first three points:

The variables until line 38

let triple = [ // First three points clipped to the area and translated to backend coords
  [92, 728],
  [40, 728],
  [315, 728],
];

// Tangent and normal vector between triple[0] and triple[1]
let a_t = (-1, 0);
let a_n = (-0, -1);

// Tangent and normal vector between triple[1] and triple[2]
let b_t = (-1, 0);
let b_n = (0, 1);

Multiplying triple[1] with a_n and b_n yields different points and therefore passes the colinearity test on line 38.
But, on line 68, x and y are not updated and therefore stay at INTY.

To Reproduce
You can reproduce it using this example:

use plotters::prelude::*;

const OUT_FILE_NAME: &'static str = "plotters-doc-data/sample.png";
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let root_area = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area();
    root_area.fill(&WHITE)?;

    let mut cc = ChartBuilder::on(&root_area)
        .build_cartesian_2d(-10.0f64..10.0, -10.0f64..10.0)?;

    let pts = [
        (-8.9312, -20.0187),
        (-10.1495, -22.5886),
        (-11.1510, -24.7366),
        (-4.3868, -12.9378),
        (9.4977, 14.7489)
    ];

    cc.draw_series(LineSeries::new(pts, RED.stroke_width(2)))
        .unwrap();

    // To avoid the IO failure being ignored silently, we manually call the present function
    root_area.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir");
    println!("Result has been saved to {}", OUT_FILE_NAME);
    Ok(())
}

#[test]
fn entry_point() {
    main().unwrap()
}

Possible fix
See the pull request below.

Changing the colinearity test to the following fixes the issue. It compares the delta x / delta y for both the a and b vectors.

    // Check if 3 points are colinear. If so, just emit the point.
    if a_t.1 * b_t.0 == a_t.0 * b_t.1 {
        buf.push((b_p.0 as i32, b_p.1 as i32));
        return;
    }

Version Information
I was able to reproduce it on 0.3.2 and on the current master branch.

Thanks in advance

@egordm
Copy link
Contributor Author

egordm commented Sep 15, 2022

@38

Thanks for the merge.
Would it also be possible to release a new version of plotters_backend?
I believe the issue can be closed afterward.

raldone01 pushed a commit to ink-feather-org/plotters that referenced this issue Jan 8, 2023
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