I am using core plot (0.4) to render a graph and it is working fine. However (especially when on the iPad) the graph can take a while to render. I have added a UIActivityIndicatorView to the graph which shows up when the graphs starts to be drawn, but I can't find any event to hook that I can use to stop the spinner.
I have tried using the numberForPlot method and detecting when the last datapoint has been requested, but this is called multiple times for each line on the scatterGraph, so I can't easily use this. Is there any sort of graph rendered event that I can hook for this?
If you're doing [graph reloadData] to update the graph, can you just bracket that call with your indicator start/stop calls? I think that core-plot does everything in the main thread.
Core Plot uses Core Animation for all rendering. A single graph contains many CA layers that are rendered independently. -reloadData just tells the graph to update its data cache next time it draws and tells Core Animation that it needs to be redrawn. Similarly, just bracketing the data source calls only captures the data caching that happens before the render. You would miss the actual drawing time and would never know if Core Animation re-rendered the graph at another time, such as after a resize.
If you only care about the time to render the plot and not the other parts of the graph, one way to do this would be to subclass CPTScatterPlot and override the -renderAsVectorInContext: method. Bracket the calls to super with your activity indicator code.
Related
I'd like to make use of an ILNumerics 3D plot but I would like to add a slider control. The slider would be responsible for filtering values on the backing data set so I can visualize my data under certain conditions. Basically, user moves slider and plot automatically updates based on criteria set by slider.
The functionality that I am looking for is very similar to Mathematica's manipulate feature. Is this type of functionality possible?
Thanks!
Yes. Interactivity is one specialty of ILNumerics. All objects can be modified dynamically. Simply place your code into the event handler of the slider and change everyting you need there.
Afterwards, call Configure() on the affected part of the scene in order to lock your changes in. ILPanel.Refresh() causes an immediate refresh of the display.
I've been working on custom drawings using drawRect in UIView subclasses. That's cool, but you have to wait until the end of the run loop for drawRect to be called and I'm wondering how you can control frame by frame animations where you change the drawings over time, or if this is possible? Perhaps Quartz isn't really designed for this type of animated graphics? I gather that perhaps it is designed for static drawings that don't change so frequently.
Quartz by itself its not able to sustain a high frame rate, due to its need to redraw everything each time. But you can have Quartz work together with CoreAnimation to have Quartz based animations. The idea behind this is that you can cache previously drawn content inside CALayer objects and then use CoreAnimation to create the continuous drawing effect.
A good example of this technique can be see in the AccelerometerGraph sample code provided by Apple. Inside this sample the UIView subclass that uses this technique is the "GraphView" object. Basically this object draws as completely new only a portion of the graph (the newly generated segments), backs it in a dedicated layer and then animates the layers in order to provide the "scrolling graph" animation.
Clearly this technique works only when you have full control of the drawing elements and can manage this incremental way of adding objects in the screen. Of course things become much more complicated when you must redraw many different parts of the screen and you need to modify previously generated layers.
Anyway have a look at the mentioned code: it is quite interesting.
Your app should exit to the run loop before each frame. Do all your custom frame animation setup between each frame. So frame-by-frame drawing in drawRect should work just fine. This can work in iOS apps at a 60 Hz frame update rate, not just for static views, as long as all your methods between frame times, as well as your drawRects, are fast enough. Chop them up if needed.
Is there a way using Core Plot to have periodic labels assigned to data plots? Such as 10-20 labels listed across my plot points.
Here is an example (mockup) of what I am hoping to do:
Is it possible to do this when the graph loads, or maybe when you swipe across the graph you see the data points showing their call out?
You'll have to draw the callout bubbles yourself, but it is possible to label data points. To make a callout, you could subclass CPTextLayer and have it draw the bubble around the text. Use this new class to make your labels.
You can implement a datasource method to inform Core Plot which data points should be labeled and provide your own labels if you wish (this is how you'd do the callouts). You can also respond to touch events (click events on the Mac) and show a label for the point that was touched. You have to touch each point individually--you won't get the delegate notification if you drag from one point to the next.
The examples included with Core Plot demonstrate how both techniques work.
I am very new to Iphone programming with Objective-C but I have picked up pretty fast in the last 1 month.
I have an application that reads data from a .csv which I then use to plot a continous graph on the Iphone. The problem is that there are close to 84,000 data points ( a major requirement) and the current design I used with Quartz 2D has helped to make the required plots but it takes close to 3mins for the UIView to show the infinitely long plot I desire.
The solution I am looking for is this
I intend to use a function in normal C language to sequential access the file within a thread and pass it to the drawing function which will then update the screen as the data arrives so that the user has a feel of how the data is been plotted continously. The problem I have however is that the CGRECT drawing function and the setNEEDSDisplay would just take all the points at once and display on the UIView,
How do I update only specific point on the UIView as the data arrives without clearing the whole View
You'll want to use setNeedsDisplayInRect as described here:
Drawing incrementally in a UIView (iPhone)
Have you looked at using Core Plot?
http://code.google.com/p/core-plot/
It's a little hard to figure out, google for example uses. But it may be able to handle what you need through selective plotting of large data sets.
I am trying to implement simple paint functionality in my iPhone app. I tried updating a bitmap with a bitmap brush, and I also tried this tutorial.
Both methods have the same problem, even though the code is almost totally different. It happens only on the device - the simulator works fine.
When I touch the screen and move my finger, the screen does not get updated. When I pause or lift my finger, then the screen gets updated. This is not a very good user experience!
I tried calling drawRect from touchesMoved directly, but found that the drawing context (which I retrieve using UIGraphicsGetCurrentContext) is invalid for many of the calls, so painting the screen myself for every touchesMoved doesn't work.
Any ideas?
Thanks for any help, this has been quite frustrating!
Henning
It sounds to me like you're not giving the main run loop a chance to update the display. Your drawing code may be taking longer to execute than the time between touch events, so the display is never updated. When you lift your finger, it does the updating because it's no longer burdened with your drawing.
You might consider optimizing your drawing to speed it up (drawing only within the dirty region of the screen, for example), using something like NSOperationQueue to queue up the heavy calculations of your drawing to run on a background thread, or selectively dropping touch drawing events to keep your response smooth.
One additional possibility is placing your heavy drawing code in a separate method and calling it via performSelector:withObject:afterDelay, with a 10 millisecond (or smaller) delay. This might give the main run loop a chance to update the display with its current state. I haven't tested this, but if I remember correctly I've seen this work.
You can't directly call drawRect:. To refresh your screen on demand, try calling [self setNeedsDisplay] from your touchesMoved method, which will setup the proper contexts for a call to drawRect:.