绘制平滑曲线

时间:2017-08-03 10:10:30

标签: ios swift3 uibezierpath

我有两个点通过向Y添加一些静态值而X是左右AVG我创建了第3个点 center < / strong>

之后我使用bezier路径绘制曲线并且一切正常。

enter image description here

在上面的曲线中

现在我想再创建两个点(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!)
}

错误的结果

enter image description here

问题:如何计算点以使形状不受影响我在曲线上得到5分

1 个答案:

答案 0 :(得分:0)

很难说,你想要实现什么,但如果你的目标是找到你在第一步中定义的贝塞尔曲线的一部分,那么看看如何首先定义贝塞尔曲线。 Wikipedia。通常,只有贝塞尔曲线的第一个和最后一个控制点也是曲线的一部分。

要找到特定t(0..1)的贝塞尔曲线上的点P(t),您可以使用De Casteljau's Algorithm

在游乐场试试这个简单的片段。我选择控制点,因此x线性地依赖于Bezier t参数。 y的形状与贝塞尔曲线具有相同的形状,很容易将其视为游乐场中的数值图表

//: 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
}

给你相同的结果。函数bezier可用于“任意”数量的控制点。接受该帐户,bezier函数仅对定义中的区间(0 ... 1.0)中的t有效,即使您可以计算任何区间中的值。