Skip to content

Commit

Permalink
Fix the issue of tracking when the value is equal to the max value an…
Browse files Browse the repository at this point in the history
…d add tests for this part
  • Loading branch information
HamzaGhazouani committed Jul 27, 2019
1 parent 93fb96c commit a19a4fc
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 17 deletions.
50 changes: 50 additions & 0 deletions Example/Tests/CircularSliderHelperTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// CircularSliderHelperTests.swift
// HGCircularSlider_Tests
//
// Created by Hamza GHAZOUANI on 24/07/2019.
// Copyright © 2019 CocoaPods. All rights reserved.
//

import XCTest
@testable import HGCircularSlider

extension CGFloat {

var toDegrees: CGFloat {
return self * 180.0 / CGFloat(Double.pi)
}
}

class CircularSliderHelperTests: XCTestCase {

let cirlceInterval = Interval(min: 0 , max: CGFloat(2 * Double.pi))
let valuesInterval = Interval(min: 0, max: 1.2)

func testInitialValueScale() {
// Given
let value = valuesInterval.min

// Thene
let angle = CircularSliderHelper.scaleValue(value, fromInterval: valuesInterval, toInterval: cirlceInterval).toDegrees
XCTAssertEqual(angle, 0)
}

func testFinalValueScale() {
// Given
let value: CGFloat = valuesInterval.max

// Thene
let angle = CircularSliderHelper.scaleValue(value, fromInterval: valuesInterval, toInterval: cirlceInterval).toDegrees
XCTAssertEqual(angle, 360)
}

func testMedianValueScale() {
// Given
let value: CGFloat = valuesInterval.max / 2

// Thene
let angle = CircularSliderHelper.scaleValue(value, fromInterval: valuesInterval, toInterval: cirlceInterval).toDegrees
XCTAssertEqual(angle, 180)
}
}
42 changes: 25 additions & 17 deletions HGCircularSlider/Classes/CircularSliderHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal struct Interval {
var min: CGFloat = 0.0
var max: CGFloat = 0.0
var rounds: Int

init(min: CGFloat, max: CGFloat, rounds: Int = 1) {
assert(min <= max && rounds > 0, NSLocalizedString("Illegal interval", comment: ""))

Expand Down Expand Up @@ -42,7 +42,7 @@ internal struct Arc {
var endAngle: CGFloat = 0.0

init(circle: Circle, startAngle: CGFloat, endAngle: CGFloat) {

self.circle = circle
self.startAngle = startAngle
self.endAngle = endAngle
Expand Down Expand Up @@ -87,9 +87,9 @@ internal extension CGVector {
}

internal extension CGRect {

// get the center of rect (bounds or frame)
internal var center: CGPoint {
var center: CGPoint {
get {
let center = CGPoint(x: midX, y: midY)
return center
Expand All @@ -114,7 +114,7 @@ internal class CircularSliderHelper {
internal static func degrees(fromRadians value: CGFloat) -> CGFloat {
return value * 180.0 / CGFloat(Double.pi)
}

/**
Returns the angle AÔB of an circle

Expand Down Expand Up @@ -176,12 +176,20 @@ internal class CircularSliderHelper {
- returns: the value in the new interval
*/
internal static func scaleValue(_ value: CGFloat, fromInterval source: Interval, toInterval destination: Interval) -> CGFloat {
let sourceRange = (source.max - source.min) / CGFloat(source.rounds)
let destinationRange = (destination.max - destination.min) / CGFloat(destination.rounds)
let scaledValue = source.min + (value - source.min).truncatingRemainder(dividingBy: sourceRange)
let newValue = (((scaledValue - source.min) * destinationRange) / sourceRange) + destination.min

return newValue
// If the value is equal to the min or the max no need to calculate
switch value {
case source.min:
return destination.min
case source.max:
return destination.max
default:
let sourceRange = (source.max - source.min) / CGFloat(source.rounds)
let destinationRange = (destination.max - destination.min) / CGFloat(destination.rounds)
let scaledValue = source.min + (value - source.min).truncatingRemainder(dividingBy: sourceRange)
let newValue = (((scaledValue - source.min) * destinationRange) / sourceRange) + destination.min

return newValue
}
}

/**
Expand All @@ -192,7 +200,7 @@ internal class CircularSliderHelper {
the angle value is equal to π

@see value(inInterval: fromAngle:)

- parameter aValue: the original value
- parameter oldIntreval: the original interval

Expand Down Expand Up @@ -223,16 +231,16 @@ internal class CircularSliderHelper {

return value
}

internal static func delta(in interval: Interval, for angle: CGFloat, oldValue: CGFloat) -> CGFloat {
let angleIntreval = Interval(min: circleMinValue , max: circleMaxValue)

let oldAngle = scaleToAngle(value: oldValue, inInterval: interval)
let deltaAngle = self.angle(from: oldAngle, to: angle)

return scaleValue(deltaAngle, fromInterval: angleIntreval, toInterval: interval)
}

/**
* Length (angular) of a shortest way between two angles.
* It will be in range [-π/2, π/2], where sign means dir (+ for clockwise, - for counter clockwise).
Expand All @@ -242,7 +250,7 @@ internal class CircularSliderHelper {
// Rotate right
let offset = alpha >= halfValue ? circleMaxValue - alpha : -alpha
let offsetBeta = beta + offset

if offsetBeta > halfValue {
return offsetBeta - circleMaxValue
}
Expand Down

0 comments on commit a19a4fc

Please sign in to comment.