- (void)drawRect:(CGRect)rect {
// Drawing code
float width = rect.size.width ;
float height = rect.size.height ;
CGContextRef currentContext ;
int i = 0 ;
// Get the graphics context that we are currently executing under
currentContext = UIGraphicsGetCurrentContext() ;
;
In the first lines of the drawRect, I save the width and the height, I'll use this to calculate the scale factors.
To understand this you need to know a bit of coordinatesystems. The iPhone coordinates are simply the pixels that can be drawn. So for example a view can be 200 px wide and 300 px high.
But of course what more important is , is the world coordinatessystem. And these coordinates are the coordinates of your world.
For example if I want to plot 600 points and the range of those points are between 0.5 and 3.5 then my user coordinatessystem is: X-axis =(0,600) Y-axis = (0.5,3.5).
So to convert user points into iphone points (or view points) I need to apply a scale factor. The scale factor is calculated as follows.
#define OFFSET_X 30.0f
#define OFFSET_Y 10.0f
scale_factor_x = ( width - OFFSET_X ) / ( [dataPoints count] - 0 );
scale_factor_y = (height - OFFSET_Y ) / (max_y - min_y ) ; // max_y = max(dataPoints) ;min_y = min(dataPoints)
Note: OFFSET_X and OFFSET_Y are 2 constants to let some space in the view where I can are plot the axes and labels of the axes.
So let's draw the axes , please note that in this first version I don't use CGPath's , later I'll refactor the code and use CGPath's.
And also be aware that I use the default orientation and default location of the origin of the view ( point (0,0) is in the upper left corner).
// draw the axes
CGContextSetRGBStrokeColor(currentContext, 0.83, 0.83, 0.83, 0.7); // this is sort of gray
CGContextMoveToPoint( currentContext, OFFSET_X, height - OFFSET_Y );
CGContextAddLineToPoint( currentContext, OFFSET_X, OFFSET_Y );
CGContextMoveToPoint( currentContext, OFFSET_X, height - OFFSET_Y );
CGContextAddLineToPoint( currentContext, width, height - OFFSET_Y );
CGContextStrokePath(currentContext);
And draw some gridlines
CGContextSetRGBStrokeColor(currentContext, 0.83, 0.83, 0.83, 1);
CGFloat len[] = {4,2} ;
CGContextSetLineDash( currentContext, 0, len, 2 ) ;
for ( i = OFFSET_X ; i <= height ; i = i + OFFSET_X )
{
CGContextMoveToPoint( currentContext, OFFSET_X, height - OFFSET_Y - i );
CGContextAddLineToPoint( currentContext, width, height - OFFSET_Y - i);
}
CGContextStrokePath(currentContext);
And then draw the graph of datapoints
CGContextSetRGBStrokeColor(currentContext, 1.0, 0.65, 0, 1);
UIImage *red = [UIImage imageNamed: @"red.png"] ;
UIImage *green = [UIImage imageNamed: @"green.png"] ;
CGPoint aPoint ;
// draw the history graph
for( i = 0 ; i< [dataPoints count] ; i++ )
{
x = OFFSET_X + i * scale_factor_x ;
old_y = [[dataPoints objectAtIndex: i] floatValue];
y = (height -OFFSET_Y) - ([[dataPoints objectAtIndex: i] floatValue] - min_y) * scale_factor_y ;
if ( old_x < 0 )
{
CGContextMoveToPoint( currentContext, x, y );
old_x = x ;
}
else
{
old_x = x ;
CGContextAddLineToPoint( currentContext, x, y );
}
}
CGContextStrokePath(currentContext);
And now I show you how to add text in the graph (drawing the Y-labels, I will not give the code for the X-labels).
// this is for the font
CGContextSetRGBStrokeColor(currentContext, 1, 1, 1, 1);
CGContextSetRGBFillColor(currentContext, 1.0, 1.0, 1.0, 0.8);
CGContextSelectFont(
currentContext,
"Helvetica-Bold",
FONT_SIZE,
kCGEncodingMacRoman
);
// this transformation is to make sure that the text is written in the right direction
CGAffineTransform transform = CGAffineTransformMake(1.0,0, 0.0, -1.0, 0.0, 0.0);
CGContextSetTextMatrix(currentContext, transform);
CGContextSetTextDrawingMode(currentContext, kCGTextFill);
// set Y-labels
float j1 = min_y ;
float step = (max_y - min_y)/ 7.0f ; // 7 labels
for ( i = 0.0f ; i <=height ; i = i + OFFSET_X )
{
// set the precision of the label
if ( j1 > 999.0f )
{
s1 = [NSString stringWithFormat:@"%4.0f", j1] ;
}
else
{
s1 = [NSString stringWithFormat:@"%4.2f", j1] ;
}
j1 += step ;
CGContextShowTextAtPoint( currentContext,0 , height - OFFSET_Y - i , [s1 UTF8String] , [s1 length] ) ;
}
CGContextStrokePath(currentContext);
No comments:
Post a Comment