Commit 1dd15f99 by Dmitriy Stepanets

Working on Radar widget

parent f4fb00c6
......@@ -12,12 +12,12 @@
<key>OneWeatherNotificationServiceExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>4</integer>
<integer>1</integer>
</dict>
<key>OneWeatherWidgetExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>7</integer>
<integer>2</integer>
</dict>
<key>PG (Playground) 1.xcscheme</key>
<dict>
......
......@@ -3,4 +3,54 @@
uuid = "55281C35-FE9F-4CED-865E-FBED0E7393F6"
type = "0"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "2AEA01B2-AF80-46FA-B4C5-20C0F7D9FA66"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OneWeatherWidget/UI/SnapshotLoader.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "58"
endingLineNumber = "58"
landmarkName = "addTile(to:region:completion:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "98A2F173-7F6B-413E-9927-ED39D7C7ECC6"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OneWeatherWidget/UI/SnapshotLoader.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "73"
endingLineNumber = "73"
landmarkName = "addTile(to:region:completion:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "EF99E3C2-5A50-4B1F-B927-70187D4FD76C"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Pods/Swarm/Swarm/SwarmTileOverlayRenderer.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "85"
endingLineNumber = "85"
landmarkName = "getTileImages(_:zoomLevel:completion:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
......@@ -32,6 +32,7 @@ class RadarViewController: UIViewController {
self.mapView.removeOverlay(oldOverlay)
}
if let overlay = swarmOverlay {
overlay.debug = true
overlay.startUpdating(block: { [weak self] (dataAvailable, updateError) in
self?.swarmRenderer?.setNeedsDisplay()
})
......
......@@ -7,20 +7,110 @@
import SwiftUI
import MapKit
import Swarm
private let WDT_APP_ID = "e3b73414"
private let WDT_APP_KEY = "25e8d6b72de3bcd528f7769b073cc335"
@available(iOS 14, *)
class SnapshotLoader: ObservableObject {
private static let swarmOverlay = SwarmManager.sharedManager.overlayForGroup(.none, baseLayer: .radar)
static func load(at coordinates: CLLocationCoordinate2D, size: CGSize, completion:@escaping (_ snapshot:UIImage?) -> Void) {
SwarmManager.sharedManager.authentication = SkywiseAuthentication(
app_id: WDT_APP_ID,
app_key: WDT_APP_KEY
)
let region = MKCoordinateRegion(center: coordinates,
latitudinalMeters: 30000,
longitudinalMeters: 30000)
let options = MKMapSnapshotter.Options()
options.mapType = .standard
options.showsBuildings = true
options.size = size
options.region = MKCoordinateRegion(center: coordinates,
latitudinalMeters: 30000,
longitudinalMeters: 30000)
options.region = region
let snapshotter = MKMapSnapshotter(options: options)
snapshotter.start { snapshot, error in
completion(snapshot?.image)
guard let snapshotObject = snapshot else {
completion(nil)
return
}
addTile(to: snapshotObject, region: region) { tileImage in
completion(tileImage)
}
}
}
private static func addTile(to snapshot: MKMapSnapshotter.Snapshot,
region: MKCoordinateRegion,
completion:@escaping (_ finalImage: UIImage?) -> Void
) {
DispatchQueue.main.async {
let mapView = MKMapView(frame: .init(origin: .zero, size: .init(width: 340, height: 280)))
mapView.setRegion(region, animated: false)
let mapRect = MKMapRect(origin: .init(region.center), size: mapView.visibleMapRect.size)
let renderer = SwarmTileOverlayRenderer(overlay: SnapshotLoader.swarmOverlay)
let zoomLevel = Int(SnapshotLoader.zoomLevel(for: region).rounded(.up))
renderer.getTileImages(mapRect, zoomLevel: zoomLevel) { tileImage in
guard let tile = tileImage else {
completion(snapshot.image)
return
}
let finalImageFrame = CGSize(width: snapshot.image.size.width * snapshot.image.scale,
height: snapshot.image.size.height * snapshot.image.scale)
let tileFinalFrame = CGSize(width: tile.size.width * snapshot.image.scale,
height: tile.size.height * snapshot.image.scale)
UIGraphicsBeginImageContext(finalImageFrame)
snapshot.image.draw(in: .init(origin: .zero, size: finalImageFrame))
tile.draw(in: .init(origin: .zero, size: tileFinalFrame), blendMode: .normal, alpha: 0.7)
let finalImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
completion(finalImage)
}
}
}
private static func draw(_ mapSize: CGSize, coordinates: CLLocationCoordinate2D) {
DispatchQueue.main.async {
let mapView = MKMapView(frame: .init(origin: .zero, size: .init(width: 340, height: 280)))
let coord = CLLocationCoordinate2D(latitude: 43.800618, longitude: -83.002119)
let region = MKCoordinateRegion(center: coord, latitudinalMeters: 30000, longitudinalMeters: 30000)
mapView.setRegion(region, animated: false)
let mapRect = MKMapRect(origin: .init(coord), size: mapView.visibleMapRect.size)
let renderer = SwarmTileOverlayRenderer(overlay: swarmOverlay)
let zoomLevel = Int(self.zoomLevel(for: region).rounded(.down))
renderer.getTileImages(mapRect, zoomLevel: zoomLevel) { tileImage in
//
}
}
// // WDT radar setup
// SwarmManager.sharedManager.authentication = SkywiseAuthentication(
// app_id: WDT_APP_ID,
// app_key: WDT_APP_KEY
// )
//
// let swarmOverlay = SwarmManager.sharedManager.overlayForGroup(.none, baseLayer: .surfaceTemp)
// let renderer = SwarmTileOverlayRenderer(overlay: swarmOverlay)
// if let ctx = UIGraphicsGetCurrentContext() {
// renderer.draw(.init(origin: .init(coordinates),
// size: .init(width: 280, height: 280)),
// zoomScale: 2, in: ctx)
// if let cgImage = ctx.makeImage() {
// let uiImage = UIImage(cgImage: cgImage)
// }
// }
}
private static func zoomLevel(for region: MKCoordinateRegion) -> Double {
let lonRatio = region.span.longitudeDelta / 360
var z = log(1/lonRatio)/log(2) - 1
z += 2 //Screen scale
return z
}
}
......@@ -2,16 +2,13 @@ import Foundation
import MapKit
let coord = CLLocationCoordinate2D(latitude: 40.730610, longitude: -73.935242)
let options = MKMapSnapshotter.Options()
options.mapType = .standard
options.showsBuildings = true
options.region = MKCoordinateRegion(center: coord, latitudinalMeters: 100000, longitudinalMeters: 100000)
options.size = .init(width: 1024, height: 768)
let snapshotter = MKMapSnapshotter(options: options)
snapshotter.start { snapshotImage, error in
let testImage = snapshotImage?.image
let testError = error
}
let region = MKCoordinateRegion(center: coord, latitudinalMeters: 100000, longitudinalMeters: 100000)
let z = log2(360 * 338 / (region.span.longitudeDelta * 256))
let point = MKMapPoint(coord)
let rect = MKMapRect(origin: point, size: .init(width: 340, height: 280))
let x = point.x
let y = point.y
print("x: \(x) y: \(y) z: \(z)")
print("rect: \(rect)")
......@@ -71,13 +71,6 @@ target 'OneWeatherCore' do
core_pods
end
#UI
#target 'OneWeatherUI' do
# use_frameworks!
# project 'OneWeatherUI/OneWeatherUI.project'
# pod 'BezierKit'
#end
#CoreDataStorage
target 'CoreDataStorage' do
project 'CoreDataStorage/CoreDataStorage.project'
......@@ -114,6 +107,7 @@ end
target 'OneWeatherWidgetExtension' do
pod 'Localize-Swift'
pod 'Swarm', :git => 'git@gitlab.pinsightmedia.com:oneweather/wdt-skywisetilekit-ios.git', :branch => 'develop'
end
#post_install do |installer|
......
......@@ -290,6 +290,6 @@ SPEC CHECKSUMS:
Swarm: 95393cd52715744c94e3a8475bc20b4de5d79f35
XMLCoder: f884dfa894a6f8b7dce465e4f6c02963bf17e028
PODFILE CHECKSUM: f93b0cf871ad7dd67a011fd0254c35263544aa13
PODFILE CHECKSUM: 62fca2be289770da54f757489617473cd28ef5b6
COCOAPODS: 1.10.1
......@@ -290,6 +290,6 @@ SPEC CHECKSUMS:
Swarm: 95393cd52715744c94e3a8475bc20b4de5d79f35
XMLCoder: f884dfa894a6f8b7dce465e4f6c02963bf17e028
PODFILE CHECKSUM: f93b0cf871ad7dd67a011fd0254c35263544aa13
PODFILE CHECKSUM: 62fca2be289770da54f757489617473cd28ef5b6
COCOAPODS: 1.10.1
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -148,8 +148,8 @@ extension SwarmOverlay {
return compositeTile ? URL(string: urlForSwarmCompositeTile(path, timestamp: timestamp))! : URL(string: urlForSwarmTile(path, timestamp: timestamp))!
}
func downloadTileAtURL(_ url: URL, result: @escaping (NSError?)->Void) {
tileQueue.addOperation(downloadOperation(url) { result($1) })
func downloadTileAtURL(_ url: URL, result: @escaping (UIImage?, NSError?)->Void) {
tileQueue.addOperation(downloadOperation(url) { result($0, $1) })
}
func downloadOperation(_ url: URL, completionBlock:@escaping (UIImage?, NSError?)->Void) -> Operation {
......
......@@ -39,7 +39,7 @@ open class SwarmTileOverlayRenderer: MKTileOverlayRenderer {
}
swarmOverlay.downloadTileAtURL(url) { [weak self] error in
swarmOverlay.downloadTileAtURL(url) { [weak self] _, error in
// guard error == nil else { return }
self?.setNeedsDisplay(inRect, zoomScale: zoomScale)
}
......@@ -75,6 +75,60 @@ open class SwarmTileOverlayRenderer: MKTileOverlayRenderer {
if swarmOverlay.debug { drawDebug(path, rect: rect, color: UIColor.blue.withAlphaComponent(0.6), context: context, note: "\(url.path)") }
}
}
public func getTileImages(_ forRect: MKMapRect,
zoomLevel: Int,
completion:@escaping (_ tileImage: UIImage?) -> Void
) {
let swarm = swarmOverlay
self.getValidTime(swarmOverlay: swarm) { validDate in
guard let timeStamp = validDate else {
completion(nil)
return
}
let path = self.pathForMapRect(forRect, zoomLevel: zoomLevel)
let url = swarm.urlForTile(path, timestamp: timeStamp)
swarm.downloadTileAtURL(url) { image, error in
if let tileImage = image {
completion(tileImage)
}
}
}
}
private func pathForMapRect(_ mapRect: MKMapRect, zoomLevel: Int, contentScale: CGFloat = 1.0) -> MKTileOverlayPath {
let coordinateRegion = MKCoordinateRegion(mapRect)
let regionCenterX = (coordinateRegion.center.longitude) * (.pi/180.0)
let regionCenterY = (coordinateRegion.center.latitude) * (.pi/180.0)
let logy = log(tan(regionCenterY)+1.0/cos(regionCenterY))
let px = (1.0 + (regionCenterX / .pi)) * 0.5
let py = (1.0 - (logy / .pi)) * 0.5
let mercatorTileOrigin = CGPoint(x: px, y: py)
let worldTileWidth = Int(pow(Double(2), Double(zoomLevel)))
let x = Int(mercatorTileOrigin.x * CGFloat(worldTileWidth))
let y = Int(mercatorTileOrigin.y * CGFloat(worldTileWidth))
func adjustX(_ x:Int) -> Int { return (x >= worldTileWidth) ? x - worldTileWidth : x }
return MKTileOverlayPath(x: adjustX(x), y: y, z: zoomLevel, contentScaleFactor: contentScale)
}
private func getValidTime(swarmOverlay: SwarmOverlay,
completion: @escaping (_ dateString: String?) -> Void
) {
swarmOverlay.queryTimes { dataAvailable, error in
guard
let validTimes = swarmOverlay.validTimes as? [String:AnyObject],
let dates = (validTimes.map{$0.value}).first as? [String]
else {
completion(nil)
return
}
completion(dates.last)
}
}
}
fileprivate extension MKMapRect {
......
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Localize-Swift"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Localize-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/Swarm"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Localize-Swift/Localize_Swift.framework/Headers"
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Localize-Swift/Localize_Swift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swarm/Swarm.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks'
OTHER_LDFLAGS = $(inherited) -framework "Localize_Swift"
OTHER_LDFLAGS = $(inherited) -framework "Localize_Swift" -framework "Swarm"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
......
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Localize-Swift"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Localize-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/Swarm"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Localize-Swift/Localize_Swift.framework/Headers"
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Localize-Swift/Localize_Swift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Swarm/Swarm.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks'
OTHER_LDFLAGS = $(inherited) -framework "Localize_Swift"
OTHER_LDFLAGS = $(inherited) -framework "Localize_Swift" -framework "Swarm"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
......
APPLICATION_EXTENSION_API_ONLY = YES
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Swarm
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
......
APPLICATION_EXTENSION_API_ONLY = YES
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Swarm
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment