作者热门文章
- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
因为 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
}
关于ios - 我如何获得 uibezierPath 的面积和周长,因为 fill() 方法使用了封闭区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40762704/
好吧,这不起作用!有什么问题呢。有人可以向我指出吗?我已经盯着它看了好几个小时了。我之前寻求过帮助,他提出了结构,但我并没有真正理解它,所以它不起作用。 没有得到正确的计算。我认为读取文件时可能出现问
我需要显示一个圆周。为了做到这一点,我认为我可以为很多 x 计算 y 的两个值,所以我做了: import sympy as sy from sympy.abc import x,y f = x**2
3个不同的类 1个用于处理Circle实例,1个用于Square实例,第3个用于比较之间他们(main) 。在 main 函数中,我找到了 circle (在 c1..c4 之间)和 square (
我是一名优秀的程序员,十分优秀!