6

Is there a way to add an average horizontal line (or a whatever single line) to a bar chart graph using core plot framework?

Thanks.

dorin
  • 873
  • 2
  • 15
  • 34

3 Answers3

6

One way of doing this is by using CPTScatterPlot:

Add Following lines to your code after you have initialized and added your bar plot(or what ever your actual data plot is) to your graph.

// Before following code, initialize your data, actual data plot and add plot to graph

CPTScatterPlot *dataSourceLinePlot = [[[CPTScatterPlot alloc] init] autorelease];
CPTMutableLineStyle * lineStyle                      = [CPTMutableLineStyle lineStyle];
lineStyle.lineWidth              = 3.f;
lineStyle.lineColor              = [CPTColor blackColor];
lineStyle.dashPattern            = [NSArray arrayWithObjects:[NSNumber numberWithFloat:3.0f], [NSNumber numberWithFloat:3.0f], nil];
dataSourceLinePlot.dataLineStyle = lineStyle;
dataSourceLinePlot.identifier    = @"horizontalLineForAverage";
dataSourceLinePlot.dataSource    = self;
[barChart addPlot:dataSourceLinePlot toPlotSpace:plotSpace];

Then add datasource methods, in my case I have set the datasource in above code to self, so I am defining datasource methods in the same file:

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{   
// Note this method will return number of records for both my actual plot, and for scattered plot which is used to draw horizontal average line. For latter, this will decide the horizontal length of your line
    return [myDataArray count];
}

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

        // If method is called to fetch data about drawing horizontal average line, then return your generated average value.
    if( plot.identifier==@"horizontalLineForAverage")
    {
        if(fieldEnum == CPTScatterPlotFieldX )
        {
                    // this line will remain as it is
            num =(NSDecimalNumber *)[NSDecimalNumber numberWithDouble:index];
        }
        else
        {
            num = (NSDecimalNumber *) myDataAverageValue;// Here you generate average value for location of horizontal line. You should edit this line only;
        }
    }
// handle other cases and return data for other plots       
    return num;
}
  • You can't compare a String in this way: plot.identifier==@"horizontalLineForAverage" change to [plot.identifier isEqual: @"horizontalLineForAverage"] – Andrew S Mar 28 '13 at 01:10
  • @AndrewS Compiler uniquifies references to same string. Please see this answer: http://stackoverflow.com/questions/3703554/understanding-nsstring-comparison –  Mar 28 '13 at 07:59
  • I prefer this to Eric's approach, because it treats plots equally, where they share the same start and end point. If these points change, the average line will follow. – David James Feb 12 '15 at 12:17
1

Yes. Add a scatter plot to the graph and give it two data points—one at each end of the desired line.

Eric Skroch
  • 27,381
  • 3
  • 29
  • 36
0
    CPTFill *bandFill = [CPTFill fillWithColor:[[CPTColor blackColor] colorWithAlphaComponent:1]];
    [y addBackgroundLimitBand:[CPTLimitBand limitBandWithRange:[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(800) length:CPTDecimalFromDouble(1.5)] fill:bandFill]];

and

-(CPTPlotRange *)plotSpace:(CPTPlotSpace *)space willChangePlotRangeTo:(CPTPlotRange *)newRange forCoordinate:(CPTCoordinate)coordinate
{
    if (self.segment.selectedSegmentIndex == 2) {
        if (coordinate == CPTCoordinateY) {

            //NSLog(@"%f=>%f",self.yRange.lengthDouble,newRange.lengthDouble);

            CPTGraph* graph = space.graph;
            CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
            CPTXYAxis *y = axisSet.yAxis;
            NSArray *bands = y.backgroundLimitBands;
            for (CPTLimitBand *band in bands) {
                [y removeBackgroundLimitBand:band];
            }

            CPTFill *bandFill = [CPTFill fillWithColor:[[CPTColor blackColor] colorWithAlphaComponent:1]];
            [y addBackgroundLimitBand:[CPTLimitBand limitBandWithRange:[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(800) length:CPTDecimalFromDouble(1.5 * newRange.lengthDouble / 1200)] fill:bandFill]];
        }

    }

    return newRange;

}

please reference the "AxisDemo" section of the official sample "Plot_Gallery_iOS"

Jagie
  • 2,190
  • 3
  • 27
  • 25