2013-01-04 37 views
1

我想編程一個自動滾動的圖,所以實際時間在右側。 (標記爲紅色)CorePlot滾動實時圖

enter image description here

數據被添加不規則用一個時間間隔。我怎樣才能做到這一點?我已經有一個滾動圖(基於coreplot提供的示例代碼)。但它並不完全準確,相當耗費CPU。此外,標籤應該像14:52:00 14:52:20等那樣是「圓形」時間。

這是我到目前爲止的代碼:

TestWindowController.h

@interface TestWindowController : NSWindowController<CPTPlotDataSource> { 
    NSMutableArray *plotData; 
    double currentIndex; 
    NSDate *referenceDate; 
    NSTimer *scrollTimer; 
    NSTimer *newDataTimer; 
} 
@property (weak) IBOutlet CPTGraphHostingView *graphView; 

TestWindowController.m

NSString *kPlotIdentifier  = @"Data Source Plot"; 
const double kTimePeriod = 60.0; // 1 Minute 
const double kFrameRate   = 10.0; // frames per second 
const double kAlpha    = 0.25; // smoothing constant 

@interface DataObj : NSObject { 
    NSTimeInterval timeInterval; 
    double testValue; 
} 
@property(readwrite) NSTimeInterval timeInterval; 
@property(readwrite) double testValue; 
@end 

@implementation DataObj 
@synthesize timeInterval; 
@synthesize testValue; 
@end 


@implementation TestWindowController 
@synthesize graphView; 

- (id)initWithWindow:(NSWindow *)window 
{ 
    self = [super initWithWindow:window]; 
    if (self) { 
     // Initialization code here. 
    } 

    return self; 
} 

- (void)windowDidLoad 
{ 
    // Set a reference Date 
    NSCalendar *gregorian = [[NSCalendar alloc] 
          initWithCalendarIdentifier:NSGregorianCalendar]; 
    NSDateComponents *dateComponents = [gregorian components:(NSHourCalendarUnit | NSMinuteCalendarUnit) 
                fromDate:[NSDate date]]; 
    [dateComponents setSecond:0]; 
    referenceDate = [gregorian dateFromComponents:dateComponents]; 
    currentIndex = 0.0; 

    // Core Plot 
    CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:CGRectZero]; 
    graphView.hostedGraph = graph; 
    [graph applyTheme:[CPTTheme themeNamed:kCPTPlainBlackTheme]]; 

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

    graph.plotAreaFrame.paddingTop = 15.0; 
    graph.plotAreaFrame.paddingRight = 15.0; 
    graph.plotAreaFrame.paddingBottom = 70.0; 
    graph.plotAreaFrame.paddingLeft = 55.0; 

    // Grid line styles 
    CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle]; 
    majorGridLineStyle.lineWidth = 0.75; 
    majorGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.5]; 

    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; 
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
    dateFormatter.dateStyle = kCFDateFormatterNoStyle; 
    dateFormatter.timeStyle = kCFDateFormatterMediumStyle; 
    CPTTimeFormatter *timeFormatter = [[CPTTimeFormatter alloc] initWithDateFormatter:dateFormatter]; 
    timeFormatter.referenceDate = referenceDate; 
    x.labelFormatter   = timeFormatter; 

    // 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.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; 

    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:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromDouble(kTimePeriod)]; 
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromUnsignedInteger(0) length:CPTDecimalFromUnsignedInteger(1)]; 

    plotData = [[NSMutableArray alloc] init]; 
    scrollTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/kFrameRate 
             target:self 
             selector:@selector(scrollPlot:) 
             userInfo:nil 
             repeats:YES]; 
    newDataTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 
                target:self 
               selector:@selector(newData:) 
               userInfo:nil 
                repeats:YES]; 
} 

#pragma mark Test Methods 

-(void)scrollPlot:(NSTimer *)theTimer 
{ 
    CPTGraph *theGraph = graphView.hostedGraph; 
    CPTPlot *thePlot = [theGraph plotWithIdentifier:kPlotIdentifier]; 

    if (thePlot) { 
     currentIndex = (-[referenceDate timeIntervalSinceNow])-kTimePeriod; 
     CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)theGraph.defaultPlotSpace; 
     double location  = currentIndex; 
     plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(location) 
                 length:CPTDecimalFromDouble(kTimePeriod)]; 

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

-(void)newData:(NSTimer *)theTimer 
{ 
    CPTGraph *theGraph = graphView.hostedGraph; 
    CPTPlot *thePlot = [theGraph plotWithIdentifier:kPlotIdentifier]; 

    if (thePlot) { 
     DataObj *test = [[DataObj alloc] init]; 
     test.timeInterval = -[referenceDate timeIntervalSinceNow]; 
     test.testValue = rand()/(double)RAND_MAX; 

     [plotData addObject:test]; 
     [thePlot insertDataAtIndex:plotData.count - 1 numberOfRecords:1]; 
    } 
} 

#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; 
    DataObj *dataObj = [plotData objectAtIndex:index]; 
    switch (fieldEnum) { 
     case CPTScatterPlotFieldX: 
      num = [NSNumber numberWithDouble:dataObj.timeInterval]; 
      break; 

     case CPTScatterPlotFieldY: 
      num = [NSNumber numberWithDouble:dataObj.testValue]; 
      break; 

     default: 
      break; 
    } 

    return num; 
} 

我怎樣才能讓程序是時間準確和更少的CPU消耗? 謝謝。

+0

什麼是關於圖的「不準確」? –

+0

當它是14:52:30時,圖表是14:52:28或14:52:26,與實際時間差異2-4秒。 – thomasguenzel

+1

您的意思是說需要2-4秒才能顯示數據?它可能只是在更新後面,因爲它試圖滾動得太快。如果將滾動幀速率降至每秒一次(僅用於測試),會發生什麼情況? –

回答

2

自動軸標籤策略不適用於日期。例如,如果您想每隔20秒標註一次,請使用固定時間間隔標籤政策。

高CPU使用率可能與重新繪製軸和每個繪圖範圍更新的繪圖有關。您需要嘗試使用不同的滾動幀速率來查找CPU使用率和平滑更新的最佳組合。