表示中のマップ(MKMapView)領域内に含まれている座標かどうかを判定する
検証環境:
Xcode 12
Swift 5.3
まずMapKitをインポートしておく。
import MapKit
MKMapRect を使う
ある座標が表示中のマップMKMapView領域内に含まれているかで判定する方法。
座標の緯度経度はCLLocationCoordinate2Dで扱っているとする。
- 表示中のマップ領域の矩形
MKMapRectをmapView.visibleMapRectで取得する。 - 緯度経度
CLLocationCoordinate2Dをマップ座標系MKMapPointに変換する。 MKMapRect#contains(_ point: MKMapPoint)メソッドで領域内の点であるかを判定する。
let mapRect = mapView.visibleMapRect let mapPoint = MKMapPoint(coordinate) if mapRect.contains(mapPoint) { // 領域内に含まれる }
使用例: 表示中のマップ領域内に含まれるアノテーションのみ抽出する
let mapRect: MKMapRect = mapView.visibleMapRect for annotation in mapView.annotations { let mapPoint = MKMapPoint(annotation.coordinate) if mapRect.contains(mapPoint) { // 領域内に含まれる } }
MKCoordinateRegion を使う
ある座標がMKCoordinateRegion領域内に含まれているかで判定する方法。
func standardAngle(_ angle: CLLocationDegrees) -> CLLocationDegrees { let angle = angle.truncatingRemainder(dividingBy: 360) return angle < -180 ? -360 - angle : angle > 180 ? 360 - angle : angle } func regionContains(region: MKCoordinateRegion, location: CLLocationCoordinate2D) -> Bool { let deltaLat = abs(standardAngle(region.center.latitude - location.latitude)) let deltaLon = abs(standardAngle(region.center.longitude - location.longitude)) return region.span.latitudeDelta / 2 >= deltaLat && region.span.longitudeDelta / 2 >= deltaLon }
使用例: 表示中のマップ領域内に含まれるアノテーションのみ抽出する
let region: MKCoordinateRegion = mapView.region for annotation in mapView.annotations { if regionContains(region: region, location: annotation.coordinate) { // 領域内に含まれる } }
MKCoordinateRegion の Extension にした場合。
extension MKCoordinateRegion { func contains(location: CLLocationCoordinate2D) -> Bool { let deltaLat = abs(standardAngle(center.latitude - location.latitude)) let deltaLon = abs(standardAngle(center.longitude - location.longitude)) return span.latitudeDelta / 2 >= deltaLat && span.longitudeDelta / 2 >= deltaLon } private func standardAngle(_ angle: CLLocationDegrees) -> CLLocationDegrees { let angle = angle.truncatingRemainder(dividingBy: 360) return angle < -180 ? -360 - angle : angle > 180 ? 360 - angle : angle } }
if mapView.region.contains(location: coordinate) { // 領域内に含まれる }