I canโt understand why the accepted answer adds some complex logic to the close path (maybe it is necessary in some circumstances), but for those who just need the initial path conversion, the version of this code that is implemented as a regular method is cleared here:
- (CGMutablePathRef)CGPathFromPath:(NSBezierPath *)path { CGMutablePathRef cgPath = CGPathCreateMutable(); NSInteger n = [path elementCount]; for (NSInteger i = 0; i < n; i++) { NSPoint ps[3]; switch ([path elementAtIndex:i associatedPoints:ps]) { case NSMoveToBezierPathElement: { CGPathMoveToPoint(cgPath, NULL, ps[0].x, ps[0].y); break; } case NSLineToBezierPathElement: { CGPathAddLineToPoint(cgPath, NULL, ps[0].x, ps[0].y); break; } case NSCurveToBezierPathElement: { CGPathAddCurveToPoint(cgPath, NULL, ps[0].x, ps[0].y, ps[1].x, ps[1].y, ps[2].x, ps[2].y); break; } case NSClosePathBezierPathElement: { CGPathCloseSubpath(cgPath); break; } default: NSAssert(0, @"Invalid NSBezierPathElement"); } } return cgPath; }
Btw, I needed this to implement the "NSBezierPath stroke contains a point" method.
I was looking for this conversion to call CGPathCreateCopyByStrokingPath() , which converts the NSBezierPath hatch NSBezierPath to the normal path, so that you can also check hits on hits, and here is the solution:
// stroke (0,0) to (10,0) width 5 --> rect (0, -2.5) (10 x 5) NSBezierPath *path = [[NSBezierPath alloc] init]; [path moveToPoint:NSMakePoint(0.0, 0.0)]; [path lineToPoint:NSMakePoint(10.0, 0.0)]; [path setLineWidth:5.0]; CGMutablePathRef cgPath = [self CGPathFromPath:path]; CGPathRef strokePath = CGPathCreateCopyByStrokingPath(cgPath, NULL, [path lineWidth], [path lineCapStyle], [path lineJoinStyle], [path miterLimit]); CGPathRelease(cgPath); NSLog(@"%@", NSStringFromRect(NSRectFromCGRect(CGPathGetBoundingBox(strokePath)))); // {{0, -2.5}, {10, 5}} CGPoint point = CGPointMake(1.0, 1.0); BOOL hit = CGPathContainsPoint(strokePath, NULL, point, (bool)[path windingRule]); NSLog(@"%@: %@", NSStringFromPoint(NSPointFromCGPoint(point)), (hit ? @"yes" : @"no")); // {1, 1}: yes CGPathRelease(strokePath);
This is similar to QPainterPathStroker from Qt, but for NSBezierPath .