1

Piston's graphics library provides a function for drawing a line between two points, but nothing for more than two. How do I efficiently draw a path through many points without having to draw a line for every segment?

Let's say I have the following code:

extern crate piston_window;

use piston_window::*;

fn main() {
    let mut window: PistonWindow = WindowSettings::new("Hello Piston!", [640, 480])
        .exit_on_esc(true).build().unwrap();
    while let Some(e) = window.next() {
        window.draw_2d(&e, |c, g| {
            clear([1.0; 4], g);
            let points = [
                [100., 100.],
                [200., 200.],
                [150., 350.],
                //...
            ];

            let mut prev = points[0];
            for pt in points[1..].iter() {
                line([0., 0., 0., 255.], 1., [
                    prev[0], prev[1], pt[0], pt[1]
                ], c.transform, g);
                prev = *pt;
            }
        });
    }
}

Is there a way to turn it into something like this?

extern crate piston_window;

use piston_window::*;

fn main() {
    let mut window: PistonWindow = WindowSettings::new("Hello Piston!", [640, 480])
        .exit_on_esc(true).build().unwrap();
    while let Some(e) = window.next() {
        window.draw_2d(&e, |c, g| {
            clear([1.0; 4], g);
            let points = [
                [100., 100.],
                [200., 200.],
                [150., 350.],
                //...
            ];
            path([0., 0., 0., 255.], 1., &points, c.transform, g);
        });
    }
}

I was referred to the lyon library but I don't know how to use it with piston.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
Sunjay Varma
  • 5,007
  • 6
  • 34
  • 51
  • 1
    How could you draw a path without drawing each segment? And what's inefficient about your for loop? – interjay Sep 25 '17 at 08:44
  • I'm looking for something that would draw all the segments continuously without having to send a drawing command for each individual segment. – Sunjay Varma Sep 25 '17 at 12:11

1 Answers1

1

How do I efficiently draw a path through many points without having to draw a line for every segment?

I'm not hugely familiar with Piston, but I would question your assumption that line() has some overhead that makes it inefficient to call repeatedly. In the end, whether you draw lots of lines or a library function draws them they will get drawn and there shouldn't be much difference in performance.

It doesn't look like there is currently a method to draw a sequence of lines between points, but it should just be a matter of looping through them as you were already doing. Using Vec::windows is a bit nicer though, as you don't need temporary mutable variables:

pub fn path<G>(color: Color, radius: Radius, points: &[[Scalar; 2]], transform: Matrix2d, g: &mut G)
where
    G: Graphics,
{
    for w in points.windows(2) {
        line(
            color,
            radius,
            [w[0][0], w[0][1], w[1][0], w[1][1]],
            transform,
            g,
        );
    }
}

You might consider making a feature request or a PR to the Piston project.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Peter Hall
  • 53,120
  • 14
  • 139
  • 204
  • Hi, I already filed [an issue on piston graphics](https://github.com/PistonDevelopers/graphics/issues/1089). They recommended I use lyon (see my question) but I haven't figured out how to do that yet. I am already drawing each line in a tight loop like you described. The overhead occurs when I start drawing around 200 lines. I plan to draw even more in the future so I need to speed this up with a path or something else. – Sunjay Varma Sep 27 '17 at 15:53
  • @SunjayVarma I don't think you got the point of "In the end, whether you draw lots of lines or a library function draws them they will get drawn and there shouldn't be much difference in performance." What makes you so sure that the slowdown you're experiencing is because of the overhead of calling `line`? Have you profiled it? – trent Sep 27 '17 at 20:34
  • Yes I've profiled it. That's how I know. I timed only the loop with the line calls and just executing that will make me drop a frame because it takes so long as I add more lines. – Sunjay Varma Sep 28 '17 at 06:25