计算用户在圆形路径中完成了多少圈

Calculate how much laps the user did in a Circle Path

我制作了一个蓝球,用户只能在红色圆圈路径上拖动:

我想检查用户向前或向后跑了多少圈(起点和终点在圆形路径的顶部),例如 - 如果他以顺时针方向拖动球,那么圈数是+1,如果他把它拖到其他地方,圈数是-1。

我试过这样做(这包括拖球和我尝试计算圈数):

@IBAction func dragBall(recognizer: UIPanGestureRecognizer) {
        let point = recognizer.locationInView(self.view);
        let earthX = Double(point.x)
        let earthY = Double(point.y)
        let midViewXDouble = Double(midViewX)
        let midViewYDouble = Double(midViewY)
        let angleX = (earthX - midViewXDouble)
        let angleY = (earthY - midViewYDouble)
        let angle = atan2(angleY, angleX)
        let earthX2 = midViewXDouble + cos(angle)*100
        let earthY2 = midViewYDouble + sin(angle)*100
        circlePath2 = UIBezierPath(arcCenter: CGPoint(x: earthX2,y: earthY2), radius: CGFloat(10), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
        shapeLayer2.path = circlePath2.CGPath

    if degrees == 0 {
                laps += 1
                print(laps)
            }
    }

而且成功了!但是当用户快速拖动球时它不计算,并且不向后计算。

这是一个可能的解决方案,遵循评论中指出的方法。首先你需要一些额外的实例变量:

var previousAngle = -M_PI_2 // top position if y-coordinate points down
var totalAngle = 0.0
var laps = 0

dragBall中,你计算角度改变了多少。 由于角度可以 "jump" 从 -π 到 π,反之亦然,差值 归一化到范围 -π ... π:

var delta = angle - previousAngle
if delta > M_PI {
    delta -= 2 * M_PI
} else if delta < -M_PI {
    delta += 2 * M_PI
}
previousAngle = angle

然后更新角度的总变化:

totalAngle += delta

然后您可以确定圈数:

laps = Int(floor(totalAngle/(2 * M_PI)))