Drawing crosshairs with iOS CoreGraphics - ios

How does one draw a crosshairs in an iOS app?
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 0.0, 0.5); // yellow line
CGContextBeginPath(context);
CGContextMoveToPoint(context, 40.0, 40.0); //start point
// Crosshairs go here?!?!?!?
// What do I fill in?
CGContextClosePath(context);
CGContextSetLineWidth(context, 2.0);
CGContextStrokePath(context);
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.0);
CGContextFillRect(context, rect);
}
See example image below.

This should help you get started in seeing what you are missing. You are very close. Add an ellipse and you'll be done but as others have suggested, a simple quick look at the Quart2d programming guide or any Quart2d tuts will show all of this and more.
Drawing a circle
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor);
CGContextSetLineWidth(context, 2.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, 20, 20);
CGContextAddLineToPoint(context, 40, 20);
CGContextStrokePath(context);
CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor);
CGContextSetLineWidth(context, 2.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, 30, 10);
CGContextAddLineToPoint(context, 30, 30);
CGContextStrokePath(context);
}

Related

Why The CGContext draw nothing when I fill path color before stroke path color.

Code like this
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(context, 5, 5);
CGContextAddLineToPoint(context, 100, 100);
CGContextSetLineWidth(context, 5);
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
CGContextFillPath(context);
CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);
CGContextStrokePath(context);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
when I remove the fill color the image is correct.
But I can't understand why I add fill color the image is nothing?
The problem is the how you draw on the context.
Please try the following:
CGRect rect = CGRectMake(0.0,0.0, 100, 100);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
//Set background color
CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0);
CGContextFillRect(context,rect);
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
CGContextMoveToPoint(context, 5, 5);
CGContextAddLineToPoint(context, 100, 100);
CGContextStrokePath(context);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Now
_testImage.image = image;
You will get the result. Please let me know your feedback.

how to clip a circle created using CGContextFillEllipseInRect with another circle

I am drawing a simple filled circle using following code in draw rect.
CGContextRef con = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(con, CGRectMake(0,0,self.bounds.size.width,self.bounds.size.height));
CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
CGContextFillPath(con);
it draws a circle properly. Now I want to clip the circle with another small circle in the middle so that it becomes a hollow circle and you can see whatever is behind the main circle. How can i do that?
Use the even-odd rule with CGContextEOClip()
CGSize size = rect.size;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, 0);
CGContextSaveGState(context);
CGContextAddPath(context, ([UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, size.width, size.height)].CGPath));
CGContextAddPath(context, ([UIBezierPath bezierPathWithOvalInRect:CGRectMake(size.width/4, size.height/4, size.width/2, size.height/2)].CGPath));
CGContextEOClip(context); //clip
CGContextAddPath(context, [UIBezierPath bezierPathWithRect:rect].CGPath);
CGContextSetFillColorWithColor(context, [UIColor greenColor].CGColor);
CGContextFillPath(context);
CGContextRestoreGState(context);
I was able to do that using the EO rule.
CGContextRef con = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(con, rect);
CGContextAddEllipseInRect(con, CGRectInset(rect, 40, 40));
CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
CGContextEOFillPath(con);

iPhone CGContext: drawing line with two different colors

I want to draw a line with different colors using CGContext.
This is my code
CGSize size = CGSizeMake(200, 200);
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGContextMoveToPoint(context, 1, 1);
CGContextBeginPath(context);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextAddLineToPoint(context, 50, 50);
CGContextAddLineToPoint(context, 100, 50);
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextAddLineToPoint(context, 200, 100);
CGContextStrokePath(context);
I am trying this code, its returns error:
<Error>: CGContextAddLineToPoint: no current point.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
CGContextSetLineWidth(context, 2.0);
CGContextBeginPath(context);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextMoveToPoint(context, 1, 1);
CGContextAddLineToPoint(context, 100, 100);
CGContextStrokePath(context); // and draw blue line
CGContextBeginPath(context);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextMoveToPoint(context, 100, 100);
CGContextAddLineToPoint(context, 200, 100);
CGContextStrokePath(context); // draw red line
Following code maybe help you:
CGSize size = CGSizeMake(200, 200);
//UIGraphicsBeginImageContextWithOptions(size, NO, 0); //comment this line, if you want a image, see bottom two line.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGContextBeginPath(context);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextMoveToPoint(context, 1, 1); //MoveToPoint First
CGContextAddLineToPoint(context, 50, 50);
CGContextAddLineToPoint(context, 100, 50);
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextMoveToPoint(context, 100, 50); //MoveToPoint First
CGContextAddLineToPoint(context, 200, 100);
CGContextStrokePath(context);
//UIImage* resultImage = UIGraphicsGetImageFromCurrentImageContext(); //if you just need a image
//UIGraphicsEndImageContext(); //match UIGraphicsBeginImageContextWithOptions, if need a image

drawInRect: losing Quality of Image resolution

I am trying to erase image using following code
CGColorRef strokeColor = [UIColor whiteColor].CGColor;
UIGraphicsBeginImageContext(imgForeground.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[imgForeground.image drawInRect:CGRectMake(0, 0, imgForeground.frame.size.width, imgForeground.frame.size.height)];
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, 10);
CGContextSetStrokeColorWithColor(context, strokeColor);
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextBeginPath(context);
CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(context, currentPoint.x, currentPoint.y);
CGContextStrokePath(context);
imgForeground.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
But I just find out Image losing its resolution due to drawInRect.
You should go with UIGraphicsBeginImageContextWithOptions instead of UIGraphicsBeginImageContext, so that a scale factor can be specified.
For example, this will use the scale factor of the device's main screen:
UIGraphicsBeginImageContextWithOptions(imgForeground.frame.size, NO, 0);

Custom map path line

I'm having trouble with drawing a line on the map with a stroke. (inside color and outside color) I beleive i'm on the right path and have subclassed mkOverlayView to override the drawing (needs to fill with the road size) so inside drawMapRect...
CGFloat lineWidth = MKRoadWidthAtZoomScale(zoomScale);
MKMapRect clipRect = MKMapRectInset(mapRect, -lineWidth, -lineWidth);
...
CGContextAddPath(context, path);
CGContextSetStrokeColorWithColor(context, line.color.CGColor);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, lineWidth);
CGContextSetAlpha(context, 0.4f);
CGContextStrokePath(context);
CGPathRelease(path);
I'm not sure how to add the stroke. Any help would be greatly appreciated. xcode 4.6 / ios 6.0+
stroke first a path ( road with) with color 1, then change stroke width and color to a thinner line with road with * 0.6 in color 2, and stroke again.
Ok, I managed to figure it out based on Mathew's suggestion but with a few tweaks...
Essentially I created a stroked path using CGPathCreateCopyByStrokingPath and made the stroke slightly darker than the base color. Then created a transparentLayer with the path and stroke, used the blend mode kCGBlendModeDestinationAtop and drew another path with only a fill this time on top. I'm not sure if this is the best approach but appears to work well.
CGPathRef newpath = CGPathCreateCopyByStrokingPath(path, NULL, lineWidth, kCGLineCapRound, kCGLineJoinMiter, 0.0);
CGContextAddPath(context, newpath);
CGContextSetStrokeColorWithColor(context, line.color.CGColor);
CGContextSetFillColorWithColor(context, line.color.CGColor);
CGContextSetLineWidth(context, lineWidth * 0.3);
CGContextSetAlpha(context, 0.8f);
CGContextBeginTransparencyLayer (context, NULL);
CGContextStrokePath(context);
CGContextBeginPath(context);
CGContextAddPath(context, newpath);
CGContextFillPath(context);
CGContextEndTransparencyLayer(context);
CGContextSetBlendMode(context, kCGBlendModeDestinationAtop);
CGContextSetAlpha(context, 0.3f);
CGContextBeginPath(context);
CGContextAddPath(context, newpath);
CGContextFillPath(context);
CGPathRelease(path);
CGPathRelease(newpath);
EDIT Here is a simpler solution based on AlexWien's approach
if (path != nil)
{
CGPathRef path2 = CGPathCreateCopy(path);
CGFloat hue;
CGFloat saturation;
CGFloat brightness;
CGFloat alpha;
[line.color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha];
UIColor *c2 =[UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:0.4];
CGContextAddPath(context, path);
CGContextSetStrokeColorWithColor(context, c2.CGColor);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, lineWidth);
CGContextStrokePath(context);
CGPathRelease(path);
CGContextSetBlendMode(context, kCGBlendModeSourceAtop);
CGContextAddPath(context, path2);
CGContextSetRGBStrokeColor(context, 1.0f, 1.0f, 1.0f, 0.3f);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, lineWidth/2.0f);
CGContextStrokePath(context);
CGPathRelease(path2);
}

Resources