I am developing a project using Core-Plot with Objective-C. The client asks to create a line chart (using Scatter Plot for this) where plots the number of ocurrencies x the time.
Well, after study for almost a week, this isn't working. My dots aren't connected and I don't know why.
This blue line should've been connected, since it is one plot.
Here is my code:
-(void)renderInLayer:(CPTGraphHostingView *)layerHostingView withTheme:(CPTTheme *)theme animated:(BOOL)animated{
CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:bounds];
[self addGraph:graph toHostingView:layerHostingView];
[self applyTheme:theme toGraph:graph withDefault:[CPTTheme themeNamed:kCPTDarkGradientTheme]];
graph.paddingTop = 20.0;
graph.paddingRight = 20.0;
graph.paddingLeft = 20.0;
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.allowsUserInteraction = YES;
plotSpace.delegate = self;
CPTMutableLineStyle *axesLineStyle = [CPTMutableLineStyle lineStyle];
axesLineStyle.lineWidth = 1.0f;
axesLineStyle.miterLimit = 1.0f;
axesLineStyle.lineColor = [CPTColor grayColor];
CPTTextStyle *labelTextStyle = [CPTTextStyle textStyleWithAttributes:#{ NSForegroundColorAttributeName: BoardGraphValueColor, NSFontAttributeName: BoardGraphValueFont}];
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
NSNumberFormatter * axisFormat = [[NSNumberFormatter alloc] init];
[axisFormat setNumberStyle:NSNumberFormatterNoStyle];
CPTXYAxis *x = axisSet.xAxis;{
x.visibleRange = [CPTPlotRange plotRangeWithLocation:#(-1.0) length:#(100)];
x.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
x.majorIntervalLength = #2;
x.minorTicksPerInterval = 1;
x.majorTickLineStyle = axesLineStyle;
x.minorTickLineStyle = axesLineStyle;
x.axisLineStyle = axesLineStyle;
x.plotSpace = plotSpace;
x.labelTextStyle = labelTextStyle;
x.labelFormatter = axisFormat;
x.labelOffset = 5.0;
}
CPTXYAxis *y = axisSet.yAxis;{
y.visibleRange = [CPTPlotRange plotRangeWithLocation:#(-1.0) length:#(200)];
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.majorIntervalLength = #30;
y.minorTicksPerInterval = 6;
y.majorTickLineStyle = axesLineStyle;
y.minorTickLineStyle = axesLineStyle;
y.axisLineStyle = axesLineStyle;
y.plotSpace = plotSpace;
y.labelTextStyle = labelTextStyle;
y.labelFormatter = axisFormat;
y.labelOffset = 5.0;
}
graph.axisSet.axes = #[x, y];
CPTMutableLineStyle *lineStyle = [[CPTMutableLineStyle alloc] init];
lineStyle.lineWidth = 2.0;
CPTScatterPlot *scatterLinePlot = [[CPTScatterPlot alloc] init];
scatterLinePlot.areaBaseValue = #(0.0);
scatterLinePlot.identifier = #(1);
scatterLinePlot.title = #"Title";
lineStyle.lineColor = [CPTColor blueColor];
scatterLinePlot.dataLineStyle = lineStyle;
scatterLinePlot.histogramOption = self.histogramOption;
scatterLinePlot.areaBaseValue = #(0);
scatterLinePlot.delegate = self;
scatterLinePlot.plotSymbolMarginForHitDetection = 5.0;
scatterLinePlot.dataSource = self;
[graph addPlot:scatterLinePlot];
CPTPlotRange *globalYRange = [CPTPlotRange plotRangeWithLocation:#0.0
length:#12.0];
plotSpace.globalYRange = globalYRange;
[plotSpace scaleToFitEntirePlots:[graph allPlots]];}
This is the code for create just one plot, but I need to create six. I did a loop but it is working that way too.
Here's the datasource:
-(NSUInteger)numberOfRecordsForPlot:(nonnull CPTPlot *)plot{
return [self.plotData objectAtIndex:0].count;}
-(NSNumber *)numberForPlot:(nonnull CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index{
NSNumber *num = nil;
NSString *key;
NSArray *currentDataPoint;
NSString *plotIdentifier = (NSString *)plot.identifier;
if ([plotIdentifier isEqual:#(1)]){
currentDataPoint = [self.plotData objectAtIndex:0];
} else if ([plotIdentifier isEqual:#(2)]){
currentDataPoint = [self.plotData objectAtIndex:1];
} else if ([plotIdentifier isEqual:#(3)]){
currentDataPoint = [self.plotData objectAtIndex:2];
} else if ([plotIdentifier isEqual:#(4)]){
currentDataPoint = [self.plotData objectAtIndex:3];
} else if ([plotIdentifier isEqual:#(5)]){
currentDataPoint = [self.plotData objectAtIndex:4];
} else if ([plotIdentifier isEqual:#(6)]){
currentDataPoint = [self.plotData objectAtIndex:5];
}
if (fieldEnum == CPTScatterPlotFieldX) {
return #(index);
} else if (fieldEnum == CPTScatterPlotFieldY) {
key = #"count";
int number = [[[currentDataPoint objectAtIndex:index] valueForKey:key] intValue];
NSLog(#"Y value for index %lu is %d", index, number);
num = [[currentDataPoint objectAtIndex:index] valueForKey:key];
return num;}
return num;
}
What am I doing wrong?
PS: Well, another bug is the color of the bar chart. Each of this should have a different color, but it doesn't work too. The colors provided is that for the legends.
Thanks in advance.
To change the bar color for each bar, implement the -barFillForBarPlot:recordIndex: method in the datasource and return the correct fill for each index. You can also set the border line style for each bar (e.g., to use a different color) with the -barLineStyleForBarPlot:recordIndex: datasource method.
It looks like the data line is getting clipped outside the visible area. Make sure the plot data is available from the datasource when you call -scaleToFitEntirePlots:.
Related
I am using CorePlot to plot average prices over few months.
This is what I am trying to achieve
I have been able to produce this
So clearly graph does not look plotted correctly.
Heres the code I am using in my viewController to set up the graph and plot it.
- (void)viewDidLoad {
[super viewDidLoad];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
NSDictionary *jsonDataDictionary;
// Can be done async with loading timers
NSURL *url = [NSURL URLWithString:
#"http://greyloft.com/analytics/query.php?project=PARC%20VISTA&area=1200&months=5"];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if (urlData) {
NSError *error=nil;
jsonDataDictionary = [NSJSONSerialization JSONObjectWithData:urlData
options:kNilOptions
error:&error];
// We receive the order of the months in reverse order in the json i.e. most recent first.
// e.g. Feb-15, Jan-15, Dec-14 and so on
// We need to show plotting in reverse order on x axis effectively needing to reverse the array.
NSArray *reverseAvgRentals = [[jsonDataDictionary objectForKey:#"results"] objectForKey:#"average"];
_averageRentals = [[reverseAvgRentals reverseObjectEnumerator] allObjects];
_transactions = [[jsonDataDictionary objectForKey:#"results"] objectForKey:#"transactions"];
_months = [[NSMutableArray alloc] init];
_rentals = [[NSMutableArray alloc] init];
for (NSDictionary *rental in _averageRentals) {
[_months addObject:[rental objectForKey:#"month"]];
[_rentals addObject:[rental objectForKey:#"average"]];
}
// KVC to find min/max in an array
_minRental = _maxRental = 0;
_minRental = [[_rentals valueForKeyPath:#"#min.intValue"] intValue];
_maxRental = [[_rentals valueForKeyPath:#"#max.intValue"] intValue];
}}
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
return [_months count];
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
NSNumber *num = [[NSNumber alloc] init];
if (fieldEnum == CPTScatterPlotFieldX) {
// Simply return index as we want to return number for each month
num = [NSNumber numberWithInt:index+1];
} else {
num = [[_averageRentals objectAtIndex:index] valueForKey:#"average"];
}
return num;
}
-(void)initPlot {
[self configureHost];
[self configureGraph];
[self configurePlots];
[self configureAxes];
}
-(void)configureHost {
self.graphHostView = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:self.graphContainerView.bounds];
self.graphHostView.allowPinchScaling = YES;
[self.graphContainerView addSubview:self.graphHostView];
}
-(void)configureGraph {
// Create the graph
CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:self.graphHostView.bounds];
[graph applyTheme:nil];
self.graphHostView.hostedGraph = graph;
[graph.plotAreaFrame setPaddingLeft:30.0f];
[graph.plotAreaFrame setPaddingBottom:30.0f];
[graph.plotAreaFrame setPaddingTop:10.0f];
}
-(void)configurePlots {
// Get graph and plot space
CPTGraph *graph = self.graphHostView.hostedGraph;
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
// 2 - Create the plot
CPTScatterPlot *rentPlot = [[CPTScatterPlot alloc] init];
rentPlot.dataSource = self;
rentPlot.identifier = #"Rent";
[graph addPlot:rentPlot toPlotSpace:plotSpace];
// 3 - Set up plot space
CGFloat xMin = 0.0f;
CGFloat xMax = [_months count];
CGFloat yMin = _minRental;
CGFloat yMax = _maxRental;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(xMin)
length:CPTDecimalFromFloat(xMax)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(yMin)
length:CPTDecimalFromFloat(yMax)];
[plotSpace scaleToFitPlots:[graph allPlotSpaces]];
CPTMutablePlotRange *xRange = [plotSpace.xRange mutableCopy];
CPTMutablePlotRange *yRange = [plotSpace.yRange mutableCopy];
[xRange expandRangeByFactor:CPTDecimalFromDouble(1.4)];
[yRange expandRangeByFactor:CPTDecimalFromDouble(3.0)];
plotSpace.xRange = xRange;
plotSpace.yRange = yRange;
// 4 - Create styles and symbols
//CPTColor *orangeColor = [CPTColor colorWithComponentRed:239.0f green:92.0f blue:94.0f alpha:1.0f];
CPTColor *orangeColor = [CPTColor orangeColor];
CPTMutableLineStyle *lineStyle = [rentPlot.dataLineStyle mutableCopy];
lineStyle.lineWidth = 2.5f;
lineStyle.lineColor = orangeColor;
rentPlot.dataLineStyle = lineStyle;
CPTMutableLineStyle *symbolLineStyle = [CPTMutableLineStyle lineStyle];
symbolLineStyle.lineWidth = 2.5f;
symbolLineStyle.lineColor = orangeColor;
CPTPlotSymbol *symbol = [CPTPlotSymbol ellipsePlotSymbol];
symbol.fill = [CPTFill fillWithColor:[CPTColor colorWithComponentRed:248.0f
green:244.0f
blue:251.0f
alpha:1.0f]];
symbol.lineStyle = symbolLineStyle;
symbol.size = CGSizeMake(11.0f, 11.0f);
rentPlot.plotSymbol = symbol;
}
-(void)configureAxes {
// 1 - Create styles
CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
axisLineStyle.lineWidth = 0.0f;
CPTMutableTextStyle *axisTextStyle = [[CPTMutableTextStyle alloc] init];
axisTextStyle.color = [CPTColor grayColor];
axisTextStyle.fontName = #"Ubuntu-Bold";
axisTextStyle.fontSize = 14.0f;
CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
majorGridLineStyle.lineWidth = 0.75;
majorGridLineStyle.lineColor = [CPTColor lightGrayColor];
// 2 - Get axis set
CPTXYAxisSet *axisSet = (CPTXYAxisSet *) self.graphHostView.hostedGraph.axisSet;
// 3 - Configure x-axis
CPTXYAxis *x = axisSet.xAxis;
x.axisLineStyle = axisLineStyle;
x.labelingPolicy = CPTAxisLabelingPolicyNone;
x.majorIntervalLength = CPTDecimalFromDouble(1.0);
x.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0.0);
x.preferredNumberOfMajorTicks = 6;
x.labelOffset = 50.0f;
x.labelTextStyle = axisTextStyle;
x.majorTickLineStyle = nil;
x.minorTickLineStyle = nil;
NSMutableSet *xLabelSet = [NSMutableSet setWithCapacity:[_months count]];
NSMutableSet *xLocationSet = [NSMutableSet setWithCapacity:[_months count]];
int location = 0;
for (NSString *month in _months) {
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:month textStyle:x.labelTextStyle];
label.tickLocation = CPTDecimalFromInt(location++);
[xLabelSet addObject:label];
[xLocationSet addObject:[NSNumber numberWithInteger:location]];
}
x.axisLabels = xLabelSet;
x.majorTickLocations = xLocationSet;
// 4 - Configure y-axis
CPTXYAxis *y = axisSet.yAxis;
y.axisLineStyle = axisLineStyle;
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.orthogonalCoordinateDecimal = CPTDecimalFromDouble(-0.1);
y.preferredNumberOfMajorTicks = 6;
y.majorGridLineStyle = majorGridLineStyle;
y.labelTextStyle = axisTextStyle;
y.majorTickLineStyle = nil;
y.minorTickLineStyle = nil;
}
I am not getting the concept of how CorePlot will take the data provided and turn it into the required set.
Any suggestions?
As noted in my comment above, plot ranges take a location and length like NSRange. You can use the min value for the location and max - min for the length.
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromCGFloat(yMin)
length:CPTDecimalFromCGFloat(yMax - yMin)];
For your example of a range covering 1,500 to 4,000, use 1,500 for the location and 2,500 (4,000 - 1,500) for the length.
I am trying to draw a real time plot of a 4-channel input stream using 4 separate plots on the same graph. Currently I am taking this data out of a text file, but will eventually work to get this data using bluetooth. My plot itself works fine, but core-plot appears to draw an extra horizontal line for each plot at the beginning of the plotting at the levels of the first data set. I think this has something to do with core-plot trying to get all the points to be plotted before it starts to display them. The following image shows these lines, while the actual waveforms, square waves, are in the middle of being plot.
As the plotting progresses and the displayed range of the x-axis changes, these lines disappear. Like in here:
Following is the relevant section of my code. It is based on Ray Wenderlich's scatter plot tutorial and Eric Skrooch's real time plot example. (I hope I spelt those names right!). Personally, I believe that this is a bug in core-plot and not a coding error though. Any help on how to get rid of these troubling lines is greatly appreciated! Thanks!
-(void)configurePlots {
//Get graph and plot space
CPTGraph *graph = self.hostView.hostedGraph;
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
//Create the four plots
CPTScatterPlot *channel1Plot = [[CPTScatterPlot alloc]init];
channel1Plot.dataSource = self;
channel1Plot.identifier = #"channel1";
[graph addPlot:channel1Plot toPlotSpace:plotSpace];
CPTScatterPlot *channel2Plot = [[CPTScatterPlot alloc]init];
channel2Plot.dataSource = self;
channel2Plot.identifier = #"channel2";
[graph addPlot:channel2Plot toPlotSpace:plotSpace];
CPTScatterPlot *channel3Plot = [[CPTScatterPlot alloc]init];
channel3Plot.dataSource = self;
channel3Plot.identifier = #"channel3";
[graph addPlot:channel3Plot toPlotSpace:plotSpace];
CPTScatterPlot *channel4Plot = [[CPTScatterPlot alloc]init];
channel4Plot.dataSource = self;
channel4Plot.identifier = #"channel4";
[graph addPlot:channel4Plot toPlotSpace:plotSpace];
//Set up plot space
[plotSpace scaleToFitPlots:[NSArray arrayWithObjects:channel1Plot, channel2Plot, channel3Plot, channel4Plot, nil]];
CPTMutablePlotRange *xRange = [plotSpace.xRange mutableCopy];
[xRange expandRangeByFactor:CPTDecimalFromCGFloat(1.1f)];
plotSpace.xRange = xRange;
CPTMutablePlotRange *yRange = [plotSpace.yRange mutableCopy];
[yRange expandRangeByFactor:CPTDecimalFromCGFloat(1.2f)];
plotSpace.yRange = yRange;
//Create styles and symbols
CPTMutableLineStyle *channelLineStyle = [channel1Plot.dataLineStyle mutableCopy];
channelLineStyle.lineWidth = 1.0;
channelLineStyle.lineColor = [CPTColor redColor];
channel1Plot.dataLineStyle = channelLineStyle;
channel2Plot.dataLineStyle = channelLineStyle;
channel3Plot.dataLineStyle = channelLineStyle;
channel4Plot.dataLineStyle = channelLineStyle;
}
-(void)configureAxes {
//Create styles
CPTMutableTextStyle *axisTitleStyle = [CPTMutableTextStyle textStyle];
axisTitleStyle.color = [CPTColor whiteColor];
axisTitleStyle.fontName = #"Helvetica-Bold";
axisTitleStyle.fontSize = 12.0f;
CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
axisLineStyle.lineWidth = 2.0f;
axisLineStyle.lineColor = [CPTColor whiteColor];
CPTMutableTextStyle *axisTextStyle = [[CPTMutableTextStyle alloc] init];
axisTextStyle.color = [CPTColor yellowColor];
axisTextStyle.fontName = #"Helvetica-Bold";
axisTextStyle.fontSize = 11.0f;
CPTMutableLineStyle *tickLineStyle = [CPTMutableLineStyle lineStyle];
tickLineStyle.lineWidth = 2.0f;
tickLineStyle.lineColor = [CPTColor yellowColor];
CPTMutableLineStyle *gridLineStyle = [CPTMutableLineStyle lineStyle];
tickLineStyle.lineColor = [CPTColor purpleColor];
tickLineStyle.lineWidth = 1.0f;
//Get axis set
CPTXYAxisSet *axisSet = (CPTXYAxisSet *) self.hostView.hostedGraph.axisSet;
//Configure X-axis
CPTAxis *x = axisSet.xAxis;
x.title = #"Time";
x.titleTextStyle = axisTitleStyle;
x.titleOffset = 15.0f;
x.axisLineStyle = axisLineStyle;
x.labelingPolicy = CPTAxisLabelingPolicyNone;
x.labelTextStyle = axisTextStyle;
x.majorTickLineStyle = axisLineStyle;
x.majorTickLength = 4.0f;
x.tickDirection = CPTSignNegative;
CGFloat pointsCount = POINTS_ON_SCREEN;
NSMutableSet *xLabels = [NSMutableSet setWithCapacity:pointsCount];
NSMutableSet *xLocations = [NSMutableSet setWithCapacity:pointsCount];
NSInteger i=0;
//NSString *loc = [NSString stringWithFormat:#"d",j];
for (NSInteger j=0; j<POINTS_ON_SCREEN; j++) {
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:#"%ld", (long)j+1] textStyle:x.labelTextStyle];
CGFloat location = i++;
label.tickLocation = CPTDecimalFromCGFloat(location);
label.offset = x.majorTickLength;
if (label) {
[xLabels addObject:label];
[xLocations addObject:[NSNumber numberWithFloat:location]];
}
}
x.axisLabels = xLabels;
x.majorTickLocations = xLocations;
//Configure Y-axis
axisSet.yAxis.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
CPTAxis *y = axisSet.yAxis;
y.title = #"Channel outputs";
y.titleTextStyle = axisTitleStyle;
y.titleOffset = -40.0f;
y.axisLineStyle = axisLineStyle;
y.majorGridLineStyle = gridLineStyle;
y.labelingPolicy = CPTAxisLabelingPolicyNone;
y.labelTextStyle = axisTextStyle;
y.labelOffset = 16.0f;
y.majorTickLineStyle = axisLineStyle;
y.majorTickLength = 4.0f;
y.minorTickLength = 2.0f;
y.tickDirection = CPTSignPositive;
CGFloat majorIncrement = 0.0005;
CGFloat minorIncrement = 0.0001;
CGFloat yMax = 0.0040f;
NSMutableSet *yLabels = [NSMutableSet set];
NSMutableSet *yMajorLocations = [NSMutableSet set];
NSMutableSet *yMinorLocations = [NSMutableSet set];
for (CGFloat j = minorIncrement; j<=yMax; j+=minorIncrement) {
j = roundf(j*100000)/100000;
CGFloat mod = j / majorIncrement;
NSInteger modInt = (NSInteger)mod;
CGFloat modMantissa = mod - modInt;
modMantissa = roundf(modMantissa * 100)/100;
if (modMantissa < 0.1 || modMantissa > 0.9) {
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:#"%.5f", j] textStyle:y.labelTextStyle];
NSDecimal location = CPTDecimalFromCGFloat(j);
//NSNumber *location = [NSNumber numberWithFloat:j];
label.tickLocation = location;
label.offset = -y.majorTickLength -y.labelOffset -9;
//label.offset = 0;
if (label) {
[yLabels addObject:label];
}
[yMajorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:location]];
} else {
[yMinorLocations addObject:[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:#"%f",j]]];
}
}
y.axisLabels = yLabels;
y.majorTickLocations = yMajorLocations;
y.minorTickLocations = yMinorLocations;
}
-(void)createTimer {
NSTimer *dataTimer = [NSTimer timerWithTimeInterval:0.002 target:self selector:#selector(dynamicUpdate:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:dataTimer forMode:NSDefaultRunLoopMode];
}
-(void)dynamicUpdate: (NSTimer *)dataTimer {
CPTGraph *graph = self.hostView.hostedGraph;
CPTPlot *channel1Plot = [graph plotWithIdentifier:#"channel1"];
CPTPlot *channel2Plot = [graph plotWithIdentifier:#"channel2"];
CPTPlot *channel3Plot = [graph plotWithIdentifier:#"channel3"];
CPTPlot *channel4Plot = [graph plotWithIdentifier:#"channel4"];
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
if (channel1Plot && channel2Plot && channel3Plot && channel4Plot) {
if ( arrayIndex1 >= POINTS_ON_SCREEN-1
|| arrayIndex2 >= POINTS_ON_SCREEN-1
|| arrayIndex3 >= POINTS_ON_SCREEN-1
|| arrayIndex4 >= POINTS_ON_SCREEN-1) {
[channel1Array removeObjectAtIndex:0];
[channel1Plot deleteDataInIndexRange:NSMakeRange(0, 1)];
[channel2Array removeObjectAtIndex:0];
[channel2Plot deleteDataInIndexRange:NSMakeRange(0, 1)];
[channel3Array removeObjectAtIndex:0];
[channel3Plot deleteDataInIndexRange:NSMakeRange(0, 1)];
[channel4Array removeObjectAtIndex:0];
[channel4Plot deleteDataInIndexRange:NSMakeRange(0, 1)];
}
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(currentIndex >= POINTS_ON_SCREEN ? currentIndex-POINTS_ON_SCREEN +1 : 0) length:CPTDecimalFromUnsignedInteger(POINTS_ON_SCREEN-1)];
currentIndex++;
[channel1Plot insertDataAtIndex:POINTS_ON_SCREEN-1 numberOfRecords:1];
[channel2Plot insertDataAtIndex:POINTS_ON_SCREEN-1 numberOfRecords:1];
[channel3Plot insertDataAtIndex:POINTS_ON_SCREEN-1 numberOfRecords:1];
[channel4Plot insertDataAtIndex:POINTS_ON_SCREEN-1 numberOfRecords:1];
}
}
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
return POINTS_ON_SCREEN;
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)idx {
// NSLog(#"Plotting point");
NSNumber *num = nil;
if ([self.activityIndicator isAnimating] == YES) {
[self.activityIndicator stopAnimating];
}
switch (fieldEnum) {
case CPTScatterPlotFieldX:
if (idx < POINTS_ON_SCREEN) {
return [NSNumber numberWithUnsignedInteger:idx + currentIndex - POINTS_ON_SCREEN];
};
break;
case CPTScatterPlotFieldY:
if ([plot.identifier isEqual:#"channel1"]) {
num = [channel1Array objectAtIndex:idx];
arrayIndex1 = idx;
} else if ([plot.identifier isEqual:#"channel2"]) {
num = [channel2Array objectAtIndex:idx];
arrayIndex2 = idx;
} else if ([plot.identifier isEqual:#"channel3"]) {
num = [channel3Array objectAtIndex:idx];
arrayIndex3 = idx;
} else if ([plot.identifier isEqual:#"channel4"]) {
num = [channel4Array objectAtIndex:idx];
arrayIndex4 = idx;
} else {
NSLog(#"data unavailable");
}
break;
default:
NSLog(#"ERROR: trying to plot on unidentified axis");
break;
}
NSString *numString = [NSString stringWithFormat:#"%#", num];
dispatch_async(AddToArrayQ, ^{[self writeData:numString];});
return num;
}
Unless I have misread this, you are returning a hardcoded value from numberOfRecordsForPlot:, so CorePlot expects to be able to fill all of those points on the x axis. Those lines you see are probably due to having initialized those arrays to a constant value (they must be initialized, right, or you would be getting an error when you try to access uninitialized indices?)
Notice in Eric Skroch's example that he is returning [plotData count] from numberOfRecordsForPlot:, and that plotData is empty on initialization.
The problem here lied not in hardcoding the numberOfRecordsForPlot: method as RishiG suggested, but in hardcoding the case CPTScatterPlotFieldX in the numberForPlot:field:recordIndex method. But RishiG's suggestion was a good one nonetheless and I made some changes before I resolved the problem.
Original: Arrays channel1Array - channel4Array already contained the data to be plotted and I went on deleting items from the array as I plotted them. This meant that I could not use something like [channel1Array count] in the numberOfRecordsForPlot: method and had to rely on the plot index instead. This also would have worked but is inefficient anyway.
Modified: Followed Eric Skroch's example fully to start with empty arrays and update them as plotting proceeded.
The original case CPTScatterPlotFieldX in the numberForPlot:field:recordIndex method used here had the return value as (idx + currrentIndex - POINTS_ON_SCREEN) which might have produced a negative result. It looks like core-plot perhaps used its absolute value to get the x-coordinate, and hence the horizontal line. This can be remedied by removing the if condition and having the return value as (idx + currentIndex - channel1Array.count).
P.S.: #vikingosegundo I know, thanks. But I had to take photos in quick succession so my camera's burst mode was best suited!
As mentioned in title, I have succesfully add CorePlot into my project and it works as expected. Except there are still axes label shown which I cannot remove or hide. This is my renderInLayer code,
-(void)renderInLayer:(CPTGraphHostingView *)layerHostingView withTheme:(CPTTheme *)theme animated:(BOOL)animated
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
CGRect bounds = layerHostingView.bounds;
#else
CGRect bounds = NSRectToCGRect(layerHostingView.bounds);
#endif
CPTGraph *graph = [[[CPTXYGraph alloc] initWithFrame:bounds] autorelease];
[self addGraph:graph toHostingView:layerHostingView];
graph.plotAreaFrame.paddingTop = 0.0;
graph.plotAreaFrame.paddingRight = 0.0;
graph.plotAreaFrame.paddingBottom = 0.0;
graph.plotAreaFrame.paddingLeft = 0.0;
graph.plotAreaFrame.masksToBorder = NO;
// Create the plot
CPTScatterPlot *dataSourceLinePlot = [[[CPTScatterPlot alloc] init] autorelease];
dataSourceLinePlot.identifier = kPlotIdentifier;
dataSourceLinePlot.cachePrecision = CPTPlotCachePrecisionDouble;
CPTMutableLineStyle *lineStyle = [[dataSourceLinePlot.dataLineStyle mutableCopy] autorelease];
lineStyle.lineWidth = 3.0;
lineStyle.lineColor = [CPTColor whiteColor];
dataSourceLinePlot.dataLineStyle = lineStyle;
dataSourceLinePlot.dataSource = self;
dataSourceLinePlot.interpolation = CPTScatterPlotInterpolationCurved;
[graph addPlot:dataSourceLinePlot];
// Plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(kMaxDataPoints - 2)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(1)];
[dataTimer invalidate];
[dataTimer release];
if ( animated ) {
dataTimer = [[NSTimer timerWithTimeInterval:1.0 / kFrameRate
target:self
selector:#selector(newData:)
userInfo:nil
repeats:YES] retain];
[[NSRunLoop mainRunLoop] addTimer:dataTimer forMode:NSRunLoopCommonModes];
}
else {
dataTimer = nil;
}
}
And visual out with bad data,
EDIT
I have tried this but it didnt work,
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTXYAxis *axis = axisSet.xAxis;
axis.hidden = YES;
for (CPTAxisLabel *axisLabel in axis.axisLabels) {
axisLabel.contentLayer.hidden = YES;
}
Ok so I have managed to find the answer my self. If anyone in future wants to remove just the label. Then please do this,
axis.labelingPolicy = CPTAxisLabelingPolicyNone;
If you want to remove the axis of graph completly, then.
graph.axisSet = nil;
Boom all gone, you have clear and nice looking graph now :)
You can simply hide all labels.
CPTAxis *axis = xAxis;
axis.hidden = YES;
for (CPTAxisLabel *axisLabel in axis.axisLabels) {
axisLabel.contentLayer.hidden = YES;
}
I am posting how I customized my xAxis labels:
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)_graph.axisSet;
CPTXYAxis *x = axisSet.xAxis;
x.majorIntervalLength = CPTDecimalFromString(#"5");
x.orthogonalCoordinateDecimal = CPTDecimalFromString(#"0");
x.minorTicksPerInterval = 4;
x.title = #"";
x.titleTextStyle = axisTitleStyle;
x.labelingPolicy = CPTAxisLabelingPolicyNone; //No labels provided; user sets labels and tick locations.
//x.majorTickLineStyle = axisLineStyle;
x.majorTickLength = 5.0f;
x.tickDirection = CPTSignNegative;
CPTMutableTextStyle *axisLabelStyle = [CPTMutableTextStyle textStyle];
axisLabelStyle.fontName = #"Helvetica Neue Thin";
axisLabelStyle.fontSize = 8.0f;
NSArray *lastThirtyDates = [self.analyticsDataController lastThirtyDays];
NSUInteger daysCount = 31;
NSMutableSet *xLabels = [NSMutableSet setWithCapacity:daysCount];
NSMutableSet *xLocations = [NSMutableSet setWithCapacity:daysCount];
NSMutableSet *xMinorLocations = [NSMutableSet setWithCapacity:daysCount];
for (//iterate over your data source for x values and create your custom labels) {
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:#"" textStyle:axisLabelStyle];
CGFloat location = i;
label.tickLocation = CPTDecimalFromCGFloat(location);
label.offset = x.majorTickLength;
if (label) {
[xLabels addObject:label];
[xLocations addObject:[NSNumber numberWithFloat:location]];
}
}
x.axisLabels = xLabels;
x.majorTickLocations = xLocations;
x.minorTickLocations = xMinorLocations;
My Issues is as follows:
I'm trying to graph two data sets (One is in Feet and one is in degrees) in such a way that they can be compared (they do share a common x-axis value).
As you can see my data seems to be interlaced correctly but I'm having trouble getting the yAxises to behave as I'd like. I would like the X-Axis Max/Min to actually line up with both Y-Axises. My code is as follows:
- (void)initPlot {
[self loadCoreData];
[self configureHost];
[self configureGraph];
[self configurePlots];
[self configureAxes];
}
- (void)configureHost {
self.hostView = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:self.view.bounds];
self.hostView.allowPinchScaling = YES;
[self.view addSubview:self.hostView];
}
- (void)configureGraph {
// 1 - Create the graph
CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:self.hostView.bounds];
[graph applyTheme:[CPTTheme themeNamed:kCPTDarkGradientTheme]];
self.hostView.hostedGraph = graph;
// 2 - Set graph title
NSString *title = [NSString stringWithFormat:#"Altitude Plot [%# to %#]", self.flightRecording.originAirport, self.flightRecording.destinationAirport];
graph.title = title;
// 3 - Create and set text style
CPTMutableTextStyle *titleStyle = [CPTMutableTextStyle textStyle];
titleStyle.color = [CPTColor whiteColor];
titleStyle.fontName = #"Helvetica-Bold";
titleStyle.fontSize = 16.0f;
graph.titleTextStyle = titleStyle;
graph.titlePlotAreaFrameAnchor = CPTRectAnchorTop;
graph.titleDisplacement = CGPointMake(0.0f, -20.0f);
// 4 - Set padding for plot area
float padding = 10.0f;
[graph.plotAreaFrame setPaddingLeft:padding];
[graph.plotAreaFrame setPaddingBottom:50.0f];
[graph.plotAreaFrame setPaddingRight:padding];
[graph.plotAreaFrame setPaddingTop:padding];
// 5 - Enable user interactions for plot space
altSpace= (CPTXYPlotSpace *) graph.defaultPlotSpace;
altSpace.allowsUserInteraction = NO;
rollSpace = [[CPTXYPlotSpace alloc] init];
rollSpace.allowsUserInteraction = NO;
[self.hostView.hostedGraph addPlotSpace:rollSpace];
//
// pitchSpace = [[CPTXYPlotSpace alloc] init];
// pitchSpace.allowsUserInteraction = NO;
// [self.hostView.hostedGraph addPlotSpace:pitchSpace];
//
//
// slipSpace = [[CPTXYPlotSpace alloc] init];
// slipSpace.allowsUserInteraction = NO;
// [self.hostView.hostedGraph addPlotSpace:slipSpace];
//
//
// gSpace = [[CPTXYPlotSpace alloc] init];
// gSpace.allowsUserInteraction = NO;
// [self.hostView.hostedGraph addPlotSpace:gSpace];
}
- (void)configurePlots {
// 1 - Get graph and plot space
CPTGraph *graph = self.hostView.hostedGraph;
// 2 - Create the three plots
// Custom AHRS Plot
CPTScatterPlot *ahrsAltPlot = [[CPTScatterPlot alloc] init];
ahrsAltPlot.dataSource = self;
ahrsAltPlot.identifier = #"AHRSALT";
CPTColor *ahrsAltColor = [CPTColor yellowColor];
[graph addPlot:ahrsAltPlot toPlotSpace:altSpace];
CPTScatterPlot *rollPlot = [[CPTScatterPlot alloc] init];
rollPlot.dataSource = self;
rollPlot.identifier = #"ROLL";
CPTColor *rollColor = [CPTColor greenColor];
[graph addPlot:rollPlot toPlotSpace:rollSpace];
// 3 - Set up plot space
CPTMutablePlotRange *xRange = [altSpace.xRange mutableCopy];
xRange=[CPTMutablePlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0f ) length:CPTDecimalFromFloat(maxEpoch + 300.0f )];
// [xRange expandRangeByFactor:CPTDecimalFromCGFloat(1.1f)];
altSpace.xRange = xRange;
CPTMutablePlotRange *yRange = [altSpace.yRange mutableCopy];
yRange = [CPTMutablePlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0f) length:CPTDecimalFromFloat(maxAlt)];
[yRange expandRangeByFactor:CPTDecimalFromCGFloat(1.2f)];
altSpace.yRange = yRange;
rollSpace.xRange = xRange;
CPTMutablePlotRange *yRangeRoll =[CPTMutablePlotRange plotRangeWithLocation:CPTDecimalFromFloat(0 ) length:CPTDecimalFromFloat(40 )];
[yRangeRoll expandRangeByFactor:CPTDecimalFromCGFloat(1.2f)];
rollSpace.yRange = yRangeRoll;
[altSpace scaleToFitPlots:[NSArray arrayWithObjects:ahrsAltPlot, nil] ];
[rollSpace scaleToFitPlots:[NSArray arrayWithObjects:rollPlot, nil] ];
[rollSpace setYRange:yRangeRoll];
// 4 - Create styles and symbols
// AHRS Style
CPTMutableLineStyle *ahrsLineStyle = [ahrsAltPlot.dataLineStyle mutableCopy];
ahrsLineStyle.lineWidth = 2.5;
ahrsLineStyle.lineColor = [CPTColor blueColor];
ahrsAltPlot.dataLineStyle = ahrsLineStyle;
}
- (void)configureAxes {
// 1 - Create styles
CPTMutableTextStyle *axisTitleStyle = [CPTMutableTextStyle textStyle];
axisTitleStyle.color = [CPTColor whiteColor];
axisTitleStyle.fontName = #"Helvetica-Bold";
axisTitleStyle.fontSize = 12.0f;
CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
axisLineStyle.lineWidth = 2.0f;
axisLineStyle.lineColor = [CPTColor whiteColor];
CPTMutableTextStyle *axisTextStyle = [[CPTMutableTextStyle alloc] init];
axisTextStyle.color = [CPTColor whiteColor];
axisTextStyle.fontName = #"Helvetica-Bold";
axisTextStyle.fontSize = 11.0f;
CPTMutableLineStyle *tickLineStyle = [CPTMutableLineStyle lineStyle];
tickLineStyle.lineColor = [CPTColor whiteColor];
tickLineStyle.lineWidth = 2.0f;
CPTMutableLineStyle *gridLineStyle = [CPTMutableLineStyle lineStyle];
tickLineStyle.lineColor = [CPTColor blackColor];
tickLineStyle.lineWidth = 1.0f;
// 2 - Get axis set
CPTXYAxisSet *axisSet = (CPTXYAxisSet *) self.hostView.hostedGraph.axisSet;
// 3 - Configure x-axis
CPTAxis *x = axisSet.xAxis;
x.title = #"Flight Time";
x.titleTextStyle = axisTitleStyle;
x.titleOffset = 15.0f;
x.axisLineStyle = axisLineStyle;
x.labelingPolicy = CPTAxisLabelingPolicyNone;
x.labelTextStyle = axisTextStyle;
x.majorTickLineStyle = axisLineStyle;
x.majorTickLength = 4.0f;
x.tickDirection = CPTSignNegative;
NSMutableSet *xLabels = [NSMutableSet new];
NSMutableSet *xLocations = [NSMutableSet new];
NSInteger i = 0;
for (i; i < maxEpoch; i += 600) {
int hour = i / (68 * 60);
int min = i / 60;
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:#"%02d:%02d", hour, min] textStyle:x.labelTextStyle];
CGFloat location = i++;
label.tickLocation = CPTDecimalFromCGFloat(location);
label.offset = x.majorTickLength;
if (label) {
[xLabels addObject:label];
[xLocations addObject:[NSNumber numberWithInteger:i]];
}
}
x.axisLabels = xLabels;
x.majorTickLocations = xLocations;
// 4 - Configure y-axis
CPTAxis *y = axisSet.yAxis;
y.title = #"Altitude in Feet";
y.titleTextStyle = axisTitleStyle;
y.titleOffset = 20.0f;
y.axisLineStyle = axisLineStyle;
y.majorGridLineStyle = gridLineStyle;
y.labelingPolicy = CPTAxisLabelingPolicyNone;
y.labelTextStyle = axisTextStyle;
y.labelOffset = 21.0f;
y.majorTickLineStyle = axisLineStyle;
y.majorTickLength = 20.0f;
y.minorTickLength = 10.0f;
y.tickDirection = CPTSignNegative;
// Axis #2
CPTXYAxis *yRoll = [[CPTXYAxis alloc] init];
yRoll.title = #"Degrees";
// Styling
yRoll.titleTextStyle = axisTitleStyle;
yRoll.labelTextStyle = axisTextStyle;
yRoll.axisLineStyle = axisLineStyle;
yRoll.majorTickLineStyle = axisLineStyle;
yRoll.plotSpace = rollSpace;
yRoll.delegate = self;
yRoll.labelingPolicy = CPTAxisLabelingPolicyNone;
yRoll.coordinate = CPTCoordinateY;
yRoll.tickDirection = CPTSignNone;
yRoll.separateLayers = NO;
yRoll.tickDirection = CPTSignNegative;
yRoll.labelOffset = 21.0f;
yRoll.axisConstraints = [CPTConstraints constraintWithLowerOffset:40.0];
yRoll.orthogonalCoordinateDecimal = CPTDecimalFromFloat(0.0f);
NSMutableSet *rollLabels = [NSMutableSet new];
NSMutableSet *rollLocations = [NSMutableSet new];
for (int i =0; i <= 40; i+= 5) {
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:#"%02d˚", (i - 20)] textStyle:yRoll.labelTextStyle];
CGFloat location = i;
label.tickLocation = CPTDecimalFromCGFloat(location);
label.offset = -16.0f;
if (label) {
[rollLabels addObject:label];
[rollLocations addObject:[NSNumber numberWithInteger:i]];
}
}
yRoll.axisLabels = rollLabels;
yRoll.majorTickLocations = rollLocations;
NSInteger majorIncrement = 500;
NSInteger minorIncrement = 100;
CGFloat yMax = maxAlt; // should determine dynamically based on max price
NSMutableSet *yLabels = [NSMutableSet set];
NSMutableSet *yMajorLocations = [NSMutableSet set];
NSMutableSet *yMinorLocations = [NSMutableSet set];
for (NSInteger j = minorIncrement; j <= yMax; j += minorIncrement) {
NSUInteger mod = j % majorIncrement;
if (mod == 0) {
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:#"%i ft", j] textStyle:y.labelTextStyle];
NSDecimal location = CPTDecimalFromInteger(j);
label.tickLocation = location;
label.offset = -y.majorTickLength - y.labelOffset;
if (label) {
[yLabels addObject:label];
}
[yMajorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:location]];
} else {
[yMinorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:CPTDecimalFromInteger(j)]];
}
}
// Position the y2 axis
// y2.axisConstraints = [CPTConstraints constraintWithUpperOffset:40.0];
axisSet.yAxis.axisConstraints = [CPTConstraints constraintWithUpperOffset:40.0];
y.axisLabels = yLabels;
y.majorTickLocations = yMajorLocations;
y.minorTickLocations = yMinorLocations;
self.hostView.hostedGraph.axisSet.axes = [NSArray arrayWithObjects:x,y,yRoll,nil];
// Position floating YAxis
// y2.axisConstraints = [CPTConstraints constraintWithUpperOffset:150.0];
}
EDIT::
I tried adding the following lines and they did nothing either
y.orthogonalCoordinateDecimal = CPTDecimalFromFloat(0.0f);
x.orthogonalCoordinateDecimal = CPTDecimalFromFloat(0.0f);
I seem to be making progress actually: It appears that if I remove
yAxis2.axisConstraints = [CPTConstraints constraintWithLowerOffset:40.0];
Then my axis actually seems to pin to the x-axis (although its off the screen) now but its a start.
Problem Solved:
I had some conflicting directives going on.
In order to achieve what I needed I had to use the two calls:
yAxis2.orthogonalCoordinateDecimal = CPTDecimalFromFloat(0.0f);
y.orthogonalCoordinateDecimal = CPTDecimalFromFloat(maxEpoch); // maximum X value
x.orthogonalCoordinateDecimal = CPTDecimalFromFloat(0.0f);
Then in order to make sure everything could be seen correctly I had to play with the padding values:
float padding = 50.0f;
[graph.plotAreaFrame setPaddingLeft:padding];
[graph.plotAreaFrame setPaddingBottom:50.0f];
[graph.plotAreaFrame setPaddingRight:padding];
[graph.plotAreaFrame setPaddingTop:padding];
And I had to remove all the constraints that were messing with things:
// yAxis2.axisConstraints = [CPTConstraints constraintWithLowerOffset:40.0];
// y.axisConstraints = [CPTConstraints constraintWithUpperOffset:150.0];
I am using code from this link . And currently If I have 50 bar columns or 150 bar columns then the labels below is compressed and I would like to have horizontal scroll on x-Axis instead of having compressed x-Axis.
I have tried this:
plotSpace.xRange = CPTPlotRangeplotRangeWithLocation:CPTDecimalFromInt(-1)length:CPTDecimalFromInt(50)];
Attaching code from the file :
#import "GraphView.h"
#implementation GraphView
- (void)generateData
{
NSMutableDictionary *dataTemp = [[NSMutableDictionary alloc] init];
//Array containing all the dates that will be displayed on the X axis
dates = [NSArray arrayWithObjects:#"2012-05-01", #"2012-05-02", #"2012-05-03",
#"2012-05-04", #"2012-05-05", #"2012-05-06", #"2012-05-07", nil];
//Dictionary containing the name of the two sets and their associated color
//used for the demo
sets = [NSDictionary dictionaryWithObjectsAndKeys:[UIColor blueColor], #"Plot 1",
[UIColor redColor], #"Plot 2",
[UIColor greenColor], #"Plot 3", nil];
//Generate random data for each set of data that will be displayed for each day
//Numbers between 1 and 10
for (NSString *date in dates) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for (NSString *set in sets) {
NSNumber *num = [NSNumber numberWithInt:arc4random_uniform(10)+1];
[dict setObject:num forKey:set];
}
[dataTemp setObject:dict forKey:date];
}
data = [dataTemp copy];
[dataTemp release];
NSLog(#"%#", data);
}
- (void)generateLayout
{
//Create graph from theme
graph = [[CPTXYGraph alloc] initWithFrame:CGRectZero];
[graph applyTheme:[CPTTheme themeNamed:kCPTStocksTheme]];
self.hostedGraph = graph;
graph.plotAreaFrame.masksToBorder = NO;
graph.paddingLeft = 0.0f;
graph.paddingTop = 0.0f;
graph.paddingRight = 0.0f;
graph.paddingBottom = 0.0f;
CPTMutableLineStyle *borderLineStyle = [CPTMutableLineStyle lineStyle];
borderLineStyle.lineColor = [CPTColor whiteColor];
borderLineStyle.lineWidth = 2.0f;
graph.plotAreaFrame.borderLineStyle = borderLineStyle;
graph.plotAreaFrame.paddingTop = 10.0;
graph.plotAreaFrame.paddingRight = 10.0;
graph.plotAreaFrame.paddingBottom = 80.0;
graph.plotAreaFrame.paddingLeft = 70.0;
//Add plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.delegate = self;
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(0)
length:CPTDecimalFromInt(10 * sets.count)];
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(-1)
length:CPTDecimalFromInt(8)];
//Grid line styles
CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
majorGridLineStyle.lineWidth = 0.75;
majorGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.1];
CPTMutableLineStyle *minorGridLineStyle = [CPTMutableLineStyle lineStyle];
minorGridLineStyle.lineWidth = 0.25;
minorGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.1];
//Axes
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
//X axis
CPTXYAxis *x = axisSet.xAxis;
x.orthogonalCoordinateDecimal = CPTDecimalFromInt(0);
x.majorIntervalLength = CPTDecimalFromInt(1);
x.minorTicksPerInterval = 0;
x.labelingPolicy = CPTAxisLabelingPolicyNone;
x.majorGridLineStyle = majorGridLineStyle;
x.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
//X labels
int labelLocations = 0;
NSMutableArray *customXLabels = [NSMutableArray array];
for (NSString *day in dates) {
CPTAxisLabel *newLabel = [[CPTAxisLabel alloc] initWithText:day textStyle:x.labelTextStyle];
newLabel.tickLocation = [[NSNumber numberWithInt:labelLocations] decimalValue];
newLabel.offset = x.labelOffset + x.majorTickLength;
newLabel.rotation = M_PI / 4;
[customXLabels addObject:newLabel];
labelLocations++;
[newLabel release];
}
x.axisLabels = [NSSet setWithArray:customXLabels];
//Y axis
CPTXYAxis *y = axisSet.yAxis;
y.title = #"Value";
y.titleOffset = 50.0f;
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.majorGridLineStyle = majorGridLineStyle;
y.minorGridLineStyle = minorGridLineStyle;
y.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
//Create a bar line style
CPTMutableLineStyle *barLineStyle = [[[CPTMutableLineStyle alloc] init] autorelease];
barLineStyle.lineWidth = 1.0;
barLineStyle.lineColor = [CPTColor whiteColor];
CPTMutableTextStyle *whiteTextStyle = [CPTMutableTextStyle textStyle];
whiteTextStyle.color = [CPTColor whiteColor];
//Plot
BOOL firstPlot = YES;
for (NSString *set in [[sets allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)]) {
CPTBarPlot *plot = [CPTBarPlot tubularBarPlotWithColor:[CPTColor blueColor] horizontalBars:NO];
plot.lineStyle = barLineStyle;
CGColorRef color = ((UIColor *)[sets objectForKey:set]).CGColor;
plot.fill = [CPTFill fillWithColor:[CPTColor colorWithCGColor:color]];
if (firstPlot) {
plot.barBasesVary = NO;
firstPlot = NO;
} else {
plot.barBasesVary = YES;
}
plot.barWidth = CPTDecimalFromFloat(0.8f);
plot.barsAreHorizontal = NO;
plot.dataSource = self;
plot.identifier = set;
[graph addPlot:plot toPlotSpace:plotSpace];
}
//Add legend
CPTLegend *theLegend = [CPTLegend legendWithGraph:graph];
theLegend.numberOfRows = sets.count;
theLegend.fill = [CPTFill fillWithColor:[CPTColor colorWithGenericGray:0.15]];
theLegend.borderLineStyle = barLineStyle;
theLegend.cornerRadius = 10.0;
theLegend.swatchSize = CGSizeMake(15.0, 15.0);
whiteTextStyle.fontSize = 13.0;
theLegend.textStyle = whiteTextStyle;
theLegend.rowMargin = 5.0;
theLegend.paddingLeft = 10.0;
theLegend.paddingTop = 10.0;
theLegend.paddingRight = 10.0;
theLegend.paddingBottom = 10.0;
graph.legend = theLegend;
graph.legendAnchor = CPTRectAnchorTopLeft;
graph.legendDisplacement = CGPointMake(80.0, -10.0);
}
- (void)createGraph
{
//Generate data
[self generateData];
//Generate layout
[self generateLayout];
}
- (void)dealloc
{
[data release];
[super dealloc];
}
#pragma mark - CPTPlotDataSource methods
- (NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
return dates.count;
}
- (double)doubleForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
double num = NAN;
//X Value
if (fieldEnum == 0) {
num = index;
}
else {
double offset = 0;
if (((CPTBarPlot *)plot).barBasesVary) {
for (NSString *set in [[sets allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)]) {
if ([plot.identifier isEqual:set]) {
break;
}
offset += [[[data objectForKey:[dates objectAtIndex:index]] objectForKey:set] doubleValue];
}
}
//Y Value
if (fieldEnum == 1) {
num = [[[data objectForKey:[dates objectAtIndex:index]] objectForKey:plot.identifier] doubleValue] + offset;
}
//Offset for stacked bar
else {
num = offset;
}
}
//NSLog(#"%# - %d - %d - %f", plot.identifier, index, fieldEnum, num);
return num;
}
#pragma mark - CPTBarPlotDelegate methods
-(void)barPlot:(CPTBarPlot *)plot barWasSelectedAtRecordIndex:(NSUInteger)index {
NSLog(#"barWasSelectedAtRecordIndex %d", index);
}
#end
to get scrolling you need to set the globalXRange on the plotspace to be the entire range, and set the xRange will be the visible area.
for example a globalXRange of 0-150, and a xRange of 0-50. then you could scroll up to view the 51-150 range.