SKShapeNode puzzle

I'm trying to define and fill segments of an intersecting circles diagram using SKShapeNode with Bezier paths. It works fine when I combine two circle arc paths to make a shape, as in this case:


The arcs I used to create the path are marked in red. But when I try to do the same thing using three arcs, the fill doesn't work properly:


Here's what I use to get the individual arcs:


func circleArcPath(circle: VennCircle, start: CGFloat, end: CGFloat) -> UIBezierPath {
  let arcUnit = CGFloat(M_PI / 3.0)
  let path = UIBezierPath()
  path.addArcWithCenter(circle.center, radius: circle.radius, startAngle: start * arcUnit, endAngle: end * arcUnit, clockwise: true)
  return path
}


(The VennCircles are the white circles in the image.) And here's what I do to construct the SKShapeNode:


let path = circleArcPath(middleCircle, start: 2, end: 3)
path.appendPath(circleArcPath(leftCircle, start: 4, end: 5))
path.appendPath(circleArcPath(rightCircle, start: 3, end: 4))
let filledSection = SKShapeNode.init(path: path.CGPath)


As I said, this works fine with two arcs, but not with three. Can anyone see what might be going wrong here?


dkj

I tried to post some links to images, but they don't appear in the message. Here they are again:

http://picpaste.com/2paths-dbx43hha.png

http://picpaste.com/3paths-57PDcEI4.png

Accepted Answer

It doesn't work in either case, but you can't see that it's wrong in the 2-path case.


At the very least, the path you create isn't closed, so it won't fill the way you want. Also, the documentation is not absolutely clear about whether (or how) the subpaths will connect when you use 'appendPath'. You'd be better off using the 'addArc…' calls directly, rather than trying to sub-package sub-paths, though if you're lucky just closing the main path might work.

Your suggestion worked perfectly. Here's the code I used:


let path = UIBezierPath()
path.addArcWithCenter(middleCircle.center, radius: middleCircle.radius, startAngle: 2*arcUnit, endAngle: 3*arcUnit, clockwise: true)
path.addArcWithCenter(leftCircle.center, radius: leftCircle.radius, startAngle: 4*arcUnit, endAngle: 5*arcUnit, clockwise: true)
path.addArcWithCenter(rightCircle.center, radius: rightCircle.radius, startAngle: 3*arcUnit, endAngle: 4*arcUnit, clockwise: true)
path.closePath()
let filledSection = SKShapeNode.init(path: path.CGPath)


It gave me just what I wanted. Many thanks.


dkj

To simplify the code, I used this:

extension UIBezierPath {
  var arcUnit: CGFloat { return CGFloat(M_PI/3.0) }
  func addVennArc(circle: VennCircle, start: CGFloat, end: CGFloat) {
    self.addArcWithCenter(circle.center, radius: circle.radius, startAngle: start*arcUnit, endAngle: end*arcUnit, clockwise: true)
  }
}

Now I can write:

let path = UIBezierPath()
path.addVennArc(middleCircle, start: 2, end: 3)
path.addVennArc(leftCircle, start: 4, end: 5)
path.addVennArc(rightCircle, start: 3, end: 4)
path.closePath()
let filledSection = SKShapeNode.init(path: path.CGPath)
SKShapeNode puzzle
 
 
Q