From 5dd109174f145ecee11df8338ce64cc4d0fcacb6 Mon Sep 17 00:00:00 2001 From: Jacob Christie Date: Mon, 13 Nov 2017 14:58:26 -0800 Subject: [PATCH 1/4] Replaced relevant `ChartUtils` methods with `Double` extensions Improves readability. `nextUp` is built in and provides the same functionality. --- Source/Charts/Charts/ChartViewBase.swift | 2 +- .../Charts/Renderers/AxisRendererBase.swift | 6 +- .../Renderers/YAxisRendererRadarChart.swift | 6 +- Source/Charts/Utils/ChartUtils.swift | 79 ++++++++----------- 4 files changed, 42 insertions(+), 51 deletions(-) diff --git a/Source/Charts/Charts/ChartViewBase.swift b/Source/Charts/Charts/ChartViewBase.swift index f72dad9ee9..740b3afe7b 100755 --- a/Source/Charts/Charts/ChartViewBase.swift +++ b/Source/Charts/Charts/ChartViewBase.swift @@ -343,7 +343,7 @@ open class ChartViewBase: NSUIView, ChartDataProvider, AnimatorDelegate if _defaultValueFormatter is DefaultValueFormatter { // setup the formatter with a new number of digits - let digits = ChartUtils.decimals(reference) + let digits = reference.decimalPlaces (_defaultValueFormatter as? DefaultValueFormatter)?.decimals = digits diff --git a/Source/Charts/Renderers/AxisRendererBase.swift b/Source/Charts/Renderers/AxisRendererBase.swift index 52a234e011..f1171cbba7 100644 --- a/Source/Charts/Renderers/AxisRendererBase.swift +++ b/Source/Charts/Renderers/AxisRendererBase.swift @@ -112,7 +112,7 @@ open class AxisRendererBase: Renderer // Find out how much spacing (in y value space) between axis values let rawInterval = range / Double(labelCount) - var interval = ChartUtils.roundToNextSignificant(number: Double(rawInterval)) + var interval = rawInterval.roundedToNextSignficant() // If granularity is enabled, then do not allow the interval to go below specified granularity. // This is used to avoid repeated values when rounding values for display. @@ -122,7 +122,7 @@ open class AxisRendererBase: Renderer } // Normalize interval - let intervalMagnitude = ChartUtils.roundToNextSignificant(number: pow(10.0, Double(Int(log10(interval))))) + let intervalMagnitude = pow(10.0, Double(Int(log10(interval)))).roundedToNextSignficant() let intervalSigDigit = Int(interval / intervalMagnitude) if intervalSigDigit > 5 { @@ -162,7 +162,7 @@ open class AxisRendererBase: Renderer first -= interval } - let last = interval == 0.0 ? 0.0 : ChartUtils.nextUp(floor(yMax / interval) * interval) + let last = interval == 0.0 ? 0.0 : (floor(yMax / interval) * interval).nextUp if interval != 0.0 && last != first { diff --git a/Source/Charts/Renderers/YAxisRendererRadarChart.swift b/Source/Charts/Renderers/YAxisRendererRadarChart.swift index cab45f7125..6236d3163d 100644 --- a/Source/Charts/Renderers/YAxisRendererRadarChart.swift +++ b/Source/Charts/Renderers/YAxisRendererRadarChart.swift @@ -45,7 +45,7 @@ open class YAxisRendererRadarChart: YAxisRenderer // Find out how much spacing (in yValue space) between axis values let rawInterval = range / Double(labelCount) - var interval = ChartUtils.roundToNextSignificant(number: Double(rawInterval)) + var interval = rawInterval.roundedToNextSignficant() // If granularity is enabled, then do not allow the interval to go below specified granularity. // This is used to avoid repeated values when rounding values for display. @@ -55,7 +55,7 @@ open class YAxisRendererRadarChart: YAxisRenderer } // Normalize interval - let intervalMagnitude = ChartUtils.roundToNextSignificant(number: pow(10.0, floor(log10(interval)))) + let intervalMagnitude = pow(10.0, floor(log10(interval))).roundedToNextSignficant() let intervalSigDigit = Int(interval / intervalMagnitude) if intervalSigDigit > 5 @@ -98,7 +98,7 @@ open class YAxisRendererRadarChart: YAxisRenderer first -= interval } - let last = interval == 0.0 ? 0.0 : ChartUtils.nextUp(floor(yMax / interval) * interval) + let last = interval == 0.0 ? 0.0 : (floor(yMax / interval) * interval).nextUp if interval != 0.0 { diff --git a/Source/Charts/Utils/ChartUtils.swift b/Source/Charts/Utils/ChartUtils.swift index 21601a7030..6ea463166c 100755 --- a/Source/Charts/Utils/ChartUtils.swift +++ b/Source/Charts/Utils/ChartUtils.swift @@ -16,6 +16,40 @@ import CoreGraphics import UIKit #endif +extension Double { + /// Rounds the number to the nearest multiple of it's order of magnitude, rounding away from zero if halfway. + func roundedToNextSignficant() -> Double { + guard + !isInfinite, + !isNaN, + self != 0 + else { return self } + + let d = ceil(log10(self < 0 ? -self : self)) + let pw = 1 - Int(d) + let magnitude = pow(10.0, Double(pw)) + let shifted = (self * magnitude).rounded() + return shifted / magnitude + } + + var decimalPlaces: Int { + guard + !isNaN, + !isInfinite, + self != 0.0 + else { return 0 } + + let i = self.roundedToNextSignficant() + + guard + !i.isInfinite, + !i.isNaN + else { return 0 } + + return Int(ceil(-log10(i))) + 2 + } +} + open class ChartUtils { fileprivate static var _defaultValueFormatter: IValueFormatter = ChartUtils.generateDefaultValueFormatter() @@ -27,50 +61,7 @@ open class ChartUtils internal static let DEG2RAD = Double.pi / 180.0 internal static let RAD2DEG = 180.0 / Double.pi } - - internal class func roundToNextSignificant(number: Double) -> Double - { - if number.isInfinite || number.isNaN || number == 0 - { - return number - } - - let d = ceil(log10(number < 0.0 ? -number : number)) - let pw = 1 - Int(d) - let magnitude = pow(Double(10.0), Double(pw)) - let shifted = round(number * magnitude) - return shifted / magnitude - } - - internal class func decimals(_ number: Double) -> Int - { - if number.isNaN || number.isInfinite || number == 0.0 - { - return 0 - } - - let i = roundToNextSignificant(number: Double(number)) - - if i.isInfinite || i.isNaN - { - return 0 - } - - return Int(ceil(-log10(i))) + 2 - } - - internal class func nextUp(_ number: Double) -> Double - { - if number.isInfinite || number.isNaN - { - return number - } - else - { - return number + Double.ulpOfOne - } - } - + /// Calculates the position around a center point, depending on the distance from the center, and the angle of the position around the center. internal class func getPosition(center: CGPoint, dist: CGFloat, angle: CGFloat) -> CGPoint { From 593e73c431c33e1b28001c41a114d6c81d49464a Mon Sep 17 00:00:00 2001 From: Jacob Christie Date: Mon, 13 Nov 2017 18:04:52 -0800 Subject: [PATCH 2/4] Updated `ChartUtilsTests` to match changes --- Tests/Charts/ChartUtilsTests.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tests/Charts/ChartUtilsTests.swift b/Tests/Charts/ChartUtilsTests.swift index d464a25220..9e5da3a07b 100644 --- a/Tests/Charts/ChartUtilsTests.swift +++ b/Tests/Charts/ChartUtilsTests.swift @@ -17,7 +17,7 @@ class ChartUtilsTests: XCTestCase { let number = Double.nan - let actual = ChartUtils.decimals(number) + let actual = number.decimalPlaces let expected = 0 XCTAssertEqual(expected, actual) @@ -27,7 +27,7 @@ class ChartUtilsTests: XCTestCase { let number = Double.infinity - let actual = ChartUtils.decimals(number) + let actual = number.decimalPlaces let expected = 0 XCTAssertEqual(expected, actual) @@ -37,7 +37,7 @@ class ChartUtilsTests: XCTestCase { let number = 0.0 - let actual = ChartUtils.decimals(number) + let actual = number.decimalPlaces let expected = 0 XCTAssertEqual(expected, actual) @@ -47,7 +47,7 @@ class ChartUtilsTests: XCTestCase { let number = Double.greatestFiniteMagnitude - let actual = ChartUtils.decimals(number) + let actual = number.decimalPlaces let expected = 0 XCTAssertEqual(expected, actual) @@ -57,7 +57,7 @@ class ChartUtilsTests: XCTestCase { let number = Double.leastNormalMagnitude - let actual = ChartUtils.decimals(number) + let actual = number.decimalPlaces let expected = 310 // Don't think this is supposed to be this value maybe 0? XCTAssertEqual(expected, actual) @@ -67,7 +67,7 @@ class ChartUtilsTests: XCTestCase { let number = 13.123123 - let actual = ChartUtils.decimals(number) + let actual = number.decimalPlaces let expected = 1 // Don't think this is supposed to be this value maybe 6? XCTAssertEqual(expected, actual) From 7a341873717a29dfe687edd95933e56216a14795 Mon Sep 17 00:00:00 2001 From: Jacob Christie Date: Wed, 15 Nov 2017 10:34:19 -0800 Subject: [PATCH 3/4] Pulled latest master --- Source/Charts/Utils/ChartUtils.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) mode change 100755 => 100644 Source/Charts/Utils/ChartUtils.swift diff --git a/Source/Charts/Utils/ChartUtils.swift b/Source/Charts/Utils/ChartUtils.swift old mode 100755 new mode 100644 index 5df3b693a9..8197839604 --- a/Source/Charts/Utils/ChartUtils.swift +++ b/Source/Charts/Utils/ChartUtils.swift @@ -16,6 +16,20 @@ import CoreGraphics import UIKit #endif +extension CGSize { + func rotatedBy(degrees: CGFloat) -> CGSize { + let radians = ChartUtils.Math.FDEG2RAD * degrees + return rotatedBy(radians: radians) + } + + func rotatedBy(radians: CGFloat) -> CGSize { + return CGSize( + width: abs(width * cos(radians)) + abs(height * sin(radians)), + height: abs(width * sin(radians)) + abs(height * cos(radians)) + ) + } +} + extension Double { /// Rounds the number to the nearest multiple of it's order of magnitude, rounding away from zero if halfway. func roundedToNextSignficant() -> Double { From 672f25e4a02461788fc478ef945b4e8834bc013b Mon Sep 17 00:00:00 2001 From: Jacob Christie Date: Sun, 10 Dec 2017 22:04:00 -0400 Subject: [PATCH 4/4] Pulled latest master --- Source/Charts/Utils/ChartUtils.swift | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Source/Charts/Utils/ChartUtils.swift b/Source/Charts/Utils/ChartUtils.swift index d67026592c..df9ef3243c 100644 --- a/Source/Charts/Utils/ChartUtils.swift +++ b/Source/Charts/Utils/ChartUtils.swift @@ -83,15 +83,7 @@ extension Double { open class ChartUtils { - fileprivate static var _defaultValueFormatter: IValueFormatter = ChartUtils.generateDefaultValueFormatter() - - internal struct Math - { - internal static let FDEG2RAD = CGFloat(Double.pi / 180.0) - internal static let FRAD2DEG = CGFloat(180.0 / Double.pi) - internal static let DEG2RAD = Double.pi / 180.0 - internal static let RAD2DEG = 180.0 / Double.pi - } + private static var _defaultValueFormatter: IValueFormatter = ChartUtils.generateDefaultValueFormatter() /// Calculates the position around a center point, depending on the distance from the center, and the angle of the position around the center. internal class func getPosition(center: CGPoint, dist: CGFloat, angle: CGFloat) -> CGPoint