CorePlot Visible Range Not Working As Expected - ios

So I've been modifying the sample code to try to have a graph show the y values of 0-20 and to only show the max of 6 x values on the screen at a time. A visible range of 0-6 for x;
Here's a picture of what I'm shooting for
And this is what it looks like
So here's the part of the code I think is most important. Here I'll show you how I made the visible Axis Range, plot space ranges and plot space global ranges:
CPTMutablePlotRange *xRange = [plotSpace.xRange mutableCopy];
CPTMutablePlotRange *yRange = [plotSpace.yRange mutableCopy];
// I'm not sure what the difference is between the two
// constrict this to 0-20 for y and 0-6 for x
x.visibleRange = nil;
y.visibleRange = nil;
x.visibleAxisRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0f) length:CPTDecimalFromFloat(6.f)];
y.visibleAxisRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0f) length:CPTDecimalFromFloat(20.f)];
// expand the X, y axis to be more than we need
[xRange expandRangeByFactor:CPTDecimalFromDouble(1.05)];
[yRange expandRangeByFactor:CPTDecimalFromDouble(1.05)];
plotSpace.xRange = xRange;
plotSpace.yRange = yRange;
// expand it to be even bigger
[xRange expandRangeByFactor:CPTDecimalFromDouble(3.0)];
[yRange expandRangeByFactor:CPTDecimalFromDouble(3.0)];
plotSpace.globalXRange = xRange;
plotSpace.globalYRange = yRange;
So in the picture of what is displayed on the app, seems to shows all my values instead of just the six, but it seems to know that I only want to show 6 since the labels stop at six. I'd like to get the app to scroll left and right to show the other points after I get it to show the proper length of the line, but one thing at a time.
Here's the code. It's pretty sloppy, I was just hacking around to see what was possible before I clean it up and bring it to my real project. All the work is done in the controlChart.m file, I mucked around with some of the Plain White theme file but that should be unimportant.
coreplot-horrible-code

Since the x data points are one unit apart, giving the xRange a length of 6 (plus a bit for the plot symbols) will do what you want. In the code you posted, the xRange is set up with -scaleToFitPlots: before expanding the range. This makes it fit all of the plot data.

Related

How to show the graph with high data in a given space?

I am using Line Graph of Core Plot in my project. The thing is when I kept the data of my X-axis and Y-axis like: 1,2,3....10, everything worked fine. But now the data is like: X-axis: 0, 150, 500.... and on Y-axis: 0,1000,2000 and so on.
So now my graph is not fully visible in the given area. I know it is because the range on my Y-axis is getting too high and it is not visible. Some code that might possibly the reason for it:
// Setup scatter plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.allowsUserInteraction = YES;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInteger(0.0) length:CPTDecimalFromInteger(8)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInteger(0.0) length:CPTDecimalFromInteger(5)];
// Restrict y range to a global range
CPTPlotRange *globalYRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-2.5)
length:CPTDecimalFromDouble(5.0)];
plotSpace.globalYRange = globalYRange;
CPTPlotRange *globalXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-0.2)
length:CPTDecimalFromDouble(17.0)];
plotSpace.globalXRange=globalXRange;
The xRange and yRange are too small to display all of the plot data.
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInteger(0)
length:CPTDecimalFromInteger(500)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInteger(0)
length:CPTDecimalFromInteger(2000)];
No luck :( It becomes as per its shown above. I dont want to compress the data. The distance between the months should be as same as the figure posted in the question. The Y axis data is still not getting visible completely. My global X and Y range is like this
CPTPlotRange *globalYRange = [CPTPlotRange
plotRangeWithLocation:CPTDecimalFromDouble(-2.5)
length:CPTDecimalFromDouble(5.0)];
plotSpace.globalYRange = globalYRange;
CPTPlotRange *globalXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-0.2)
length:CPTDecimalFromDouble(17.0)];
plotSpace.globalXRange=globalXRange;

Plot area padding to prevent symbols from being truncated. (Core Plot)

In Core Plot for iOS, is there a way to add some sort of padding to a plot area, as opposed to a plot area frame? When using plot symbols, the symbols can be truncated if they fall on an axis line or boundary of the frame. Admittedly, I understand why this is the case when plotting a non-zero sized circle as a data symbol, but I'm curious if there's a way to add some padding to prevent this.
Or maybe there's a way to do with the axis ranges, but if so I haven't figured out the magic combination other than creating axis ranges that are "magically" large enough to account for the size of these symbols.
In the attached screenshot, the x-axis represents a week. Any data point for the first day will be truncated because it's getting drawn right on the y-axis. Ideally, I'd like this data point drawn just "a bit inside". (Which really means I want the x-axis range to increase by just enough to take this in to account.)
Likewise for the y-axis. A value of '0' plots right on the x-axis.
I don't really want the axis to show a range wider than required (i.e. I don't want the y-axis to go -1, for example.)
Thank you.
Here's some sample code from the "Control Chart" demo in the Plot Gallery example app:
// Adjust visible ranges so plot symbols along the edges are not clipped
CPTMutablePlotRange *xRange = [[plotSpace.xRange mutableCopy] autorelease];
CPTMutablePlotRange *yRange = [[plotSpace.yRange mutableCopy] autorelease];
x.orthogonalCoordinateDecimal = yRange.location;
y.orthogonalCoordinateDecimal = xRange.location;
x.visibleRange = xRange;
y.visibleRange = yRange;
x.gridLinesRange = yRange;
y.gridLinesRange = xRange;
[xRange expandRangeByFactor:CPTDecimalFromDouble(1.05)];
[yRange expandRangeByFactor:CPTDecimalFromDouble(1.05)];
plotSpace.xRange = xRange;
plotSpace.yRange = yRange;
You can adjust the expansion factor as needed based on the size of the graph and plot symbols.
Only this solved for me, values aligned properly from both sides(leading and trialing)
[xRange expandRangeByFactor:[NSNumber numberWithDouble:1.2]];

iOS Core Plot: Adjust y axis padding to label size

I have spent the last couple of days to use Core Plot for the first time. It took me some some figure out how it works but I could realize almost all features I was looking for. But for one thing I did not find a solution:
I am using a XY-Plot with labels on both axes. The plotAreaFrame has a left padding to shift the plotArea to the right and create some free space for the y axis labels. This works fine as long as the labels are not to big, e.g. for values up to 100. But if the y values become bigger, eg. 10.0000, the padding is not enough to show the complete label.
Of course I could just use a higher padding but this would waste space if I have only small y values.
Is there any way to autosize the padding according to the labels?
Andrei,
I realize this is an old question but perhaps this is a useful thought to you or others. I wonder if you can do a bit better than just guessing the padding size you need. How about this code snippet:
// set up the Y axis
float minY = 0;
float maxY = 100; // just some max value
float tickLength = 10; // just a pleasing value
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(minY) length:CPTDecimalFromFloat(maxY)];
// set up the line style for y axis
CPTMutableLineStyle * lineStyle = [CPTLineStyle lineStyle];
lineStyle.lineColor = [CPTColor blackColor];
lineStyle.lineWidth = 2.0f; // just picked a pleasing value
// set up the y axis
axisSet = [[CPTXYAxisSet alloc]init];
axisSet.yAxis.majorTickLength = tickLength;
// Now you can determine the size of the rectangle needed to display axis and labels by getting
// the axis font and measureing how many pixels were needed to draw the maximum Y axis label.
UIFont * font = [UIFont fontWithName:axisSet.yAxis.labelTextStyle.fontName size:axisSet.yAxis.labelTextStyle.fontSize];
NSString * maxYLabel = [axisSet.xAxis.labelFormatter stringFromNumber:[NSNumber numberWithDouble:plotSpace.yRange.maxLimitDouble] ];
CGSize textSize = [maxYLabel sizeWithFont:font];
// The offset you are looking for can now be computed by:
textSize.width + axisSet.yAxis.majorTickLength + axisSet.yAxis.labelOffset;
Anyway, I haven't testing the code above but the concept should apply I think...
After getting no answer here I looked all over the web but found no answer there either. The solution which now works for me is just checking the current range of the Y axis, look how many digits the value have and calculate the necessary width manually: number_of_digits * width_per_digit + fixed_padding
Of course this is only an estimation. But it is better that a fixed padding wich is too big for small numbers and too small for large number...
I've used the proposed solution by Yohst first. But then I realized that sometimes bigger number for the maximum range won't result in a bigger label, for example when the Y value is time (as on the screenshot below).
So I iterated over the labels of the axis to find the maximum width of the label and to set it as graph's left padding:
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)_graph.axisSet;
CPTXYAxis *yAxis = axisSet.yAxis;
[yAxis relabel];
CGFloat maxLabelWidth = 0;
for (CPTAxisLabel *label in yAxis.axisLabels) {
maxLabelWidth = MAX(maxLabelWidth, label.contentLayer.bounds.size.width);
}
_graph.plotAreaFrame.paddingLeft = /* extra padding + */ maxLabelWidth;
// force update axes because of the new padding
[axisSet relabelAxes];
[axisSet setNeedsLayout];

Sticking Lables in Core-Plot to the Bottom of the GraphView

in the moment im wrestling with core plot, and I´m trying to achieve that the labels of my x-Axis are sticking to the bottom bounds of my graphView. Means:
when I set a range depending on the min/max Values of my PlotData I want to see the Labels everytime on the bottom of the graph.
This is how I set the AutoScaling to make the scaling depending on the min/max values to see only whats needed:
// Auto scale the plot space to fit the plot data
[plotSpace scaleToFitPlots:[NSArray arrayWithObjects:dataSourceLinePlot, nil]];
CPTMutablePlotRange *xRange = [[plotSpace.xRange mutableCopy] autorelease];
CPTMutablePlotRange *yRange = [[plotSpace.yRange mutableCopy] autorelease];
[xRange expandRangeByFactor:CPTDecimalFromDouble(1.0)];
[yRange expandRangeByFactor:CPTDecimalFromDouble(8.15)];
So when I now want to zoom the graph, the labels are staying where they are.
In some cases they´re not visible but they have to be visible all the time. Any tips?
Thanks in Advance
Cheers
// EDIT
I worked with the labelOffset already, but it´s not working when you want to zoom the view or the min/max values are changing.
If you want to have x-axis labels visible all the time even when zooming in, you should set CPTConstraints for the axis. The following code should do the trick:
CPTXYGraph *barchar = <#(create the chart here)#>
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)barChart.axisSet;
CPTXYAxis *xAxis = axisSet.xAxis;
CPTConstraints *axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0f];
xAxis.axisConstraints = axisConstraints;

Force grid lines to update when range changes in Core-Plot scatter plot on iOS

I have a CPTXYGraph with a CPTScatterPlot, which I update with new data using [graph reloadData]. I also set the ranges based on the data. My problem is that though the axes update fine when the range changes, the gridlines do not, so I end up with this http://inky.ws/g/hw (no grid lines at the end of the x-axis).
I set axis.gridLinesRange = nil, and I tried re-setting all the gridline properties when updating ranges, to no avail.
To clarify, the original plot looks fine, but when I update with a bigger data set, the grid lines are missing in the added range.
I've had the same issue and used the following workaround: calculate new bounds of your values and replace the default plot space range with a new one using the plotRangeWithLocation:length: convenience method.
Not very satisfying performance-wise and conceptually (feels a bit like doing the job of the framework) but it worked for me.
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat([valuesMin floatValue]) length:CPTDecimalFromFloat([valuesMax floatValue]-[valuesMin floatValue])];
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTXYAxis *y = axisSet.yAxis;
float amplitude = ([valuesMax floatValue]-[valuesMin floatValue]);
NSDecimal intervalLength = CPTDecimalFromFloat(100);
y.majorIntervalLength = intervalLength;

Resources