2

是否有某种方法(代码或伪代码算法)来利用UIBezierPath实例方法,例如appendPath将任意数量的连接的、不同UIBezierPath的 s “合并”到单个大路径中?在具有许多路径的文档中,我试图通过减少路径数量来减小编码文件的大小,因为那里肯定有一些冗余信息。如果我叫错了树,请告诉我。

4

2 回答 2

1

就我而言,我几乎没有逻辑连接的路径,它们一起形成一个封闭的形状,我想填充这个封闭的形状。如果您只是将它们附加(_:)在一起,则无法做到这一点,因为填充只会应用于每个路径。我查看了类似的问题,但没有一个能解决问题。所以我写了这个扩展来将逻辑连接的路径合并在一起形成一个单一的路径。

如果你有path1path2并且path3逻辑上形成一个封闭的形状。以相同的顺序调用它们

let mergedPath = UIBezierPath()
mergedPath.merge(with: path1)
mergedPath.merge(with: path2)
mergedPath.merge(with: path3)

在此处输入图像描述

在此处输入图像描述

import UIKit

extension UIBezierPath {
    func merge(with path: UIBezierPath) {
        let currentPath = self.cgPath.mutableCopy()!
        let lastPoint = self.lastPoint()
        let firstPoint = path.firstPoint()
        
        var index = -1
        path.cgPath.applyWithBlock { block in
            index += 1
            let element = block.pointee
            
            switch (element.type) {
            case .moveToPoint:
                if index != 0 && lastPoint != firstPoint || lastPoint == nil {
                    currentPath.move(to: element.points[0])
                }
            case .addLineToPoint:
                currentPath.addLine(to: element.points[0])
            case .addQuadCurveToPoint:
                currentPath.addQuadCurve(to: element.points[1], control: element.points[0])
            case .addCurveToPoint:
                currentPath.addCurve(to: element.points[2], control1: element.points[0], control2: element.points[1])
            case .closeSubpath:
                currentPath.closeSubpath()
            @unknown default:
                fatalError()
            }
        }
        
        self.cgPath = currentPath
    }
    
    func firstPoint() -> CGPoint? {
        var firstPoint: CGPoint? = nil
        
        var index = -1
        self.cgPath.applyWithBlock { block in
            index += 1
            let element = block.pointee
            
            if index == 0 {
                if element.type == .moveToPoint || element.type == .addLineToPoint {
                    firstPoint = element.points[0]
                } else if element.type == .addQuadCurveToPoint {
                    firstPoint = element.points[1]
                } else if element.type == .addCurveToPoint {
                    firstPoint = element.points[2]
                }
            }
        }
        
        return firstPoint
    }
    
    func lastPoint() -> CGPoint? {
        var lastPoint: CGPoint? = nil
        
        var index = -1
        self.reversing().cgPath.applyWithBlock { block in
            index += 1
            let element = block.pointee
            
            if index == 0 {
                if element.type == .moveToPoint || element.type == .addLineToPoint {
                    lastPoint = element.points[0]
                } else if element.type == .addQuadCurveToPoint {
                    lastPoint = element.points[1]
                } else if element.type == .addCurveToPoint {
                    lastPoint = element.points[2]
                }
            }
        }
        
        return lastPoint
    }
}
于 2021-08-19T12:39:44.357 回答
0

好吧,如果它只是一个美学问题......只需将第二条贝塞尔曲线的第一点设置为第一条的最后一点......等等......

如果不是,我认为没有办法合并 2 条或更多贝塞尔路径,因为......嗯..它们是贝塞尔曲线,如果你这样做,它看起来就不正确

阅读有关贝塞尔曲线的更多信息 贝塞尔 曲线,看看为什么它不起作用

于 2012-03-30T13:36:35.973 回答