Eliko - 8 months ago 27

Swift Question

I have made a blue ball that can be dragged by the **user** only on a red circled path:

I want to check how many times the user make a forward or backward lap (the start & end is at the top of the circle path), for example - If he drag the ball in a clockwise way so the laps is +1, and if he drag it to other way the laps is -1.

I tried to do this(**This inculdes the dragging of the ball and my try to count laps**):

`@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)

}

}

And it worked! but when the user drags the ball very fast it do not calculate, and it do not calculate backwards.

Answer

Here is a possible solution, following the approach indicated in the comments. First you need some additional instance variables:

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

In `dragBall`

, you calculate how much the angle has changed.
Since the angle can "jump" from -π to π, or vice versa, the difference
is normalised to the range -π ... π:

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

Then update the total change in the angle:

```
totalAngle += delta
```

and from that you can determine the number of laps:

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