问题
How to draw a closed crescent moon using bezier paths, when the stroke and fill are configurable? So car I can get once curve but haven't found a strategy to connect and draw the other curve.

回答1:
If you want something better approximating an astronomically correct crescent (where the outer arc is 180 degrees), I might suggest something like:
CGFloat angle = M_PI_2 * 0.60; // how much of a crescent do you want (must be less than M_PI_2 and greater than zero)
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:-M_PI_2 endAngle:M_PI_2 clockwise:TRUE];
[path addArcWithCenter:CGPointMake(center.x - radius * tan(angle), center.y) radius:radius / cosf(angle) startAngle:M_PI_2 - angle endAngle:angle - M_PI_2 clockwise:FALSE];
[path closePath];
That yields:

As you can see, the path is basically defined by two circular arcs, one clockwise, one counter clockwise. The specifics of the center, radius, and starting and ending angles of the inner arc is a matter of basic trigonometry (but the actual formulae will vary depending upon the precise desired look and feel). For example, in my code snippet, the angle
in my code above is the blue angle in the following diagram, and I then calculate red triangle that will be used to determine the correct starting and ending angles and center for the inner arc.

Below, someone asked about rotating this counter clockwise 90 degrees like:
In Swift, that would be:
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: -.pi, endAngle: 0, clockwise: true)
path.addArc(withCenter: CGPoint(x: center.x, y: center.y + radius * tan(angle)), radius: radius / cos(angle), startAngle: -angle, endAngle: -.pi + angle, clockwise: false)
path.close()
回答2:
The bezier path can be constructed from two arcs. In swift:
var big = UIBezierPath()
var angle: CGFloat = 5.0 // in radians
var rad : CGFloat = 50.0
big.addArcWithCenter(CGPointMake(0.0, 0.0), radius: rad, startAngle:-angle/2.0, endAngle: angle/2.0, clockwise: true)
big.addArcWithCenter(CGPointMake(rad * cos(angle/2.0), 0.0), radius: rad * sin(angle/2.0), startAngle: 3.14/2.0, endAngle: -3.14/2.0, clockwise: false)
big.closePath()
Will create a path that when drawn will look like:

Edit: Objective-C with fill and stroke with upper left corner in x,y = 100,100):
UIBezierPath *big = [UIBezierPath new];
CGFloat angle = 5.0; // in radians
CGFloat rad = 50.0;
CGFloat x= 100.0;
CGFloat y = 100.0;
[big addArcWithCenter:CGPointMake(x, y) radius:rad startAngle:-angle/2.0 endAngle:angle/2.0 clockwise:YES];
[big addArcWithCenter:CGPointMake(x + rad * cos(angle/2.0), y) radius: rad * sin(angle/2.0) startAngle:M_PI_2 endAngle:-M_PI_2 clockwise:NO];
big.lineWidth = 2.0;
[[UIColor lightGrayColor] setFill];
[[UIColor darkGrayColor] setStroke];
[big closePath];
[big fill];
[big stroke];
回答3:
For complex shape drawing, I could suggest you a great application called PaintCode. With it, you can import vector graphics and get the associated path formatted in form of a bezierPath. There is a trial available. Here is what I got after converting your provided shape into a SVG file:
UIBezierPath* bezierPath = UIBezierPath.bezierPath;
[bezierPath moveToPoint: CGPointMake(47.18, 5.32)];
[bezierPath addCurveToPoint: CGPointMake(67.96, 17.62) controlPoint1: CGPointMake(55.58, 7.5) controlPoint2: CGPointMake(61.06, 10.72)];
[bezierPath addCurveToPoint: CGPointMake(81.46, 49.5) controlPoint1: CGPointMake(77.56, 27.15) controlPoint2: CGPointMake(81.46, 36.45)];
[bezierPath addCurveToPoint: CGPointMake(67.96, 81.37) controlPoint1: CGPointMake(81.46, 62.55) controlPoint2: CGPointMake(77.56, 71.85)];
[bezierPath addCurveToPoint: CGPointMake(47.18, 93.67) controlPoint1: CGPointMake(61.06, 88.27) controlPoint2: CGPointMake(55.58, 91.5)];
[bezierPath addCurveToPoint: CGPointMake(24.98, 93.67) controlPoint1: CGPointMake(41.33, 95.17) controlPoint2: CGPointMake(30.83, 95.17)];
[bezierPath addCurveToPoint: CGPointMake(9.16, 86.32) controlPoint1: CGPointMake(19.81, 92.32) controlPoint2: CGPointMake(12.38, 88.87)];
[bezierPath addLineToPoint: CGPointMake(7.06, 84.52)];
[bezierPath addLineToPoint: CGPointMake(10.13, 80.47)];
[bezierPath addCurveToPoint: CGPointMake(19.13, 61.27) controlPoint1: CGPointMake(13.81, 75.52) controlPoint2: CGPointMake(18.01, 66.67)];
[bezierPath addCurveToPoint: CGPointMake(18.83, 38.25) controlPoint1: CGPointMake(20.33, 55.5) controlPoint2: CGPointMake(20.18, 43.42)];
[bezierPath addCurveToPoint: CGPointMake(9.98, 19.95) controlPoint1: CGPointMake(17.11, 31.57) controlPoint2: CGPointMake(14.03, 25.35)];
[bezierPath addLineToPoint: CGPointMake(6.31, 15.07)];
[bezierPath addLineToPoint: CGPointMake(8.78, 13.05)];
[bezierPath addCurveToPoint: CGPointMake(24.08, 5.55) controlPoint1: CGPointMake(12.16, 10.27) controlPoint2: CGPointMake(18.53, 7.12)];
[bezierPath addCurveToPoint: CGPointMake(47.18, 5.32) controlPoint1: CGPointMake(29.93, 3.82) controlPoint2: CGPointMake(41.11, 3.75)];
[bezierPath closePath];
self.shapeLayer = [CAShapeLayer new];
self.shapeLayer.path = bezierPath.CGPath;
self.shapeLayer.frame = CGRectMake(80, 80, 85, 98);
self.shapeLayer.strokeColor = [UIColor blueColor].CGColor;
self.shapeLayer.lineWidth = 4;
self.shapeLayer.fillColor = [UIColor lightGrayColor].CGColor;
[self.layer addSublayer:self.shapeLayer];
The result:

来源:https://stackoverflow.com/questions/30084585/how-to-create-a-crescent-moon-using-bezier-paths-in-ios