Changing the labels on the axis

77 views
Skip to first unread message

rambius

unread,
Aug 28, 2009, 3:53:27 PM8/28/09
to coreplot-discuss
Hello,

I successfully created my first bar chart on iphone with core-plot.
Now I would like to change the labels on the x axis. Currently they
are generated by core-plot and are {.0, 1.0, 2.0, 3.0, 4.0}. I would
like to change them a set of strings that will better explain the data
on the chart.

I appreciate all ideas and hints you can give me.

Regards
Rambius

neuroNotes

unread,
Aug 28, 2009, 4:02:54 PM8/28/09
to coreplot-discuss
I'm wondering if we can create some kind of abstract labeling policy
for both dates and numbers. I'm thinking something that would
automatically decide on whether it should use increments of 10, 50,
100, 200 etc based on range and a preferred number of labels. It would
have a preference for as many zeros as possible as opposed to just
dividing the max by the number of labels and ending up with funky
looking intervals.

Anyone planning on doing this or have any thoughts? Maybe an existing
algorithm?

Drew McCormack

unread,
Aug 29, 2009, 4:26:17 AM8/29/09
to coreplot...@googlegroups.com
There are plans to do this 'automatic' labeling of axes. In fact, we
were discussing it last week on the list.
There is even code in Core Plot to do it, but it must be integrated in
the axis classes. Probably an hour of work.

Drew

Drew McCormack

unread,
Aug 29, 2009, 4:29:29 AM8/29/09
to coreplot...@googlegroups.com
There were some discussions about this last week on the list. You have
a few choices:

1) Set the axis labeling policy to none, and then just manually create
CPAxisLabels and set those.
2) Implement the axisShouldRelabel: delegate method, and create
CPAxisLabels there, and return NO so the auto labeling doesn't take
place.
3) Create a NSNumberFormatter subclass that creates the strings you
want from the numeric values. Set this formatter for the axis formatter.

Drew

Cliff R

unread,
Aug 31, 2009, 5:42:53 AM8/31/09
to coreplot-discuss
Hello
I too wanted custom labels for the months in the year.
My x axis range spanned the days in the year from 0 - 365(6)
I tried the CPTimeFormatter, which worked. But for me the conversion
required
from a large number of seconds back to days in year was too
cumbersome.

Hope my simplified solution below will be usefull to someone, here
goes:

Create an array of tick locations: (in this case, month positions)
NSArray *customTickLocations = [NSArray arrayWithObjects:
[NSDecimalNumber numberWithInt:0],
[NSDecimalNumber numberWithInt:31],
[NSDecimalNumber numberWithInt:59],
[NSDecimalNumber numberWithInt:90],
[NSDecimalNumber numberWithInt:120],
[NSDecimalNumber numberWithInt:151],
[NSDecimalNumber numberWithInt:181],
[NSDecimalNumber numberWithInt:212],
[NSDecimalNumber numberWithInt:243],
[NSDecimalNumber numberWithInt:273],
[NSDecimalNumber numberWithInt:304],
[NSDecimalNumber numberWithInt:334],
[NSDecimalNumber numberWithInt:365],
nil ];

Create an array of labels for each tick location:
NSString *aMonth[]= {
@"JAN",
@"FEB",
@"MAR",
@"APR",
@"MAY",
@"JUN",
@"JUL",
@"AUG",
@"SEP",
@"OCT",
@"NOV",
@"DEC",
@" "
};

Then setup the axis:

// Axes
CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet;
CPXYAxis *x = axisSet.xAxis;
// x.majorIntervalLength = CPDecimalFromString(@"30.4");
x.constantCoordinateValue = CPDecimalFromString(@"0");
x.minorTicksPerInterval = 0;
x.axisLabelOffset = -5.0f;

// setup labels and tick locations
x.axisLabelingPolicy = CPAxisLabelingPolicyNone;

int i = 0;
NSMutableArray *customLabels = [[NSMutableArray alloc]
initWithCapacity: customTickLocations.count];
for (NSNumber *tickLocation in customTickLocations)
{
CPAxisLabel *newLabel = [[CPAxisLabel alloc] initWithText: aMonth[i+
+] textStyle:x.axisLabelTextStyle];
newLabel.tickLocation = [tickLocation decimalValue];
newLabel.textStyle = x.axisLabelTextStyle;
newLabel.offset = x.axisLabelOffset +
x.majorTickLength;
[customLabels addObject:newLabel];
[newLabel release];
}

x.axisLabels = [NSSet setWithArray:customLabels];
x.majorTickLocations = [NSSet setWithArray:customTickLocations];

Please note also, in order for this to work, the framework method -
(void)relabel, in CPAxis.m
needs to be changed (as pointed out by a previous poster on his
subject) as below:
(Addition of if statement wrapping the original code to execute
depending on the labellingPolicy)

if (self.axisLabelingPolicy != CPAxisLabelingPolicyNone)
{
// Filter and set tick locations
self.majorTickLocations = [self
filteredMajorTickLocations:allNewMajorLocations];
self.minorTickLocations = [self
filteredMinorTickLocations:allNewMinorLocations];
// Label ticks
NSArray *newLabels = [self
newAxisLabelsAtLocations:self.majorTickLocations.allObjects];
self.axisLabels = [NSSet setWithArray:newLabels];
[newLabels release];

}

self.needsRelabel = NO;

I don't know if this change has been made to the framework yet.
Hope this helps.

Cliff

Drew McCormack

unread,
Aug 31, 2009, 5:55:31 AM8/31/09
to coreplot...@googlegroups.com
I just committed the change to relabel, so you shouldn't need to do
that anymore if you update to the latest tip.

Drew

Cliff R

unread,
Aug 31, 2009, 10:00:43 AM8/31/09
to coreplot-discuss
Thanks Drew,
Just did an update.

Cliff

Neel

unread,
Sep 2, 2009, 1:50:20 AM9/2/09
to coreplot-discuss
Hi,

Thanks for the code example.

I am having a problem that only occurs on the device (iPod Touch) and
not in the iPhone Simulator.

Here is the problem:

First I get this message-
GDB: Program received signal: "SIGABRT"

Here the stack trace:
#0 0x31dd594c in __kill
#1 0x31dd5940 in kill
#2 0x31dd5934 in raise
#3 0x31deccfe in abort
#4 0x374ef848 in __gnu_cxx::__verbose_terminate_handler
#5 0x300166c0 in _objc_terminate
#6 0x374ecf3c in __cxxabiv1::__terminate
#7 0x374ecfb4 in std::terminate
#8 0x374ed0dc in __cxa_throw
#9 0x300165e4 in objc_exception_throw
#10 0x30292f84 in -[NSObject doesNotRecognizeSelector:]
#11 0x3021806e in ___forwarding___
#12 0x3020ede8 in __forwarding_prep_1___
#13 0x00014dcc in -[CPTextLayer sizeToFit] at CPTextLayer.m:90
#14 0x00014c3c in -[CPTextLayer setText:] at CPTextLayer.m:70
#15 0x00014d56 in -[CPTextLayer initWithText:style:] at CPTextLayer.m:
39
#16 0x00014cda in -[CPTextLayer initWithText:] at CPTextLayer.m:53
#17 0x00013120 in -[CPAxisLabel initWithText:textStyle:] at
CPAxisLabel.m:60
#18 0x00005eb4 in -[BatteryGraphViewController
axisLabelText:tickLocation:unitLabel:labelArray:tickLocationArray:] at
BatteryGraphViewController.m:383

Some how I don't think this line of code from CPTextLayer is finding
the correct selector:

CGSize textSize = [self.text sizeWithStyle:textStyle];

Any ideas why this would fail on the device and not in the iPhone
Simulator?

Thanks,
Neel

Drew McCormack

unread,
Sep 2, 2009, 2:32:08 AM9/2/09
to coreplot...@googlegroups.com
Yes, this problem has arisen a few times now. For some reason,
categories are not added to the executable on the iPhone.
To fix it, add the -all_load flag to your linker settings.

Drew

Larry

unread,
Sep 3, 2009, 10:13:59 AM9/3/09
to coreplot-discuss
thank you Cliff, this code sample helps me a lot. :)
Larry
> >> Myxaxis range spanned the days in the year from 0 -  365(6)
> >>     CPXYAxis *x= axisSet.xAxis;
> >> //    x.majorIntervalLength = CPDecimalFromString(@"30.4");
> >>    x.constantCoordinateValue = CPDecimalFromString(@"0");
> >>    x.minorTicksPerInterval = 0;
> >>    x.axisLabelOffset = -5.0f;
>
> >> // setup labels and tick locations
> >>        x.axisLabelingPolicy = CPAxisLabelingPolicyNone;
>
> >>         int i = 0;
> >>         NSMutableArray *customLabels = [[NSMutableArray alloc]
> >> initWithCapacity: customTickLocations.count];
> >>         for (NSNumber *tickLocation in customTickLocations)
> >>         {
> >>                 CPAxisLabel *newLabel = [[CPAxisLabel alloc]  
> >> initWithText: aMonth[i+
> >> +] textStyle:x.axisLabelTextStyle];
> >>                 newLabel.tickLocation = [tickLocation decimalValue];
> >>                 newLabel.textStyle =x.axisLabelTextStyle;
> >>                 newLabel.offset =x.axisLabelOffset +
Reply all
Reply to author
Forward
0 new messages