绘制平滑的曲线

我有两个点左右增加一些静态值的Y和X是左右两边的AVG我创build了第三点中心

之后,我用他们之间的贝塞尔path绘制曲线和所有工作正常。

在这里输入图像说明

在上面的曲线

现在我想创build两个点(5点曲线)。

一个在中间左边之间,一个在中间右边之间。

试图再次采取平均和使用5点曲线

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点的曲线

很难说,你想要达到什么目的,但是如果你的目标是find你在第一步中定义的贝塞尔曲线的一部分,看看贝塞尔曲线是如何定义的。 维基百科 。 一般来说,只有Bezier曲线的第一个和最后一个控制点也是曲线的一部分。

要find特定t(0..1)的Bezier曲线上的点P(t),可以使用De Casteljau的algorithm

试试这个简单的片段在你的操场上。 我select控制点,所以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(px, py) px py // 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(px, py) px py // 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 } 

这给你相同的结果。 函数bezier可以用于任意数量的控制点。 在帐户中,即使您可以在任何时间间隔内计算值,贝塞尔函数仅在定义的时间间隔(0 … 1.0)内有效。