how to draw multiple plots in coreplot - core-plot

I need to draw multiple plots in the same graph at different times. Please look at the image below:
Except that the number of plots would change dynamically. Sometimes I would only require only blue and orange datasets some times all four and some times only 3. I am able to manage for one bar plot like this.
CPTScatterPlot *plot = [[[CPTScatterPlot alloc] init] autorelease];
plot.dataSource = self;
plot.identifier = #"mainplot";
plot.dataLineStyle = lineStyle;
plot.plotSymbol = plotSymbol;
[self.graph addPlot:plot];
In my case I can put them in a for loop and do [self.graph addplot:plot] in each iteration. But how do I manage the datasource. How do I manage the code below, if the number of datasets changes dynamically.
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
if ( [plot.identifier isEqual:#"mainplot"] )
{
NSValue *value = [self.graphData objectAtIndex:index];
CGPoint point = [value CGPointValue];
// FieldEnum determines if we return an X or Y value.
if ( fieldEnum == CPTScatterPlotFieldX )
{
return [NSNumber numberWithFloat:point.x];
}
else // Y-Axis
{
return [NSNumber numberWithFloat:point.y];
}
}
return [NSNumber numberWithFloat:0];
}

I did it before and it worked! You can use an NSArray for plots, and create some plot data and add them as objects into a NSDictionary. for more detail you can see this sample:
NSDictionary *firstLineDic = [NSDictionary dictionaryWithObjectsAndKeys:#"firstLine", PLOT_IDENTIFIER, firstLineData, PLOT_DATA, nil];
NSDictionary *secondLineDic = [NSDictionary dictionaryWithObjectsAndKeys:#"secondLine", PLOT_IDENTIFIER, secondLineData, PLOT_DATA, nil];
NSArray *arrayData = [NSArray arrayWithObjects:firstLineDic, secondLineDic, nil];
scatterPlot = [[ScatterPlot alloc] initWithHostingView:plotView data:arrayData];
[scatterPlot initialisePlot];
Now in ScatterPlot class write these functions:
-(id)initWithHostingView:(CPTGraphHostingView *)_hostingView data:(NSArray *)_data{
self = [super init];
if ( self != nil ) {
self.hostingView = _hostingView;
data = [[NSArray alloc] initWithArray:_data];
self.graph = nil;
}
return self;
}
-(void)initialisePlot
{
...
for (NSDictionary *dic in data) {
CPTScatterPlot *plot = [[[CPTScatterPlot alloc] init] autorelease];
plot.dataSource = self;
plot.identifier = [dic objectForKey:PLOT_IDENTIFIER];
plot.dataLineStyle = [lineStyles objectAtIndex:[dic objectForKey:PLOT_COLOR]];
plot.plotSymbol = plotSymbol;
[self.graph addPlot:plot];
}
...
}
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
for (NSDictionary *dic in data) {
NSString *identity = [dic objectForKey:PLOT_IDENTIFIER];
if([plot.identifier isEqual:identity]){
NSArray *arr = [dic objectForKey:PLOT_DATA];
return [arr count];
}
}
return 0;
}

Check for different plot identifiers, and return other data then.

Related

Core Plot ScatterPlot on Horizontal Bar plot

I'm trying to display a line using a ScatterPlot on Bar plot, which is horizontal. It does work for vertical bar plots, but not for the horizontal one.
This is the source code:
-(id)init
{
if ( (self = [super init]) ) {
self.section = kBarPlots;
self.isOneBarPlot = TRUE;
}
return self;
}
-(void)generateData
{
[[BPDatabaseController sharedController] dataForTopFiveObservationPeriodIncidents:^(NSArray *resultArray) {
self.plotData = resultArray;
FilterManager *fm = [FilterManager sharedInstance];
self.isOneBarPlot = fm.filterPendingIncidents; //is responsible for showing the legend correctly
[self renderInLayer:self.defaultLayerHostingView withTheme:self.theme animated:YES];
[super generateData];
}];
}
-(void)renderInLayer:(CPTGraphHostingView *)layerHostingView withTheme:(CPTTheme *)theme animated:(BOOL)animated
{
CGRect bounds = layerHostingView.bounds;
CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:bounds];
[self addGraph:graph toHostingView:layerHostingView];
[self applyTheme:theme toGraph:graph withDefault:nil];
[self setTitleDefaultsForGraph:graph withBounds:bounds];
[self setPaddingDefaultsForGraph:graph withBounds:bounds];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
graph.paddingLeft = 0.0f;
}else{
graph.paddingLeft = 65.0f;
}
graph.paddingRight = 0.0f;
NSNumberFormatter *format = [[NSNumberFormatter alloc] init];
[format setNumberStyle:NSNumberFormatterNoStyle];
// Create bar plot
CPTBarPlot *barPlot = [[CPTBarPlot alloc] init];
barPlot.lineStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] axisLineStyle:kBarLineStyle];
barPlot.barWidth = CPTDecimalFromFloat(0.60f); // bar is 75% of the available space
barPlot.barCornerRadius = 0.0;
barPlot.barsAreHorizontal = YES;
barPlot.dataSource = self;
barPlot.identifier = kBarPlotPending;
barPlot.delegate = self;
barPlot.fill = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barFillForBarPlotOfType:kHorizontalRed];
barPlot.labelTextStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle];
barPlot.labelFormatter = format;
barPlot.labelOffset = 1.0;
barPlot.anchorPoint = CGPointMake(0.0, 0.0);
[barPlot addAnimation:[self plotAnimationWithKeyPath:#"transform.scale.x"] forKey:#"someKey"];
if(!self.isOneBarPlot){
[graph addPlot:barPlot];
}
// Create bar plot
CPTBarPlot *barPlot2 = [[CPTBarPlot alloc] init];
barPlot2.lineStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] axisLineStyle:kBarLineStyle];;
barPlot2.barWidth = CPTDecimalFromFloat(0.60f); // bar is 75% of the available space
barPlot2.barCornerRadius = 0.0;
barPlot2.barsAreHorizontal = YES;
barPlot2.dataSource = self;
barPlot2.identifier = kBarPlotOfficial;
barPlot2.delegate = self;
barPlot2.labelFormatter = format;
barPlot2.fill = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barFillForBarPlotOfType:kHorizontalBlue];
barPlot2.anchorPoint = CGPointMake(0.0, 0.0);
barPlot2.labelTextStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle];
if(!self.isOneBarPlot){
barPlot2.labelOffset = -1.0;
}
[graph addPlot:barPlot2];
[barPlot2 addAnimation:[self plotAnimationWithKeyPath:#"transform.scale.x"] forKey:#"someKey"];
// make the bars thinner if only one data set is available
if ([self.plotData count] == 1) {
barPlot.barWidthScale = kBarWithScaleOneItem;
barPlot2.barWidthScale = kBarWithScaleOneItem;
}
if ([self.plotData count] > 0) {
// Plot space
CPTMutablePlotRange *barRange = [[barPlot plotRangeEnclosingBars] mutableCopy];
[barRange expandRangeByFactor:CPTDecimalFromDouble(1.05)];
CPTXYPlotSpace *barPlotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
barPlotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0f) length:CPTDecimalFromFloat([self calculateDatasourcePeak])];
barPlotSpace.yRange = barRange;
CPTScatterPlot *targetLinePlot = [[CPTScatterPlot alloc] init];
targetLinePlot.identifier = kBarPlotTarget;
targetLinePlot.title = NSLocalizedString(kBarPlotTarget, nil);
CPTMutableLineStyle *barLineStyleTarget = [[CPTMutableLineStyle alloc] init];
barLineStyleTarget.lineWidth = 2.0;
barLineStyleTarget.lineColor = [CPTColor grayColor];
targetLinePlot.dataLineStyle = barLineStyleTarget;
targetLinePlot.dataSource = self;
[graph addPlot:targetLinePlot toPlotSpace:barPlotSpace];
[self configureAxis:graph];
[self createDarkBackgroundPlot:graph isHorizontal:TRUE];
}else{
self.emtyPlot.alpha = 1.0;
// Create axes
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTXYAxis *y = axisSet.yAxis;
{
y.majorIntervalLength = CPTDecimalFromInteger(0);
y.axisLineStyle = nil;
y.labelingPolicy = CPTAxisLabelingPolicyNone;
y.labelTextStyle = nil;
y.majorTickLineStyle = nil;
y.minorTickLineStyle = nil;
y.axisConstraints = [CPTConstraints constraintWithLowerOffset:7.0];
}
CPTXYAxis *x = axisSet.xAxis;
{
x.majorIntervalLength = CPTDecimalFromInteger(0);
x.axisConstraints = [CPTConstraints constraintWithLowerOffset:8.0];
x.axisLineStyle = nil;
x.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
x.majorTickLineStyle = nil;
x.minorTickLineStyle = nil;
x.labelTextStyle = nil;
}
}
}
-(void)configureAxis:(CPTGraph *)graph{
[super configureAxis:graph];
NSNumberFormatter *format = [[NSNumberFormatter alloc] init];
[format setNumberStyle:NSNumberFormatterNoStyle];
//legend
CPTLegend *theLegend = [CPTLegend legendWithGraph:graph];
theLegend.borderLineStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] axisLineStyle:kBarLineStyle];
theLegend.cornerRadius = 0.0;
theLegend.swatchSize = CGSizeMake(16.0, 16.0);
theLegend.textStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle];
theLegend.numberOfRows = 1;
graph.legend = theLegend;
graph.legendAnchor = CPTRectAnchorBottom;
graph.legendDisplacement = CGPointMake(0.0, 0.0);
// Create axes
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTXYAxis *y = axisSet.yAxis;
{
y.majorIntervalLength = CPTDecimalFromInteger(1);
y.axisLineStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] axisLineStyle:kYAxisLineStyle];
y.labelingPolicy = CPTAxisLabelingPolicyNone;
y.orthogonalCoordinateDecimal = CPTDecimalFromInteger(1);
y.labelTextStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle];
y.axisConstraints = [CPTConstraints constraintWithLowerOffset:5.0];
}
NSMutableSet *yAxisLegend = [NSMutableSet set];
for (int i = 0; i < self.plotData.count; i++) {
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[self addLineBreakToString:(NSString*)[[self.plotData objectAtIndex:i] objectForKey:kResultLabel] ]textStyle:[[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle]];
label.tickLocation = CPTDecimalFromInteger(i);
[yAxisLegend addObject:label];
}
y.axisLabels = yAxisLegend;
CPTXYAxis *x = axisSet.xAxis;
{
x.majorIntervalLength = CPTDecimalFromInteger(1);
x.axisConstraints = [CPTConstraints constraintWithLowerOffset:8.0];
x.axisLineStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] axisLineStyle:kXAxisLineStyle];
x.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
x.majorTickLineStyle = nil;
x.minorTickLineStyle = nil;
//x.labelFormatter = format;
x.orthogonalCoordinateDecimal = CPTDecimalFromInteger(-1);
x.labelTextStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle];
x.labelOffset = 5.0f;
}
}
#pragma mark -
#pragma mark Plot Data Source Methods
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
return self.plotData.count;
}
-(NSArray *)numbersForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndexRange:(NSRange)indexRange
{
NSArray *nums = [super numbersForPlot:plot field:fieldEnum recordIndexRange:indexRange];
if (!nums) {
switch ( fieldEnum ) {
case CPTBarPlotFieldBarLocation:
nums = [NSMutableArray arrayWithCapacity:indexRange.length];
for ( NSUInteger i = indexRange.location; i < NSMaxRange(indexRange); i++ ) {
[(NSMutableArray *)nums addObject : #(i)];
}
break;
case CPTBarPlotFieldBarTip: {
if ([plot.identifier isEqual:kBarPlotTarget]) {
nums = [NSMutableArray arrayWithCapacity:indexRange.length];
for ( NSUInteger i = indexRange.location; i < NSMaxRange(indexRange); i++ ) {
[(NSMutableArray *)nums addObject:#(100)];
}
}else{
NSString *dataKey = nil;
if ([plot.identifier isEqual:kBarPlotOfficial]) {
dataKey = kResultOfficial;
}
else {
dataKey = kResultSum;
}
nums = [NSMutableArray arrayWithCapacity:indexRange.length];
for ( NSUInteger i = indexRange.location; i < NSMaxRange(indexRange); i++ ) {
NSNumber *number = [[self.plotData objectAtIndex:i] objectForKey:dataKey];
[(NSMutableArray *)nums addObject : number];
}
}
break;
}
default:
break;
}
}
return nums;
}
-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)idx
{
CPTTextLayer *textLayer = (id)[NSNull null];;
NSNumber *number = nil;
if ([plot.identifier isEqual:kBarPlotPending]) {
number = [[self.plotData objectAtIndex:idx] objectForKey:kResultSum];
}
else if ([plot.identifier isEqual:kBarPlotOfficial]) {
NSNumber *officialNumber = [[self.plotData objectAtIndex:idx] objectForKey:kResultOfficial];
NSNumber *pendingNumber = [[self.plotData objectAtIndex:idx] objectForKey:kResultSum];
CGFloat maxNumber = [self calculateDatasourcePeak];
// 1.) if the max peak it to high and the current value to low the
// official is not shown correclty (not enough space) => do not show it
// 2.) do not show the official if its the same number as pending
if (!(maxNumber > 100 && [officialNumber intValue] < 50) && ([officialNumber intValue] != [pendingNumber intValue])) {
number = officialNumber;
}
}
if ([number intValue] > 0) {
textLayer = [[CPTTextLayer alloc] initWithText:[number stringValue] style:[[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle]];
}
return textLayer;
}
#pragma mark - CPTBarPlot delegate methods
-(void)plot:(CPTPlot *)plot dataLabelWasSelectedAtRecordIndex:(NSUInteger)index
{
NSLog(#"Data label for '%#' was selected at index %d.", plot.identifier, (int)index);
}
The legend on the bottom does show that there should be a target line, but no one is displayed
Different plot types use different datasource field enumerations. Bar plots will use CPTBarPlotFieldBarLocation and CPTBarPlotFieldBarTip. Scatter plots like the target line plot will use CPTScatterPlotFieldX and CPTScatterPlotFieldY. Make sure the datasource is checking the right field enum values for each plot.

Real Time line graph with Core Plot not updating plot range

I just found core-plot the other day and have been trying to implement it in our current app (ARC is used) for a real-time line graph with multiple data lines. However, I can't seem to get the graph to scroll to the right as new data points are found and added. Instead, I see the data lines travel off the right side of the graph. I've tried to follow the Plot Gallery app (Real Time Plot); to no avail. I've looked at the other questions here that resemble my problem, but none of the answers seems to be fixing my problem.
Here's what I'm doing:
I have a custom UIViewController attached to an object in my storyboard. Here is the relevant code:
#interface RealTimeSignalsViewController : UIViewController <CPTPlotDataSource, CPTLegendDelegate, MCPacketProtocol>
{
//Key equals the ID of the line, value is MCPlotDataObject.
NSMutableDictionary* plotData;
BOOL newPacketReceived;
CPTGraphHostingView* hostView;
}
.m
#define SIG_A_ID #"SIG_A"
#define SIG_B_ID #"SIG_B"
-(void)viewWillAppear:(BOOL)animated
{
newPacketReceived = NO;
NSString* curDev = [[Model instance] cur_deviceSpeakingWith];
plotData = [[NSMutableDictionary alloc] init];
[plotData setObject:[[MCPlotDataObject alloc] initWithID:[NSString stringWithFormat:SIG_A_ID]] forKey:[NSString stringWithFormat:SIG_A_ID]];
//If a second channel is detected
{
[plotData setObject:[[MCPlotDataObject alloc] initWithID:[NSString stringWithFormat:SIG_B_ID]] forKey:[NSString stringWithFormat:SIG_B_ID]];
}
[self configureHost];
[self configureGraph];
[self configurePlots];
}
- (void)viewDidLoad
{
[[DeviceHandler sharedInstance] addPacketDelegate:self];
[self checkForNewPackets];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
-(void)configureHost
{
CGRect hvRect = [[self view] frame];
hvRect.size.height -= 150;
hvRect.size.width -= 50;
hvRect.origin.x += 25;
hvRect.origin.y += 75;
hostView = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:hvRect];
[[self view] addSubview:hostView];
}
-(void)configureGraph
{
CPTGraph* graph = [[CPTXYGraph alloc] initWithFrame:[hostView bounds]];
[graph applyTheme:[CPTTheme themeNamed:kCPTSlateTheme]];
[hostView setHostedGraph:graph];
graph.plotAreaFrame.paddingBottom = 40;
graph.plotAreaFrame.paddingLeft = 40;
graph.plotAreaFrame.paddingRight = 40;
graph.plotAreaFrame.paddingTop = 40;
CPTXYPlotSpace* space = (CPTXYPlotSpace*)[graph defaultPlotSpace];
CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
[majorGridLineStyle setLineWidth:0.75];
[majorGridLineStyle setLineColor:[[CPTColor colorWithGenericGray:0.2] colorWithAlphaComponent:0.75]];
CPTMutableLineStyle *minorGridLineStyle = [CPTMutableLineStyle lineStyle];
[minorGridLineStyle setLineWidth:0.25];
[minorGridLineStyle setLineColor:[[CPTColor whiteColor] colorWithAlphaComponent:0.1]];
// Axes
// X axis
CPTXYAxisSet* axisSet = (CPTXYAxisSet *)[graph axisSet];
CPTXYAxis* x = [axisSet xAxis];
[x setLabelingPolicy:CPTAxisLabelingPolicyNone];
[x setMajorGridLineStyle:majorGridLineStyle];
[x setMinorGridLineStyle:minorGridLineStyle];
[x setPlotSpace:[graph defaultPlotSpace]];
// Y axis
NSSet *majorTickLocations = [NSSet setWithObjects:[NSDecimalNumber zero],
[NSDecimalNumber numberWithUnsignedInteger:10],
[NSDecimalNumber numberWithUnsignedInteger:20],
[NSDecimalNumber numberWithUnsignedInteger:30],
[NSDecimalNumber numberWithUnsignedInteger:40],
[NSDecimalNumber numberWithUnsignedInteger:50],
[NSDecimalNumber numberWithUnsignedInteger:60],
[NSDecimalNumber numberWithUnsignedInteger:70],
[NSDecimalNumber numberWithUnsignedInteger:80],
[NSDecimalNumber numberWithUnsignedInteger:90],
[NSDecimalNumber numberWithUnsignedInteger:100],
nil];
CPTXYAxis *y = [axisSet yAxis];
[y setPlotSpace:[graph defaultPlotSpace]];
[y setLabelingPolicy:CPTAxisLabelingPolicyNone];
[y setOrthogonalCoordinateDecimal:CPTDecimalFromUnsignedInteger(0)];
[y setMajorGridLineStyle:majorGridLineStyle];
[y setMinorGridLineStyle:minorGridLineStyle];
[y setMinorTicksPerInterval:4];
[y setLabelOffset:5.0];
[y setMajorTickLocations:majorTickLocations];
[y setAxisConstraints:[CPTConstraints constraintWithLowerOffset:0.0]];
CPTMutableTextStyle *axisTitleTextStyle = [CPTMutableTextStyle textStyle];
[axisTitleTextStyle setColor:[CPTColor blackColor]];
axisTitleTextStyle.fontName = #"Helvetica-Bold";
axisTitleTextStyle.fontSize = 14.0;
NSMutableSet *newAxisLabels = [NSMutableSet set];
for(id n in majorTickLocations)
{
CPTAxisLabel *newLabel = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:#"%lu", (unsigned long)[n unsignedIntegerValue]] textStyle:axisTitleTextStyle];
NSDecimal loc = CPTDecimalFromUnsignedInt([n unsignedIntegerValue]); [newLabel setTickLocation:loc];
[newLabel setOffset:[y labelOffset] + [y majorTickLength] / 2.0];
if(newLabel)
[newAxisLabels addObject:newLabel];
}
[y setAxisLabels:newAxisLabels];
[space setYRange:[CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInt(0) length:CPTDecimalFromUnsignedInt(100)]];
space.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger([MCPlotDataObject getMaxDataPoints] - 2)];
}
-(void)configurePlots
{
CPTGraph* graph = [hostView hostedGraph];
//Keep track of the colors used for data lines
NSMutableArray* unusedKeys = [[NSMutableArray alloc] init];
for(NSString* keyID in plotData)
{
CPTScatterPlot* plot = (CPTScatterPlot*)[graph plotWithIdentifier:keyID];
if(plot)
{
//Mark off color used
}
else
{
[unusedKeys addObject:keyID];
}
}
for(NSString* keyID in unusedKeys)
{
CPTScatterPlot* linePlot = [[CPTScatterPlot alloc] init];
[linePlot setIdentifier:keyID];
[linePlot setCachePrecision:CPTPlotCachePrecisionDouble];
CPTMutableLineStyle *lineStyle = [linePlot.dataLineStyle mutableCopy];
[lineStyle setLineWidth:1.0];
//Assign a unique color
[linePlot setDataLineStyle:lineStyle];
[linePlot setDataSource:self];
[graph addPlot:linePlot];
}
CPTLegend* legend = [CPTLegend legendWithGraph:graph];
[legend setFill:[[graph plotAreaFrame] fill]];
[legend setBorderLineStyle:[[graph plotAreaFrame] borderLineStyle]];
[legend setCornerRadius:5.0];
[legend setSwatchSize:CGSizeMake(25.0, 25.0)];
[legend setSwatchCornerRadius:5.0];
[graph setLegendAnchor:CPTRectAnchorBottom];
[graph setLegendDisplacement:CGPointMake(0.0, 0.0)];
[graph setLegend:legend];
[[graph legend] setDelegate:self];
}
-(void)checkForNewPackets
{
if(newPacketReceived)
{
[self updateGraph];
newPacketReceived = false;
}
[self performSelector:#selector(checkForNewPackets) withObject:nil afterDelay:.01];
}
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
NSString* plotID = (NSString*)[plot identifier];
return [[(MCPlotDataObject*)[plotData objectForKey:plotID] points] count];
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSNumber *num = nil;
NSString* plotID = (NSString*)[plot identifier];
MCPlotDataObject* mcpd = (MCPlotDataObject*)[plotData objectForKey:plotID];
switch(fieldEnum)
{
case CPTScatterPlotFieldX:
num = [NSNumber numberWithUnsignedInteger:index + [mcpd currrentIndex] - [[mcpd points] count]];
break;
case CPTScatterPlotFieldY:
num = [[mcpd points] objectAtIndex:index];
break;
default:
break;
}
return num;
}
-(void)updateGraph
{
CPTGraph* graph = [hostView hostedGraph];
CPTXYPlotSpace* plotSpace = (CPTXYPlotSpace*)[graph defaultPlotSpace];
NSUInteger curIndex = 0;
NSUInteger maxPoints = [MCPlotDataObject getMaxDataPoints];
NSUInteger location = 0;
//Delete the unnecessary points from each plot line, get the curIndex, maxPoints, and location using the first keyID
for(NSString* keyID in plotData)
{
MCPlotDataObject* mcpd = (MCPlotDataObject*)[plotData objectForKey:keyID];
CPTPlot* linePlot = [graph plotWithIdentifier:keyID];
if([mcpd removePlotPoint])
{
[linePlot deleteDataInIndexRange:NSMakeRange(0, 1)];
}
if(curIndex == 0)
{
curIndex = [mcpd currrentIndex];
location = (curIndex >= maxPoints ? curIndex - maxPoints + 2 : 0 );
}
}
//Animate based on the found location/max points
CPTPlotRange *newRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(location) length:CPTDecimalFromUnsignedInteger(maxPoints - 2)];
[CPTAnimation animate:plotSpace property:#"xRange" fromPlotRange:plotSpace.xRange toPlotRange:newRange duration:CPTFloat(0.01f) animationCurve:CPTAnimationCurveDefault delegate:nil];
NSLog(#"Old range:%#\nNew range:%#", plotSpace.xRange, newRange);
//Get the newest data
[self updateUIToPacketDataForDevice:[[Model instance] cur_deviceSpeakingWith]];
//Add it to the plot
for(NSString* keyID in plotData)
{
MCPlotDataObject* mcpd = (MCPlotDataObject*)[plotData objectForKey:keyID];
CPTPlot* linePlot = [graph plotWithIdentifier:keyID];
[linePlot insertDataAtIndex:[[mcpd points] count] - 1 numberOfRecords:1];
}
}
-(void)updateToNewPacketDataForDevice:(NSString *)deviceName
{
//Gets called from a different thread, so notify object it can update data and animations will happen on main thread.
newPacketReceived = YES;
}
-(void)updateUIToPacketDataForDevice:(NSString*)deviceName
{
//Get latest packet data
}
And the corresponding object holding onto the data points and the index, MCPlotDataObject.h
#interface MCPlotDataObject : NSObject
{
NSUInteger numPointsRemoved;
}
#property (readonly) NSUInteger currrentIndex;
#property (readonly) NSMutableArray* points;
#property (readonly) NSString* ID;
/**
This function adds a plot point for a plot line and then increments the currentIndex.
#param newPlotPoint The new NSNumber value for the line to plot and follow.
*/
-(void)addPlotPoint:(NSNumber*)newPlotPoint;
/**
This function attempts to remove a plot point. It will return YES if [points count] >= maxDataPoints.
#return NO if no points were removed
#return OR
#return YES if a plot point was removed.
*/
-(BOOL)removePlotPoint;
/**
This function returns the max data points value that each MCPDO has.
#return The maximum number of data points that are allowed in points array.
*/
+(NSUInteger)getMaxDataPoints;
#end
And corresponding .m
static const NSUInteger kMaxDataPoints = 102;
-(void)addPlotPoint:(NSNumber *)newPlotPoint
{
currrentIndex++;
[points addObject:newPlotPoint];
}
-(BOOL)removePlotPoint
{
if([points count] >= kMaxDataPoints)
{
[points removeObjectAtIndex:0];
numPointsRemoved++;
return YES;
}
else
return NO;
}
+(NSUInteger)getMaxDataPoints
{
return kMaxDataPoints;
}
Can anyone point me in the right direction as to why the plotSpace in updateGraph() is not being moved?
After a day of debugging this, I found out that my problem was the animation duration. 1/100 second was too quick for it. When I went to 1/25 second like what was in the Plot_Gallery example project, the graph scrolled.
Edit:
After a little more debugging, 60 fps seems to be the maximum.

Core Plot scatter is not visible, what am I doing wrong?

The delegate numberForPlot is being called correctly and the values returned are NSNumbers e.g. 40. (The Y axis range is going from 0-100 -> percentages.)
The x-axis is working ok as you can see in the screenshot below.
The code
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(#"Schedule: %#", self.schedule.name);
self.plotData = [NSMutableArray array];
NSSet *logs = self.schedule.logs;
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"dateTimeOriginal" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedLogsByDate = [logs sortedArrayUsingDescriptors:sortDescriptors];
NSDate *oldestDate = ((LogEntry *)[sortedLogsByDate objectAtIndex:0]).dateTimeOriginal;
NSDate *newestDate = ((LogEntry *)[sortedLogsByDate lastObject]).dateTimeOriginal;
NSLog(#"First: %#", oldestDate);
NSLog(#"Last: %#", newestDate);
NSInteger intervalInSeconds = 60*60*24*7; //One Week
NSInteger oldestDateInSeconds = [oldestDate timeIntervalSince1970];
NSInteger newestDateInSeconds = [newestDate timeIntervalSince1970];
NSInteger numberOfWeeks = (newestDateInSeconds - oldestDateInSeconds + intervalInSeconds - 1)/intervalInSeconds; //Integer division and round up (faster then converting to floats and round()
NSLog(#"Number of weeks: %d", numberOfWeeks);
NSDate *previousDate = oldestDate;
for (int i = 1; i < numberOfWeeks+1; i++) {
NSDate *nextDate = [previousDate dateByAddingTimeInterval:i*intervalInSeconds]; //Add one week
NSPredicate *datePredicate = [NSPredicate predicateWithFormat:#"(dateTimeOriginal >= %#) AND (dateTimeOriginal <= %#)", previousDate, nextDate];
NSSet *logsInThisPeriod = [logs filteredSetUsingPredicate:datePredicate];
if (logsInThisPeriod.count > 0) {
//Get logs between previous and next date
NSPredicate *onTimePredicate = [NSPredicate predicateWithFormat:#"status == %#", #"onTime"];
NSSet *onTime = [logs filteredSetUsingPredicate:onTimePredicate];
NSPredicate *postponedPredicate = [NSPredicate predicateWithFormat:#"status == %#", #"postPoned"];
NSSet *postponed = [logs filteredSetUsingPredicate:postponedPredicate];
NSPredicate *missedPredicate = [NSPredicate predicateWithFormat:#"status == %#", #"missed"];
NSSet *missed = [logs filteredSetUsingPredicate:missedPredicate];
NSInteger onTimeCount = onTime.count;
NSInteger postponedCount = postponed.count;
NSInteger missedCount = missed.count;
NSInteger total = onTimeCount + postponedCount + missedCount;
NSInteger onTimePercentage = onTimeCount*100/total;
NSInteger postponedPercentage = postponedCount*100/total;
NSInteger missedPercentage = missedCount*100/total;
NSDictionary *dataPoint = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInteger:onTimePercentage], #"onTime", [NSNumber numberWithInteger:postponedPercentage], #"postponed", [NSNumber numberWithInteger:missedPercentage], #"missed", nextDate, #"date", nil];
[self.plotData addObject:dataPoint];
}
else {
NSMutableDictionary *previousDictionary = [[self.plotData lastObject] mutableCopy];
[previousDictionary setObject:nextDate forKey:#"date"];
[self.plotData addObject:previousDictionary];
}
previousDate = nextDate;
}
//Create host view
self.hostingView = [[CPTGraphHostingView alloc] initWithFrame:[[UIScreen mainScreen]bounds]];
[self.view addSubview:self.hostingView];
// Create graph from theme
graph = [(CPTXYGraph *)[CPTXYGraph alloc] initWithFrame:CGRectZero];
CPTTheme *theme = [CPTTheme themeNamed:kCPTDarkGradientTheme];
[graph applyTheme:theme];
[self.hostingView setHostedGraph:self.graph];
// Setup scatter plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
NSTimeInterval xLow = 0.0f;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(xLow) length:CPTDecimalFromFloat((newestDateInSeconds - oldestDateInSeconds))];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat(100.0)];
plotSpace.allowsUserInteraction = YES;
// Axes
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTXYAxis *x = axisSet.xAxis;
x.majorIntervalLength = CPTDecimalFromFloat((float)intervalInSeconds);
x.minorTicksPerInterval = 0;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateStyle = kCFDateFormatterShortStyle;
CPTTimeFormatter *timeFormatter = [[CPTTimeFormatter alloc] initWithDateFormatter:dateFormatter];
timeFormatter.referenceDate = oldestDate;
x.labelFormatter = timeFormatter;
CPTXYAxis *y = axisSet.yAxis;
y.majorIntervalLength = CPTDecimalFromString(#"10.0");
y.minorTicksPerInterval = 1;
//Ontime plot
CPTScatterPlot *onTimePlot = [[CPTScatterPlot alloc] init];
onTimePlot.identifier = #"onTimePlot";
CPTMutableLineStyle *onTimeLineStyle = [onTimePlot.dataLineStyle mutableCopy];
onTimeLineStyle.lineWidth = 3.f;
onTimeLineStyle.lineColor = [CPTColor greenColor];
onTimePlot.dataLineStyle = onTimeLineStyle;
onTimePlot.dataSource = self;
[graph addPlot:onTimePlot];
// Put an area gradient under the plot above
CPTColor *areaColor = [CPTColor colorWithComponentRed:0.3 green:1.0 blue:0.3 alpha:0.3];
CPTGradient *areaGradient = [CPTGradient gradientWithBeginningColor:areaColor endingColor:[CPTColor clearColor]];
areaGradient.angle = -90.0f;
CPTFill *areaGradientFill = [CPTFill fillWithGradient:areaGradient];
onTimePlot.areaFill = areaGradientFill;
onTimePlot.areaBaseValue = CPTDecimalFromString(#"1.75");
//Postponed plot
CPTScatterPlot *postponedPlot = [[CPTScatterPlot alloc] init];
postponedPlot.identifier = #"postponedPlot";
CPTMutableLineStyle *postponedLineStyle = [postponedPlot.dataLineStyle mutableCopy];
postponedLineStyle.lineWidth = 3.f;
postponedLineStyle.lineColor = [CPTColor orangeColor];
postponedPlot.dataLineStyle = postponedLineStyle;
postponedPlot.dataSource = self;
[graph addPlot:postponedPlot];
//Missed plot
CPTScatterPlot *missedPlot = [[CPTScatterPlot alloc] init];
missedPlot.identifier = #"missedPlot";
CPTMutableLineStyle *missedLineStyle = [missedPlot.dataLineStyle mutableCopy];
missedLineStyle.lineWidth = 3.f;
missedLineStyle.lineColor = [CPTColor redColor];
missedPlot.dataLineStyle = missedLineStyle;
missedPlot.dataSource = self;
[graph addPlot:missedPlot];
}
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
return self.plotData.count;
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSDictionary *plotPoint = [self.plotData objectAtIndex:index];
if (plot.identifier == #"onTimePlot") {
NSNumber *onTime = [plotPoint valueForKey:#"onTime"];
return onTime;
}
else if (plot.identifier == #"postponedPlot") {
NSNumber *postponed = [plotPoint valueForKey:#"postponed"];
return postponed;
}
else if (plot.identifier == #"missedPlot") {
NSNumber *missed = [plotPoint valueForKey:#"missed"];
return missed;
}
else {
return nil;
}
}
Update
This didn't change a thing:
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSDictionary *plotPoint = [self.plotData objectAtIndex:index];
NSNumber *num = nil;
// FieldEnum determines if we return an X or Y value.
if ( fieldEnum == CPTScatterPlotFieldX )
{
return [NSNumber numberWithFloat:[[plotPoint valueForKey:#"date"] timeIntervalSince1970]];
}
else // Y-Axis
{
if (plot.identifier == #"onTimePlot") {
num = [plotPoint valueForKey:#"onTime"];
}
else if (plot.identifier == #"postponedPlot") {
num = [plotPoint valueForKey:#"postponed"];
}
else if (plot.identifier == #"missedPlot") {
num = [plotPoint valueForKey:#"missed"];
}
return [NSNumber numberWithFloat:[num floatValue]];
}
}
Bonusquestion:
How can I make the axis labels static and let the plot area be scrollable?
How can I change the 'viewport' of the y-axis labels? (I want 0-100 visible on launch, now it's 20-80 or something like that...)
I think you need something like this in numberForPlot:field:recordIndex:
if (plot.identifier == #"onTimePlot")
{
// FieldEnum determines if we return an X or Y value.
if ( fieldEnum == CPTScatterPlotFieldX )
{
return [NSNumber numberWithFloat:point.x];
}
else // Y-Axis
{
return [NSNumber numberWithFloat:point.y];
}
}
You have to return the X value one time through the method and the Y value the next.

How to plot a graph real time using coreplot?

I'm trying to plot the decibel values of sound on a graph(CPScatterPlot) using coreplot. But the problem is I'm getting the graph with a line that is perpendicular for Y axis, and it's moving up and down on the Y axis with respect to the changes in the decibel values. I need to plot a graph like this.
here is my code:
`
-(void) generateDataSamples
{
samples = [[NSMutableArray alloc]initWithCapacity:NUM_SAMPLES];
for (int i=0; i < NUM_SAMPLES; i++)
{
// peakVal is a variable that holds the decibel value
NSDictionary *sample = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:peakVal],Y_VAL,nil];
[samples addObject:sample];
}
}
-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot;
{
return [samples count];
}
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index{
NSDictionary *sample = [samples objectAtIndex:index];
NSDecimalNumber *num = [NSDecimalNumber zero];
if (fieldEnum == CPScatterPlotFieldX)
{
num = (NSDecimalNumber *) [NSDecimalNumber numberWithInt:index + 1];
}
else if (fieldEnum == CPScatterPlotFieldY)
{
return [sample valueForKey:Y_VAL];
}
return num;
}
So, what should I do to get a graph as in the figure above? Please help me, I'm new on here.
And one more, as you can in the above picture, the Y axis labels are placed inside the plot area, how it can be done?
Here is my entire code, please suggest the modifications:
#import "MicBlowViewController.h"
#import "SecondVC.h"
#define DBOFFSET -74.0
#define START_POINT 0.0
#define END_POINT 100.0
#define NUM_SAMPLES 200.0
#define MAX_PEAK 100.0
#define X_VAL #"X_VAL"
#define Y_VAL #"Y_VAL"
#define S_VAL #"S_VAL"
#implementation MicBlowViewController
#synthesize avgLabel, peakLabel,absValue,pageControl;
-(void)reloadData
{
if(!graph)
{
//setting graph
double xAxisStart = START_POINT;
double xAxisLength = END_POINT - START_POINT;
double maxY = 100;//[[samples valueForKeyPath:#"#max.Y_VAL"] doubleValue];
double yAxisStart = START_POINT;
double yAxisLength = maxY+3;
xVal=START_POINT+0.1;
hostingView = [[CPGraphHostingView alloc] initWithFrame:CGRectMake(0, 79, 320, 361)];
[self.view addSubview:hostingView];
graph = [[CPXYGraph alloc] initWithFrame:CGRectMake(0, 79, 320, 361)];
hostingView.hostedGraph = graph;
CPTheme *theme = [CPTheme themeNamed:kCPDarkGradientTheme];
[graph applyTheme:theme];
graph.paddingTop = 0.0;
graph.paddingBottom = 0.0;
graph.paddingLeft = 0.0;
graph.paddingRight = 0.0;
[[graph defaultPlotSpace] setAllowsUserInteraction:TRUE];
CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet;
axisSet.yAxis.labelOffset=0.1;
CPXYAxis *x = axisSet.xAxis;
x.majorIntervalLength = CPDecimalFromDouble(10.0);
x.orthogonalCoordinateDecimal = CPDecimalFromInteger(0);
x.minorTicksPerInterval = 1;
CPXYAxis *y = axisSet.yAxis;
y.majorIntervalLength=CPDecimalFromDouble(10.0);
y.orthogonalCoordinateDecimal = CPDecimalFromInteger(0);
y.minorTicksPerInterval = 1;
y.tickDirection = CPSignPositive;
y.labelAlignment = CPAlignmentLeft;
y.alternatingBandFills = [NSArray arrayWithObjects:[[CPColor whiteColor] colorWithAlphaComponent:0.1], [NSNull null], nil];
CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromDouble(xAxisStart)
length:CPDecimalFromDouble(xAxisLength)];
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromDouble(yAxisStart)
length:CPDecimalFromDouble(yAxisLength)];
CPScatterPlot *dataSourceLinePlot = [[CPScatterPlot alloc] init];
dataSourceLinePlot.dataSource = self;
//[dataSourceLinePlot insertDataAtIndex:[samplesY count]-1 numberOfRecords:1];
CPMutableLineStyle *lineStyle = [[dataSourceLinePlot.dataLineStyle mutableCopy] autorelease];
lineStyle.lineWidth = 2.f;
lineStyle.lineColor = [CPColor cyanColor];
dataSourceLinePlot.dataLineStyle = lineStyle;
[graph addPlot:dataSourceLinePlot];
[dataSourceLinePlot release];
[graph release];
[hostingView release];
}
}
- (void)generateData
{
// if (plotData == nil) {
NSMutableArray *contentArray = [NSMutableArray array];
for (NSUInteger i = 0; i < 200; i++) {
//double test = (double)[peakLabel.text doubleValue];
absValue.text =[NSString stringWithFormat:#"%.2f",peakVal];
id x = [NSDecimalNumber numberWithDouble:1.0 + i ];
id y = [NSDecimalNumber numberWithDouble:peakVal * rand()/(double)RAND_MAX + 0.05];
[contentArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, #"x", y, #"y", nil]];
}
plotData = [contentArray retain];
//}
}
-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot ;
{
return [plotData count];
}
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index;
{
NSNumber *num = [[plotData objectAtIndex:index] valueForKey:(fieldEnum == CPScatterPlotFieldX ? #"x" : #"y")];
if (fieldEnum == CPScatterPlotFieldY) {
num = [NSNumber numberWithDouble:[num doubleValue]];
}
return num;
}
- (void)viewDidLoad {
[super viewDidLoad];
pageControl = [[UIPageControl alloc]init];
[pageControl addTarget:self action:#selector(changePage) forControlEvents:UIControlEventValueChanged];
samplesY = [[NSMutableArray alloc]init];
//checking for sound
NSURL *url = [NSURL fileURLWithPath:#"/dev/null"];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey,
nil];
NSError *error;
recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
if (recorder) {
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
[recorder record];
levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.03 target: self selector: #selector(levelTimerCallback:) userInfo: nil repeats: YES];
}// else
//NSLog([error description]);
}
- (void)levelTimerCallback:(NSTimer *)timer {
// getting decibel values....
[recorder updateMeters];
const double ALPHA = 0.05;
double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0]));
lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;
NSLog(#"Average input: %f Peak input: %f Low pass results: %f",
[recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults);
peakval=fabs([recorder peakPowerForChannel:0]);
double avgval=fabs([recorder averagePowerForChannel:0]);
peakVal=MAX_PEAK - peakval;
avgVal=MAX_PEAK - avgval;
NSLog(#"First: %.2f",peakVal);
avgLabel.text=[NSString stringWithFormat:#"%.2f",avgVal];
peakLabel.text=[NSString stringWithFormat:#"%.2f",peakVal];
if (lowPassResults < 0.95)
NSLog(#"Mic blow detected: %d",lowPassResults);
[self generateData];
[self reloadData];
}
- (IBAction) changePage:(id)sender{
SecondVC *vc = [[SecondVC alloc]init];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:vc animated:YES];
[vc release];
}
- (void)dealloc {
[peakLabel.text release];
[avgLabel.text release];
[samples release];
[levelTimer release];
[recorder release];
[super dealloc];
}
#end
It looks like you're using the same peakVal for every data point. Check the -generateDataSamples method and make sure you're storing the correct values in the samples array. If you already have the data in an array, you can skip that method completely and just do the lookup by index in -numberForPlot:field:recordIndex:.
Also, check the xRange and yRange on the plot space to make sure they fit your data. Remember that plot ranges are like NSRange—they are created using a starting location and length, not start and end values.
To move the labels to the right side of the y-axis, use yAxis.tickDirection = CPTSignPositive;.
Edit in response to the comments
Don't call -generateDataSamples every time you get new data. Instead, add the new value to the samples array. Don't forget to initialize the array before using it for the first time.
NSDictionary *sample = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:peakVal],Y_VAL,nil];
[samples addObject:sample];
Once the data is in the array, tell Core Plot to load only the new point. This will be faster than reloading all of the data every time you update.
[myScatterPlot insertDataAtIndex:(samples.count - 1)
numberOfRecords:1];
You can use the CPTPlot method -deleteDataInIndexRange: to remove old data points if you don't need to keep all of the history in the graph. Don't forget to remove the corresponding point from the samples array also.

Core plot gives a SIGABRT and doesn't run Linegraph

I have a problem with my code, core plot gives a SIGBRT.
can someone help me ?
Thanks..
header:
#interface CorePLotTestAppDelegate : NSObject <CPPlotDataSource>
{
IBOutlet CPLayerHostingView *view;
CPXYGraph *graph;
NSMutableArray *xvalues;
NSMutableArray *yvalues;
}
-(void)clear;
-(void)addPointFloat:(float)x y:(float)y;
-(void)addPointNumber:(NSNumber*)x y:(NSNumber*)y;
// CPPlotDataSource protocol:
-(NSUInteger)numberOfRecordsForPlot:(CPPlot*)plot;
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index;
main:
#implementation CorePLotTestAppDelegate
-(id)init
{
if ([super init]) {
xvalues = [[NSMutableArray alloc] init];
yvalues = [[NSMutableArray alloc] init];
}
return self;
}
-(void)dealloc
{
[xvalues release];
[yvalues release];
[graph release];
[super dealloc];
}
-(void)clear
{
[xvalues removeAllObjects];
[yvalues removeAllObjects];
}
-(void)addPointFloat:(float)x y:(float)y
{
[xvalues addObject:[NSNumber numberWithFloat:x]];
[yvalues addObject:[NSNumber numberWithFloat:y]];
}
-(void)addPointNumber:(NSNumber*)x y:(NSNumber*)y
{
[xvalues addObject:x];
[yvalues addObject:y];
}
-(NSUInteger)numberOfRecordsForPlot:(CPPlot*)plot
{
return [xvalues count];
}
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index
{
if (fieldEnum == CPScatterPlotFieldX)
return [xvalues objectAtIndex:index];
else
return [yvalues objectAtIndex:index];
}
- (void) awakeFromNib
{
//Daten YAchse
NSString *filePath = #"pegel";//file path...
NSString *fileRoot = [[NSBundle mainBundle] pathForResource:filePath ofType:#"txt"];
// read everything from text
NSString *fileContents = [NSString stringWithContentsOfFile:fileRoot encoding:NSUTF8StringEncoding error:nil];
// first, separate by new line
NSArray *allLinedStrings = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
// then break down even further
NSString *strsInOneLine;
int d;
for (d=0; d < [allLinedStrings count]; d=d+1) {
strsInOneLine = [allLinedStrings objectAtIndex:d];
// choose whatever input identity you have decided. in this case ;
NSArray *workingArray = [strsInOneLine componentsSeparatedByString:#";"];
NSMutableArray *pegel = [workingArray lastObject];
yvalues = pegel;
xvalues = pegel;
NSLog(#"%#", pegel);
}
// Create graph and set a theme
graph = [[CPXYGraph alloc] initWithFrame:CGRectZero];
CPTheme *theme = [CPTheme themeNamed:kCPDarkGradientTheme];
[graph applyTheme:theme];
view.hostedLayer = graph;
// Setup plot space
CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(-3) length:CPDecimalFromFloat(20.0)];
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(-3.5) length:CPDecimalFromFloat(10.0)];
// ScatterPlot
CPScatterPlot *linePlot = [[[CPScatterPlot alloc] init] autorelease];
linePlot.identifier = #"LinienDiagramm";
linePlot.dataLineStyle.lineWidth = 3.f;
linePlot.dataLineStyle.lineColor = [CPColor blueColor];
linePlot.dataSource = self;
[graph addPlot: linePlot];
// linien effekt
CPGradient *areaGradient =
[CPGradient gradientWithBeginningColor:[CPColor blueColor]
endingColor:[CPColor blackColor]];
areaGradient.angle = -90.0f;
linePlot.areaFill = [CPFill fillWithGradient:areaGradient];
linePlot.areaBaseValue = CPDecimalFromString(#"0");
// X und Y achse einstellungen
CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet;
CPXYAxis *x = axisSet.xAxis;
CPXYAxis *y = axisSet.yAxis;
// x-achse
x.minorTicksPerInterval = 5;
x.minorTickLength = 2.0f;
x.majorTickLength = 7.0f;
x.labelOffset = 2.0f;
x.labelRotation = 45;
x.majorIntervalLength = CPDecimalFromFloat(5.0f);
// y-achse
y.minorTicksPerInterval = 5;
y.minorTickLength = 2.0f;
y.majorTickLength = 7.0f;
y.labelOffset = 5.0f;
y.majorIntervalLength = CPDecimalFromFloat(5.0f);
NSLog(#"%#", graph);
}
In -awakeFromNib, you're setting xvalues and yvalues to the object retrieved from workingArray. You're leaking the original value arrays, you're setting both xvalues and yvalues to the same object, and--just guessing without seeing the actual error message--the new object is not an array.

Resources