Skip to content

Commit

Permalink
Added a real-time plot sample to the Plot Gallery app.
Browse files Browse the repository at this point in the history
  • Loading branch information
eskroch committed Jul 9, 2011
1 parent c92afd9 commit 9c13904
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 0 deletions.
Expand Up @@ -28,6 +28,7 @@
4FABDD421291110D003A2DB7 /* CorePlot.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F4892891290FFCD00EDB93F /* CorePlot.framework */; };
4FABDD4612911127003A2DB7 /* CorePlot.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 4F4892891290FFCD00EDB93F /* CorePlot.framework */; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
C354C0D713C7CDBE00DA8822 /* RealTimePlot.m in Sources */ = {isa = PBXBuildFile; fileRef = C354C0D613C7CDBE00DA8822 /* RealTimePlot.m */; };
C360E1C613B18AAF007994B6 /* OHLCPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = C360E1C513B18AAF007994B6 /* OHLCPlot.m */; };
C360E1E013B18CAF007994B6 /* CandlestickPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = C360E1DF13B18CAE007994B6 /* CandlestickPlot.m */; };
C39C4E4113BFE1A900CD9194 /* LabelingPolicyDemo.m in Sources */ = {isa = PBXBuildFile; fileRef = C39C4E4013BFE1A900CD9194 /* LabelingPolicyDemo.m */; };
Expand Down Expand Up @@ -114,6 +115,8 @@
4F8E1CC012908B0000D2035F /* AxisDemo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AxisDemo.h; path = src/plots/AxisDemo.h; sourceTree = "<group>"; };
4F8E1CC112908B0000D2035F /* AxisDemo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AxisDemo.m; path = src/plots/AxisDemo.m; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* Plot Gallery.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Plot Gallery.app"; sourceTree = BUILT_PRODUCTS_DIR; };
C354C0D513C7CDBE00DA8822 /* RealTimePlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealTimePlot.h; path = src/plots/RealTimePlot.h; sourceTree = "<group>"; };
C354C0D613C7CDBE00DA8822 /* RealTimePlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealTimePlot.m; path = src/plots/RealTimePlot.m; sourceTree = "<group>"; };
C360E1C413B18AAF007994B6 /* OHLCPlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OHLCPlot.h; path = src/plots/OHLCPlot.h; sourceTree = "<group>"; };
C360E1C513B18AAF007994B6 /* OHLCPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OHLCPlot.m; path = src/plots/OHLCPlot.m; sourceTree = "<group>"; };
C360E1DE13B18CAE007994B6 /* CandlestickPlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CandlestickPlot.h; path = src/plots/CandlestickPlot.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -260,6 +263,8 @@
C39C4E4313BFE1B400CD9194 /* PlotSpaceDemo.m */,
C3A14BEA13AEB7E700D103EA /* RangePlot.h */,
C3A14BEB13AEB7E700D103EA /* RangePlot.m */,
C354C0D513C7CDBE00DA8822 /* RealTimePlot.h */,
C354C0D613C7CDBE00DA8822 /* RealTimePlot.m */,
4F8E1C84129083B000D2035F /* SteppedScatterPlot.h */,
4F8E1C85129083B000D2035F /* SteppedScatterPlot.m */,
4F22FF9E12342D7C006BF615 /* SimplePieChart.h */,
Expand Down Expand Up @@ -389,6 +394,7 @@
C360E1E013B18CAF007994B6 /* CandlestickPlot.m in Sources */,
C39C4E4113BFE1A900CD9194 /* LabelingPolicyDemo.m in Sources */,
C39C4E4413BFE1B400CD9194 /* PlotSpaceDemo.m in Sources */,
C354C0D713C7CDBE00DA8822 /* RealTimePlot.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Expand Up @@ -34,6 +34,7 @@
4F754284126D0C5F00313026 /* DetailView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4F754283126D0C5F00313026 /* DetailView.xib */; };
4F8E1C6012907C1800D2035F /* DatePlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F8E1C5F12907C1800D2035F /* DatePlot.m */; };
4F8E1CA0129089D600D2035F /* SteppedScatterPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F8E1C9F129089D600D2035F /* SteppedScatterPlot.m */; };
C354C0D413C7CDA900DA8822 /* RealTimePlot.m in Sources */ = {isa = PBXBuildFile; fileRef = C354C0D313C7CDA900DA8822 /* RealTimePlot.m */; };
C360E1C913B18ABC007994B6 /* OHLCPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = C360E1C813B18ABC007994B6 /* OHLCPlot.m */; };
C360E1DA13B18B24007994B6 /* AxisDemo.m in Sources */ = {isa = PBXBuildFile; fileRef = C360E1D913B18B24007994B6 /* AxisDemo.m */; };
C360E1EE13B18CCC007994B6 /* CandlestickPlot.m in Sources */ = {isa = PBXBuildFile; fileRef = C360E1ED13B18CCC007994B6 /* CandlestickPlot.m */; };
Expand Down Expand Up @@ -105,6 +106,8 @@
4F8E1C9E129089D600D2035F /* SteppedScatterPlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SteppedScatterPlot.h; path = src/plots/SteppedScatterPlot.h; sourceTree = "<group>"; };
4F8E1C9F129089D600D2035F /* SteppedScatterPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SteppedScatterPlot.m; path = src/plots/SteppedScatterPlot.m; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* Plot_Gallery-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Plot_Gallery-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
C354C0D213C7CDA900DA8822 /* RealTimePlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealTimePlot.h; path = src/plots/RealTimePlot.h; sourceTree = "<group>"; };
C354C0D313C7CDA900DA8822 /* RealTimePlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealTimePlot.m; path = src/plots/RealTimePlot.m; sourceTree = "<group>"; };
C360E1C713B18ABC007994B6 /* OHLCPlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OHLCPlot.h; path = src/plots/OHLCPlot.h; sourceTree = "<group>"; };
C360E1C813B18ABC007994B6 /* OHLCPlot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OHLCPlot.m; path = src/plots/OHLCPlot.m; sourceTree = "<group>"; };
C360E1D813B18B24007994B6 /* AxisDemo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AxisDemo.h; path = src/plots/AxisDemo.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -254,6 +257,8 @@
C39C4E3A13BFE19200CD9194 /* PlotSpaceDemo.m */,
C3A14C1313AEE7CC00D103EA /* RangePlot.h */,
C3A14C1413AEE7CC00D103EA /* RangePlot.m */,
C354C0D213C7CDA900DA8822 /* RealTimePlot.h */,
C354C0D313C7CDA900DA8822 /* RealTimePlot.m */,
4F22FE40123404C2006BF615 /* SimplePieChart.h */,
4F22FE41123404C2006BF615 /* SimplePieChart.m */,
4F22FE42123404C2006BF615 /* SimpleScatterPlot.h */,
Expand Down Expand Up @@ -372,6 +377,7 @@
C360E1EE13B18CCC007994B6 /* CandlestickPlot.m in Sources */,
C39C4E3B13BFE19200CD9194 /* PlotSpaceDemo.m in Sources */,
C39C4E3E13BFE19E00CD9194 /* LabelingPolicyDemo.m in Sources */,
C354C0D413C7CDA900DA8822 /* RealTimePlot.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
17 changes: 17 additions & 0 deletions examples/CorePlotGallery/src/plots/RealTimePlot.h
@@ -0,0 +1,17 @@
//
// RealTimePlot.h
// CorePlotGallery
//

#import "PlotItem.h"

@interface RealTimePlot : PlotItem < CPTPlotDataSource >
{
NSMutableArray* plotData;
NSUInteger currentIndex;
NSTimer *dataTimer;
}

-(void)newData:(NSTimer *)theTimer;

@end
193 changes: 193 additions & 0 deletions examples/CorePlotGallery/src/plots/RealTimePlot.m
@@ -0,0 +1,193 @@
//
// RealTimePlot.m
// CorePlotGallery
//

#import "RealTimePlot.h"

const double kFrameRate = 5.0; // frames per second
const double kAlpha = 0.25; // smoothing constant
const NSUInteger kMaxDataPoints = 51;
NSString * kPlotIdentifier = @"Data Source Plot";

@implementation RealTimePlot

+ (void)load
{
[super registerPlotItem:self];
}

- (id)init
{
if ((self = [super init])) {
title = @"Real Time Plot";
plotData = [[NSMutableArray alloc] initWithCapacity:kMaxDataPoints];
dataTimer = nil;
}

return self;
}

- (void)killGraph
{
[dataTimer invalidate];
[dataTimer release];
dataTimer = nil;

[super killGraph];
}

- (void)generateData
{
[plotData removeAllObjects];
currentIndex = 0;
[dataTimer release];
dataTimer = [[NSTimer timerWithTimeInterval:1.0 / kFrameRate
target:self
selector:@selector(newData:)
userInfo:nil
repeats:YES] retain];
[[NSRunLoop mainRunLoop] addTimer:dataTimer forMode:NSDefaultRunLoopMode];
}

- (void)renderInLayer:(CPTGraphHostingView *)layerHostingView withTheme:(CPTTheme *)theme
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
CGRect bounds = layerHostingView.bounds;
#else
CGRect bounds = NSRectToCGRect(layerHostingView.bounds);
#endif

CPTGraph *graph = [[[CPTXYGraph alloc] initWithFrame:[layerHostingView bounds]] autorelease];
[self addGraph:graph toHostingView:layerHostingView];
[self applyTheme:theme toGraph:graph withDefault:[CPTTheme themeNamed:kCPTDarkGradientTheme]];

[self setTitleDefaultsForGraph:graph withBounds:bounds];
[self setPaddingDefaultsForGraph:graph withBounds:bounds];

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;
[labelFormatter release];

// 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.isFloatingAxis = YES;
y.constraints = CPTMakeConstraints(CPTConstraintFixed, CPTConstraintNone);

// 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] autorelease];
dataSourceLinePlot.identifier = kPlotIdentifier;
dataSourceLinePlot.cachePrecision = CPTPlotCachePrecisionDouble;

CPTMutableLineStyle *lineStyle = [[dataSourceLinePlot.dataLineStyle mutableCopy] autorelease];
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:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(kMaxDataPoints - 1)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(1)];
}

- (void)dealloc
{
[plotData release];
[dataTimer invalidate];
[dataTimer release];

[super dealloc];
}

#pragma mark -
#pragma mark Timer callback

-(void)newData:(NSTimer *)theTimer
{
CPTGraph *theGraph = [graphs objectAtIndex:0];
CPTPlot *thePlot = [theGraph plotWithIdentifier:kPlotIdentifier];
if ( thePlot ) {
if ( plotData.count >= kMaxDataPoints ) {
[plotData removeObjectAtIndex:0];
[thePlot deleteDataInIndexRange:NSMakeRange(0, 1)];
}

CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)theGraph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(currentIndex >= kMaxDataPoints ? currentIndex - kMaxDataPoints + 1: 0)
length:CPTDecimalFromUnsignedInteger(kMaxDataPoints - 1)];

currentIndex++;
[plotData addObject:[NSNumber numberWithDouble:(1.0 - kAlpha) * [[plotData lastObject] doubleValue] + kAlpha * rand() / (double)RAND_MAX]];
[thePlot insertDataAtIndex:plotData.count - 1 numberOfRecords:1];
}
}

#pragma mark -
#pragma mark Plot Data Source Methods

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
return [plotData count];
}

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSNumber *num = nil;

switch ( fieldEnum ) {
case CPTScatterPlotFieldX:
num = [NSNumber numberWithUnsignedInteger:index + currentIndex - plotData.count];
break;

case CPTScatterPlotFieldY:
num = [plotData objectAtIndex:index];
break;

default:
break;
}

return num;
}

@end

0 comments on commit 9c13904

Please sign in to comment.