2

when i draw a lot of lines, the apps takes a long time to finish drawing. My goal is to connecting of the points in a1[] to form a line. Is there is faster way of doing this? please help!

           > $ for (int i = 0; i < x.length - 1; i++) {
       >        _canvas.drawLine(a1[i].x, a1[i].y, a1[i + 1].x, a1[i + 1].y,_paint);}
mgiuffrida
  • 3,299
  • 1
  • 26
  • 27
Evans Kakpovi
  • 312
  • 1
  • 5
  • 12

3 Answers3

6

Use draw lines. Pack the points into a float[] with 2 points for each point in the line then do this:

if (count >= 4) {
    if ((count & 2) != 0) {
        canvas.drawLines(pointlist, 0, count-2, linePaint);
        canvas.drawLines(pointlist, 2, count-2, linePaint);
    }
    else {
        canvas.drawLines(pointlist, 0, count, linePaint);
        canvas.drawLines(pointlist, 2, count - 4, linePaint);
    }
}

Where count is the number usable length in the float[] of points. Drawlines goes by 4 floats per segment, but if you stagger them like that you get the result you want without needing to waste 2x the memory and you can effectively move the points if need be.

Tatarize
  • 10,238
  • 4
  • 58
  • 64
  • 1
    It seems a bit slow as compared to single DrawLines call for large no of points – Ana Feb 26 '16 at 06:50
  • You must be doing something else wrong then because it's orders of magnitude faster. I mean maybe if it were software only or whatever, but it's much much faster than a loop. Are you like creating the points to draw the lines or actually storing the points in that datastructure from the get go? – Tatarize Feb 26 '16 at 07:15
  • 1
    Oh, wait you're talking a single drawlines call, yeah, it should perhaps be half the speed. It's just that the points are much more memory compact which matters a lot. You're still doing 2 calls rather than 1 call. And each call to the canvas costs you some time. If you don't care about the memory or need the lines broken apart, you'd be better off duplicating the numbers and doing it thusly. – Tatarize Feb 26 '16 at 07:22
  • The advantage here is if you're doing a series of lines, you can get connected line segments and change one bit of memory to move a point, and the limited memory on Android means taking half as much memory is likely worth it from whatever tiny hit you might take. It matters when you're at like 100k lines a lot. Or if you are going to be changing the points a lot and don't want to do multiple writes to each line segment important. – Tatarize Feb 26 '16 at 07:26
2

Use Canvas.drawLines(float[] pts, Paint paint);

Using Canvas.drawLines instead of Canvas.drawLine i have halved the time of drawing.

I have to draw 12 lines with 5000 points for line and the time of drawing with this code is 2393 milliseconds instead of 6000 milliseconds using Canvas.drawLine() method.

            int lineIndex = 0;
            float[] lines = new float[a1.length * 4];
            for (int i = 0; i < a1.length-1; i++) // -1 to deal with last point
            {
                    lines[lineIndex++] = a1[i].x;
                    lines[lineIndex++] = a1[i].y;
                    lines[lineIndex++] = a1[i + 1].x
                    lines[lineIndex++] = a1[i + 1].y;
            }
            _canvas.drawLines(lines, _paint);
Ryan M
  • 18,333
  • 31
  • 67
  • 74
Giuseppe Laera
  • 272
  • 2
  • 14
  • 1
    This routine is actually solid if and only if, you do not actually build the lines[] element in the draw. You can call set a dirty flag when things change and build it, when it's dirty maybe one time in the draw routine. But, don't build a temporary object and use that in the draw every time. You'd want to keep it for everytime draw is called and use it, and save a dirty flag that requires you rebuild it. Also, for best results keep the original object and replace those elements in memory since garbage collecting that in any case other than it's gotten larger is a resource hog. – Tatarize Oct 14 '19 at 21:44
-1

Try creating a Path first, then calling _canvas.drawPath():

Path p = new Path();
p.moveTo(a1[0].x, a1[0].y);
for (int i = 1; i < x.length; i++) {
    p.lineTo(a1[i].x, a1[i].y);
}
_canvas.drawPath(p, _paint);
mgiuffrida
  • 3,299
  • 1
  • 26
  • 27
  • 6
    drawPath uses the CPU and is therefore slow. If the path is too long you might get an error. Better use drawLine or drawLines because it is hardware-accelerated: [see this link](http://stackoverflow.com/questions/15039829/drawing-paths-and-hardware-acceleration). And if you draw many lines, you should prepare the array of line-points and then use the method drawLines. This is only one call to the GPU instead of many calls when drawing each single line segment by drawLine – Matthias Apr 24 '14 at 08:42