Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the intersection of two CGPath?

I am using CAShapeLayer.path and CALayer.mask to set up image mask, i can achieve "difference set" and "union" effect for CGPath by setting

maskLayer.fillRule = kCAFillRuleEvenOdd/kCAFillRuleZero

However, how can i get the intersection of two paths? I cannot achieve it with even-odd rule

Here is an example: enter image description here

let view = UIImageView(frame: CGRectMake(0, 0, 400, 400))
view.image = UIImage(named: "scene.jpg")
let maskLayer = CAShapeLayer()
let maskPath = CGPathCreateMutable()    
CGPathAddEllipseInRect(maskPath, nil, CGRectOffset(CGRectInset(view.bounds, 50, 50), 50, 0))
CGPathAddEllipseInRect(maskPath, nil, CGRectOffset(CGRectInset(view.bounds, 50, 50), -50, 0))
maskLayer.path = maskPath
maskLayer.fillRule = kCAFillRuleEvenOdd
maskLayer.path = maskPath
view.layer.mask = maskLayer

how can i get the middle intersection area to be shown?

like image 485
duan Avatar asked Apr 22 '15 14:04

duan


Video Answer


1 Answers

extension UIImage {

    func doubleCircleMask(diameter: CGFloat)-> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        defer { UIGraphicsEndImageContext() }
        let x = size.width/2 - diameter/2
        let y = size.height/2 - diameter/2
        let offset = diameter/4
        let bezierPath: UIBezierPath = .init(ovalIn: .init(origin: .init(x: x-offset, y: y), size: .init(width: diameter, height: diameter)))
        bezierPath.append(.init(ovalIn: .init(origin: .init(x: x+offset, y: y), size: .init(width: diameter, height: diameter))))
        bezierPath.addClip()
        draw(in: .init(origin: .zero, size: size))
        return UIGraphicsGetImageFromCurrentImageContext()
    }

    func doubleCircleIntersectionMask(diameter: CGFloat)-> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        defer { UIGraphicsEndImageContext() }
        let x = size.width/2 - diameter/2
        let y = size.height/2 - diameter/2
        let offset = diameter/4
        UIBezierPath(ovalIn: .init(origin: .init(x: x-offset, y: y), size: .init(width: diameter, height: diameter))).addClip()
        UIBezierPath(ovalIn: .init(origin: .init(x: x+offset, y: y), size: .init(width: diameter, height: diameter))).addClip()
        draw(in: .init(origin: .zero, size: size))
        return UIGraphicsGetImageFromCurrentImageContext()
    }

}

Testing

let image = UIImage(data: try! Data(contentsOf: URL(string: "http://i.stack.imgur.com/Xs4RX.jpg")!))!
let imageUnion = image.doubleCircleMask(diameter: 300)
let imageIntersection = image.doubleCircleIntersectionMask(diameter: 300)

enter image description here

like image 182
Leo Dabus Avatar answered Sep 28 '22 03:09

Leo Dabus