How can I get an array with all the CGPoint
(s) contained in a given CGPath
(CGMutablePathRef
)?
Using Swift 2.x (for Swift 3.x, Swift 4.x and Swift 5.x read here below..) , i've found this fantastic article about C Callbacks in Swift.
Trying to obtain "all the CGPoint
(s)", as explained by Lily Ballard, can be a bad idea as she said.
So, I think maybe the best way is to get the path elements points used to create a particular CGPath
:
//MARK: - CGPath extensions extension CGPath { func forEach(@noescape body: @convention(block) (CGPathElement) -> Void) { typealias Body = @convention(block) (CGPathElement) -> Void func callback(info: UnsafeMutablePointer<Void>, element: UnsafePointer<CGPathElement>) { let body = unsafeBitCast(info, Body.self) body(element.memory) } print(sizeofValue(body)) let unsafeBody = unsafeBitCast(body, UnsafeMutablePointer<Void>.self) CGPathApply(self, unsafeBody, callback) } func getPathElementsPoints() -> [CGPoint] { var arrayPoints : [CGPoint]! = [CGPoint]() self.forEach { element in switch (element.type) { case CGPathElementType.MoveToPoint: arrayPoints.append(element.points[0]) case .AddLineToPoint: arrayPoints.append(element.points[0]) case .AddQuadCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) case .AddCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) arrayPoints.append(element.points[2]) default: break } } return arrayPoints } }
With this extension you can do for example:
var bezier = UIBezierPath(ovalInRect: CGRectMake(0, 0, 400, 300)) let myOval = bezier.CGPath let junctionPoints = myOval.getPathElementsPoints() print("junction points are: \(junctionPoints)")
(there are some corrections due to syntax re-introduction of @convention(c)
):
extension CGPath { 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)) } func getPathElementsPoints() -> [CGPoint] { var arrayPoints : [CGPoint]! = [CGPoint]() self.forEach { element in switch (element.type) { case CGPathElementType.moveToPoint: arrayPoints.append(element.points[0]) case .addLineToPoint: arrayPoints.append(element.points[0]) case .addQuadCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) case .addCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) arrayPoints.append(element.points[2]) default: break } } return arrayPoints } func getPathElementsPointsAndTypes() -> ([CGPoint],[CGPathElementType]) { var arrayPoints : [CGPoint]! = [CGPoint]() var arrayTypes : [CGPathElementType]! = [CGPathElementType]() self.forEach { element in switch (element.type) { case CGPathElementType.moveToPoint: arrayPoints.append(element.points[0]) arrayTypes.append(element.type) case .addLineToPoint: arrayPoints.append(element.points[0]) arrayTypes.append(element.type) case .addQuadCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) arrayTypes.append(element.type) arrayTypes.append(element.type) case .addCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) arrayPoints.append(element.points[2]) arrayTypes.append(element.type) arrayTypes.append(element.type) arrayTypes.append(element.type) default: break } } return (arrayPoints,arrayTypes) } }
extension CGPath { func forEach( body: @escaping @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)) } func getPathElementsPoints() -> [CGPoint] { var arrayPoints : [CGPoint]! = [CGPoint]() self.forEach { element in switch (element.type) { case CGPathElementType.moveToPoint: arrayPoints.append(element.points[0]) case .addLineToPoint: arrayPoints.append(element.points[0]) case .addQuadCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) case .addCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) arrayPoints.append(element.points[2]) default: break } } return arrayPoints } func getPathElementsPointsAndTypes() -> ([CGPoint],[CGPathElementType]) { var arrayPoints : [CGPoint]! = [CGPoint]() var arrayTypes : [CGPathElementType]! = [CGPathElementType]() self.forEach { element in switch (element.type) { case CGPathElementType.moveToPoint: arrayPoints.append(element.points[0]) arrayTypes.append(element.type) case .addLineToPoint: arrayPoints.append(element.points[0]) arrayTypes.append(element.type) case .addQuadCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) arrayTypes.append(element.type) arrayTypes.append(element.type) case .addCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) arrayPoints.append(element.points[2]) arrayTypes.append(element.type) arrayTypes.append(element.type) arrayTypes.append(element.type) default: break } } return (arrayPoints,arrayTypes) } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With