i am drawing Custom shape using Core Graphics and i want to make Rounded Corners for this shape this is my code of Drawing my custom Shape
CGPoint p1=[self getPointFromAngleQuarter:start_angle2 andRaduis:card.small_Raduis andCenter:center];
CGContextMoveToPoint(context, p1.x, p1.y);
CGPoint p2=[self getPointFromAngleQuarter:start_angle2 andCenter:center andRaduis:self.large_Raduis];
CGContextAddLineToPoint(context, p2.x, p2.y);
CGContextAddArc(context,center.x, center.y, selectedLargeRaduis, start, end,0);
CGPoint p5=[self getPointFromAngle:end_Angle andCenter:center andRaduis:self.small_Raduis];
CGContextAddLineToPoint(context, p5.x, p5.y);
CGContextAddArc(context,center.x, center.y,selectedSmallRaduis, end, start,1);
CGContextDrawPath(context, kCGPathFill);
and here is the final Result of my custom Shape
If this shape is a solid color, the easy solution is to use a very wide line width, plus a round line cap and round line join. I presume, though, that you want this rounded shape to lay entirely inside the shape you included in your picture. Then the trick is to offset the arcs you draw by an amount equal to corner radius of the path (and stroke the line with twice the width of the corner radius).
For example, considering this diagram (which is not the desired shape, but shows us how to get there):
The black shape in the background is your original shape. The white path is the path I'm going to draw to achieve the rounded corners. The light gray is that path stroked with a large line width, a rounded line join, and a rounded line cap. The dark gray is that path filled in with another color.
So hopefully this illustrates the idea. Create a new path, offset by the corner radius, and drawn with a line width twice the corner radius. If you simply draw the new path with a solid back stroke (replacing the light gray in the above image) and solid black fill (replacing the dark gray in the above image), you get your desired shape:
Here is routine to get the path (the white line in my first image) in Objective-C:
- (UIBezierPath *)arcWithRoundedCornerAt:(CGPoint)center
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngle
innerRadius:(CGFloat)innerRadius
outerRadius:(CGFloat)outerRadius
cornerRadius:(CGFloat)cornerRadius {
CGFloat innerTheta = asin(cornerRadius / 2.0 / (innerRadius + cornerRadius)) * 2.0;
CGFloat outerTheta = asin(cornerRadius / 2.0 / (outerRadius - cornerRadius)) * 2.0;
UIBezierPath *path = [UIBezierPath bezierPath];
[path addArcWithCenter:center
radius:innerRadius + cornerRadius
startAngle:endAngle - innerTheta
endAngle:startAngle + innerTheta
clockwise:false];
[path addArcWithCenter:center
radius:outerRadius - cornerRadius
startAngle:startAngle + outerTheta
endAngle:endAngle - outerTheta
clockwise:true];
[path closePath];
return path;
}
Or in Swift 3:
private func arcWithRoundedCorners(at center: CGPoint, startAngle: CGFloat, endAngle: CGFloat, innerRadius: CGFloat, outerRadius: CGFloat, cornerRadius: CGFloat) -> UIBezierPath {
let innerTheta = asin(cornerRadius / 2 / (innerRadius + cornerRadius)) * 2
let outerTheta = asin(cornerRadius / 2 / (outerRadius - cornerRadius)) * 2
let path = UIBezierPath()
path.addArc(withCenter: center, radius: innerRadius + cornerRadius, startAngle: endAngle - innerTheta, endAngle: startAngle + innerTheta, clockwise: false)
path.addArc(withCenter: center, radius: outerRadius - cornerRadius, startAngle: startAngle + outerTheta, endAngle: endAngle - outerTheta, clockwise: true)
path.close()
return path
}
(You can do the above with Core Graphics calls if you want, but I generally use UIBezierPath
.)
If, though, you needed the fill to be a different color than the stroke, then the process is more complicated, because you can't just use this technique. Instead, you actually have to define a path that is an outline of the above shape, but consists of drawing not only the two big arcs, but four little arcs for each of the corners. It's tedious, but simple, trigonometry to construct that path, but I wouldn't go through that effort unless you had to.