Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIBezierPath appending overlapping isn't filled

I'm trying to merge two overlapping UIBezierPaths using UIBezierPath.append, and I want the overlapping space to be filled. I tried setting the usesEvenOddFillRule property to false, but it still doesn't fill. Here is minimal example of the problem:

override func draw(_ rect: CGRect) {
    let firstShape = UIBezierPath()

    firstShape.move(to: CGPoint(x: 100, y: 100))
    firstShape.addLine(to: CGPoint(x: 100, y: 150))
    firstShape.addLine(to: CGPoint(x: 150, y: 170))
    firstShape.close()

    let secondShape = UIBezierPath(rect: CGRect(x: 125, y: 125, width: 75, height: 75))

    let combined = UIBezierPath()
    combined.append(firstShape)
    combined.append(secondShape)

    UIColor.black.setFill()
    combined.fill()
}

This yields the following shape:

Shape

What I would like it to look like:

Wanted shape

This problem also seems to occur when using move(to: CGPoint) on one UIBezierPath. If you would draw both these shapes on the same UIBezierPath, the same problem would occur.

Does anyone know how to make the overlapping region filled? Preferably the solution would also work when doing addClip()

like image 410
Loovjo Avatar asked Apr 02 '17 13:04

Loovjo


1 Answers

You were on the right track with setting the usesEvenOddFillRule to false. In addition to that, you need to make sure your shapes are both drawn in the same direction (clockwise or counter-clockwise).

I reversed the order of your addLines when drawing the triangle to reverse it.

override func draw(_ rect: CGRect) {
    let firstShape = UIBezierPath()

    firstShape.move(to: CGPoint(x: 100, y: 100))
    firstShape.addLine(to: CGPoint(x: 150, y: 170))
    firstShape.addLine(to: CGPoint(x: 100, y: 150))
    firstShape.close()

    let secondShape = UIBezierPath(rect: CGRect(x: 125, y: 125, width: 75, height: 75))

    let combined = UIBezierPath()
    combined.append(firstShape)
    combined.append(secondShape)
    combined.usesEvenOddFillRule = false

    UIColor.black.setFill()
    combined.fill()
}
like image 164
vacawama Avatar answered Oct 31 '22 13:10

vacawama