2016-06-09 3 views
3

Как определить форму, созданную с использованием CAShapeLayer путем применения UIBezierPath, является замкнутым контуром или нет? Какой алгоритм используется для определения того же.Алгоритм определения замкнутого контура в iOS

Как показано 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)]; 

ответ

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

+0

Что делать, если форма состоит из нескольких подпутей? – Codo

+0

он будет работать на нескольких подпутьях. – Shrawan

+0

Если путь имеет несколько подпутов и не все из них закрыты, ваш код возвращает * true *. Это правильный ответ? Я сомневаюсь. Хороший код в противном случае. – Codo