Based on the example RealTime presented in the library Core Plot, I tried to reimplement it on my project.
I am able to update y axis, add a symbol, draw label, etc. But I'm totally unable to draw the line.
CPTMutableLineStyle object seems to be correctly instantied and correctly setted to the CPTGraph object but is not rendered in the graph
Here is how I add line style to my graph
CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle]; // [dataSourceLinePlot.dataLineStyle mutableCopy];
lineStyle.lineWidth = 3.0;
lineStyle.lineColor = [CPTColor greenColor];
dataSourceLinePlot.dataLineStyle = lineStyle;
And here is the full class code
#import "TUTSimpleScatterPlot.h"
const double kFrameRate = 5.0; // frames per second
const double kAlpha = 0.15; // smoothing constant
const NSUInteger kMaxDataPoints = 21;
NSString *kPlotIdentifier = #"Data Source Plot";
#implementation TUTSimpleScatterPlot
// Initialise the scatter plot in the provided hosting view with the provided data.
// The data array should contain NSValue objects each representing a CGPoint.
-(id)initWithHostingView:(CPTGraphHostingView *)hostingView andData:(NSMutableArray *)data
{
self = [super init];
if ( self != nil ) {
self.hostingView = hostingView;
self.graphData = data;
self.graph = nil;
}
return self;
}
-(void)initialisePlot
{
self.graphData = [NSMutableArray array];
CGRect bounds = self.hostingView.bounds;
CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:bounds] ;
[self.hostingView setHostedGraph:graph];
graph.title = #"Measure";
CPTMutableTextStyle *textStyle = [CPTMutableTextStyle textStyle];
textStyle.color = [CPTColor grayColor];
textStyle.fontName = #"Helvetica-Bold";
textStyle.fontSize = round(bounds.size.height / (CGFloat)20.0);
graph.titleTextStyle = textStyle;
graph.titleDisplacement = CGPointMake( 0.0f, round(bounds.size.height / (CGFloat)18.0) ); // Ensure that title displacement falls on an integral pixel
graph.titlePlotAreaFrameAnchor = CPTRectAnchorTop;
CGFloat boundsPadding = round(bounds.size.width / (CGFloat)20.0); // Ensure that padding falls on an integral pixel
graph.paddingLeft = boundsPadding;
if ( graph.titleDisplacement.y > 0.0 ) {
graph.paddingTop = graph.titleDisplacement.y * 2;
}
else {
graph.paddingTop = boundsPadding;
}
graph.paddingRight = boundsPadding;
graph.paddingBottom = boundsPadding;
graph.plotAreaFrame.paddingTop = 15.0;
graph.plotAreaFrame.paddingRight = 15.0;
graph.plotAreaFrame.paddingBottom = 55.0;
graph.plotAreaFrame.paddingLeft = 55.0;
// Grid line styles
CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
majorGridLineStyle.lineWidth = 0.75;
majorGridLineStyle.lineColor = [[CPTColor colorWithGenericGray:0.2] colorWithAlphaComponent:0.75];
CPTMutableLineStyle *minorGridLineStyle = [CPTMutableLineStyle lineStyle];
minorGridLineStyle.lineWidth = 0.25;
minorGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.1];
// Axes
// X axis
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTXYAxis *x = axisSet.xAxis;
x.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
x.orthogonalCoordinateDecimal = CPTDecimalFromUnsignedInteger(0);
x.majorGridLineStyle = majorGridLineStyle;
x.minorGridLineStyle = minorGridLineStyle;
x.minorTicksPerInterval = 9;
x.title = #"X Axis";
x.titleOffset = 35.0;
NSNumberFormatter *labelFormatter = [[NSNumberFormatter alloc] init];
labelFormatter.numberStyle = NSNumberFormatterNoStyle;
x.labelFormatter = labelFormatter;
// Y axis
CPTXYAxis *y = axisSet.yAxis;
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.orthogonalCoordinateDecimal = CPTDecimalFromUnsignedInteger(0);
y.majorGridLineStyle = majorGridLineStyle;
y.minorGridLineStyle = minorGridLineStyle;
y.minorTicksPerInterval = 3;
y.labelOffset = 5.0;
y.title = #"Y Axis";
y.titleOffset = 30.0;
y.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
// Rotate the labels by 45 degrees, just to show it can be done.
x.labelRotation = M_PI * 0.25;
// Create the plot
CPTScatterPlot *dataSourceLinePlot = [[CPTScatterPlot alloc] init];
dataSourceLinePlot.identifier = kPlotIdentifier;
dataSourceLinePlot.cachePrecision = CPTPlotCachePrecisionDouble;
// dataSourceLinePlot.interpolation = CPTScatterPlotInterpolationCurved;
CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle]; // [dataSourceLinePlot.dataLineStyle mutableCopy];
lineStyle.lineWidth = 3.0;
lineStyle.lineColor = [CPTColor greenColor];
dataSourceLinePlot.dataLineStyle = lineStyle;
CPTMutableLineStyle *symbolLineStyle = [CPTMutableLineStyle lineStyle];
symbolLineStyle.lineColor = [[CPTColor blackColor] colorWithAlphaComponent:0.5];
CPTPlotSymbol *plotSymbol = [CPTPlotSymbol ellipsePlotSymbol];
plotSymbol.fill = [CPTFill fillWithColor:[[CPTColor blueColor] colorWithAlphaComponent:0.5]];
plotSymbol.lineStyle = symbolLineStyle;
plotSymbol.size = CGSizeMake(10.0, 10.0);
dataSourceLinePlot.plotSymbol = plotSymbol;
dataSourceLinePlot.dataSource = self;
[graph addPlot:dataSourceLinePlot];
// Plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(kMaxDataPoints - 1)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(1)];
self.graph = graph;
self.dataTimer = [NSTimer timerWithTimeInterval:1.0 / kFrameRate
target:self
selector:#selector(newData:)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.dataTimer forMode:NSDefaultRunLoopMode];
}
#pragma mark -
#pragma mark Timer callback
-(void)newData:(NSTimer *)theTimer
{
CPTGraph *theGraph = self.graph;
CPTPlot *thePlot = [theGraph plotWithIdentifier:kPlotIdentifier];
if ( thePlot ) {
// if ( self.graphData.count >= kMaxDataPoints - 5 ) {
// [self.graphData removeObjectAtIndex:0];
// [thePlot deleteDataInIndexRange:NSMakeRange(0, 1)];
// }
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)theGraph.defaultPlotSpace;
NSUInteger location = (_currentIndex >= kMaxDataPoints ? _currentIndex - kMaxDataPoints + 5 : 0);
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(location)
length:CPTDecimalFromUnsignedInteger(kMaxDataPoints - 1)];
_currentIndex++;
NSNumber * num;
if (_currentIndex == 1) {
num = [NSNumber numberWithDouble: 5 + (arc4random() % 15) ];
} else {
NSLog(#"lastVal: %d", [[self.graphData lastObject] intValue]);
float low_bound = (1 - kAlpha) * [[self.graphData lastObject] floatValue];
float high_bound = (1.01 + kAlpha) * [[self.graphData lastObject] floatValue];
float random = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);
NSLog(#"random: %f", random);
num = [NSNumber numberWithDouble:random];
}
// Update y range if necessary
if (_currentIndex < kMaxDataPoints) {
int maxValue = -1;
for (int i = self.graphData.count -1 ; (i >= 0); i--) {
if ([[self.graphData objectAtIndex:i] intValue] > maxValue) {
maxValue = [[self.graphData objectAtIndex:i] intValue];
}
}
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(maxValue + 1)];
} else if (_currentIndex >= kMaxDataPoints) {
int maxValue = -1;
for (int i = self.graphData.count -1 ; (i >= self.graphData.count - kMaxDataPoints + 2); i--) {
if ([[self.graphData objectAtIndex:i] intValue] > maxValue) {
maxValue = [[self.graphData objectAtIndex:i] intValue];
}
}
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(maxValue + 1)];
}
[self.graphData addObject:num];
[thePlot insertDataAtIndex:self.graphData.count - 1 numberOfRecords:1];
}
}
#pragma mark -
#pragma mark Plot Data Source Methods
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
return [self.graphData count];
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSNumber *num = nil;
switch ( fieldEnum ) {
case CPTScatterPlotFieldX:
num = [NSNumber numberWithUnsignedInteger:index + _currentIndex - self.graphData.count];
break;
case CPTScatterPlotFieldY:
num = [self.graphData objectAtIndex:index];
break;
default:
break;
}
return num;
}
#end
Any ideas ? Tips ? Hack ?
UPDATE 1
In my project I used the 1.2 version of the library. I tried to regress to 1.0 version and lines are now displayed. Any ideas on how to convert my project to work with the last version ?
UPDATE 2*
Changing the Podfile from pod 'CorePlot' to pod 'CorePlot', '~> 1.2' seems to be different. My line is now correctly drawn...
Seems there is difference by using cocoapods by this way
pod 'CorePlot'
or by this way
pod 'CorePlot', '~> 1.2'
Then reinstalling the libaries by executing pod install
Now the project is able to draw line
Related
I'm trying to implement the real-time plot example from core-plot into my ios project, I keep getting [CPTPlotRange objCType]: unrecognized selector sent to instance which seems to be stopping the CPTAnimation for moving the graph to the newest values.
This is pretty much all of my code, and I cannot figure out why this issue occurs
-(id)initWithGraphView:(CPTGraphHostingView *) gView name:(NSString *)label {
self = [super init];
if(self) {
_graphView = gView;
CGRect bounds = _graphView.bounds;
_graph = [[CPTXYGraph alloc] initWithFrame:bounds];
_graphView.hostedGraph = _graph;
_currentIndex = 0;
_plotData = [[NSMutableArray alloc] initWithCapacity:kMaxDataPoints];
[_plotData removeAllObjects];
CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
majorGridLineStyle.lineWidth = 0.75;
majorGridLineStyle.lineColor = [[CPTColor colorWithGenericGray:CPTFloat(0.2)] colorWithAlphaComponent:CPTFloat(0.75)];
CPTMutableLineStyle *minorGridLineStyle = [CPTMutableLineStyle lineStyle];
minorGridLineStyle.lineWidth = 0.25;
minorGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:CPTFloat(0.1)];
// Axes
// X axis
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)_graph.axisSet;
CPTXYAxis *x = axisSet.xAxis;
x.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
x.orthogonalPosition = #0.0;
x.majorGridLineStyle = majorGridLineStyle;
x.minorGridLineStyle = minorGridLineStyle;
x.minorTicksPerInterval = 9;
x.title = #"X Axis";
NSNumberFormatter *labelFormatter = [[NSNumberFormatter alloc] init];
labelFormatter.numberStyle = NSNumberFormatterNoStyle;
x.labelFormatter = labelFormatter;
// Y axis
CPTXYAxis *y = axisSet.yAxis;
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.orthogonalPosition = #0.0;
y.majorGridLineStyle = majorGridLineStyle;
y.minorGridLineStyle = minorGridLineStyle;
y.minorTicksPerInterval = 3;
y.title = #"Y Axis";
y.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
// Rotate the labels by 45 degrees, just to show it can be done.
x.labelRotation = CPTFloat(M_PI_4);
// Create the plot
CPTScatterPlot *dataSourceLinePlot = [[CPTScatterPlot alloc] init];
dataSourceLinePlot.identifier = kPlotIdentifier;
dataSourceLinePlot.cachePrecision = CPTPlotCachePrecisionDouble;
dataSourceLinePlot.interpolation = CPTScatterPlotInterpolationCurved;
CPTMutableLineStyle *lineStyle = [dataSourceLinePlot.dataLineStyle mutableCopy];
lineStyle.lineWidth = 3.0;
lineStyle.lineColor = [CPTColor greenColor];
dataSourceLinePlot.dataLineStyle = lineStyle;
dataSourceLinePlot.dataSource = self;
[_graph addPlot:dataSourceLinePlot];
// Plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)_graph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:#0.0 length:#(kMaxDataPoints - 2)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:#0.0 length:#1000000.0];
}
return self;
}
-(void)newData:(int)value
{
NSLog(#"adding, %i", value);
CPTGraph *theGraph = _graph;
CPTPlot *thePlot = [theGraph plotWithIdentifier:kPlotIdentifier];
if ( thePlot ) {
if ( self.plotData.count >= kMaxDataPoints ) {
[self.plotData removeObjectAtIndex:0];
[thePlot deleteDataInIndexRange:NSMakeRange(0, 1)];
}
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)_graph.defaultPlotSpace;
NSUInteger location = (self.currentIndex >= kMaxDataPoints ? self.currentIndex - kMaxDataPoints + 2 : 0);
CPTPlotRange *oldRange = [CPTPlotRange plotRangeWithLocation:#( (location > 0) ? (location - 1) : 0 )
length:#(kMaxDataPoints - 2)];
CPTPlotRange *newRange = [CPTPlotRange plotRangeWithLocation:#(location)
length:#(kMaxDataPoints - 2)];
[CPTAnimation animate:plotSpace
property:#"xRange"
fromPlotRange:oldRange
toPlotRange:newRange
duration:CPTFloat(1.0 / kFrameRate)];
self.currentIndex++;
[self.plotData addObject:#(value)];
[thePlot insertDataAtIndex:self.plotData.count - 1 numberOfRecords:1];
}
}
-(NSUInteger)numberOfRecordsForPlot:(nonnull CPTPlot *)plot
{
return _plotData.count;
}
-(nullable id)numberForPlot:(nonnull CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSNumber *num = nil;
switch ( fieldEnum ) {
case CPTScatterPlotFieldX:
num = #(index + _currentIndex - _plotData.count);
break;
case CPTScatterPlotFieldY:
num = _plotData[index];
break;
default:
break;
}
return num;
}
There was a bug in Core Plot 2.1 that caused this error when animating plot ranges. It's fixed on the master branch and will be in the next release.
In the meantime, you can pull the latest code from GitHub or point Cocoapods to the latest code on master rather than to a release package (pod 'CorePlot', :git => 'https://github.com/core-plot/core-plot.git').
I am using coreplot to display graph. Annotations are not showing above the location points.
When i debug the graph.plotAreaFrame.plotArea touchedPoints are showing NAN instead of correct points.
-(void)configureGraph {
// 1 - Create the graph
CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:CGRectMake(0.0, 0.0, 320, 260)];
[graph applyTheme:[CPTTheme themeNamed:kCPTStocksTheme]];
graph.fill = [CPTFill fillWithColor:[CPTColor clearColor]];
graph.plotAreaFrame.fill = [CPTFill fillWithColor:[CPTColor clearColor]];
// 2 - Set graph title
NSString *title = #"Speed";
//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, 10.0f);
// 4 - Set padding for plot area
[graph.plotAreaFrame setPaddingLeft:35.0f];
[graph.plotAreaFrame setPaddingBottom:25.0f];
[graph.plotAreaFrame setPaddingTop:5.0f];
[graph.plotAreaFrame setPaddingRight:0.0f];
graph.plotAreaFrame.masksToBorder = YES;
//graph.plotAreaFrame.plotArea.delegate = self;
// 5 - Enable user interactions for plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
plotSpace.allowsUserInteraction = YES;
plotSpace.delegate = self;
// 2 - Create the three plots
CPTScatterPlot *aaplPlot = [[CPTScatterPlot alloc] init];
aaplPlot.dataSource = self;
aaplPlot.delegate = self;
aaplPlot.plotSymbolMarginForHitDetection = 5.0;
aaplPlot.interpolation = CPTScatterPlotInterpolationCurved;
aaplPlot.identifier = #"A";
CPTColor *aaplColor = [CPTColor colorWithComponentRed:127.0f/255.0f green:255.0f/255.0f blue:255.0f/255.0f alpha:1.0f];
[graph addPlot:aaplPlot toPlotSpace:plotSpace];
// 3 - Set up plot space
[plotSpace scaleToFitPlots:[NSArray arrayWithObjects:aaplPlot, nil]];
[plotSpace setYRange: [CPTPlotRange plotRangeWithLocation:[NSNumber numberWithInt:0] length:[NSNumber numberWithInt:maxY+10]]];
[plotSpace setXRange: [CPTPlotRange plotRangeWithLocation:[NSNumber numberWithInt:0] length:[NSNumber numberWithInt:maxX]]];
// 4 - Create styles and symbols
CPTMutableLineStyle *aaplLineStyle = [aaplPlot.dataLineStyle mutableCopy];
aaplLineStyle.lineWidth = 2.5;
aaplLineStyle.lineColor = aaplColor;
aaplPlot.dataLineStyle = aaplLineStyle;
CPTMutableLineStyle *aaplSymbolLineStyle = [CPTMutableLineStyle lineStyle];
aaplSymbolLineStyle.lineColor = aaplColor;
CPTPlotSymbol *aaplSymbol = [CPTPlotSymbol ellipsePlotSymbol];
aaplSymbol.fill = [CPTFill fillWithColor:aaplColor];
aaplSymbol.lineStyle = aaplSymbolLineStyle;
aaplSymbol.size = CGSizeMake(6.0f, 6.0f);
aaplPlot.plotSymbol = aaplSymbol;
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 *) graph.axisSet;
// 3 - Configure x-axis
CPTAxis *x = axisSet.xAxis;
x.title = #"Distance --> (Points are 200 meter apart)";
x.titleTextStyle = axisTitleStyle;
x.titleOffset = 8.0f;
x.labelOffset = 0.0f;
x.axisLineStyle = axisLineStyle;
x.labelingPolicy = CPTAxisLabelingPolicyNone;
x.preferredNumberOfMajorTicks = 4;
x.labelTextStyle = axisTextStyle;
x.majorTickLineStyle = axisLineStyle;
x.majorTickLength = 0.0f;
x.minorTickLength = 0.0f;
x.tickDirection = CPTSignNegative;
CGFloat dateCount = [self.arrayOfDates count];
NSMutableSet *xLabels = [NSMutableSet setWithCapacity:dateCount];
NSMutableSet *xLocations = [NSMutableSet setWithCapacity:dateCount];
float i = 0.0;
for (int index = 0 ; index < [self.arrayOfDates count]; index++) {
float distanceX = (float)([[[self.arrayOfDates objectAtIndex:index] objectForKey:#"Distance"] floatValue]);
NSString *labelDist = [NSString stringWithFormat:#"%.2f", distanceX];
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:labelDist textStyle:x.labelTextStyle];
CGFloat location = i++;
label.tickLocation = [NSNumber numberWithFloat:i];
label.offset = x.majorTickLength;
if (label) {
[xLabels addObject:label];
[xLocations addObject:[NSNumber numberWithFloat:location]];
}
}
//x.axisLabels = xLabels;
//x.majorTickLocations = xLocations;
// 4 - Configure y-axis
CPTAxis *y = axisSet.yAxis;
y.title = #"Traffic Density";
y.titleTextStyle = axisTitleStyle;
y.titleOffset = 18.0f;
y.axisLineStyle = axisLineStyle;
//y.majorGridLineStyle = gridLineStyle;
y.labelingPolicy = CPTAxisLabelingPolicyNone;
y.preferredNumberOfMajorTicks = 4;
y.labelTextStyle = axisTextStyle;
y.labelOffset = 0.0f;
y.majorTickLineStyle = axisLineStyle;
y.majorTickLength = 0.0f;
y.minorTickLength = 0.0f;
y.tickDirection = CPTSignNegative;
int majorIncrement = ceil(maxY/4);
NSInteger minorIncrement = maxY/8;
CGFloat yMax = maxY; // should determine dynamically based on max price
NSMutableSet *yLabels = [NSMutableSet set];
NSMutableSet *yMajorLocations = [NSMutableSet set];
NSMutableSet *yMinorLocations = [NSMutableSet set];
for (NSInteger j = 0; j <= yMax + majorIncrement; j++) {
NSUInteger mod = j % majorIncrement;
if (mod == 0) {
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:#"%i", j] textStyle:y.labelTextStyle];
NSDecimal location = CPTDecimalFromInteger(j);
label.tickLocation = [NSNumber numberWithInt:j];
label.offset = -y.majorTickLength - y.labelOffset;
if (label) {
[yLabels addObject:label];
}
[yMajorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:location]];
}
}
y.axisLabels = yLabels;
y.majorTickLocations = yMajorLocations;
// Create a plot that uses the data source method
axisSet.xAxis.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
axisSet.xAxis.orthogonalPosition = [NSNumber numberWithInt:0];
axisSet.yAxis.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
self.hostView.collapsesLayers = NO;
self.hostView.hostedGraph = graph;}
This is the coreplot annotation display method.
-(void)scatterPlot:(nonnull CPTScatterPlot *)plot plotSymbolWasSelectedAtRecordIndex:(NSUInteger)index
{
CPTGraph *graph = self.hostView.hostedGraph;
CPTPlotSpaceAnnotation *annotation = self.symbolTextAnnotation;
if ( annotation ) {
[graph.plotAreaFrame.plotArea removeAnnotation:annotation];
self.symbolTextAnnotation = nil;
}
// Setup a style for the annotation
CPTMutableTextStyle *hitAnnotationTextStyle = [CPTMutableTextStyle textStyle];
hitAnnotationTextStyle.color = [CPTColor whiteColor];
hitAnnotationTextStyle.fontName = #"Helvetica-Bold";
hitAnnotationTextStyle.fontSize = 16.0;
// Determine point of symbol in plot coordinates
NSNumber *x = [NSNumber numberWithFloat:[[[self.arrayOfDates objectAtIndex:index] objectForKey:#"Distance"] floatValue]] ;
NSNumber *y = [NSNumber numberWithFloat:[[[self.arrayOfValues objectAtIndex:index] objectForKey:#"Speed"] floatValue]];
CPTNumberArray *anchorPoint = #[x, y];
// Add annotation
// First make a string for the y value
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.maximumFractionDigits = 2;
NSString *yString = [formatter stringFromNumber:y];
CPTPlotSpace *defaultSpace = graph.defaultPlotSpace;
if ( defaultSpace ) {
CPTTextLayer *textLayer = [[CPTTextLayer alloc] initWithText:yString style:hitAnnotationTextStyle];
annotation = [[CPTPlotSpaceAnnotation alloc] initWithPlotSpace:defaultSpace anchorPlotPoint:anchorPoint];
annotation.contentLayer = textLayer;
annotation.displacement = CGPointMake(0.0, 10.0);
[graph.plotAreaFrame.plotArea addAnnotation:annotation];
}
}
Please check the screenshot the points are not aligned with the points of the graph.
Data Source methods
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
NSInteger valueCount = [self.arrayOfDates count];
switch (fieldEnum) {
case CPTScatterPlotFieldX:
if (index < valueCount) {
distanceX += [[[self.arrayOfDates objectAtIndex:index] objectForKey:#"Distance"] floatValue];
NSLog(#"Distance = %f",distanceX);
return [NSNumber numberWithFloat:distanceX];
}
break;
case CPTScatterPlotFieldY:{
float distance = [[[self.arrayOfValues objectAtIndex:index] objectForKey:#"Speed"] floatValue];
return [NSNumber numberWithFloat:distance];
break;
}
}
return [NSDecimalNumber zero];}
When i touched the point, plotAreaFrame.plotArea.touchedPoint is NAN. Please refer this screenshot
The question doesn't show the datasource methods, but based on how the x-axis labels are set up, it looks like the x-values are plotted as the data index. Try using the following anchor point calculation when positioning the annotation:
NSNumber *y = [[self.arrayOfValues objectAtIndex:index] objectForKey:#"Speed"];
CPTNumberArray *anchorPoint = #[#(index), y];
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!
I have the following code below to display two Y axes (one on the right and one on the left). I would like to be able to plot to each graph per a different data set (mapping to the same X value). I can't seem to get two CPTXYPlotSpaces to display at the same time. How would I go about this so I can plot to two different Plot Spaces and see the graphed lines at the same time.
-(void)configureHost
{
CGRect bounds = self.view.bounds;
bounds.size.height = bounds.size.height;
self.hostView = [[CPTGraphHostingView alloc] initWithFrame:bounds];
self.hostView.allowPinchScaling = YES;
[self.view addSubview:self.hostView];
}
-(void)configureGraph
{
self.graph = [[CPTXYGraph alloc] initWithFrame:self.hostView.bounds];
[self.graph applyTheme:[CPTTheme themeNamed:kCPTPlainWhiteTheme]];
self.hostView.hostedGraph = self.graph;
self.graph.paddingLeft = 20.0;
self.graph.paddingTop = 20.0;
self.graph.paddingRight = 20.0;
self.graph.paddingBottom = 20.0;
}
NSString *const kPlot1 = #"Plot 1";
NSString *const kPlot2 = #"Plot 2";
-(void)configurePlots
{
CGRect bounds = self.hostView.bounds;
self.plotSpace1 = (CPTXYPlotSpace *) self.graph.defaultPlotSpace;
self.plotSpace1.allowsUserInteraction = NO;
self.scatterPlot1 = [[CPTScatterPlot alloc]init];
self.scatterPlot1.identifier = kPlot1;
self.scatterPlot1.dataSource = self;
[self.graph addPlot:self.scatterPlot1 toPlotSpace:self.plotSpace1];
self.scatterPlot2 = [[CPTScatterPlot alloc]init];
self.scatterPlot2.identifier = kPlot2;
self.scatterPlot2.dataSource =self;
[self.graph addPlot:self.scatterPlot2 toPlotSpace:self.plotSpace2];
[self.plotSpace1 scaleToFitPlots:#[self.scatterPlot1, self.scatterPlot2]];
[self.plotSpace2 scaleToFitPlots:#[self.scatterPlot1, self.scatterPlot2]];
CPTGraph *graph = self.hostView.hostedGraph;
graph.plotAreaFrame.fill = [CPTFill fillWithColor:[CPTColor whiteColor]];
[self setTitleDefaultsForGraph:graph withBounds:bounds];
[self setPaddingDefaultsForGraph:graph withBounds:bounds];
graph.plotAreaFrame.paddingTop = 20.0;
graph.plotAreaFrame.paddingBottom = 50.0;
graph.plotAreaFrame.paddingLeft = 50.0;
graph.plotAreaFrame.paddingRight = 50.0;
graph.plotAreaFrame.cornerRadius = 10.0;
graph.plotAreaFrame.masksToBorder = NO;
graph.plotAreaFrame.axisSet.borderLineStyle = [CPTLineStyle lineStyle];
// Setup plot space
self.plotSpace1.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.0) length:CPTDecimalFromDouble(10.0)];
self.plotSpace1.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.0) length:CPTDecimalFromDouble(10.0)];
self.plotSpace2 = [[CPTXYPlotSpace alloc] init];
self.plotSpace2.xRange = self.plotSpace1.xRange;
self.plotSpace2.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.0) length:CPTDecimalFromDouble(10.0)];
[graph addPlotSpace:self.plotSpace2];
}
-(void)setPaddingDefaultsForGraph:(CPTGraph *)graph withBounds:(CGRect)bounds
{
// CGFloat boundsPadding = round( bounds.size.width / CPTFloat(20.0) ); // Ensure that padding falls on an integral pixel
//
// graph.paddingLeft = boundsPadding;
//
// if ( graph.titleDisplacement.y > 0.0 ) {
// graph.paddingTop = graph.titleTextStyle.fontSize * 2.0;
// }
// else {
// graph.paddingTop = boundsPadding;
// }
//
// graph.paddingRight = boundsPadding;
// graph.paddingBottom = boundsPadding;
graph.paddingTop = 0.0f;
graph.paddingBottom = 0.0f;
graph.paddingLeft = 0.0f;
graph.paddingRight = 0.0f;
}
-(void)setTitleDefaultsForGraph:(CPTGraph *)graph withBounds:(CGRect)bounds
{
graph.title = self.title;
CPTMutableTextStyle *textStyle = [CPTMutableTextStyle textStyle];
textStyle.color = [CPTColor grayColor];
textStyle.fontName = #"Helvetica-Bold";
textStyle.fontSize = round( bounds.size.height / CPTFloat(20.0) );
graph.titleTextStyle = textStyle;
graph.titleDisplacement = CPTPointMake( 0.0, textStyle.fontSize * CPTFloat(1.5) );
graph.titlePlotAreaFrameAnchor = CPTRectAnchorTop;
}
-(void)configureAxis
{
CPTGraph *graph = self.hostView.hostedGraph;
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
// Line styles
CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
axisLineStyle.lineWidth = 3.0;
axisLineStyle.lineCap = kCGLineCapRound;
// Text styles
CPTMutableTextStyle *axisTitleTextStyle = [CPTMutableTextStyle textStyle];
axisTitleTextStyle.fontName = #"Helvetica-Bold";
axisTitleTextStyle.fontSize = 14.0;
CPTXYAxis *x = axisSet.xAxis;
x.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0.0);//Where the Y Axis meets the X axis
x.majorIntervalLength = CPTDecimalFromDouble(1.5);//Interval for X Axis
x.minorTicksPerInterval = 4;
x.tickDirection = CPTSignNone;
x.axisLineStyle = axisLineStyle;
x.majorTickLength = 12.0;
x.majorTickLineStyle = axisLineStyle;
x.minorTickLength = 8.0;
x.title = #"X Axis";
x.titleTextStyle = axisTitleTextStyle;
x.titleOffset = 25.0;
x.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
// Label y with an automatic labeling policy.
axisLineStyle.lineColor = [CPTColor greenColor];
CPTXYAxis *y = axisSet.yAxis;
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.minorTicksPerInterval = 9;
y.tickDirection = CPTSignNegative;
y.axisLineStyle = axisLineStyle;
y.majorTickLength = 6.0;
y.majorTickLineStyle = axisLineStyle;
y.minorTickLength = 4.0;
y.title = #"Y Axis";
y.titleTextStyle = axisTitleTextStyle;
y.titleOffset = 30.0;
// Label y2 with an equal division labeling policy.
axisLineStyle.lineColor = [CPTColor orangeColor];
CPTXYAxis *y2 = [[CPTXYAxis alloc] init];
y2.coordinate = CPTCoordinateY;
y2.plotSpace = self.plotSpace2;
y2.orthogonalCoordinateDecimal = CPTDecimalFromDouble(10.0);//Where the Y Axis meets the X axis
y2.labelingPolicy = CPTAxisLabelingPolicyEqualDivisions;
y2.preferredNumberOfMajorTicks = 6;
y2.minorTicksPerInterval = 9;
y2.tickDirection = CPTSignPositive;
y2.axisLineStyle = axisLineStyle;
y2.majorTickLength = 6.0;
y2.majorTickLineStyle = axisLineStyle;
y2.minorTickLength = 4.0;
y2.title= #"Y2 Axis";
y2.titleTextStyle = axisTitleTextStyle;
y2.titleOffset = 30.0;
// Add the y2 axis to the axis set
graph.axisSet.axes = #[x, y, y2];
}
#pragma mark CPTPlotDataSource
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
if ( [(NSString *)plot.identifier isEqualToString:kPlot1] ) {
return 10;
}
else if ( [(NSString *)plot.identifier isEqualToString:kPlot2] ) {
return 5;
} else {
return 0;
}
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)idx
{
switch (fieldEnum) {
case CPTScatterPlotFieldX:
if ([plot.identifier isEqual:kPlot1]) {
return [NSNumber numberWithUnsignedInt:idx];
break;
}else if ([plot.identifier isEqual:kPlot2]){
return [NSNumber numberWithUnsignedInt:idx];
break;
}
case CPTScatterPlotFieldY:
if ([plot.identifier isEqual:kPlot1]) {
return #(idx *2);
} else if ([plot.identifier isEqual:kPlot2]) {
return #(idx +2);
}
}
return 0;
}
You're (re-)initializing plotSpace2 after you scale it. Move the call to [self.plotSpace2 scaleToFitPlots:...] after setting up the plot space.
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.