使用 UIBezierPath 绘制极坐标函数

Graphing Polar Functions with UIBezierPath

是否可以使用 UIBezierPath 绘制极坐标函数?不只是圆圈,我说的是心形、limacons、lemniscates 等。基本上我有一个 UIView,想在视图中绘制形状。

对于这样的形状没有内置方法,但您总是可以用一系列非常短的直线来近似它们。我有理由以这种方式近似一个圆,一个有 ~100 条直线的圆看起来与用 ovalInRect 绘制的圆相同。这样做最简单,首先在极坐标中创建点,然后将循环中的点转换为直角坐标,然后再将点数组传递给方法,在该方法中我将线添加到贝塞尔曲线路径。

这是我的 swift 辅助函数(完整注释),它从极坐标函数生成给定 CGRect 中的 (x,y) 坐标。

func cartesianCoordsForPolarFunc(frame: CGRect, thetaCoefficient:Double, thetaCoefficientDenominator:Double, cosScalar:Double, iPrecision:Double) -> Array<CGPoint> {

    // Frame: The frame in which to fit this curve.
    // thetaCoefficient: The number to scale theta by in the cos.
    // thetaCoefficientDenominator: The denominator of the thetaCoefficient
    // cosScalar: The number to multiply the cos by.
    // iPrecision: The step for continuity. 0 < iPrecision <= 2.pi. Defaults to 0.1

    // Clean inputs
    var precision:Double = 0.1 // Default precision
    if iPrecision != 0 {// Can't be 0.
        precision = iPrecision
    }

    // This is ther polar function
    // var theta: Double = 0 //  0 <= theta <= 2pi
    // let r = cosScalar * cos(thetaCoefficient * theta)

    var points:Array<CGPoint> = [] // We store the points here
    for theta in stride(from: 0, to: 2*Double.pi * thetaCoefficientDenominator, by: precision) { // Try to recreate continuity
        let x = cosScalar * cos(thetaCoefficient * theta) * cos(theta) // Convert to cartesian
        let y = cosScalar * cos(thetaCoefficient * theta) * sin(theta) // Convert to cartesian

        let scaled_x = (Double(frame.width) - 0)/(cosScalar*2)*(x-cosScalar)+Double(frame.width) // Scale to the frame
        let scaled_y = (Double(frame.height) - 0)/(cosScalar*2)*(y-cosScalar)+Double(frame.height) // Scale to the frame

        points.append(CGPoint(x: scaled_x, y:scaled_y)) // Add the result
    }

    return points
}

鉴于这些点,这里有一个如何绘制 UIBezierPath 的示例。在我的示例中,这是在我称为 UIPolarCurveView 的自定义 UIView 函数中。

let flowerPath = UIBezierPath() // Declare my path

// Custom Polar scalars
let k: Double = 9/4
let length = 50

// Draw path
let points = cartesianCoordsForPolarFunc(frame: frame, thetaCoefficient: k, thetaCoefficientDenominator:4 cosScalar: length, iPrecision: 0.01)      flowerPath.move(to: points[0])
for i in 2...points.count {         
       flowerPath.addLine(to: points[i-1])
}

flowerPath.close()

结果如下: PS:如果您计划在同一帧中放置多个图形,请确保通过使第二个 cosScalar 成为 cosScalars used.You 中最大的来修改缩放加法这通过向示例中的函数添加参数来实现。