Choosing an attractive linear scale for a graph's Y Axis

后端 未结 13 1447
予麋鹿
予麋鹿 2020-12-07 08:42

I\'m writing a bit of code to display a bar (or line) graph in our software. Everything\'s going fine. The thing that\'s got me stumped is labeling the Y axis.

The

13条回答
  •  鱼传尺愫
    2020-12-07 08:54

    Converted this answer as Swift 4

    extension Int {
    
        static func makeYaxis(yMin: Int, yMax: Int, ticks: Int = 10) -> [Int] {
            var yMin = yMin
            var yMax = yMax
            var ticks = ticks
            // This routine creates the Y axis values for a graph.
            //
            // Calculate Min amd Max graphical labels and graph
            // increments.  The number of ticks defaults to
            // 10 which is the SUGGESTED value.  Any tick value
            // entered is used as a suggested value which is
            // adjusted to be a 'pretty' value.
            //
            // Output will be an array of the Y axis values that
            // encompass the Y values.
            var result = [Int]()
            // If yMin and yMax are identical, then
            // adjust the yMin and yMax values to actually
            // make a graph. Also avoids division by zero errors.
            if yMin == yMax {
                yMin -= ticks   // some small value
                yMax += ticks   // some small value
            }
            // Determine Range
            let range = yMax - yMin
            // Adjust ticks if needed
            if ticks < 2 { ticks = 2 }
            else if ticks > 2 { ticks -= 2 }
    
            // Get raw step value
            let tempStep: CGFloat = CGFloat(range) / CGFloat(ticks)
            // Calculate pretty step value
            let mag = floor(log10(tempStep))
            let magPow = pow(10,mag)
            let magMsd = Int(tempStep / magPow + 0.5)
            let stepSize = magMsd * Int(magPow)
    
            // build Y label array.
            // Lower and upper bounds calculations
            let lb = stepSize * Int(yMin/stepSize)
            let ub = stepSize * Int(ceil(CGFloat(yMax)/CGFloat(stepSize)))
            // Build array
            var val = lb
            while true {
                result.append(val)
                val += stepSize
                if val > ub { break }
            }
            return result
        }
    
    }
    

提交回复
热议问题