Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/103.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 绘制平滑曲线_Ios_Swift3_Uibezierpath - Fatal编程技术网

Ios 绘制平滑曲线

Ios 绘制平滑曲线,ios,swift3,uibezierpath,Ios,Swift3,Uibezierpath,我有两个点左和右,通过向Y添加一些静态值,X是左右两侧的平均值,我创建了第三个点中心 之后,我用贝塞尔路径在它们之间画出曲线,一切都很好 在上述曲线中 现在我想再创建两个点(5点曲线) 一个在中间和左侧之间,一个在中间和右侧之间 我再次尝试取平均值,并使用 func drawFivePoint(_ startPoint: CGPoint?, leftCenterPoint: CGPoint?, toControlPoint controlPoint: CGPoint?, toRightCo

我有两个点,通过向Y添加一些静态值,X是左右两侧的平均值,我创建了第三个点中心

之后,我用贝塞尔路径在它们之间画出曲线,一切都很好

在上述曲线中

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

很难说,你想实现什么,但如果你的目标是找到在第一步中定义的贝塞尔曲线的一部分,请先看看贝塞尔曲线是如何定义的。通常,只有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点一样平滑。现在你明白我的意思了吗?好的,谢谢,我会检查一下,让你知道它是否有效