我如何获得 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
}
- 创建贝塞尔曲线路径
- 使用bezierPath.length获取封闭贝塞尔曲线路径的周长
(对于 swift 3)
因为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
}
- 创建贝塞尔曲线路径
- 使用bezierPath.length获取封闭贝塞尔曲线路径的周长 (对于 swift 3)