Sean
Sean

Reputation: 440

Core Plot ScatterPlot y-axis not scaling to fit screen and plot

I have been working on a set of graphs for my app and have a very specific problem with the ScatterPlot. I cannot get the y-axis or hight of the graph to re-scale to fit on screen. I spent hours searching the web for an answer and the closest I've come is by following the raywenderlich.com tutorial. But I still cannot seem to get my y-axis to compress so that the graph fits on screen.

Ideally I want the graph to resize dynamically based on the input data because the difference in the data plotted can vary from tens to hundreds.

Here is the code that I use to set up the graph:

-(void)configureAxes{
     // 1 - 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 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 *) self.hostView.hostedGraph.axisSet;
    // 3 - Configure x-axis
    CPTAxis *x = axisSet.xAxis;
    x.title = @"Date";
    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;

    //This next line gets the number of records in the array for the date axes
    CGFloat dateCount = [timesTest count];
    NSMutableSet *xLabels = [NSMutableSet setWithCapacity:dateCount];
    NSMutableSet *xLocations = [NSMutableSet setWithCapacity:dateCount];

    //Now we build an array of dates to label the axes
    NSInteger i = 0;
    //for (NSString *date in [[CPDStockPriceStore sharedInstance] datesInMonth]) {
    for (NSString *date in datesTest) {
        CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:date  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;

    // 4 - Configure y-axis
    CPTAxis *y = axisSet.yAxis;
    y.title = @"Time";
    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;
    NSInteger majorIncrement = 100;
    NSInteger minorIncrement = 50;
    CGFloat yMax = 700.0f;  // should determine dynamically based on max time
    NSMutableSet *yLabels = [NSMutableSet set];
    NSMutableSet *yMajorLocations = [NSMutableSet set];
    NSMutableSet *yMinorLocations = [NSMutableSet set];
    for (NSInteger j = minorIncrement; j <= yMax; j += minorIncrement) {
        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 = location;
            label.offset = -y.majorTickLength - y.labelOffset;
            if (label) {
                [yLabels addObject:label];
            }
            [yMajorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:location]];
        } else {
            [yMinorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:CPTDecimalFromInteger(j)]];
        }
    }
    y.axisLabels = yLabels;
    y.majorTickLocations = yMajorLocations;
    y.minorTickLocations = yMinorLocations;

}


#pragma mark - CPTPlotDataSource methods
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
    return [timesTest count];
}

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
    //NSInteger valueCount = [[[CPDStockPriceStore sharedInstance] datesInMonth] count];
    NSInteger valueCount = [timesTest count];
    switch (fieldEnum) {
        case CPTScatterPlotFieldX:
            if (index < valueCount) {
                return [NSNumber numberWithUnsignedInteger:index];
            }
            break;

        case CPTScatterPlotFieldY:
            if ([plot.identifier isEqual:pbTest] == YES) {
                return [pbTest objectAtIndex:index];
            } else if ([plot.identifier isEqual:rollAvgTest] == YES) {
                return [rollAvgTest objectAtIndex:index];
            } else if ([plot.identifier isEqual:timesTest] == YES) {
                return [timesTest objectAtIndex:index];
            }
            break;
    }
    return [NSDecimalNumber zero];
}

And here is where I create my arrays to test the graph:

datesTest = [NSArray arrayWithObjects:@"4/27",
                                            @"4/28",
                                            @"4/29",
                                            nil];

        timesTest = [NSArray arrayWithObjects:
                     [NSDecimalNumber numberWithFloat:601.1],
                     [NSDecimalNumber numberWithFloat:614.4],
                     [NSDecimalNumber numberWithFloat:607.3],
                     nil];

        pbTest = [NSArray arrayWithObjects:
                     [NSDecimalNumber numberWithFloat:601.1],
                     [NSDecimalNumber numberWithFloat:601.1],
                     [NSDecimalNumber numberWithFloat:601.1],
                     nil];

        rollAvgTest = [NSArray arrayWithObjects:
                     [NSDecimalNumber numberWithFloat:602.1],
                     [NSDecimalNumber numberWithFloat:613.4],
                     [NSDecimalNumber numberWithFloat:605.3],
                     nil];

The raywenderlich project compiles and runs perfectly with the desired y-axis perfectly scaled to fit on screen but mine does not but I cannot figure out what I'm missing. Any suggestions as to where I am going wrong will be massively appreciated. EDIT: Added Plot Config in response to comment...

-(void)configurePlots{
    // 1 - Get graph and plot space
    CPTGraph *graph = self.hostView.hostedGraph;
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
    // 2 - Create the three plots
    // FIRST PLOT is Personal Best - pbPlot
    // SECOND PLOT is Rolling Average - rollAvgPlot
    // THIRD PLOT is Individual swims - swimssPlot

    //Plot 1 - Peronal Best
    CPTScatterPlot *pbPlot = [[CPTScatterPlot alloc] init];
    pbPlot.dataSource = self;
    NSString *pbID = [[NSString alloc] initWithFormat:@"pbID"];
    pbPlot.identifier = pbID;
    CPTColor *pbColor = [CPTColor redColor];
    [graph addPlot:pbPlot toPlotSpace:plotSpace];

    //Plot 2 - Rolling Average
    CPTScatterPlot *rollAvgPlot = [[CPTScatterPlot alloc] init];
    rollAvgPlot.dataSource = self;
    NSString *rollAvgID = [[NSString alloc] initWithFormat:@"rollAvgID"];
    rollAvgPlot.identifier = rollAvgID;
    CPTColor *rollAvgColor = [CPTColor greenColor];
    [graph addPlot:rollAvgPlot toPlotSpace:plotSpace];

    //Plot 3 - Actual Swim Times
    CPTScatterPlot *swimsPlot = [[CPTScatterPlot alloc] init];
    swimsPlot.dataSource = self;
    NSString *timesID = [[NSString alloc] initWithFormat:@"timesID"];
    swimsPlot.identifier = timesID;
    CPTColor *swimsColor = [CPTColor blueColor];
    [graph addPlot:swimsPlot toPlotSpace:plotSpace];

    // 3 - Set up plot space
    //[plotSpace scaleToFitPlots:[NSArray arrayWithObjects:pbPlot, rollAvgPlot, swimsPlot, nil]];
    [plotSpace scaleToFitPlots:[NSArray arrayWithObjects:swimsPlot, 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;

    // 4 - Create styles and symbols
    CPTMutableLineStyle *pbLineStyle = [pbPlot.dataLineStyle mutableCopy];
    pbLineStyle.lineWidth = 2.5;
    pbLineStyle.lineColor = pbColor;
    pbPlot.dataLineStyle = pbLineStyle;
    CPTMutableLineStyle *pbSymbolLineStyle = [CPTMutableLineStyle lineStyle];
    pbSymbolLineStyle.lineColor = pbColor;
    CPTPlotSymbol *pbSymbol = [CPTPlotSymbol ellipsePlotSymbol];
    pbSymbol.fill = [CPTFill fillWithColor:pbColor];
    pbSymbol.lineStyle = pbSymbolLineStyle;
    pbSymbol.size = CGSizeMake(6.0f, 6.0f);
    pbPlot.plotSymbol = pbSymbol;

    CPTMutableLineStyle *rollAvgLineStyle = [rollAvgPlot.dataLineStyle mutableCopy];
    rollAvgLineStyle.lineWidth = 1.0;
    rollAvgLineStyle.lineColor = rollAvgColor;
    rollAvgPlot.dataLineStyle = rollAvgLineStyle;
    CPTMutableLineStyle *rollAvgSymbolLineStyle = [CPTMutableLineStyle lineStyle];
    rollAvgSymbolLineStyle.lineColor = rollAvgColor;
    CPTPlotSymbol *rollAvgSymbol = [CPTPlotSymbol starPlotSymbol];
    rollAvgSymbol.fill = [CPTFill fillWithColor:rollAvgColor];
    rollAvgSymbol.lineStyle = rollAvgSymbolLineStyle;
    rollAvgSymbol.size = CGSizeMake(6.0f, 6.0f);
    rollAvgPlot.plotSymbol = rollAvgSymbol;

    CPTMutableLineStyle *swimsLineStyle = [swimsPlot.dataLineStyle mutableCopy];
    swimsLineStyle.lineWidth = 2.0;
    swimsLineStyle.lineColor = swimsColor;
    swimsPlot.dataLineStyle = swimsLineStyle;
    CPTMutableLineStyle *swimsSymbolLineStyle = [CPTMutableLineStyle lineStyle];
    swimsSymbolLineStyle.lineColor = swimsColor;
    CPTPlotSymbol *swimsSymbol = [CPTPlotSymbol diamondPlotSymbol];
    swimsSymbol.fill = [CPTFill fillWithColor:swimsColor];
    swimsSymbol.lineStyle = swimsSymbolLineStyle;
    swimsSymbol.size = CGSizeMake(6.0f, 6.0f);
    swimsPlot.plotSymbol = swimsSymbol;
}

Upvotes: 2

Views: 1671

Answers (1)

Eric Skroch
Eric Skroch

Reputation: 27381

Check your plot identifiers. You set the identifiers to one value when setting up the plots and compare them to some other value in the datasource. That test is probably failing, which means every y-value for each plot is zero (0).

Upvotes: 1

Related Questions