I want to make a graph in a UIView that shows numerical data. So I need to draw axis, a few coordinate lines, some tick marks, and then the data as connected straight lines. The data might typically consist of a few hundred x values in the range -500. to +1000. with corresponding y values in the range 300. to 350.
So I thought a good approach would be to transform the coordinates of the UIView so (for the example values given) the left side of the view is -500, and right side is 1000, the top is 400 and the bottom is 300. And y increases upwards. Then in drawRect: I could write a bunch of CGContextMoveToPoint() and CGContextAddLineToPoint() statements with my own coordinate system and not have to mentally translate each call to the UIView coordinates.
I wrote the following function to generate my own CGContextRef but it doesn't do what I expected. I've been trying variations on it for a couple days now and wasting so much time. Can someone say how to fix it? I realize I can't get clear in my mind whether the transform is supposed to specify the UIView coordinates in terms of my coordinates, or vice versa, or something else entirely.
static inline CGContextRef myCTX(CGRect rect, CGFloat xLeft, CGFloat xRight, CGFloat yBottom, CGFloat yTop) {
CGAffineTransform ctxTranslate = CGAffineTransformMakeTranslation(xLeft, rect.size.height - yTop);
CGAffineTransform ctxScale = CGAffineTransformMakeScale( rect.size.width / (xRight - xLeft), -rect.size.height / (yTop - yBottom) ); //minus so y increases toward top
CGAffineTransform combinedTransform = CGAffineTransformConcat(ctxTranslate, ctxScale);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextConcatCTM(c, combinedTransform);
return c;
}
The way I'm using this is that inside drawRect I just have:
CGContextRef ctx = myCTX(rect, self.xLeft, self.xRight, self.yBottom, self.yTop);
and then a series of statements like:
CGContextAddLineToPoint(ctx, [x[i] floatValue], [y[i] floatValue]);
self.xLeft
,self.xRight
etc? - Alfonso-xLeft
, i.e. shift by 500px to the right, because you'll start drawing to the left of the original rect (-500). - Alfonso-yBottom
, since this is before scaling, so you'd still drawing "upside down" at this point. Then in the second step you turn the drawing upside down. - Alfonso