CGContextDrawPath Stroke disappears if Fill is added - iphone

trying to draw circle divided to dynamically provided number of sectors. In the end my circle should look like pie.
I've created class Circle which contains number of Pies inside. Circle has method - (void)draw which calles [pie draw]; in for (Pie *pie in self.pies) loop.
Implementation of pie looks like this:
- (void)draw {
CGContextRef context = UIGraphicsGetCurrentContext();
float startAngleRads = degreesToRadians(_startAngle);
float endAngleRads = degreesToRadians(_endAngle);
CGContextBeginPath(context);
CGContextSetLineWidth(context, 1.0f);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGColorRef strokeColor = [_strokeColor CGColor];
CGContextSetStrokeColorWithColor(context, strokeColor);
CGColorRef fillColor = [_bgColor CGColor];
CGContextSetFillColorWithColor(context, fillColor);
CGContextMoveToPoint(context, _x, _y);
CGContextAddArc(context, _x, _y, _r, startAngleRads, endAngleRads, YES);
CGContextDrawPath(context, kCGPathStroke);
CGContextFlush(context);
}
This draws nice circle with sectors but without any filling of course. When I change last lines to CGContextDrawPath(context, kCGPathStrokeFill); my stroke lines disappears and only last line (last sector) stays at the screen, other parts of circle are filled with bgcolor and no stroke is visible anymore.
The question is: how can I draw completly separated "sectors" (every sector should look like triangle with Arc and Stroke and Fill). I need this because I want to toggle visibility of that sectors but at the moment I cant even figure out how to draw them correctly.
If this is important, all drawing happens on the layer with self.opaque = NO;.

Ok, found my error: had to set NO in CGContextAddArc call.

Related

CGContext giving unexpected line width

I'm trying to draw a L shape, the code works but the lines are not of the right width and is 5 pixels thick for vertical lines and some are 3 pixels thick despite me explicitly telling it to use 3 pixel as line width,what am I doing wrong? here's my code:
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextClearRect(ctx, rect);
CGContextAddPath(ctx, pathi);
CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
CGContextSetLineWidth(ctx, 3.0);
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetShouldAntialias(ctx, NO);
CGContextStrokePath(ctx);
I have already calculated path "pathi" The path is working fine.
The lines are actually not thick, the half of the lines gets cutoff while drawing.
You should apply padding equal to the half of the width( inn your case, 3/2 => 1.5) because the drawing always start from the mid of the points provided.

Improper borders in draw rect

I am trying to draw rounded corners on rectangle in drawRect method using bezier path, but somehow the rounded corner is being shown on inner side of rectangle, instead of both inner and outer sides. Code is given below. Also attached herewith is border that is currently being drawn (outer side of border is not rounded)
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context=UIGraphicsGetCurrentContext();
//Set gray color to whole context
[[UIColor lightGrayColor] set];
CGContextSetAlpha(context,0.7);
UIRectFill(rect);
// Configure the context colors and line
CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:131./255. green:148./255. blue:219./255. alpha:1.0].CGColor);
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextSetLineWidth(context, 10.0);
CGSize size=self.bounds.size;
CGFloat radius = 10.0;
CGSize guideSize=CGSizeMake(330, 130);
CGRect guideCoords= CGRectMake(size.width*.5-guideSize.width*.5, size.height*.5-guideSize.height*.5, guideSize.width , guideSize.height);
// Guide drawing
CGContextStrokeRect(context,guideCoords);
// Draw the Text
[kVinGuideMessage drawInRect:CGRectMake(guideCoords.origin.x+kSideMessageMargin, guideCoords.origin.y+guideSize.height+kMarginFromGuide, guideCoords.size.width-2*kSideMessageMargin,40) withFont:[UIFont systemFontOfSize:16.0] lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
//Get instersection and clear color of inner overlay
CGRect holeRectIntersection = CGRectIntersection(rect,guideCoords);
//----------ADDING ROUNDED CORNERS HERE-----------//
CGPathRef clippath = [UIBezierPath bezierPathWithRoundedRect:guideCoords cornerRadius:radius].CGPath;
CGContextAddPath(context, clippath);
CGContextClip(context);
//------------------------------------------------//
[[UIColor clearColor] setFill];
UIRectFill(holeRectIntersection);
}
The outer corners are being drawn by the CGContextStrokeRect(context,guideCoords); I think. At that point you haven't set a clipping path and your line width is 10 points, so why would the outer corners be rounded? I think you'll have better luck if you set a clipping path (probably not exactly the same clipping path you've got at the bottom) before calling stroke rect on the guideCoords rectangle.

iPhone Quartz Drawing Eraser

I am trying to make an iPhone application with erasing. I am running into 2 problems, if you have a solution for either one please answer this. I would like to erase part of an image.
1) I am currently just clearing the rect but it has a square edge. I would like it to be round, I have previously tried translating but this does not work. I also need it to translate/rotate as few times as possible to maintain the same performance.
2) In addition I wanted to know if there are any other ways of erasing. When erasing fast it is erasing ever 1/2 inch. Is there a way to stroke a path and clear the rect or something? Sorry if this is hard to understand.
CGRect circleRect = CGRectMake([touch CGPointValue].x, [touch CGPointValue].y, 25, 25);
CGContextClearRect(currentContext,circleRect);
This code should do what you're looking for:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.strokeWidth);
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextSetStrokeColorWithColor(context, [[UIColor clearColor] CGColor]);
CGContextBeginPath(context);
CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(context, currentPoint.x, currentPoint.y);
CGContextStrokePath(context);
CGContextFlush(context);
The key points are
1) CGContextSetLineCap(context, kCGLineCapRound), which makes it round
2) CGContextSetBlendMode(context, kCGBlendModeClear) which clears the context.
I realize this is an older question but I thought I would expand on Eric Reids answer as I was trying to use his example outside of the drawRect method and had to modify it to get it to work with a context I created in a 'touchesMoved' method in a UIView subclass.
I call this method from 'touchesMoved' and pass it the CGPoint of the touch in the view I'm drawing in.
-(void) processEraseAtPoint:(CGPoint)point
{
// setup a context with the size of our canvas view (the canvas view is the UIView instance I'm drawing into)
UIGraphicsBeginImageContext(self.canvasView.bounds.size);
// get a reference to the context we just created
CGContextRef context = UIGraphicsGetCurrentContext();
// draw the image we want to edit into this context (this is the image containing the drawing I want to erase part of)
[self.canvasView.incrementalImage drawAtPoint:CGPointZero];
// set our context options
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.canvasView.settings.brushDiameter);
CGContextSetBlendMode(context, kCGBlendModeClear);
// make the color clear since we're erasing
CGContextSetStrokeColorWithColor(context, [[UIColor clearColor] CGColor]);
// start our path in this context
CGContextBeginPath(context);
// set our first point
CGContextMoveToPoint(context, lastTouch.x, lastTouch.y);
// draw from our last point to this point
CGContextAddLineToPoint(context, point.x, point.y);
// stroke this path (in this case it's clear so it will erase what's there)
CGContextStrokePath(context);
// set our incrementalImage in the canvasView with the updated image from this context
// Note that in the canvasView 'drawRect' method I am calling
// '[self.incrementalImage drawInRect:rect]', so this new image will get drawn
// in my canvasView when I call 'setNeedsDisplay'
self.canvasView.incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
// cleanup our context
CGContextFlush(context);
UIGraphicsEndImageContext();
// set our last touch point for the next line segment
lastTouch = point;
// update our view
[self.canvasView setNeedsDisplay];
}

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.

Iphone sdk: Drawing a continuous line in Quartz with an "overlap"

From a source of points im drawing a line that crosses over itself using this code:
UIGraphicsBeginImageContext(CGSizeMake([delegate getTileWidth], [delegate getTileWidth]));
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [[delegate GetColor] CGColor]);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetAllowsAntialiasing(context, YES);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineWidth(context, [delegate getBrushWidth]);
CGContextMoveToPoint(context, xpath[0], ypath[0]);
for (int i = 0; i <= ([CurrentLine count]-2); i++) {
CGContextAddLineToPoint(context, xpath[i],ypath[i]);
}
CGContextDrawPath(context, kCGPathStroke);
CGContextStrokePath(context);
The drawing is working just fine, but if i draw it with a alpha and the lines "crosses" itself there is no overlap.
What im getting:
(The yellow lines and numbers are for debugging)
What im getting
What i want:
Compared to the first image there is a clear "overlap" where the line crosses itself
What i want
So im wonering where i can find the setting to allow "overlap", i have read around on the CGContext refrence page and tried tons of different settings. So i think im lost...
Thx in advance :)