Reputation: 35
I am trying to generate a plot with both line and point series using plotters. I have got the chart successfully displaying a line series, however the point series throws a bunch of errors. An abbreviated version of the code I am using for the point series is as follows. I think the problem is how I am specifying the point size but I am not sure how to do it correctly. Any assistance would be great!
fn main() {
let points: Vec<(f64, f64)> = vec![(2.0, 2.0), (3.0, 3.0 ), (4.0, 4.0), (8.0, 8.0)];
generate_plot(&points);
}
fn generate_plot(points: &Vec<(f64, f64)>) -> Result<(), Box<dyn std::error::Error>> {
let root = BitMapBackend::new("C:\\Users\\ppp\\Documents\\Rust\\tpy\\Data\\test.png", (800, 800)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.build_cartesian_2d(0f64..10f64, 0f64..10f64)?;
chart.configure_mesh().draw()?;
chart.draw_series(PointSeries::new(points.clone(), 5, &BLUE))?; //This does not work. I can get a line series to plot without issue.
root.present()?;
Ok(())
}
Errors:
error[E0282]: type annotations needed --> src\main.rs:29:11 | 29 | chart.draw_series(PointSeries::new(points.clone(), 5, &BLUE))?; //This does not work. I can get a line series to plot without issue.
| ^^^^^^^^^^^ cannot infer type of the type parameterB
declared on the associated functiondraw_series
| help: consider specifying the generic arguments | 29 | chart.draw_series::<B, E, R, plotters::series::PointSeries<'_, (f64, f64), Vec<(f64, f64)>, E, i32>>(PointSeries::new(points.clone(), 5, &BLUE))?; //This does not work. I can get a line series to plot without issue. |
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++error[E0283]: type annotations needed --> src\main.rs:29:23 | 29 | chart.draw_series(PointSeries::new(points.clone(), 5, &BLUE))?; //This does not work. I can get a line series to plot without issue.
| ^^^^^^^^^^^^^^^^ cannot infer type of the type parameterE
declared on the structPointSeries
| = note: multipleimpl
s satisfying_: PointElement<(f64, f64), i32>
found in theplotters
crate: - impl<Coord, Size> PointElement<Coord, Size> for Circle<Coord, Size> where Size: SizeDesc; - impl<Coord, Size> PointElement<Coord, Size> for Pixel where Size: SizeDesc; - impl<Coord, Size> PointElement<Coord, Size> for TriangleMarker<Coord, Size> where Size: SizeDesc; - impl<Coord, Size> PointElement<Coord, Size> for plotters::element::Cross<Coord, Size> where Size: SizeDesc; note: required by a bound inplotters::series::PointSeries::<'a, Coord, I, E, Size>::new
--> C:\Users\ppp.cargo\registry\src\github.com-1ecc6299db9ec823\plotters-0.3.4\src\series\point_series.rs:27:8 | 27 | E: PointElement<Coord, Size>, |
^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound inplotters::series::PointSeries::<'a, Coord, I, E, Size>::new
help: consider specifying the type argument in the function call | 29 |
chart.draw_series(PointSeries::new::(points.clone(), 5, &BLUE))?; //This does not work. I can get a line series to plot without issue.
| +++++
Upvotes: 2
Views: 481
Reputation: 421
Giving a series of points, the compiler doesn't know which type of PointElement
you want to create. (Cross
or TriangleMarker
or Circle
or Pixel
)
You need to choose the struct for E
, e.g.
change
chart.draw_series(PointSeries::new(
points.clone(),
5,
&BLUE,
))?;
to
chart.draw_series(PointSeries::<_, _, Circle<_, _>, _>::new(
points.clone(),
5,
&BLUE,
))?;
cannot infer type of the type parameter E
multiple impls satisfying _: PointElement<(f64, f64), i32> found in the plotters crate
The type E
(a struct which implement PointElement
trait) cannot be inferred, because there are multiple candidates, we have to specify which struct we want to create.
In the PointSeries::new, it use E::make_point
:
impl<'a, Coord, I: IntoIterator<Item = Coord>, E, Size: SizeDesc + Clone>
PointSeries<'a, Coord, I, E, Size>
where
E: PointElement<Coord, Size>,
{
/// Create a new point series with the element that implements point trait.
/// You may also use a more general way to create a point series with `of_element`
/// function which allows a customized element construction function
pub fn new<S: Into<ShapeStyle>>(iter: I, size: Size, style: S) -> Self {
Self {
data_iter: iter.into_iter(),
size,
style: style.into(),
make_point: &|a, b, c| E::make_point(a, b, c),
// ^
// E is a struct which implement PointElement<Coord, Size>
}
}
}
But E
have many possible choices:
impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Cross<Coord, Size> {
fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
Self::new(pos, size, style)
}
}
impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for TriangleMarker<Coord, Size> {
fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
Self::new(pos, size, style)
}
}
impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Circle<Coord, Size> {
fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
Self::new(pos, size, style)
}
}
impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Pixel<Coord> {
fn make_point(pos: Coord, _: Size, style: ShapeStyle) -> Self {
Self::new(pos, style)
}
}
You have to specify the struct you want to create in generic argument. (it's ok to fill other arguments with underscore to auto infer)
PointSeries<'a, Coord, I, E, Size>
^
DrawingBackend
(BitMapBackend
in this case).Upvotes: 1