// // ChartContext.swift // USB Meter // // Created by Bogdan Timofte on 14/04/2020. // Copyright © 2020 Bogdan Timofte. All rights reserved. // import CoreGraphics import SwiftUI class ChartContext { private var rect : CGRect? private var pad: CGFloat = 0 var isValid: Bool { get { return rect != nil && rect!.width > 0 && rect!.height > 0 } } var size: CGSize { get { guard rect != nil else { track("Invalid Context") return .zero } return rect!.size } } var origin: CGPoint { get { guard rect != nil else { track("Invalid Context") return .zero } return rect!.origin } } var minValue: Double { return rect == nil ? .nan : Double(rect!.minY) } var maxValue: Double { get { return rect == nil ? .nan : Double(rect!.maxY) } } func reset() { rect = nil pad = 0 } func include( point: CGPoint ) { if rect == nil { rect = CGRect(origin: point, size: .zero) padding() } else { rect = rect!.union(CGRect(origin: point, size: .zero)) padding() } } func padding() { guard rect != nil else { track("Invalid Context") pad = 0 return } pad = rect!.size.height * Constants.chartUnderscan } func ensureMinimumSize(width minimumWidth: CGFloat = 0, height minimumHeight: CGFloat = 0) { guard var rect else { return } if rect.width < minimumWidth { let delta = (minimumWidth - rect.width) / 2 rect = rect.insetBy(dx: -delta, dy: 0) } if rect.height < minimumHeight { let delta = (minimumHeight - rect.height) / 2 rect = rect.insetBy(dx: 0, dy: -delta) } self.rect = rect padding() } func yAxisLabel( for itemNo: Int, of items: Int ) -> Double { let labelSpace = Double(rect!.height) / Double(items - 1) let labelRelativeValue = labelSpace * Double(itemNo - 1) return minValue + labelRelativeValue } // MARK: Conversii dubioase func xAxisLabel( for itemNo: Int, of items: Int ) -> Double { let labelSpace = Double(rect!.width) / Double(items - 1) let labelRelativeValue = labelSpace * Double(itemNo - 1) return Double(rect!.origin.x) + labelRelativeValue } func placeInRect (point: CGPoint) -> CGPoint { guard let rect else { track("Invalid Context") return .zero } let width = max(rect.width, 1) let height = max(rect.height, 0.1) let x = (point.x - rect.origin.x)/width let y = (pad + point.y - rect.origin.y)/height return CGPoint(x: x, y: 1 - y * Constants.chartOverscan) } }