mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Fit extension for map annotations
This commit is contained in:
parent
5fd3215921
commit
547d250ec2
5 changed files with 46 additions and 51 deletions
|
|
@ -69,6 +69,7 @@
|
|||
DD964FBD296E6B01007C176F /* EmojiOnlyTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FBC296E6B01007C176F /* EmojiOnlyTextField.swift */; };
|
||||
DD964FBF296E76EF007C176F /* WaypointFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FBE296E76EF007C176F /* WaypointFormView.swift */; };
|
||||
DD964FC2297272AE007C176F /* WaypointEntityExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FC1297272AE007C176F /* WaypointEntityExtension.swift */; };
|
||||
DD964FC42974767D007C176F /* MapViewFitExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FC32974767D007C176F /* MapViewFitExtension.swift */; };
|
||||
DD97E96628EFD9820056DDA4 /* MeshtasticLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD97E96528EFD9820056DDA4 /* MeshtasticLogo.swift */; };
|
||||
DD97E96828EFE9A00056DDA4 /* About.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD97E96728EFE9A00056DDA4 /* About.swift */; };
|
||||
DD994B69295F88B60013760A /* IntervalEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD994B68295F88B60013760A /* IntervalEnums.swift */; };
|
||||
|
|
@ -195,6 +196,7 @@
|
|||
DD964FBE296E76EF007C176F /* WaypointFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaypointFormView.swift; sourceTree = "<group>"; };
|
||||
DD964FC029724F6D007C176F /* MeshtasticDataModelV6.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV6.xcdatamodel; sourceTree = "<group>"; };
|
||||
DD964FC1297272AE007C176F /* WaypointEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaypointEntityExtension.swift; sourceTree = "<group>"; };
|
||||
DD964FC32974767D007C176F /* MapViewFitExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewFitExtension.swift; sourceTree = "<group>"; };
|
||||
DD97E96528EFD9820056DDA4 /* MeshtasticLogo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticLogo.swift; sourceTree = "<group>"; };
|
||||
DD97E96728EFE9A00056DDA4 /* About.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = About.swift; sourceTree = "<group>"; };
|
||||
DD994B68295F88B60013760A /* IntervalEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntervalEnums.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -282,6 +284,7 @@
|
|||
C9697F9C279336B700250207 /* LocalMBTileOverlay.swift */,
|
||||
DD2AD8A7296D2DF9001FF0E7 /* MapViewSwiftUI.swift */,
|
||||
DD964FBE296E76EF007C176F /* WaypointFormView.swift */,
|
||||
DD964FC32974767D007C176F /* MapViewFitExtension.swift */,
|
||||
);
|
||||
path = Map;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -784,6 +787,7 @@
|
|||
DD964FC2297272AE007C176F /* WaypointEntityExtension.swift in Sources */,
|
||||
DD47E3CE26F103C600029299 /* NodeList.swift in Sources */,
|
||||
DD8EBF43285058FA00426DCA /* DisplayConfig.swift in Sources */,
|
||||
DD964FC42974767D007C176F /* MapViewFitExtension.swift in Sources */,
|
||||
DD47E3D626F17ED900029299 /* CircleText.swift in Sources */,
|
||||
DDC2E18F26CE25FE0042C5E4 /* ContentView.swift in Sources */,
|
||||
DD17E5DE277D49D400010EC2 /* storeforward.pb.swift in Sources */,
|
||||
|
|
|
|||
37
Meshtastic/Views/Map/MapViewFitExtension.swift
Normal file
37
Meshtastic/Views/Map/MapViewFitExtension.swift
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// MapViewFitExtension.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Garth Vander Houwen on 1/15/23.
|
||||
//
|
||||
|
||||
import MapKit
|
||||
|
||||
extension MKMapView {
|
||||
|
||||
func fitAllAnnotations(with padding: UIEdgeInsets = UIEdgeInsets(top: 100, left: 100, bottom: 100, right: 100)) {
|
||||
var zoomRect: MKMapRect = .null
|
||||
annotations.forEach({
|
||||
let annotationPoint = MKMapPoint($0.coordinate)
|
||||
let pointRect = MKMapRect(x: annotationPoint.x, y: annotationPoint.y, width: 0.01, height: 0.01)
|
||||
zoomRect = zoomRect.union(pointRect)
|
||||
})
|
||||
|
||||
setVisibleMapRect(zoomRect, edgePadding: padding, animated: true)
|
||||
}
|
||||
|
||||
func fit(annotations: [MKAnnotation], andShow show: Bool, with padding: UIEdgeInsets = UIEdgeInsets(top: 100, left: 100, bottom: 100, right: 100)) {
|
||||
var zoomRect: MKMapRect = .null
|
||||
annotations.forEach({
|
||||
let aPoint = MKMapPoint($0.coordinate)
|
||||
let rect = MKMapRect(x: aPoint.x, y: aPoint.y, width: 0.1, height: 0.1)
|
||||
zoomRect = zoomRect.isNull ? rect : zoomRect.union(rect)
|
||||
})
|
||||
|
||||
if show {
|
||||
addAnnotations(annotations)
|
||||
}
|
||||
|
||||
setVisibleMapRect(zoomRect, edgePadding: padding, animated: true)
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
let mapView = MKMapView()
|
||||
let positions: [PositionEntity]
|
||||
let waypoints: [WaypointEntity]
|
||||
let region: MKCoordinateRegion
|
||||
let mapViewType: MKMapType
|
||||
|
||||
// Offline Maps
|
||||
|
|
@ -28,11 +27,10 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
|
||||
func makeUIView(context: Context) -> MKMapView {
|
||||
// Parameters
|
||||
mapView.addAnnotations(positions)
|
||||
mapView.fit(annotations: positions, andShow: true)
|
||||
mapView.addAnnotations(waypoints)
|
||||
mapView.mapType = mapViewType
|
||||
mapView.setRegion(region, animated: true)
|
||||
mapView.setUserTrackingMode(.none, animated: false)
|
||||
mapView.setUserTrackingMode(.none, animated: true)
|
||||
// Other MKMapView Settings
|
||||
mapView.isPitchEnabled = true
|
||||
mapView.isRotateEnabled = true
|
||||
|
|
@ -61,12 +59,8 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
let tilePath = documentsDirectory.appendingPathComponent("offline_map.mbtiles", isDirectory: false).path
|
||||
if fileManager.fileExists(atPath: tilePath) {
|
||||
//if let tilePath = Bundle.main.path(forResource: "offline_map", ofType: "mbtiles") {
|
||||
|
||||
print("Loading local map file")
|
||||
|
||||
if let overlay = LocalMBTileOverlay(mbTilePath: tilePath) {
|
||||
|
||||
overlay.canReplaceMapContent = false//customMapOverlay.canReplaceMapContent
|
||||
mapView.addOverlay(overlay)
|
||||
}
|
||||
|
|
@ -79,9 +73,6 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
self.loadedLastUpdatedLocalMapFile = self.lastUpdatedLocalMapFile
|
||||
}
|
||||
}
|
||||
if dynamicRegion {
|
||||
self.moveToMeshRegion(mapView)
|
||||
}
|
||||
mapView.removeAnnotations(mapView.annotations)
|
||||
mapView.addAnnotations(positions)
|
||||
mapView.addAnnotations(waypoints)
|
||||
|
|
@ -91,53 +82,17 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
return Coordinator(self)
|
||||
}
|
||||
|
||||
func moveToMeshRegion(_ mapView: MKMapView) {
|
||||
//go through the annotations and create a bounding box that encloses them
|
||||
var minLat: CLLocationDegrees = 90.0
|
||||
var maxLat: CLLocationDegrees = -90.0
|
||||
var minLon: CLLocationDegrees = 180.0
|
||||
var maxLon: CLLocationDegrees = -180.0
|
||||
|
||||
for annotation in mapView.annotations {
|
||||
if annotation.isKind(of: MKAnnotation.self) {
|
||||
minLat = min(minLat, annotation.coordinate.latitude)
|
||||
maxLat = max(maxLat, annotation.coordinate.latitude)
|
||||
minLon = min(minLon, annotation.coordinate.longitude)
|
||||
maxLon = max(maxLon, annotation.coordinate.longitude)
|
||||
}
|
||||
}
|
||||
|
||||
//check if the mesh region looks sensible before we move to it. Otherwise we won't move the map (leave it at the current location)
|
||||
if maxLat < minLat || (maxLat-minLat) > 5 || maxLon < minLon || (maxLon-minLon) > 5 {
|
||||
return
|
||||
} else if minLat == maxLat && minLon == maxLon {
|
||||
//then we are focussed on a single point (probably because there is only one node with a position)
|
||||
//widen that out a little (don't zoom way in to that point)
|
||||
|
||||
//0.001 degrees latitude is about 100m
|
||||
//the mapView.regionThatFits call below will expand this out to a rectangle
|
||||
minLat = minLat - 0.001
|
||||
maxLat = maxLat + 0.001
|
||||
}
|
||||
|
||||
let centerCoord = CLLocationCoordinate2D(latitude: (minLat+maxLat)/2, longitude: (minLon+maxLon)/2)
|
||||
let span = MKCoordinateSpan(latitudeDelta: (maxLat-minLat)*1.5, longitudeDelta: (maxLon-minLon)*1.5)
|
||||
let region = mapView.regionThatFits(MKCoordinateRegion(center: centerCoord, span: span))
|
||||
mapView.setRegion(region, animated: true)
|
||||
}
|
||||
|
||||
final class MapCoordinator: NSObject, MKMapViewDelegate, UIGestureRecognizerDelegate {
|
||||
|
||||
var parent: MapViewSwiftUI
|
||||
var longPressRecognizer = UILongPressGestureRecognizer()
|
||||
|
||||
var overlays: [Overlay] = []
|
||||
|
||||
init(_ parent: MapViewSwiftUI) {
|
||||
self.parent = parent
|
||||
super.init()
|
||||
self.longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressHandler))
|
||||
self.longPressRecognizer.minimumPressDuration = 0.2
|
||||
self.longPressRecognizer.minimumPressDuration = 0.3
|
||||
self.longPressRecognizer.delegate = self
|
||||
self.parent.mapView.addGestureRecognizer(longPressRecognizer)
|
||||
self.overlays = []
|
||||
|
|
@ -163,7 +118,6 @@ struct MapViewSwiftUI: UIViewRepresentable {
|
|||
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "waypoint") as? MKMarkerAnnotationView ?? MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "Waypoint")
|
||||
annotationView.canShowCallout = true
|
||||
if waypointAnnotation.icon == 0 {
|
||||
print(waypointAnnotation.icon)
|
||||
annotationView.glyphText = "📍"
|
||||
} else {
|
||||
annotationView.glyphText = String(UnicodeScalar(Int(waypointAnnotation.icon)) ?? "📍")
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ struct NodeDetail: View {
|
|||
} else {
|
||||
presentingWaypointForm = true
|
||||
}
|
||||
}, positions: annotations, waypoints: Array(waypoints), region: MKCoordinateRegion(center: nodeCoordinatePosition, span: MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005)), mapViewType: mapType,
|
||||
}, positions: annotations, waypoints: Array(waypoints), mapViewType: mapType,
|
||||
customMapOverlay: self.customMapOverlay,
|
||||
overlays: self.overlays
|
||||
)
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ struct NodeMap: View {
|
|||
presentingWaypointForm = true
|
||||
}
|
||||
|
||||
}, positions: Array(positions), waypoints: Array(waypoints), region: MKCoordinateRegion(center: LocationHelper.currentLocation, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)), mapViewType: mapType,
|
||||
}, positions: Array(positions), waypoints: Array(waypoints), mapViewType: mapType,
|
||||
customMapOverlay: self.customMapOverlay,
|
||||
overlays: self.overlays
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue