plotters
plotters copied to clipboard
[BUG] "attempt to subtract with overflow" When plotting polygons out of bounds
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
@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.