我如何获得 uibezierPath 的面积和周长,因为 fill() 方法使用了封闭区域

How can i get the area and perimeter of the uibeizerPath as fill() method has used the enclosed area

因为UIBeizerPath支持fill()填充封闭区域。 我的要求是如何从 UIBeizerPath() 获取封闭区域,与 fill() 方法使用的相同。 如果我能在查找 beizerpath 的面积和周长方面得到帮助,我将不胜感激。

假设我想获取字母 'A' 中的封闭区域,我可以获得所有 beizerPath CGPoints 但无法定义子路径,因为 evenOdd 规则用于获取所需的场属性,最后得到面积。我很好奇fill()是如何得到封闭区域的

我得到了 beizerPath 中的字体 solution 并且想要获取由此绘制的任何字体的区域。

我怎样才能做到这一点。

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))
    }
}


extension UIBezierPath{
    var length: CGFloat{
        var pathLength:CGFloat = 0.0
        var current =  CGPoint.zero
        var first   =   CGPoint.zero

        self.cgPath.forEach{ element in
            pathLength += element.distance(to: current, startPoint: first)

            if element.type == .moveToPoint{
                first = element.point
            }
            if element.type != .closeSubpath{
                current = element.point
            }
        }
        return pathLength
    }
}


extension CGPathElement{

    var point: CGPoint{
        switch type {
        case .moveToPoint, .addLineToPoint:
            return self.points[0]
        case .addQuadCurveToPoint:
            return self.points[1]
        case .addCurveToPoint:
            return self.points[2]
        case .closeSubpath:
            return CGRect.null.origin
        }
    }

    func distance(to point: CGPoint, startPoint: CGPoint ) -> CGFloat{
        switch type {
        case .moveToPoint:
            return 0.0
        case .closeSubpath:
            return point.distance(to:startPoint)
        case .addLineToPoint:
            return point.distance(to:self.points[0])
        case .addCurveToPoint:
            return BezierCurveLength(p0: point, c1: self.points[0], c2: self.points[1], p1: self.points[2])
        case .addQuadCurveToPoint:
            return BezierCurveLength(p0: point, c1: self.points[0], p1: self.points[1])
        }
    }
}

extension CGPoint{
    func distance(to:CGPoint) -> CGFloat{
        let dx = pow(to.x - self.x,2)
        let dy = pow(to.y - self.y,2)
        return sqrt(dx+dy)
    }
}



// Helper Functions

func CubicBezierCurveFactors(t:CGFloat) -> (CGFloat,CGFloat,CGFloat,CGFloat){
    let t1 = pow(1.0-t, 3.0)
    let t2 = 3.0*pow(1.0-t,2.0)*t
    let t3 = 3.0*(1.0-t)*pow(t,2.0)
    let t4 = pow(t, 3.0)

    return  (t1,t2,t3,t4)
}


func QuadBezierCurveFactors(t:CGFloat) -> (CGFloat,CGFloat,CGFloat){
    let t1 = pow(1.0-t,2.0)
    let t2 = 2.0*(1-t)*t
    let t3 = pow(t, 2.0)

    return (t1,t2,t3)
}

// Quadratic Bezier Curve

func BezierCurve(t:CGFloat,p0:CGFloat,c1:CGFloat,p1:CGFloat) -> CGFloat{
    let factors = QuadBezierCurveFactors(t: t)
    return (factors.0*p0) + (factors.1*c1) + (factors.2*p1)
}


// Quadratic Bezier Curve

func BezierCurve(t:CGFloat,p0:CGPoint,c1:CGPoint,p1:CGPoint) -> CGPoint{
    let x = BezierCurve(t: t, p0: p0.x, c1: c1.x, p1: p1.x)
    let y = BezierCurve(t: t, p0: p0.y, c1: c1.y, p1: p1.y)
    return CGPoint(x: x, y: y)
}



// Cubic Bezier Curve

func BezierCurve(t:CGFloat,p0:CGFloat, c1:CGFloat, c2:CGFloat, p1:CGFloat) -> CGFloat{
    let factors = CubicBezierCurveFactors(t: t)
    return (factors.0*p0) + (factors.1*c1) + (factors.2*c2) + (factors.3*p1)
}


// Cubic Bezier Curve

func BezierCurve(t: CGFloat, p0:CGPoint, c1:CGPoint, c2: CGPoint, p1: CGPoint) -> CGPoint{
    let x = BezierCurve(t: t, p0: p0.x, c1: c1.x, c2: c2.x, p1: p1.x)
    let y = BezierCurve(t: t, p0: p0.y, c1: c1.y, c2: c2.y, p1: p1.y)
    return CGPoint(x: x, y: y)
}


// Cubic Bezier Curve Length

func BezierCurveLength(p0:CGPoint,c1:CGPoint, c2:CGPoint, p1:CGPoint) -> CGFloat{
    let steps = 12
    var current  = p0
    var previous = p0
    var length:CGFloat = 0.0

    for i in 1...steps{
        let t = CGFloat(i) / CGFloat(steps)
        current = BezierCurve(t: t, p0: p0, c1: c1, c2: c2, p1: p1)
        length += previous.distance(to: current)
        previous = current
    }

    return length
}


// Quadratic Bezier Curve Length

func BezierCurveLength(p0:CGPoint,c1:CGPoint, p1:CGPoint) -> CGFloat{
    let steps = 12

    var current  = p0
    var previous = p0
    var length:CGFloat = 0.0

    for i in 1...steps{
        let t = CGFloat(i) / CGFloat(steps)
        current = BezierCurve(t: t, p0: p0, c1: c1, p1: p1)
        length += previous.distance(to: current)
        previous = current
    }
    return length
}