Replies: 4 comments 1 reply
-
The code above won't work because the if branches produce I'm not sure whether the let backend: Box<dyn DrawingBackend> = if svg
{
Box::new(SVGBackend::new(&plot_filename, (width, height)))
}
else
{
Box::new(BitMapBackend::new(&plot_filename, (width, height)))
};
let root = DrawingArea::from(backend); |
Beta Was this translation helpful? Give feedback.
-
Use the generic typing. use plotters::{prelude::*, *};
type Canvas<B> = DrawingArea<B, coord::Shift>;
impl MyFigure {
fn plot<B, R>(&self, root: R) -> Result<(), DrawingAreaErrorKind<B::ErrorType>>
where
B: DrawingBackend,
Canvas<B>: From<R>, // or R: Into<...>
{
// Draw here
let root = Canvas::from(root);
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root).build_cartesian_2d(...)?;
...
Ok(())
}
}
if is_svg {
my_figure.plot(SVGBackend::new(&path, (w, h)))?;
} else {
my_figure.plot(BitMapBackend::new(&path, (w, h)))?;
}
// also works with
for b in big_backend.into_drawing_area().split_evenly(shape) {
my_figure.plot(b)?;
} |
Beta Was this translation helpful? Give feedback.
-
Thanks. Can one also abstract MyFigure.plot returns chart? I figured it works as argument but not as return type. So my solution was:
|
Beta Was this translation helpful? Give feedback.
-
The chart ( If you want to do a little customization during the plot function, a function can be designed with generics. use plotters::{prelude::*, *};
type Canvas<B> = DrawingArea<B, coord::Shift>;
type PResult<T, B> = Result<T, DrawingAreaErrorKind<<B as DrawingBackend>::ErrorType>>;
fn plot_on_backend<B, R>(opt: Opt, root: R) -> PResult<(), B>
where
B: DrawingBackend,
Canvas<B>: From<R>,
{
let root = Canvas::from(root);
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root).build_cartesian_2d(...)?;
...
opt.draw_foo(&mut chart, df, ...)?; // a customization
// or
// df.draw_foo(&mut chart, opt, ...)?;
...
Ok(())
} The method // impl Opt {
fn draw_foo<'a, DB, CT, I>(
&self,
chart: &mut ChartContext<'a, DB, CT>, // a generic chart
df: &DataFrame,
// other arguments below here
line: I, // like an iterator (works with 2D/3D points)
color: ShapeStyle,
label: &str,
font: f64,
) -> PResult<(), DB>
where
DB: DrawingBackend + 'a,
CT: CoordTranslate,
CT::From: Clone + 'static,
I: IntoIterator<Item = CT::From>,
I::IntoIter: Clone,
{
// Draw here!
// For example:
let line = LineSeries::new(line, color);
let anno = chart.draw_series(line)?;
if has_label {
anno.label(label).legend(move |c| {
EmptyElement::at(c)
+ PathElement::new([(gap, 0), (font - gap, 0)], color)
});
}
Ok(())
} |
Beta Was this translation helpful? Give feedback.
-
Hi,
how is one supposed to abstract over DrawingBackends?
Beta Was this translation helpful? Give feedback.
All reactions