Add route files, show overview
This commit is contained in:
83
CHDataManagement/Workouts/MapImageCreator.swift
Normal file
83
CHDataManagement/Workouts/MapImageCreator.swift
Normal file
@@ -0,0 +1,83 @@
|
||||
import Foundation
|
||||
import AppKit
|
||||
import MapKit
|
||||
|
||||
struct MapImageCreator {
|
||||
|
||||
let locations: [CLLocation]
|
||||
|
||||
func createMapSnapshot(
|
||||
size layoutSize: CGSize,
|
||||
scale: CGFloat = 2.0,
|
||||
lineWidth: CGFloat = 5,
|
||||
paddingFactor: Double = 1.2,
|
||||
completion: @escaping ((image: NSImage, imagePoints: [CGPoint])?) -> Void
|
||||
) {
|
||||
guard !locations.isEmpty else {
|
||||
completion(nil)
|
||||
return
|
||||
}
|
||||
let coordinates = locations.map { $0.coordinate }
|
||||
|
||||
let pixelSize = CGSize(width: layoutSize.width * scale, height: layoutSize.height * scale)
|
||||
|
||||
let options = MKMapSnapshotter.Options()
|
||||
options.size = pixelSize
|
||||
options.preferredConfiguration = MKHybridMapConfiguration(elevationStyle: .flat)
|
||||
|
||||
let polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
|
||||
let boundingMapRect = polyline.boundingMapRect
|
||||
let region = MKCoordinateRegion(boundingMapRect)
|
||||
|
||||
let latDelta = region.span.latitudeDelta * paddingFactor
|
||||
let lonDelta = region.span.longitudeDelta * paddingFactor
|
||||
let paddedRegion = MKCoordinateRegion(
|
||||
center: region.center,
|
||||
span: MKCoordinateSpan(latitudeDelta: latDelta, longitudeDelta: lonDelta)
|
||||
)
|
||||
|
||||
options.region = paddedRegion
|
||||
|
||||
let snapshotter = MKMapSnapshotter(options: options)
|
||||
snapshotter.start { snapshotOrNil, error in
|
||||
guard let snapshot = snapshotOrNil, error == nil else {
|
||||
print("Snapshot error: \(error?.localizedDescription ?? "unknown error")")
|
||||
completion(nil)
|
||||
return
|
||||
}
|
||||
|
||||
let image = NSImage(size: pixelSize)
|
||||
image.lockFocus()
|
||||
|
||||
snapshot.image.draw(in: CGRect(origin: .zero, size: pixelSize))
|
||||
|
||||
let path = NSBezierPath()
|
||||
path.lineJoinStyle = .round
|
||||
let imagePoints = coordinates.map { snapshot.point(for: $0) }
|
||||
|
||||
if let first = imagePoints.first {
|
||||
path.move(to: first)
|
||||
for point in imagePoints.dropFirst() {
|
||||
path.line(to: point)
|
||||
}
|
||||
|
||||
NSColor.systemBlue.setStroke()
|
||||
path.lineWidth = lineWidth * scale
|
||||
path.stroke()
|
||||
}
|
||||
|
||||
image.unlockFocus()
|
||||
|
||||
// Recalculate imagePoints since they were inside the drawing block
|
||||
let widthFactor = 1 / pixelSize.width
|
||||
let heightFactor = 1 / pixelSize.height
|
||||
let finalImagePoints = coordinates.map { coordinate in
|
||||
let point = snapshot.point(for: coordinate)
|
||||
return CGPoint(x: point.x * widthFactor,
|
||||
y: point.y * heightFactor)
|
||||
}
|
||||
|
||||
completion((image, finalImagePoints))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user