Re: graphing/data visualisation Wade Tregaskis Thu Jun 12 12:01:41 2008
I'm new to the list, so I'm sorry if this question has been asked and answered, but I couldn't find anything while searching the archives. I'm trying to develop a (simple) visualisation tool for inspecting waveforms. These would be vectors of about 1600 points, and the problem we are facing is how to get a feel for the diversity in shape/standard deviation etc. What I have in mind is something that would allow us to quickly pan through our data, with the option of examining individual waveforms as well as looking at batches of ~100-1000 in one plot. The code I have right now will load a batch of waveforms from a file upon request, then create a CGPathRef containing all the waveforms. The problem is that when I call CGContextDrawPath, the drawing takes forever ( ~10 mins). I realise that this brute force method might not be the best approach, as I would be asking Quartz to draw roughly 1600*100 individual path elements. My question, then, is if anyone has a more efficient way of doing this?
The most important suggestions I have for you are:a) Use a [pixel] line width of 1.0 or less. The bezier path drawing for such cases uses a different algorithm compared with >1.0, and is several orders of magnitude faster. b) Ensure you keep around your NSBezierPath/CGPathRefs if you intend to redraw them. c) I think there's performance caveats with using a single CGPathRef containing multiple subpaths... I can't recall exactly what, though... in any case, to facilitate (b) above it's probably best to use a separate CGPathRef for each waveform.
In certain configurations it's possible to render tens of millions of [semi]contiguous line segments in reasonable time - in the order of seconds - even on fairly old hardware. The most critical part of that is point (a), above.
Try using CGContextStrokeLineSegments instead. The basic problem your seeing is that Quartz is spending time creating a single path, whereas CGContextStrokeLineSegments will simply draw each pair of points as a single line (i.e. the lines are not joined).
Whether drawing lines segmented is faster or not depends very much on several things... if you're drawing a very large number of segments into a relatively small pixel area, the cost of all those extra reads and redundant writes can hurt more than calculating intersections for a contiguous line. Typically this approach isn't faster for <=1.0 width lines. For >1.0, it may be faster.
I'd suggest you look into drawing stuff with OpenGL. VBO's should give you the best performance - without the overhead of having thousands of function calls.
In my experience vertex arrays are actually the best way for static data, and for dynamic data vertex arrays or mere immediate mode are superior. They also scale indefinitely, whereas VBOs seem to hit some opaque limit and cause crashes when subsequently used. Line primitives don't look very good, though, and the look will vary across graphics cards. They typically have pretty serious rasterisation artefacts, for lines greater than 1.0 wide, when the line segments cross a 45° boundary. They also don't tend to have consistent thickness across curves (e.g. the tips of a sine wave will be thinner than the middle).
You can use textured lines (e.g. glAArg), but the performance is nearly an order of magnitude less (for glAArg specifically; improvements may be possible), and there are numerous visual glitches (most critically, that very short line segments aren't drawn at all, so parts of - or even the whole of - your waveforms may disappear).
_______________________________________________ Do not post admin requests to the list. They will be ignored. Quartz-dev mailing list ([EMAIL PROTECTED]) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/quartz-dev/alexiscircle%40gmail.com This email sent to [EMAIL PROTECTED]