Using CPTAnnotation in CorePlot DatePlot (iOS) - objective-c

I am Using CorePlot in my app, and I want to display a annotation over the plotSymbol. I haven't found any code in the sample projects of the latest 0.9 version of CorePlot. After some research i have come to this point:
- (void)scatterPlot:(CPTScatterPlot *)plot plotSymbolWasSelectedAtRecordIndex:(NSUInteger)index
{
CPTLayerAnnotation *annot = [[CPTLayerAnnotation alloc]initWithAnchorLayer:graph];
CPTBorderedLayer * logoLayer = [[(CPTBorderedLayer *) [CPTBorderedLayer alloc] initWithFrame:CGRectMake(10,10,100,50)] autorelease];
CPTFill *fillImage = [CPTFill fillWithImage:[CPTImage imageForPNGFile:#"whatEver!"]];
logoLayer.fill = fillImage;
annot.contentLayer = logoLayer;
annot.rectAnchor=CPTRectAnchorTop;
[graph addAnnotation:annot];
}
But its obviously not working.... Can anybody help me?
My goal is to get an annotation over the selected plot symbol, similar to annotations in MKMapView.
Update
It is a DatePlot, just to clarify things and it is working with time intervals since 2001 on the x-axis.

There are several examples of this in the Core Plot example apps. The gradient scatter plot in the Plot Gallery app (and several other apps as well) use this method to attach a text label to the selected point. The point selection demo in the Mac version of CPTTestApp uses a second scatter plot to draw a crosshairs over the selected point.
Remember to set the plotSymbolMarginForHitDetection property on the scatter plot, too. The default is 0, which means you have to hit the center of the point exactly to register a touch.
There are two types of annotation in Core Plot. A CPTLayerAnnotation is anchored to a given Core Animation layer (the graph in your case). A CPTPlotSpaceAnnotation is anchored to a plot space coordinate (== data coordinate). Your comment below makes it sound like you want to use a plot space annotation instead of a layer annotation.

Related

How can I get and set the position of a draggable legend in matplotlib

I'm trying to get and set the position of a draggable legend in matplotlib. My application consists of an interactive GUI, which has a redraw/plot function that should perform the follow steps:
save the position of the current legend.
clear the current axes and perform various plotting operations, which may or may add labels to their plots.
build a new draggable legend (ax.legend().draggable()) and restore the old position of the legend.
In between these steps the user is free to drag the legend around, and the goal is to persist the legend position when the plots are redrawn.
My first approach was to use oldpos = legend.get_bbox_to_anchor() and legend.set_bbox_to_anchor(oldpos) in steps 1 and 3. However this causes to move the legend completely off the visible area.
Note that I have to use ax.legend() and cannot use fig.legend(lines, labels), since step 2 is completely decoupled, i.e., I don't know anything about lines and labels in step 3. According to answers to the question How to position and align a matplotlib figure legend? there seems to be a difference between these two possibilities regarding axes or figure coordinates. Obviously my problem calls for figure coordinates, but I haven't fully understood how to convert the bbox to a "bbox in figure coordinates".
The even more severe problem I just realized is that apparently legend.get_bbox_to_anchor() always seems to return the same values irrespective of the drag position. So maybe the anchor can only be (ab-)used to manipulate the position of static legends? Is there another/proper way to save and restore the position of a draggable legend?
By looking at the implementation of Legend I found out that there is an undocumented property _loc, which exactly does what I want. My solution now looks astonishingly simple:
oldLegPos = ax.get_legend()._loc
# perform all plotting operations...
legend = ax.legend().draggable()
legend._loc = oldLegPos
It looks like _loc automatically stores figure coordinates, since I do not have to convert the coordinates in any way (eg. when the plotting operations completely change the axes ranges/coordinates).

core plot datasource - issue

I have a question for optimize a core plot graph, if I want to plot the function y=8*sin(x) I use a parse and I get the value of a range (for example -5,+5), after calculate it I plot the graph.
If I drag up or down the plot some value are covered, so they are unnecessary and I can remove it, after this add some point on visible range for have a better line.
Now I have a datasource of more interval, 3 array with the y value of this interval: -5,-2 one of 0,3 and one 4,5 (this number are for example). How can I plot this line on my plot View, I need to add some code like this:
CPTScatterPlot *xSquaredPlot = [[CPTScatterPlot alloc] initWithFrame:graph.defaultPlotSpace.accessibilityFrame];
xSquaredPlot.identifier = #"Grafico";
xSquaredPlot.interpolation = CPTScatterPlotInterpolationLinear;
xSquaredPlot.delegate = self;
CPTMutableLineStyle *lineStyleFunc = [CPTMutableLineStyle lineStyle];
lineStyleFunc.lineWidth = 1.0f;
lineStyleFunc.lineColor = [CPTColor redColor];
xSquaredPlot.dataLineStyle = lineStyleFunc;
xSquaredPlot.dataSource = self;
[graph addPlot:xSquaredPlot];
but the problem i that I don't know how line I have, I need to create it dynamically, how can I do it? adding this code when I create the arrays of new interval? but when I need to update datasource?
Core Plot will skip drawing points that fall outside the visible plot area when it can, so you don't have to worry too much about doing that in your datasource. You don't want to be adding and removing a lot of data points as the user scrolls around—that will just cause more work for the plotting code and slow it down.
Since you are plotting a function, one thing you can do is only generate data points in a fairly small range, say just slightly outside the visible x-range. Use a plot space delegate to monitor changes and add points as needed when the user scrolls or zooms the graph.
Use the -insertDataAtIndex:numberOfRecords: method to add data points to the plot. This will have better performance than -reloadData which forces the plot to load all of its data, not just the new values.

Core Plot bar Graph iPhone

I have followed this link http://www.gilthonwe.com/2012/06/09/stacked-bar-chart-coreplot-ios/ and have succeeded in making bar graph what i needed. but now i want something change in this graph i want 2 bar graph lines on single x axis date. i want bar graph like this one.
(source: tqn.com)
but i want 2 bars not 3.
What i have to change or how can i achieve to make this bar graph.
If it's just the bar graph I don't think you need the code provided in your link. The easiest way to achieve something like that would be to simple use CALayer to represent the bars in the graph. You just set their frames and backgroundcolors as needed, add them as sublayer to your view and your done (besides creating the axis and labels)
CALayer *layer = [[CALayer alloc] init];
layer.frame = /* ... */;
layer.backgroundColor = [[UIColor redColor] CGColor];
[someView.layer addSublayer:layer];
You should use two bar plots, one for each set of bars with the same fill. Use the barOffset on each plot to shift one a little bit to the left and the other a little to the right so they join above the bar location. See the Plot Gallery example app for sample code.

Core Plot - adding a vertical/horizontal line indicator on a selected value point

I am using core plot to make a line graph for my iPhone app. So far I successfully made the line graph from my xml data.
Furthermore I added a text layer that shows the value (for example 40) once I select the cell
holding the value 40. For this, I use the function:
(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index
So now I want to have a vertical line on the graph to indicate the selected value (the 40). I tried adding CPTBarplot but somehow the bars show only at the beginning of the graph axis.
Is there a function from core plot like the above that will create a line indicator?
I would appreciate if someone can give me some hint how to solve this problem and thank you very much in advance.
You could use a scatter plot for that. There's a point selection demo in the Mac CPTTestApp that draws a crosshair over the selected point. It would be trivial to modify that to only draw the vertical line.
The -numberOfRecordsForPlot: datasource method returns the number of points in the selection indicator (5 for the crosshairs) or zero (0) if there is no current selection. The -numberForPlot:field:recordIndex: method returns the points in the indicator. The points are drawn in this order:
Left
Right
Center (with plot symbol)
Top
Bottom
The -symbolForScatterPlot:recordIndex: method controls the plot symbol in the center. You can eliminate this method if you don't need any symbols on the indicator plot.

Coreplot editing plotspace

I came up with a small problem. Now, I've got a program which plots
graphs. For that I've set up few functions.
First when loaded the graph gets initialized with the plotspace
etc. Then when the user clicks a button, a new plot gets added to the
graph. But with that I have the necessity to change the
plotSpace.xRange and plotsPace.yRange. How can I do so after having
initialized the graph already?
Thanks for your thoughts!
You can change the plot space ranges at any point, not just on creation of the graph. Once you do so, the graph should adjust the displayed axis ranges onscreen. I don't believe you even need to reload the data for a given graph after this.
As an example, the following code should adjust the X range of a plot to be from 0 to 100:
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
[plotSpace setXRange:[CPTPlotRange plotRangeWithLocation:CPTDecimalFromInteger(0) length:CPTDecimalFromInteger(100)]];
where graph is a CPTXYGraph instance, in this case.