При использовании преобразований обводка CAShapeLayer иногда выходит за пределы заполненной области того же пути - PullRequest
1 голос
/ 01 мая 2020

Я столкнулся с проблемой, когда я пытаюсь установить простой путь для CAShapeLayer, который, в свою очередь, находится в трехмерном преобразованном родительском виде / слое. Для некоторых преобразований, которые я хочу использовать, слой будет проходить по пути, отличному от того, который заполнен цветом заливки.

Я создал образец, который покажет этот эффект. Артефакты могут быть видны с различными формами и преобразованиями, по крайней мере, если форма включает кривые Безье и преобразование имеет перспективу и вращение.

Есть ли решение для этого? Я в порядке с заполненной областью, которая несколько искажается, пока штрих идет по заполненному пути.

// Create a single view app and paste this as the main view controller to test
class ViewController: UIViewController {

    var shapeView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        shapeView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
        let layer = createShapeLayer()
        layer.frame = shapeView.bounds
        layer.path = createPath()
        shapeView.layer.addSublayer(layer)
        shapeView.layer.transform = getTransform()
        view.addSubview(shapeView)
    }

    func createShapeLayer() -> CAShapeLayer {
        let layer = CAShapeLayer()
        layer.fillColor = UIColor.red.cgColor
        layer.strokeColor = UIColor.black.cgColor
        layer.lineWidth = 5

        return layer
    }

    func getTransform() -> CATransform3D {
        var transform = CATransform3DIdentity
        transform.m34 = 1.0 / -76.28
        transform = CATransform3DTranslate(transform, 0.0, 59.59, 50.45)
        transform = CATransform3DRotate(transform, 147.43 * .pi / 180.0, 1.0, 0.0, 0.0)

        return transform
    }

    // Simple banana shape
    func createPath() -> CGPath {
        let path = CGMutablePath()
        path.move(to: CGPoint(x: 45, y: 0))
        let cp1 = CGPoint(x: 50, y: -25)
        path.addCurve(to: CGPoint(x: 55, y: 0), control1: cp1, control2: cp1)
        let cp2 = CGPoint(x: 80, y: 50)
        path.addCurve(to: CGPoint(x: 55, y: 100), control1: cp2, control2: cp2)
        let cp3 = CGPoint(x: 50, y: 125)
        path.addCurve(to: CGPoint(x: 45, y: 100), control1: cp3, control2: cp3)
        let cp4 = CGPoint(x: 70, y: 50)
        path.addCurve(to: CGPoint(x: 45, y: 0), control1: cp4, control2: cp4)

        return path
    }
}

Вот как выглядит результат. Одна фигура с красным цветом заливки и черным цветом обводки.

Я подозреваю, что проблема заключается в том, что алгоритм заполнения нарушается в некоторых случаях, а алгоритм обводки - нет. Области, которые должны быть заполнены, становятся очень большими в направлении Z, хотя и маленькими на экране. Тем не менее, в идеале я думаю, что обводка всегда должна находиться на краю заполненной области, даже если она искажается.

Result

...