绘制平滑曲线 [英] Drawing Smooth Curve

查看:138
本文介绍了绘制平滑曲线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have two points left and right by adding some static value to Y and X is AVG of both left and right I have create 3rd point centre

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

After that I draw curve using bezier path between them And all works fine.

在上面的曲线中

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

Now I want to create two more points (5 Points curve).

一个在中心之间,一个在中心之间。

One Between centre and left and one between centre and right .

尝试再次采取平均值并使用

  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分

推荐答案

很难说,你想要达到什么目标,但如果你的目标是找到积分您在第一步中定义的贝塞尔曲线的一部分,请参见如何首先定义贝塞尔曲线。 维基百科。通常,只有贝塞尔曲线的第一个和最后一个控制点也是曲线的一部分。

it is hard to say, what are you trying to achieve, but if your goal is to find points which are part of the Bezier curve which you defined in the first step, see how the Bezier curve is defined first. Wikipedia. Generally, only first and last control point of Bezier curve is also the part of the curve.

在Bezier曲线上找到特定t的点P(t) (0..1)你可以使用 De Casteljau的算法

To find the point P(t) on the Bezier curve for a particular t (0..1) you can use De Casteljau's Algorithm

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

Try this simple snippet in your playground. I choose control points so, that x is linearly dependant on Bezier t parameter. The shape of y has the same shape as Bezier curve and is easy to see it as a graph of values in the playground

//: 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有效,即使您可以计算任何区间中的值。

which gives you the same results. The function bezier could be used for 'any' number of control points. Take in the account, that the bezier function is valid only for t in the interval (0...1.0) by the definition, even though you can calculate the values in any interval.

这篇关于绘制平滑曲线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆