【问题标题】:Merge connected UIBezierPaths合并连接的 UIBezierPaths
【发布时间】:2012-03-30 12:09:56
【问题描述】:

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

【问题讨论】:

    标签: objective-c ios core-graphics uibezierpath


    【解决方案1】:

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

    如果你有path1path2path3 逻辑上形成一个封闭的形状。按相同顺序调用它们

    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
        }
    }
    

    【讨论】:

    • Vau,非常感谢您的扩展! :)
    • @sabiland 欢迎您。我很高兴它帮助了你
    • 你的解决方案可靠吗,还是我应该在各种情况下检查它?我做了很多 UIBezierPath 操作(随机生成等)。
    • 我还没有对这种方法进行任何详尽的测试。我仅将其用于我的应用程序中的特定形状。因此,请对其进行测试,如果您发现任何问题,请告诉我。
    • 好的。我会做几千次随机检查。但就目前而言,当我测试它时,它运行良好(没问题)。
    【解决方案2】:

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

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

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

    【讨论】:

    • 问题是第2条曲线的第一个点可能没有和第1条的最后一个点相连,所以不能体现出抽屉的意图
    • 那么问题的重点是什么?我的意思是……如果它没有连接,则有 2 条不同的贝塞尔曲线……如果是……使用我的解决方案……就这么简单。没有其他方法可以使用贝塞尔曲线做你想做的事..我可能错了
    • 你说得对,我在想它可能有一些子路径的成员数组,但事实并非如此。愚蠢的问题。
    • 不是一个愚蠢的问题。不合并不仅仅是一个美学问题。如果路径是连接的,或者它们只是路径的组合,某些行为(例如剪切和填充)会有所不同。请注意,Apple 的文档指出,没有尝试排列这些点,但可能会有类似的行为。我目前正在做一个项目,如果我可以出于剪裁原因合并线条,那将是最简单的,因为我正在对每个片段进行不同的转换。它们保证将端点与端点对齐。
    • 我最近刚刚进入图像处理领域,UIBezierPath 有“appendPath:”方法,它正是这样做的。这个问题也是一年前的:)
    猜你喜欢
    • 1970-01-01
    • 2018-05-23
    • 2019-03-02
    • 2014-05-14
    • 1970-01-01
    • 2017-11-17
    • 2018-03-05
    • 2010-09-10
    • 2012-09-16
    相关资源
    最近更新 更多