Swift UI中随机生成的曲线

jvlzgdj9  于 2023-05-21  发布在  Swift
关注(0)|答案(1)|浏览(205)

我正在尝试使用Swift UI创建随机生成的波浪线。我试着在SO上复制这个问题的数学。
https://stackoverflow.com/a/54051986/1895804
但我的贝塞尔曲线是创建尖锐的点,而不是平滑弯曲。有人知道为什么会这样吗?
它应该看起来像这样:

但它看起来像这个有锯齿状的尖端。

struct SuperCurvyLine: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let canvasW = rect.width
        let canvasH = rect.height
        let canvasX = canvasW/2
        let canvasY = canvasH/2
        let angVal = 0.20
        let tension = 1.0
        let npts: CGFloat = 60
        var dw = [Double]()
        var xs = [Double]()
        var ys = [Double]()
        var vys = [Double]()
        var vxs = [Double]()
        
        xs.append(0)
        ys.append(canvasY)
        var angle = 0.0
        for i in 0...Int(npts) {
            dw.append(2 * Double.random(in: 0...1) - 1)
            vxs.append(10 * cos(2 * Double.pi * angle))
            vys.append(10 * sin(2 * Double.pi * angle))
            angle = angle + dw[i] * angVal
        }
        
        for i in 1...Int(npts) {
            xs.append(xs[i - 1] + 3 * (vxs[i - 1] + vxs[i]) / 2)
            ys.append(ys[i - 1] + 3 * (vys[i - 1] + vys[i]) / 2)
        }
        
        path.move(to: CGPoint(x: xs[0], y: ys[0]))
        
        for i in 1...Int(npts) {
            let cp1x = xs[i - 1] + tension * vxs[i - 1]
            let cp1y = ys[i - 1] + tension * vys[i - 1]
            let cp2x = xs[i] - tension * vxs[i]
            let cp2y = ys[i] - tension * vys[i]
            let to = CGPoint(x: cp1x, y: cp1y)
            let control1 = CGPoint(x: cp2x, y: cp2y)
            let control2 = CGPoint(x: xs[i], y: ys[i])
            path.addCurve(to: control1, control1: to, control2: control1)
        }
        
        return path
    }
}
polhcujo

polhcujo1#

你混淆了tocontrol1control2点。根据原始JS,它们应该是:

path.addCurve(to: control2, control1: to, control2: control1)

你给这些名字起了个让人费解的名字。它真的应该是:

let control1 = CGPoint(x: cp1x, y: cp1y)
let control2 = CGPoint(x: cp2x, y: cp2y)
let to = CGPoint(x: xs[i], y: ys[i])
path.addCurve(to: to, control1: control1, control2: control2)

现在说得通了。注意,JS中参数的顺序是“control1,control2,to”,与Swift API不同。
要获得更平滑的线条,可以使用lineJoin: .round笔划样式:

.stroke(style: .init(lineJoin: .round))

相关问题