【问题标题】:Convert CGPathRef to NSBezierPath将 CGPathRef 转换为 NSBezierPath
【发布时间】:2020-06-03 20:51:03
【问题描述】:

在 Apple 文档中,它们为您提供了如何将 NSBezierPath 转换为 CGPathRef 的代码。我需要反过来转换,从 CGPathRef 到 NSBezierPath。 UIBezierPath 有一个名为 cgPath 的属性,所以如果我在 iPhone 上工作这不会有问题,但我在 MacOS 上工作。

这一定是一个老问题,我肯定会在互联网上找到答案,但没有运气。可能是我错过了什么。任何帮助表示赞赏。

【问题讨论】:

    标签: macos nsbezierpath cgpathref


    【解决方案1】:

    老问题,但我相信这对其他人仍然有帮助。 (您没有指定 Objective-C 或 Swift;这是 Objective-C 的答案。)

    您可以使用CGPathApply()CGPathRef 转换为NSBezierPath,并使用将CGPathRef 点转换为NSBezierPath 点的应用程序函数回调。唯一棘手的部分是从CGPathRef 的二次曲线到NSBezierPath 的三次曲线但there's an equation for that 的转换:

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

     CP0 = QP0
     CP3 = QP2 
    

    三次方的两个控制点是:

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

    ...由于四舍五入而引入了轻微的错误,但通常不会引起注意。

    使用上面的等式,这是一个 NSBezierPath 类别,用于从 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];
    

    【讨论】:

      猜你喜欢
      • 2016-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多