Ios 绘制平滑曲线
我有两个点左和右,通过向Y添加一些静态值,X是左右两侧的平均值,我创建了第三个点中心 之后,我用贝塞尔路径在它们之间画出曲线,一切都很好 在上述曲线中 现在我想再创建两个点(5点曲线) 一个在中间和左侧之间,一个在中间和右侧之间 我再次尝试取平均值,并使用Ios 绘制平滑曲线,ios,swift3,uibezierpath,Ios,Swift3,Uibezierpath,我有两个点左和右,通过向Y添加一些静态值,X是左右两侧的平均值,我创建了第三个点中心 之后,我用贝塞尔路径在它们之间画出曲线,一切都很好 在上述曲线中 现在我想再创建两个点(5点曲线) 一个在中间和左侧之间,一个在中间和右侧之间 我再次尝试取平均值,并使用 func drawFivePoint(_ startPoint: CGPoint?, leftCenterPoint: CGPoint?, toControlPoint controlPoint: CGPoint?, toRightCo
func drawFivePoint(_ startPoint: CGPoint?, leftCenterPoint: CGPoint?, toControlPoint controlPoint: CGPoint?, toRightControlPoint rightPoint: CGPoint?, toEnd endPoint: CGPoint?) {
var arrPoints = [NSValue]()
if startPoint != nil {
arrPoints.append(NSValue(cgPoint: startPoint!))
}
if leftCenterPoint != nil && !(__CGPointEqualToPoint(leftCenterPoint!, .zero)) {
arrPoints.append(NSValue(cgPoint: leftCenterPoint!))
}
if controlPoint != nil {
arrPoints.append(NSValue(cgPoint: controlPoint!))
}
if rightPoint != nil && !(__CGPointEqualToPoint(rightPoint!, .zero)) {
arrPoints.append(NSValue(cgPoint: rightPoint!))
}
if endPoint != nil {
arrPoints.append(NSValue(cgPoint: endPoint!))
}
guard let bezierPath = UIBezierPath.interpolateCGPoints(withHermite: arrPoints, closed: false) else {
print("path is nil")
return
}
curveSize = bezierPath.bounds
let strokeColor = UIColor.white
if curveLayer != nil {
curveLayer?.removeFromSuperlayer()
curveLayer = nil
}
curveLayer = CAShapeLayer()
curveLayer?.lineWidth = 1.0 / self.zoomScale
curveLayer?.fillColor = UIColor.clear.cgColor
curveLayer?.path = bezierPath.cgPath
curveLayer?.strokeColor = strokeColor.cgColor
viewBase.layer.addSublayer(curveLayer!)
}
错误结果
问题:如何计算点,使形状不受影响,我在曲线上得到5个点很难说,你想实现什么,但如果你的目标是找到在第一步中定义的贝塞尔曲线的一部分,请先看看贝塞尔曲线是如何定义的。通常,只有Bezier曲线的第一个和最后一个控制点也是曲线的一部分 要查找特定t(0..1)的贝塞尔曲线上的点p(t),可以使用 在你的操场上试试这个简单的片段。我选择控制点,使x线性依赖于贝塞尔t参数。y的形状与Bezier曲线的形状相同,很容易将其视为运动场中的值图形
//: Playground - noun: a place where people can play
// point
struct Point {
var x: Double
var y: Double
}
// linear bezier
func linearBezier(p1: Point, p2: Point, t: Double)->Point {
let px = p1.x + t*(p2.x - p1.x)
let py = p1.y + t*(p2.y - p1.y)
return Point(x: px, y: py)
}
// quadratic bezier
func quadraticBezier(p1: Point, p2: Point, p3: Point, t: Double)->Point {
let p12 = linearBezier(p1: p1, p2: p2, t: t)
let p23 = linearBezier(p1: p2, p2: p3, t: t)
return linearBezier(p1: p12, p2: p23, t: t)
}
// cubic bezier
func cubicBezier(p1: Point, p2: Point, p3: Point, p4: Point, t: Double)->Point {
let p12 = linearBezier(p1: p1, p2: p2, t: t)
let p23 = linearBezier(p1: p2, p2: p3, t: t)
let p34 = linearBezier(p1: p3, p2: p4, t: t)
return quadraticBezier(p1: p12, p2: p23, p3: p34, t: t)
}
let p1 = Point(x: 0.0, y: 0.0)
let p2 = Point(x: 15.0, y: 10.0)
let p3 = Point(x: 30.0, y: 5.0)
for t in stride(from: 0.0, through: 1.0, by: 0.025) {
let p = quadraticBezier(p1: p1, p2: p2, p3: p3, t: t)
print(p.x, p.y)
p.x
p.y // see the values as a graph
}
let p4 = Point(x: 45.0, y: 10.0)
for t in stride(from: 0.0, through: 1.0, by: 0.025) {
let p = cubicBezier(p1: p1, p2: p2, p3: p3, p4: p4, t: t)
print(p.x, p.y)
p.x
p.y // see the values as a graph
}
我们还可以做得更一般一些
func bezier(controlPoints: [Point], t: Double)->[Point] {
if controlPoints.count == 1 { return controlPoints }
var reducedPoints: [Point] = []
for i in 0..<(controlPoints.count - 1) {
let p = linearBezier(p1: controlPoints[i], p2: controlPoints[i+1], t: t)
reducedPoints.append(p)
}
return bezier(controlPoints: reducedPoints, t: t)
}
let points = [p1,p2,p3,p4]
for t in stride(from: 0.0, through: 1.0, by: 0.0125) {
let p = bezier(controlPoints: points, t: t)
p.count // it is alway 1 :-)
p[0].x
p[0].y
}
func-bezier(控制点:[点],t:Double)->[点]{
如果controlPoints.count==1{返回controlPoints}
var reducedPoints:[点]=[]
对于0中的i.很难说,您试图实现什么,但是如果您的目标是找到属于您在第一步中定义的贝塞尔曲线的一部分的点,请先查看贝塞尔曲线是如何定义的。通常,贝塞尔曲线的第一个和最后一个控制点也是曲线的一部分
要查找特定t(0..1)的贝塞尔曲线上的点p(t),可以使用
在你的操场上试试这个简单的片段。我选择了控制点,这样x就线性地依赖于Bezier t参数。y的形状与Bezier曲线的形状相同,并且很容易在操场中将其视为值的图形
//: Playground - noun: a place where people can play
// point
struct Point {
var x: Double
var y: Double
}
// linear bezier
func linearBezier(p1: Point, p2: Point, t: Double)->Point {
let px = p1.x + t*(p2.x - p1.x)
let py = p1.y + t*(p2.y - p1.y)
return Point(x: px, y: py)
}
// quadratic bezier
func quadraticBezier(p1: Point, p2: Point, p3: Point, t: Double)->Point {
let p12 = linearBezier(p1: p1, p2: p2, t: t)
let p23 = linearBezier(p1: p2, p2: p3, t: t)
return linearBezier(p1: p12, p2: p23, t: t)
}
// cubic bezier
func cubicBezier(p1: Point, p2: Point, p3: Point, p4: Point, t: Double)->Point {
let p12 = linearBezier(p1: p1, p2: p2, t: t)
let p23 = linearBezier(p1: p2, p2: p3, t: t)
let p34 = linearBezier(p1: p3, p2: p4, t: t)
return quadraticBezier(p1: p12, p2: p23, p3: p34, t: t)
}
let p1 = Point(x: 0.0, y: 0.0)
let p2 = Point(x: 15.0, y: 10.0)
let p3 = Point(x: 30.0, y: 5.0)
for t in stride(from: 0.0, through: 1.0, by: 0.025) {
let p = quadraticBezier(p1: p1, p2: p2, p3: p3, t: t)
print(p.x, p.y)
p.x
p.y // see the values as a graph
}
let p4 = Point(x: 45.0, y: 10.0)
for t in stride(from: 0.0, through: 1.0, by: 0.025) {
let p = cubicBezier(p1: p1, p2: p2, p3: p3, p4: p4, t: t)
print(p.x, p.y)
p.x
p.y // see the values as a graph
}
我们还可以做得更一般一些
func bezier(controlPoints: [Point], t: Double)->[Point] {
if controlPoints.count == 1 { return controlPoints }
var reducedPoints: [Point] = []
for i in 0..<(controlPoints.count - 1) {
let p = linearBezier(p1: controlPoints[i], p2: controlPoints[i+1], t: t)
reducedPoints.append(p)
}
return bezier(controlPoints: reducedPoints, t: t)
}
let points = [p1,p2,p3,p4]
for t in stride(from: 0.0, through: 1.0, by: 0.0125) {
let p = bezier(controlPoints: points, t: t)
p.count // it is alway 1 :-)
p[0].x
p[0].y
}
func-bezier(控制点:[点],t:Double)->[点]{
如果controlPoints.count==1{返回controlPoints}
var reducedPoints:[点]=[]
对于0中的i..@MikeAlter,我可以,但我不确定您不喜欢做什么。是否要找到一个点,该点是Bezier曲线的一部分,其位置介于中点和第一个(控制点)以及中点和最后一个(控制点)之间?从你的问题中,我了解到,你已经将贝塞尔曲线定义为二次贝塞尔曲线,对吗?是的,我有两个左右点,从这两个点我创建了中点。但是现在我需要再添加两个点,而不会影响曲线。因此,在我绘制5点曲线时找到这些点后,它应该与3点一样平滑。现在你明白我的意思了吗?好的,谢谢,我会检查一下,让你知道正在工作或not@MikeAlter我可以,但我不知道你会怎么做。你想找一个点,它是贝塞尔曲线的一部分,位置在中点和第一个(控制点)之间,中点和最后一个(控制点)之间吗?从你的问题中,我了解到,你已经将贝塞尔曲线定义为二次贝塞尔曲线,对吗?是的,我有两个左右点,从这两个点我创建了中点。但是现在我需要再添加两个点,而不会影响曲线。因此,在我绘制5点曲线时找到这些点后,它应该与3点一样平滑。现在你明白我的意思了吗?好的,谢谢,我会检查一下,让你知道它是否有效