将CGPathRef转换为NSBezierPath [英] Convert CGPathRef to NSBezierPath

查看:333
本文介绍了将CGPathRef转换为NSBezierPath的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Apple文档中,他们为您提供了如何将NSBezierPath转换为CGPathRef的代码.我需要从CGPathRef到NSBezierPath进行另一种转换. UIBezierPath具有一个名为cgPath的属性,因此,如果我在iPhone上工作,那不是问题,但在MacOS上工作.

In Apple docs they give you code of how to convert NSBezierPath to CGPathRef. I need to convert the other way around, from CGPathRef to NSBezierPath. UIBezierPath has a property called cgPath so if I was working on iPhone that would not be a problem, but I'm working on MacOS.

这肯定是一个古老的问题,我确定可以在Internet上找到答案,但是没有运气.可能是我缺少了一些东西.任何帮助表示赞赏.

This must be an old question, and I was sure to find an answer on Internet but no luck. Could be I'm missing something. Any help appreciated.

推荐答案

旧问题,但我相信这对其他人还是有帮助的. (您未指定Objective-C或Swift;这是一个Objective-C答案.)

Old question but I'm sure this will still be helpful for others. (You didn't specify Objective-C or Swift; this is an Objective-C answer.)

您可以将CGPathRef转换为NSBezierPath,并将其与CGPathRef点转换为NSBezierPath点.唯一棘手的部分是从CGPathRef的二次曲线到NSBezierPath的三次曲线的转换,但有一个方程式:

You can convert a CGPathRef to an NSBezierPath using CGPathApply() with an applier function callback that translates the CGPathRef points to NSBezierPath points. The only tricky part is the conversion from CGPathRef's quadratic curves to NSBezierPath's cubic curves but there's an equation for that:

任何二次样条都可以表示为三次(三次项为零).三次方的端点将与二次方的端点相同.

Any quadratic spline can be expressed as a cubic (where the cubic term is zero). The end points of the cubic will be the same as the quadratic's.

 CP0 = QP0
 CP3 = QP2 

三次方的两个控制点是:

The two control points for the cubic are:

 CP1 = QP0 + 2/3 * (QP1-QP0)
 CP2 = QP2 + 2/3 * (QP1-QP2)

...由于四舍五入而引入了一些错误,但通常不会引起注意.

... There is a slight error introduced due to rounding, but it is usually not noticeable.

使用上面的公式,这是从CGPathRef转换的NSBezierPath类别:

Using the equation above, here's an NSBezierPath category for converting from CGPathRef:

NSBezierPath + BezierPathWithCGPath.h

@interface NSBezierPath (BezierPathWithCGPath)
+ (NSBezierPath *)JNS_bezierPathWithCGPath:(CGPathRef)cgPath; //prefixed as Apple may add bezierPathWithCGPath: method someday
@end

NSBezierPath + BezierPathWithCGPath.m

static void CGPathToBezierPathApplierFunction(void *info, const CGPathElement *element) {
    NSBezierPath *bezierPath = (__bridge NSBezierPath *)info;
    CGPoint *points = element->points;
    switch(element->type) {
        case kCGPathElementMoveToPoint: [bezierPath moveToPoint:points[0]]; break;
        case kCGPathElementAddLineToPoint: [bezierPath lineToPoint:points[0]]; break;
        case kCGPathElementAddQuadCurveToPoint: {
            NSPoint qp0 = bezierPath.currentPoint, qp1 = points[0], qp2 = points[1], cp1, cp2;
            CGFloat m = (2.0 / 3.0);
            cp1.x = (qp0.x + ((qp1.x - qp0.x) * m));
            cp1.y = (qp0.y + ((qp1.y - qp0.y) * m));
            cp2.x = (qp2.x + ((qp1.x - qp2.x) * m));
            cp2.y = (qp2.y + ((qp1.y - qp2.y) * m));
            [bezierPath curveToPoint:qp2 controlPoint1:cp1 controlPoint2:cp2];
            break;
        }
        case kCGPathElementAddCurveToPoint: [bezierPath curveToPoint:points[2] controlPoint1:points[0] controlPoint2:points[1]]; break;
        case kCGPathElementCloseSubpath: [bezierPath closePath]; break;
    }
}

@implementation NSBezierPath (BezierPathWithCGPath)
+ (NSBezierPath *)JNS_bezierPathWithCGPath:(CGPathRef)cgPath {
    NSBezierPath *bezierPath = [NSBezierPath bezierPath];
    CGPathApply(cgPath, (__bridge void *)bezierPath, CGPathToBezierPathApplierFunction);
    return bezierPath;
}
@end

这样称呼:

//...get cgPath (CGPathRef) from somewhere
NSBezierPath *bezierPath = [NSBezierPath JNS_bezierPathWithCGPath:cgPath];

这篇关于将CGPathRef转换为NSBezierPath的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆