Рисовать синусоидальную частоту?

Я рисую один период синусоиды с:

let width = rect.width
let height = rect.height

let origin = CGPoint(x: width * (1 - graphWidth) / 2, y: height * 0.50)

let path = UIBezierPath()
path.move(to: origin)

for angle in stride(from: 5.0, through: 360.0, by: 5.0) {
    let x = origin.x + CGFloat(angle/360.0) * width * graphWidth
    let y = origin.y - CGFloat(sin(angle/180.0 * Double.pi)) * height * amplitude
    path.addLine(to: CGPoint(x: x, y: y))
}

Globals.sharedInstance.palleteGlowGreen.setStroke()
path.stroke()

Как бы я:

  1. Нарисуйте несколько периодов для одной и той же ширины (теперь это 0-360)
  2. Измените число 1 (количество периодов) динамически, чтобы вы увидели сжатие волны.

1 ответ

Решение

Просто умножьте angle от periods:

@IBDesignable
class SineWaveView: UIView {

    @IBInspectable
    var graphWidth: CGFloat = 0.90  { didSet { setNeedsDisplay() } }

    @IBInspectable
    var amplitude: CGFloat = 0.20   { didSet { setNeedsDisplay() } }

    @IBInspectable
    var periods: CGFloat = 1.0      { didSet { setNeedsDisplay() } }

    override func draw(_ rect: CGRect) {
        let width = bounds.width
        let height = bounds.height

        let origin = CGPoint(x: width * (1 - graphWidth) / 2, y: height * 0.50)

        let path = UIBezierPath()
        path.move(to: origin)

        for angle in stride(from: 5.0, through: 360.0 * periods, by: 5.0) {
            let x = origin.x + angle/(360.0 * periods) * width * graphWidth
            let y = origin.y - sin(angle/180.0 * .pi) * height * amplitude
            path.addLine(to: CGPoint(x: x, y: y))
        }

        Globals.sharedInstance.palleteGlowGreen.setStroke()
        path.stroke()
    }

}

Кстати, внеся изменения в periods вызов setNeedsDisplayэто означает, что при обновлении periods, график будет автоматически перерисован.


И вместо того, чтобы перебирать градусы, а затем преобразовывать все обратно в радианы, я мог бы просто остаться в радианах:

override func draw(_ rect: CGRect) {
    let width = bounds.width
    let height = bounds.height

    let origin = CGPoint(x: width * (1 - graphWidth) / 2, y: height * 0.50)
    let maxAngle: CGFloat = 2 * .pi * periods
    let iterations = Int(min(1000, 100 * periods))

    let point = { (angle: CGFloat) -> CGPoint in
        let x = origin.x + angle/maxAngle * width * self.graphWidth
        let y = origin.y - sin(angle) * height * self.amplitude
        return CGPoint(x: x, y: y)
    }

    let path = UIBezierPath()
    path.move(to: point(0))

    for i in 1 ... iterations {
        path.addLine(to: point(maxAngle * CGFloat(i) / CGFloat(iterations)))
    }

    Globals.sharedInstance.palleteGlowGreen.setStroke()
    path.stroke()
}
Другие вопросы по тегам