BarChartDataEntry.swift 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. //
  2. // BarChartDataEntry.swift
  3. // Charts
  4. //
  5. // Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
  6. // A port of MPAndroidChart for iOS
  7. // Licensed under Apache License 2.0
  8. //
  9. // https://github.com/danielgindi/Charts
  10. //
  11. import Foundation
  12. open class BarChartDataEntry: ChartDataEntry
  13. {
  14. /// the values the stacked barchart holds
  15. private var _yVals: [Double]?
  16. /// the ranges for the individual stack values - automatically calculated
  17. private var _ranges: [Range]?
  18. /// the sum of all negative values this entry (if stacked) contains
  19. private var _negativeSum: Double = 0.0
  20. /// the sum of all positive values this entry (if stacked) contains
  21. private var _positiveSum: Double = 0.0
  22. public required init()
  23. {
  24. super.init()
  25. }
  26. /// Constructor for normal bars (not stacked).
  27. public override init(x: Double, y: Double)
  28. {
  29. super.init(x: x, y: y)
  30. }
  31. /// Constructor for normal bars (not stacked).
  32. public convenience init(x: Double, y: Double, data: Any?)
  33. {
  34. self.init(x: x, y: y)
  35. self.data = data
  36. }
  37. /// Constructor for normal bars (not stacked).
  38. public convenience init(x: Double, y: Double, icon: NSUIImage?)
  39. {
  40. self.init(x: x, y: y)
  41. self.icon = icon
  42. }
  43. /// Constructor for normal bars (not stacked).
  44. public convenience init(x: Double, y: Double, icon: NSUIImage?, data: Any?)
  45. {
  46. self.init(x: x, y: y)
  47. self.icon = icon
  48. self.data = data
  49. }
  50. /// Constructor for stacked bar entries.
  51. @objc public init(x: Double, yValues: [Double])
  52. {
  53. super.init(x: x, y: BarChartDataEntry.calcSum(values: yValues))
  54. self._yVals = yValues
  55. calcPosNegSum()
  56. calcRanges()
  57. }
  58. /// Constructor for stacked bar entries. One data object for whole stack
  59. @objc public convenience init(x: Double, yValues: [Double], icon: NSUIImage?)
  60. {
  61. self.init(x: x, yValues: yValues)
  62. self.icon = icon
  63. }
  64. /// Constructor for stacked bar entries. One data object for whole stack
  65. @objc public convenience init(x: Double, yValues: [Double], data: Any?)
  66. {
  67. self.init(x: x, yValues: yValues)
  68. self.data = data
  69. }
  70. /// Constructor for stacked bar entries. One data object for whole stack
  71. @objc public convenience init(x: Double, yValues: [Double], icon: NSUIImage?, data: Any?)
  72. {
  73. self.init(x: x, yValues: yValues)
  74. self.icon = icon
  75. self.data = data
  76. }
  77. @objc open func sumBelow(stackIndex: Int) -> Double
  78. {
  79. guard let yVals = _yVals, yVals.indices.contains(stackIndex) else
  80. {
  81. return 0
  82. }
  83. let remainder = yVals[stackIndex...].reduce(into: 0.0) { $0 += $1 }
  84. return remainder
  85. }
  86. /// The sum of all negative values this entry (if stacked) contains. (this is a positive number)
  87. @objc open var negativeSum: Double
  88. {
  89. return _negativeSum
  90. }
  91. /// The sum of all positive values this entry (if stacked) contains.
  92. @objc open var positiveSum: Double
  93. {
  94. return _positiveSum
  95. }
  96. var stackSize: Int { yValues?.count ?? 1}
  97. @objc open func calcPosNegSum()
  98. {
  99. (_negativeSum, _positiveSum) = _yVals?.reduce(into: (0,0)) { (result, y) in
  100. if y < 0
  101. {
  102. result.0 += -y
  103. }
  104. else
  105. {
  106. result.1 += y
  107. }
  108. } ?? (0,0)
  109. }
  110. /// Splits up the stack-values of the given bar-entry into Range objects.
  111. ///
  112. /// - Parameters:
  113. /// - entry:
  114. /// - Returns:
  115. @objc open func calcRanges()
  116. {
  117. guard let values = yValues, !values.isEmpty else { return }
  118. if _ranges == nil
  119. {
  120. _ranges = [Range]()
  121. }
  122. else
  123. {
  124. _ranges!.removeAll()
  125. }
  126. _ranges!.reserveCapacity(values.count)
  127. var negRemain = -negativeSum
  128. var posRemain: Double = 0.0
  129. for value in values
  130. {
  131. if value < 0
  132. {
  133. _ranges!.append(Range(from: negRemain, to: negRemain - value))
  134. negRemain -= value
  135. }
  136. else
  137. {
  138. _ranges!.append(Range(from: posRemain, to: posRemain + value))
  139. posRemain += value
  140. }
  141. }
  142. }
  143. // MARK: Accessors
  144. /// the values the stacked barchart holds
  145. @objc open var isStacked: Bool { return _yVals != nil }
  146. /// the values the stacked barchart holds
  147. @objc open var yValues: [Double]?
  148. {
  149. get { return self._yVals }
  150. set
  151. {
  152. self.y = BarChartDataEntry.calcSum(values: newValue ?? [])
  153. self._yVals = newValue
  154. calcPosNegSum()
  155. calcRanges()
  156. }
  157. }
  158. /// The ranges of the individual stack-entries. Will return null if this entry is not stacked.
  159. @objc open var ranges: [Range]?
  160. {
  161. return _ranges
  162. }
  163. // MARK: NSCopying
  164. open override func copy(with zone: NSZone? = nil) -> Any
  165. {
  166. let copy = super.copy(with: zone) as! BarChartDataEntry
  167. copy._yVals = _yVals
  168. copy.y = y
  169. copy._negativeSum = _negativeSum
  170. copy._positiveSum = _positiveSum
  171. return copy
  172. }
  173. /// Calculates the sum across all values of the given stack.
  174. ///
  175. /// - Parameters:
  176. /// - vals:
  177. /// - Returns:
  178. private static func calcSum(values: [Double]) -> Double
  179. {
  180. values.reduce(into: 0, +=)
  181. }
  182. }