High Dot Drawing Graph on iOS

I am looking for a way to draw a line chart with a lot of dots (up to 10,000) effectively on iOS. The graph receives real-time data and needs to be updated several times per second. I am trying to find a way to draw a graph efficiently so that it does not maximize the processor and block the main thread while drawing.

I am currently creating a UIBezierPath for a line chart, in a background thread, adding all the dots and drawing it in CALayer (with asynchronous drawing enabled). It is not very fast, maximizes the processor, and the drawing is so slow that the user interface becomes lagging. I plan the data in real time, and theoretically I can use the same UIBezierPath every time and just add new points, however old values ​​are discarded after a while, that is, points for deleted values ​​should be deleted from Bezier, which is impossible.

I haven’t found anything in effectively building large datasets on iOS, but I hope there are ways to use the GPU to improve performance.

+5
source share
3 answers

I finally found an implementation for drawing graphics with OpenGL: https://github.com/syedhali/EZAudio/blob/master/EZAudio/EZAudioPlotGL.m

This is actually quite simple, and the performance improvements are huge.

For devices with an A7 chip (or newer), it will probably be even faster to draw a graph with metal, which should also be quite simple. There are several guides on how to do this: https://www.raywenderlich.com/77488/ios-8-metal-tutorial-swift-getting-started

0
source

I had this situation a few years ago (on the iPhone 4 days).

I used CGMutablePathRef , to which I added points, using CGPathMoveToPoint for the first point, and CGPathAddLineToPoint for subsequent points.

To get acceptable performance, I saved the data points in a C array (not NSArray ). In addition, when building a point, if its display coordinates coincide with the last drawn point, I just missed the call to CGPathAddLineToPoint . (This often happens when you have more data points than pixels).

I do not remember the exact time of the drawing, but it was amazingly fast.

+1
source

Instead of drawing dots using UIBezierPath , you can configure the CGBitmapContext and then draw the dots “manually”, for example.

 color = (0xFF << 24) | (blue << 16) | (green << 8) | (red); // AABBGGRR for (loop = 0; loop < count; loop++) { index = indices[loop]; self.pixels[index] = color; } 

where self.pixels is the buffer you used to create the CGBitmapContext. Then in drawRect:

 CGContextRef c = UIGraphicsGetCurrentContext(); CGImageRef image = CGBitmapContextCreateImage(self.imageContext); CGContextDrawImage(c, self.bounds, image); CGImageRelease(image); 

I think you will find that it will be significantly faster (and less) than using CGPath or UIBezierPath.

0
source

Source: https://habr.com/ru/post/1240960/


All Articles