3

How to check UIBezierPath is closed path or not (closed path is like closed contour means it creates any shape like triangle, square, polygon etc), and if it is closed then only fill in the path?

The following represents the area where it should fill in the shape; last 2 shape defining closed contour and simple closed contour which in only color can be filled:

enter image description here

Image Source

The following is my code for the same, There are 4 Squares in it but fills in only 3 squares; also want to know is it possible to find the area of filled area in square feet as I get 4 squares here how to check the total area it covered in 4 squares?

UIBezierPath *mainPath =[UIBezierPath bezierPath];
[mainPath moveToPoint:CGPointMake(50, 100)];
[mainPath addLineToPoint:CGPointMake(0, 100)];
[mainPath addLineToPoint:CGPointMake(0, 150)];
[mainPath addLineToPoint:CGPointMake(50, 150)];
[mainPath addLineToPoint:CGPointMake(50, 200)];
[mainPath addLineToPoint:CGPointMake(100, 200)];
[mainPath addLineToPoint:CGPointMake(100, 150)];
[mainPath addLineToPoint:CGPointMake(50, 150)];
[mainPath addLineToPoint:CGPointMake(50, 100)];
[mainPath addLineToPoint:CGPointMake(100, 100)];
[mainPath addLineToPoint:CGPointMake(150, 100)];
[mainPath addLineToPoint:CGPointMake(150, 150)];
[mainPath addLineToPoint:CGPointMake(100, 150)];
[mainPath addLineToPoint:CGPointMake(100, 100)];
CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
shapeLayer.lineWidth = 5.0;
shapeLayer.strokeColor = [UIColor blueColor].CGColor;
shapeLayer.path =mainPath.CGPath;
shapeLayer.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.5].CGColor;
[[self.view layer] addSublayer:shapeLayer];
Bhargav Soni
  • 1,067
  • 1
  • 9
  • 22

2 Answers2

0

Why don't you use the mainPath.closePath it will automatically close the path for you and fill. If you want to have more informations about closing path automatically or manually you can have a look here, it said that :

The difference is that the [closePath] method actually adds an additional path element to the underlying CGPath that backs the UIBezierPath.

If you use [closePath], then an additional CGPathElement with a type of kCGPathElementCloseSubpath will be appended to the end of the path immediately after that last line segment.

For the area covered, you can get the bounding box of your UIBezierPath but I think that it could be more simple for you to have different UIBezierPath (one for each of your square) and then compute the bounding box for each square. If you want to have the bounding box of your path :

let bounds = CGPathGetBoundingBox(yourPath.CGPath)
Community
  • 1
  • 1
Chajmz
  • 729
  • 5
  • 11
  • 2
    Well, all the lines being added dynamically, and I don't want to closePath; I just want to check it is closed or not that's it. and taking about the area then shape could be any like triangle or so, so the area could be counted for all different shapes in square feet. – Bhargav Soni Jun 07 '16 at 06:36
0

I have answered a similar question about CGPath here. Since you can get the CGPath for a UIBezierPath, I think it applies here as well. This is for Swift 3.x. I have borrowed heavily from this answer, adding the isClosed() function.

func isClosed() -> Bool {
    var isClosed = false
    forEach { element in
        if element.type == .closeSubpath { isClosed = true }
    }
    return isClosed
}

func forEach( body: @convention(block) (CGPathElement) -> Void) {
    typealias Body = @convention(block) (CGPathElement) -> Void
    let callback: @convention(c) (UnsafeMutableRawPointer, UnsafePointer<CGPathElement>) -> Void = { (info, element) in
        let body = unsafeBitCast(info, to: Body.self)
        body(element.pointee)
    }
    print(MemoryLayout.size(ofValue: body))
    let unsafeBody = unsafeBitCast(body, to: UnsafeMutableRawPointer.self)
    self.apply(info: unsafeBody, function: unsafeBitCast(callback, to: CGPathApplierFunction.self))
}
}

Here is how you use it:

myBezierPath.cgPath.isClosed()
mogelbuster
  • 1,066
  • 9
  • 19