macOS Не удается загрузить объект NSBezierPath на CAShapeLayer [дубликат]

 $("input[name='gender']:checked").val()

для вложенных атрибутов

$("input[name='lead[gender]']:checked").val()

Не забывайте отдельные фигурные скобки для имени

25
задан Andriy 25 May 2016 в 04:15
поделиться

5 ответов

Прямо из документации Apple: Создание CGPathRef из объекта NSBezierPath

Вот соответствующий код.

@implementation NSBezierPath (BezierPathQuartzUtilities)
// This method works only in OS X v10.2 and later.
- (CGPathRef)quartzPath
{
    int i, numElements;

    // Need to begin a path here.
    CGPathRef           immutablePath = NULL;

    // Then draw the path elements.
    numElements = [self elementCount];
    if (numElements > 0)
    {
        CGMutablePathRef    path = CGPathCreateMutable();
        NSPoint             points[3];
        BOOL                didClosePath = YES;

        for (i = 0; i < numElements; i++)
        {
            switch ([self elementAtIndex:i associatedPoints:points])
            {
                case NSMoveToBezierPathElement:
                    CGPathMoveToPoint(path, NULL, points[0].x, points[0].y);
                    break;

                case NSLineToBezierPathElement:
                    CGPathAddLineToPoint(path, NULL, points[0].x, points[0].y);
                    didClosePath = NO;
                    break;

                case NSCurveToBezierPathElement:
                    CGPathAddCurveToPoint(path, NULL, points[0].x, points[0].y,
                                        points[1].x, points[1].y,
                                        points[2].x, points[2].y);
                    didClosePath = NO;
                    break;

                case NSClosePathBezierPathElement:
                    CGPathCloseSubpath(path);
                    didClosePath = YES;
                    break;
            }
        }

        // Be sure the path is closed or Quartz may not do valid hit detection.
        if (!didClosePath)
            CGPathCloseSubpath(path);

        immutablePath = CGPathCreateCopy(path);
        CGPathRelease(path);
    }

    return immutablePath;
}
@end

Bug Reporter

]

rdar: // 15758302 : NSBezierPath для CGPath.

33
ответ дан catlan 17 August 2018 в 11:07
поделиться
  • 1
    Я думаю, что довольно удивительно, что Apple помещает этот код в документы, а не просто добавляет аксессуар CGPath к NSBezierPath. – Erik Aigner 5 March 2016 в 11:20

Вот версия Swift, если кто-то еще нуждается в ней:

extension IXBezierPath {
// Adapted from : https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Paths/Paths.html#//apple_ref/doc/uid/TP40003290-CH206-SW2
// See also: http://www.dreamincode.net/forums/topic/370959-nsbezierpath-to-cgpathref-in-swift/
func CGPath(forceClose forceClose:Bool) -> CGPathRef? {
    var cgPath:CGPathRef? = nil

    let numElements = self.elementCount
    if numElements > 0 {
        let newPath = CGPathCreateMutable()
        let points = NSPointArray.alloc(3)
        var bDidClosePath:Bool = true

        for i in 0 ..< numElements {

            switch elementAtIndex(i, associatedPoints:points) {

            case NSBezierPathElement.MoveToBezierPathElement:
                CGPathMoveToPoint(newPath, nil, points[0].x, points[0].y )

            case NSBezierPathElement.LineToBezierPathElement:
                CGPathAddLineToPoint(newPath, nil, points[0].x, points[0].y )
                bDidClosePath = false

            case NSBezierPathElement.CurveToBezierPathElement:
                CGPathAddCurveToPoint(newPath, nil, points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y )
                bDidClosePath = false

            case NSBezierPathElement.ClosePathBezierPathElement:
                CGPathCloseSubpath(newPath)
                bDidClosePath = true
            }

            if forceClose && !bDidClosePath {
                CGPathCloseSubpath(newPath)
            }
        }
        cgPath = CGPathCreateCopy(newPath)
    }
    return cgPath
}
4
ответ дан Cirec Beback 17 August 2018 в 11:07
поделиться

Синтаксис в Xcode 8 GM был еще более упрощен, код был изменен из ответа rob-mayoff выше. Используя это и помощник для addLine(to point: CGPoint), я использую кросс-платформу для рисования кода.

extension NSBezierPath {

    public var cgPath: CGPath {
        let path = CGMutablePath()
        var points = [CGPoint](repeating: .zero, count: 3)

        for i in 0 ..< self.elementCount {
            let type = self.element(at: i, associatedPoints: &points)
            switch type {
            case .moveToBezierPathElement:
                path.move(to: points[0])
            case .lineToBezierPathElement:
                path.addLine(to: points[0])
            case .curveToBezierPathElement:
                path.addCurve(to: points[2], control1: points[0], control2: points[1])
            case .closePathBezierPathElement:
                path.closeSubpath()
            }
        }

        return path
    }
}
18
ответ дан Henrik 17 August 2018 в 11:07
поделиться

Это работает в Swift 3.1 и более поздних версиях:

import AppKit

public extension NSBezierPath {

    public var cgPath: CGPath {
        let path = CGMutablePath()
        var points = [CGPoint](repeating: .zero, count: 3)
        for i in 0 ..< self.elementCount {
            let type = self.element(at: i, associatedPoints: &points)
            switch type {
            case .moveToBezierPathElement: path.move(to: points[0])
            case .lineToBezierPathElement: path.addLine(to: points[0])
            case .curveToBezierPathElement: path.addCurve(to: points[2], control1: points[0], control2: points[1])
            case .closePathBezierPathElement: path.closeSubpath()
            }
        }
        return path
    }

}
9
ответ дан rob mayoff 17 August 2018 в 11:07
поделиться
  • 1
    CGPoint () отсутствует ... – highmaintenance 15 September 2016 в 17:50
  • 2
    Нет таких вещей, как moveTo или addLineTo в Swift 3, не так ли? – El Tomato 19 March 2017 в 00:28
  • 3
    Я обновил свой ответ. – rob mayoff 19 March 2017 в 03:33
  • 4
    Это было бы лучше, чем инициализатор удобства на CGPath, поэтому можно было бы использовать более стандартный CGPath(from: bezierPath) синтаксис – Ben Leggiero 4 December 2017 в 17:27
  • 5
    NSColor имеет свойство cgColor, NSGraphicsContext имеет свойство cgContext, а NSColorSpace имеет свойство cgColorSpace. NSImage имеет `cgImage (forProposedRect: context: hints:)` метод. – rob mayoff 4 December 2017 в 18:42

Я не могу понять, почему принятый ответ добавляет некоторую сложную логику близкого пути (возможно, это необходимо при некоторых обстоятельствах), но для тех, кому просто нужно девственное преобразование пути, здесь очищена версия этого кода, реализованная как обычный метод:

- (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, мне это нужно для реализации метода «NSBezierPath stroke содержит точку».

I 'look for this conversion to call CGPathCreateCopyByStrokingPath(), который преобразует контур штриховки NSBezierPath в обычный путь, так что вы также можете тестировать хиты при ударах, и вот решение:

// 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);

Это аналогично QPainterPathStroker из Qt, но для NSBezierPath.

1
ответ дан user3125367 17 August 2018 в 11:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: