co-maps/iphone/Maps/UI/PlacePage/Components/ElevationProfile/ElevationProfileFormatter.swift
2025-11-22 13:58:55 +01:00

67 lines
2.1 KiB
Swift

import Chart
import CoreApi
final class ElevationProfileFormatter {
private enum Constants {
static let metricToImperialMultiplier: CGFloat = 0.3048
static var metricAltitudeStep: CGFloat = 50
static var imperialAltitudeStep: CGFloat = 100
}
private let distanceFormatter: DistanceFormatter.Type
private let altitudeFormatter: AltitudeFormatter.Type
private let unitSystemMultiplier: CGFloat
private let altitudeStep: CGFloat
private let units: Units
init(units: Units = SettingsBridge.measurementUnits()) {
self.units = units
self.distanceFormatter = DistanceFormatter.self
self.altitudeFormatter = AltitudeFormatter.self
switch units {
case .metric:
self.altitudeStep = Constants.metricAltitudeStep
self.unitSystemMultiplier = 1
case .imperial:
self.altitudeStep = Constants.imperialAltitudeStep
self.unitSystemMultiplier = Constants.metricToImperialMultiplier
@unknown default:
fatalError("Unsupported units")
}
}
}
extension ElevationProfileFormatter: ChartFormatter {
func xAxisString(from value: Double) -> String {
distanceFormatter.distanceString(fromMeters: value)
}
func yAxisString(from value: Double) -> String {
altitudeFormatter.altitudeString(fromMeters: value)
}
func yAxisLowerBound(from value: CGFloat) -> CGFloat {
floor((value / unitSystemMultiplier) / altitudeStep) * altitudeStep * unitSystemMultiplier
}
func yAxisUpperBound(from value: CGFloat) -> CGFloat {
ceil((value / unitSystemMultiplier) / altitudeStep) * altitudeStep * unitSystemMultiplier
}
func yAxisSteps(lowerBound: CGFloat, upperBound: CGFloat) -> [CGFloat] {
let lower = yAxisLowerBound(from: lowerBound)
let upper = yAxisUpperBound(from: upperBound)
let range = upper - lower
var stepSize = altitudeStep
var stepsCount = Int((range / stepSize).rounded(.up))
while stepsCount > 6 {
stepSize *= 2 // Double the step size to reduce the step count
stepsCount = Int((range / stepSize).rounded(.up))
}
let steps = stride(from: lower, through: upper, by: stepSize)
return Array(steps)
}
}