How to draw a concentric circle in iphone? - iphone

I want to draw a ring. Ring should filled in a outer circle. I referred a documentation http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_paths/dq_paths.html#//apple_ref/doc/uid/TP30001066-CH211-TPXREF101. But still had problem to get the outcome. Here is the code.
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextClearRect(ctx, rect);
CGContextSetRGBFillColor(ctx, 0.0, 255.0, 1.0, 1.0);CGContextFillPath(ctx);
CGContextStrokeEllipseInRect(ctx, CGRectMake(125, 125, 150, 150));
CGContextBeginPath(ctx);
CGContextEOFillPath(ctx);
CGContextFillEllipseInRect(ctx, CGRectMake(100, 100, 200, 200));

You need something more like this:
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(ctx, rect);
CGContextAddEllipseInRect(ctx,
CGRectMake(
rect.origin.x + 10,
rect.origin.y + 10,
rect.size.width - 20,
rect.size.height - 20));
CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor blueColor] CGColor]));
CGContextEOFillPath(ctx);
}
This will add two ellipses to your current path (one being smaller than the other, but centered around the same point). EOFillPath will essentially "subtract" the inner ellipse from the outer ellipse when it fills the path.
To create "concentric" circles, if that's really what you wanted, you can simply repeat this for more - continually smaller - ellipses.

Related

How can i draw a semicircle using CoreGraphics

I am trying to draw a semicircle using Core Graphics and Filling it with some color.I want to replace color with image by using CALayer. Can any one help how to do this Thanks!
Code goes here.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextMoveToPoint(context, 0, 500);
CGContextAddArc(context, 60, 500, 50, 90, 180, 0);
CGContextStrokePath(context);
You need to specify the angles in radians, not degrees. 180 degrees = π radians. So in your example:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextMoveToPoint(context, 10, 500);
CGContextAddArc(context, 60, 500, 50, M_PI / 2, M_PI, 0);
CGContextStrokePath(context);
Note that I also moved the starting point (…MoveToPoint) 10 pixels to the right, because that’s where the arc begins.
The given answers are not working on iOS 7 for me!
I created a little category to create a circle with the angle of a percentage.
Maybe you wanna check it out.You can still adopt the methode if you only want to create a semicircle.
Here is the: GitHub Link
And that is what its look like:
CGPoint circleCenter = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2);
CGContextMoveToPoint(context, circleCenter.x, circleCenter.y);
CGContextAddArc(context, circleCenter.x, circleCenter.y, 50, 90, 180, 0);
CGContextAddLineToPoint(context, circleCenter.x, circleCenter.y);
CGContextSetFillColorWithColor(context, [UIColor colorWithPatternImage:[UIImage imageNamed:#"add-icon.png"]].CGColor);
CGContextFillPath(context);
CGContextAddArc(context, circleCenter.x, circleCenter.y, 50, 180, 90, 0);
CGContextAddLineToPoint(context, circleCenter.x, circleCenter.y);
CGContextSetFillColorWithColor(context, [UIColor colorWithPatternImage:[UIImage imageNamed:#"appIcon_58.png"]].CGColor);
CGContextFillPath(context);
What you need, which I found the other day, is a great tool that lets you visualise Core Graphics code - after drawing it in a graphics program.
Its called Paint Code.
PaintCode

CoreGraphics taking a while to show on a large view - can i get it to repeat pixels?

This is my coregraphics code:
void drawTopPaperBackground(CGContextRef context, CGRect rect) {
CGRect paper3 = CGRectMake(10, 14, 300, rect.size.height - 14);
CGRect paper2 = CGRectMake(13, 12, 294, rect.size.height - 12);
CGRect paper1 = CGRectMake(16, 10, 288, rect.size.height - 10);
//Shadow
CGContextSetShadowWithColor(context, CGSizeMake(0,0), 10, [[UIColor colorWithWhite:0 alpha:0.5]CGColor]);
CGPathRef path = createRoundedRectForRect(paper3, 0);
CGContextSetFillColorWithColor(context, [[UIColor blackColor] CGColor]);
CGContextAddPath(context, path);
CGContextFillPath(context);
//Layers of paper
CGContextSaveGState(context);
drawPaper(context, paper3);
drawPaper(context, paper2);
drawPaper(context, paper1);
CGContextRestoreGState(context);
}
void drawPaper(CGContextRef context, CGRect rect) {
//Shadow
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(0,0), 1, [[UIColor colorWithWhite:0 alpha:0.5]CGColor]);
CGPathRef path = createRoundedRectForRect(rect, 0);
CGContextSetFillColorWithColor(context, [[UIColor blackColor] CGColor]);
CGContextAddPath(context, path);
CGContextFillPath(context);
CGContextRestoreGState(context);
//Gradient
CGContextSaveGState(context);
CGColorRef startColor = [UIColor colorWithWhite:0.92 alpha:1.0].CGColor;
CGColorRef endColor = [UIColor colorWithWhite:0.94 alpha:1.0].CGColor;
CGRect firstHalf = CGRectMake(rect.origin.x,
rect.origin.y, rect.size.width / 2, rect.size.height);
CGRect secondHalf = CGRectMake(rect.origin.x + (rect.size.width / 2),
rect.origin.y, rect.size.width / 2, rect.size.height);
drawVerticalGradient(context, firstHalf, startColor, endColor);
drawVerticalGradient(context, secondHalf, endColor, startColor);
CGContextRestoreGState(context);
CGContextSaveGState(context);
CGRect redRect = rectForRectWithInset(rect, -1);
CGMutablePathRef redPath = createRoundedRectForRect(redRect, 0);
CGContextSaveGState(context);
CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
CGContextAddPath(context, path);
CGContextClip(context);
CGContextAddPath(context, redPath);
CGContextSetShadowWithColor(context, CGSizeMake(0, 0), 15.0, [[UIColor colorWithWhite:0 alpha:0.1] CGColor]);
CGContextStrokePath(context);
CGContextRestoreGState(context);
}
The view is a UIScrollView, which contains a textview. Every time the user types something and goes onto a new line, I call [self setNeedsDisplay]; and it redraws the code. But when the view starts to get long - around 1000 height, it has very noticeable lag. How can i make this code more efficient? Can i take a line of pixels and make it just repeat that, or stretch it, all the way down?
You can draw your repeating background once, into an offscreen context, pull out the image from it, then create a UIColor with the pattern image and set that as your background colour. The image will then be tiled for you.
You start an image context with UIGraphicsBeginImageContextWithOptions(). The options include the size of your expected image - I assume this is the width of your scrollview and x pixels high, the opacity, and scale. Send 0 for the scale for automatic retina support.
You can then act as if you were within a drawRect method - so your functions above can be called as normal.
Then, extract the image:
UIImage *background = UIGraphicsGetImageFromCurrentImageContext();
End the image context:
UIGraphicsEndImageContext();
Then create the colour:
UIColor *backgroundColor = [UIColor colorWithPatternImage:background];
And set that as the background for your scrollview. Typed on a phone, so apologies for ... everything.

How to fill the shapes with color

I am new to Objective-C and iOS development. I have a view with some figures drawn by core drawing. Now I want to fill those shapes with color and I don't know the path or context of shape. Does Objective-C have any function like flood-fill or put-pixel so that by having only the stroke color I can fill any shape inside my view.
-(void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 4.0);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {1.0, 0.0, 0.0, 1.0};
CGColorRef color = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, color);
CGContextMoveToPoint(context, 50, 0);
CGContextAddLineToPoint(context, 0,320);
CGContextStrokePath(context);
CGColorSpaceRelease(colorspace);
CGColorRelease(color);
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetRGBFillColor(context, 0, 255, 0, 1.0);
CGContextMoveToPoint(context, 100, 100);
CGContextAddLineToPoint(context, 150, 150);
CGContextAddLineToPoint(context, 100, 200);
CGContextAddLineToPoint(context, 50, 150);
CGContextAddLineToPoint(context, 100, 100);
CGContextStrokePath(context);
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGRect rectangle = CGRectMake(60,170,200,80);
CGContextAddEllipseInRect(context, rectangle);
CGContextStrokePath(context);
}
This will make a circle and a square with some common region. I want a particular region to fill with color when a user taps that region.
So you are looking for flood fill in Objective C.
This is my implementation of Scan Line Flood Fill Algorithm.
Github : UIImageScanlineFloodfill
If you want to learn basic of flood fill:
Lode's Computer Graphics Tutorial Flood Fill
I hope this will help you.
Put your drawing code in the question and I can give you a specific answer.
Normally you just need to set a fill color using
[[UIColor redColor] setFill];
And any shapes you draw your core graphics will be filled with that color automatically.
Try this command:-
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
Core Graphics is closely tied to UIView and its drawRect: method and has a C interface. As you point out, you always draw in the current graphics context. I can think of 2 approaches: (1) When the user taps myView, set a property like myView.pointTapped, and in drawRect: find the shape to fill, set a fill color, and fill the closed path using GGGeometry methods.
There is an objective-C alternative: (2) Take a look at UIBezierPath. It's not as comprehensive as drawing in Core Graphics but it can be used in your ViewController implementation.

create a non-rectangular UIView

I need to create a view (a uibutton) of strange shape.
Is this possible with quartz2d? i used this code for buil my UIView subclass
- (void)drawRect:(CGRect)rect {
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(context, 100, 100);
CGContextAddLineToPoint(context, 150, 150);
CGContextAddLineToPoint(context, 100, 200);
CGContextAddLineToPoint(context, 50, 150);
CGContextAddLineToPoint(context, 100, 100);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillPath(context);
}
but this is a draw inside a standard UIView (rectangular UIView)

iPhone CGContext: drawing two lines with two different colors

I am having some troubles using the CGContext with an iPhone app. I am trying to draw several lines with different colors, but all the lines always end up having the color which was used last. I tried several approaches, but haven't been lucky.
I set up a small sample project to deal with that issue. This is my code, I use in the drawRect method. I am trying to draw a red and a blue line:
- (void)drawRect:(CGRect)rect{
NSLog(#"drawrect!");
CGContextRef bluecontext = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(bluecontext, 2.0);
CGContextSetStrokeColorWithColor(bluecontext, [UIColor blueColor].CGColor);
CGContextMoveToPoint(bluecontext, 1, 1);
CGContextAddLineToPoint(bluecontext, 100, 100);
CGContextSetStrokeColorWithColor(bluecontext, [UIColor redColor].CGColor);
CGContextAddLineToPoint(bluecontext, 200, 100);
CGContextStrokePath(bluecontext);
}
thanks for your help
Insert this code just before you set the stroke color the second time:
CGContextStrokePath(bluecontext);
CGContextBeginPath(bluecontext);
All the AddLine and AddOther calls are building a path. The path is drawn with a call like StrokePath, using the most recently set colors and other attributes. You are trying to draw two separate paths, so you must call Begin and Stroke for each path. Begin is sort of implicit when you start drawing, although it does not hurt to call it yourself. The basic flow of drawing is:
CGContextBeginPath(bluecontext); // clears any previous path
// add lines, curves, rectangles, etc...
CGContextStrokePath(bluecontext); // renders the path
Thats what you need.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
CGContextSetLineWidth(context, 2.0);
CGContextBeginPath(context);
CGContextSetStrokeColorWithColor(context, [UIColor orangeColor].CGColor);
CGContextMoveToPoint(context, 1, 1);
CGContextAddLineToPoint(context, 100, 100);
CGContextStrokePath(context); // and draw orange line}
CGContextBeginPath(context);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextMoveToPoint(context, 100, 100);
CGContextAddLineToPoint(context, 200, 100);
CGContextStrokePath(context); // draw blue line
I think this could be working.
CGContextRef bluecontext = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(bluecontext, 2.0);
CGContextSetStrokeColorWithColor(bluecontext, [UIColor blueColor].CGColor);
CGContextMoveToPoint(bluecontext, 1, 1);
CGContextAddLineToPoint(bluecontext, 100, 100);
CGContextStrokePath(bluecontext); // draw blue line
CGContextSetStrokeColorWithColor(bluecontext, [UIColor redColor].CGColor);
CGContextAddLineToPoint(bluecontext, 200, 100);
CGContextStrokePath(bluecontext); // and draw red line
If you are interested in the way it looks in a loop:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGPoint startingPoint = [[pointsArray objectAtIndex:0] CGPointValue];
CGContextMoveToPoint(context, startingPoint.x, startingPoint.y); //start at this point
for (int i = 1; i < [pointsArray count]; i++) {
CGContextBeginPath(context);
//start at the previous point
CGContextMoveToPoint(context,
[[pointsArray objectAtIndex:i-1] CGPointValue].x,
[[pointsArray objectAtIndex:i-1] CGPointValue].y);
CGPoint point = [[pointsArray objectAtIndex:i] CGPointValue];
if (point.y < 50) { // if y is less then 50 use red color
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
} else { // else use blue color
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
}
CGContextAddLineToPoint(context, point.x, point.y); //draw to this point
CGContextStrokePath(context);
}
}