在iOS中确定闭合轮廓的算法

时间:2016-06-09 07:21:04

标签: ios objective-c algorithm uibezierpath cashapelayer

如何通过应用CAShapeLayer来确定使用UIBezierPath创建的形状是否是封闭轮廓?用哪种算法来确定相同的。

如下图2所示:一个表示它已经闭合轮廓,另一个表示没有。

封闭轮廓的图像: enter image description here

没有封闭轮廓的图像: enter image description here

用于绘制第一张图像的代码如下:

UIBezierPath *mainPath =[UIBezierPath bezierPath];

[mainPath addArcWithCenter:CGPointMake(120, 120) radius:50 startAngle:DEGREES_TO_RADIANS(0) endAngle:DEGREES_TO_RADIANS(90) clockwise:YES];
[mainPath addArcWithCenter:CGPointMake(120,120) radius:50 startAngle:DEGREES_TO_RADIANS(90) endAngle:DEGREES_TO_RADIANS(180) clockwise:YES];
[mainPath addLineToPoint:CGPointMake(170, 120)];

CAShapeLayer *sLayer = [CAShapeLayer layer];
sLayer.strokeColor = [UIColor blueColor].CGColor;
sLayer.path = mainPath.CGPath;
sLayer.fillColor = [UIColor clearColor].CGColor;
[[self.view layer] addSublayer:sLayer];

对于其他删除行:

[mainPath addLineToPoint:CGPointMake(170, 120)];

1 个答案:

答案 0 :(得分:0)

import Foundation
import UIKit

class DetectClosedCurve :UIView  {

    override init(frame: CGRect){
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func draw(_ rect: CGRect) {
        super.draw(rect)
        self.backgroundColor = UIColor.brown
        UIColor.white.setStroke()
        UIColor.red.setFill()
        let currentContext = UIGraphicsGetCurrentContext()
        currentContext?.saveGState()

        let closePath = drawClosedPath()
        closePath.lineWidth = 2
        closePath.fill()
        closePath.stroke()


        let openPath = drawOpenPath()
        openPath.lineWidth = 2
        openPath.fill()
        openPath.stroke()

        currentContext?.restoreGState()

         let status = openPath.isClosedCurve()
         print("  closePath status  == \(status)")

         let statusClose = closePath.isClosedCurve()
         print("  closePath status == \(statusClose)")

    }

    func drawClosedPath() -> UIBezierPath {

        let path = UIBezierPath()
        path.addArc(withCenter: CGPoint(x:120,y:120), radius: 50, startAngle: CGFloat(0.degreesToRadians), endAngle: CGFloat(90.degreesToRadians) , clockwise: true)
        path.addArc(withCenter: CGPoint(x:120,y:120), radius: 50, startAngle: CGFloat(90.degreesToRadians), endAngle: CGFloat(180.degreesToRadians), clockwise: true)
        path.addLine(to: CGPoint(x:170,y:120))
        //        mainPath addLineToPoint:CGPointMake(170, 120
        path.close()
        return path

    }


    func drawOpenPath() -> UIBezierPath {
        let path = UIBezierPath()
        path.addArc(withCenter: CGPoint(x:200,y:200), radius: 50, startAngle: CGFloat(0.degreesToRadians), endAngle: CGFloat(90.degreesToRadians) , clockwise: true)
        path.addArc(withCenter: CGPoint(x:200,y:200), radius: 50, startAngle: CGFloat(90.degreesToRadians), endAngle: CGFloat(180.degreesToRadians), clockwise: true)
        return path
    }


}

extension Int {
    var degreesToRadian: Double { return Double(self) * .pi / 180 }
    var radiansToDegree: Double { return Double(self) * 180 / .pi }
}

extension FloatingPoint {
    var degreesToRadian: Self { return self * .pi / 180 }
    var radiansToDegree: Self { return self * 180 / .pi }
}


extension CGPath {
    func forEachs( body: @convention(block) (CGPathElement) -> Void) {
        typealias Body = @convention(block) (CGPathElement) -> Void
        func callback(info: UnsafeMutableRawPointer?, element: UnsafePointer<CGPathElement>) {
            let body = unsafeBitCast(info, to: Body.self)
            body(element.pointee)
        }
        let unsafeBody = unsafeBitCast(body, to: UnsafeMutableRawPointer.self)
        apply(info: unsafeBody, function: callback)
    }
}
extension UIBezierPath {
    func isClosedCurve() -> Bool {
        var isClosedCurve: Bool = false

        cgPath.forEach { element in

            if(element.type == .closeSubpath){
                isClosedCurve = true

            }
        }
        return isClosedCurve
    }
}

enter image description here

enter image description here

Demo App to check closed Contour