创建两个贝塞尔路径的联合

22
我有两条贝塞尔路径,想要将它们合并成一个联合体,以便我可以描边整个外形。在我的情况下,这是一个带有尾巴的对话框,虽然它不是一个复杂的形状,但使用单个路径创建它实际上会相当困难。
目前似乎没有用于创建联合体的核心图形API。我错了吗?
如果我没有错,是否有人知道可以处理这个问题的库?我已经在GitHub中搜索了,但没有找到合适的。

1
如果有人在GitHub上提供了一个库,我就不会把这个作为答案发布,但是:不,没有内置的API可以实现这个。通常的解决方法是先描边再填充;填充(使用气泡的背景颜色)覆盖交叉的描边。确保将线宽加倍,因为这实际上是一条外描边,其线宽为原来的一半。 - Peter Hosey
嗨Peter。谢谢,暂时来说这是一个可行的解决方案,尽管它需要我传递上下文中的绘图。创建一个形状层会更好。 - tarmes
1
我刚刚发现了这个用于 NSBezierPath 的库。我想将其移植到 UIBezierPath 应该很容易:http://losingfight.com/blog/2011/07/09/how-to-implement-boolean-operations-on-bezier-paths-part-3/ - tarmes
@tarmes,结果现在已经可以使用了,太好了!请参见下面的robmayoff答案,还有https://mastodon.social/@mayoff/109750596404269990。 - Fattie
4个回答

5

如果你正在处理闭合形状,UIBezierPath可以做到这一点。

UIBezierPath *firstPath = [UIBezierPath bezierPath];
// build your path

UIBezierPath *secondPath = [UIBezierPath bezierPath];
// build your path

[firstPath appendPath:secondPath];

3
在执行合并操作之前,尝试反转第一个或第二个路径:UIBezierPath *secondPath = [[UIBezierPath bezierPath] bezierPathByReversingPath]; - cescofry
不行。我尝试了每一种组合(第一个加第二个,第一个加翻转后的第二个,翻转后的第一个加第二个,第二个加第一个,...)。 - tarmes
2
你确定你正在创建两个顺时针方向的路径吗? - cescofry
7
是的,这不是一个"联合"操作,而是一个"组合"操作,这意味着现有路径的任何部分都不会被删除。如果你描边路径,你会发现它们仍然存在。真正的"联合"操作将取得组合路径的轮廓,丢弃任何此时在内部的路径。这就是我自己要找的东西。 - Mark A. Donohoe
1
这绝对不是回答问题的方法。 - Fattie
显示剩余2条评论

3
如果您的部署目标是 iOS 16(或 macOS 13)或更高版本,则可以使用"union"方法计算两个CGPath对象的并集,如下所示:

union

let path1: CGPath = ...
let path2: CGPath = ...
let combo = path1.union(path2)

-2

SwiftUI

func createView() -> some View {
    let a = Path { path in
        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x: 50, y: 100))
        path.addLine(to: CGPoint(x: 100, y: 0))
    }
    .stroke(Color.white, style: StrokeStyle(lineWidth: 5, lineCap: .round, lineJoin: .round))

    let b = RoundedRectangle(cornerRadius: 5, style: .continuous)
        .fill(Color.white)
        .frame(width: 30, height: 30)
        .position(CGPoint.zero)

    return ZStack {
        a
        b
    }
    .compositingGroup()
    .colorMultiply(Color.red)
}

1
不要回答问题之外的内容。问题是在问如何获取联合路径,而不是绘制形状。 - Honghao Z

-2
在Swift 3中,可以通过以下方式统一贝塞尔路径:
 override func draw(_ rect: CGRect) {
    super.draw(rect)

    UIColor.black.setStroke()
    UIColor.red.setFill()

    let currentContext = UIGraphicsGetCurrentContext()
    currentContext?.saveGState() 

    let path = drawTopView()
    path.lineWidth = 5.0
    path.fill()
    path.stroke()

    let middlepath = drawMiddleView()
    middlepath.lineWidth = 2.0
    middlepath.fill()
    middlepath.stroke()

    path.append(middlepath)
    currentContext?.restoreGState()
}

这是绘图。没有得到联合贝塞尔路径。 - Honghao Z

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接