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

问题描述:

由于UIBeizerPath支持fill()来填充封闭区域。 我的要求是如何从UIBeizerPath()获得封闭区域,与fill()方法相同。 如果我能找到帮助找到beizerpath的区域和边界,我将非常感激。如何获取uibeizerPath的面积和周长,因为fill()方法使用了封闭区域

假设我想用字母'A'得到封闭区域,我可以得到所有的beizerPathCGPoints,但是不能将evenPath定义为evenOdd规则来获得所需的字段属性并最终得到区域。我很好奇知道如何fill()能够得到封闭的区域。

对于solution中的字体,我得到了beizerPath,并且想要从此处获取任何字体的区域。

我怎么能做到这一点。

+0

@matt可填写区域。因为我们知道'fill()'方法用我们指定填充的颜色填充区域。 P使用的蓝色区域请参阅[链接](https://i.stack.imgur.com/9Cyqw.png) – rjndra

+0

实际上,我正在从字体绘制一个beizer,所以我有不规则的ploygon和任何cgpoints用于使字体的beiser。 可以看到我在做什么[像](http://*.com/questions/11172207/get-path-to-trace-out-a-character-in-an-ios-uifont)和获取区域那些与手势绘制的字符比较 – rjndra

+0

这将是很好的任何人都会提供暗示'UIbeizer'如何实现这个数学部分,无论绘制的形状如何。参考任何编程语言将被接受为答案。 – rjndra

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 
} 
+0

这实际上为我获得周长。请有关于区域的任何解决方案。谢谢@Samip – rjndra

+1

对于我自己的解决方案,我可以在路径边界内的'beizerPath'中获得所有'cgpoints'。 Area实际上是边界中包含的cgpoints的单位数。 – rjndra