Search code examples
iosswift2uibezierpath

Start point in ovalInRect


is there a way to change the starting point from ovalInRect form "right" to "left"? it seems that no matter how I create it the "starting" point is always on the "right side...

 let ovalPath = UIBezierPath(ovalInRect: CGRect(x: 515, y: 276.5, width: 280.5, height: 214.5))
        let ovalShapeLayer = CAShapeLayer()
        ovalShapeLayer.fillColor = UIColor.clearColor().CGColor
        ovalShapeLayer.strokeColor = UIColor.lightGrayColor().CGColor
        ovalShapeLayer.lineWidth = 1.5
        ovalShapeLayer.path = ovalPath.CGPath

        self.view.layer.insertSublayer(ovalShapeLayer, atIndex: 1)

thanks


Solution

  • Start with a circle of diameter 1 centered at the origin, with the starting angle you want. Then transform that circle into an oval that inscribes your rect.

    extension UIBezierPath {
    
        convenience init(ovalInRect rect: CGRect, startAngle: CGFloat, clockwise: Bool) {
            self.init()
            // Create a circle at the origin with diameter 1.
            addArcWithCenter(.zero, radius: 0.5, startAngle: startAngle, endAngle: startAngle + 2 * CGFloat(M_PI), clockwise: clockwise)
            closePath()
    
            // Construct a transform that moves the circle to inscribe `rect`.
            var transform = CGAffineTransformIdentity
            // This part moves the center of the circle to the center of `rect`.
            transform = CGAffineTransformTranslate(transform, rect.midX, rect.midY)
            // This part scales the circle to an oval with the same width and height as `rect`.
            transform = CGAffineTransformScale(transform, rect.width, rect.height)
    
            applyTransform(transform)
        }
    
    }
    

    Example use:

    let oval = UIBezierPath(ovalInRect: CGRectMake(50, 20, 100, 200), startAngle: CGFloat(-M_PI), clockwise: true)
    Swift.print(oval.bounds)
    

    Output:

    (50.0, 20.0, 100.0, 200.0)