検証環境:
Xcode 12
Swift 5.3
マップ(MKMapView)上にオーバーレイしたMKCircle
やMKPolygon
などの領域内にある座標かどうかを判定する方法。
座標の緯度経度はCLLocationCoordinate2D
で扱っているとする。
マップ上に MKCircle や MKPolygon の図形をオーバーレイする方法は以下のPostで書いた。
まずMapKit
をインポートしておく。
import MapKit
MKCircle 領域内かを判定する
やり方はMKCircle
からMKCircleRenderer
を作成して、renderer.path.contains
メソッドで判定できる。
// 対象の座標 let location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) // 半径100mの円領域 let center = CLLocationCoordinate2D(latitude: 35.6809591, longitude: 139.7673068) let circle = MKCircle(center: center, radius: CLLocationDistance(100)) let renderer = MKCircleRenderer(circle: circle) // 緯度経度(CLLocationCoordinate2D)をマップ上のポイント(MKMapPoint)に変換する let mapPoint = MKMapPoint(location) // マップ上のポイントを MKCircleRenderer 領域内のポイントに変換する let rendererPoint = renderer.point(for: mapPoint) if renderer.path.contains(rendererPoint) { // 含まれる }
ちなみにMKCircle
はMKMapView
に実際に addOverlay していない状態でも判定可能。
マップ上でタップした地点が MKCircle 領域内かを判定する例
MKMapView に MKCircle を addOverlay することでマップ上に円図形がオーバーレイされる。
let circle = MKCircle(center: center, radius: radius) mapView.addOverlay(circle)
タップジェスチャ登録。
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(mapTapped(_:))) mapView.addGestureRecognizer(tapGesture)
タップジェスチャ時に呼び出すメソッド。
@objc func mapTapped(_ sender: UITapGestureRecognizer) { if sender.state == .ended { let tapPoint = sender.location(in: mapView) let coord = mapView.convert(tapPoint, toCoordinateFrom: mapView) for case let circle as MKCircle in mapView.overlays { // 1つの MKCircle が追加されていることを想定 let renderer = MKCircleRenderer(circle: circle) let mapPoint = MKMapPoint(coord) let rendererPoint = renderer.point(for: mapPoint) if renderer.path.contains(rendererPoint) { // 含まれる } } } }
MKPolygon 領域内かを判定する
MKPolygon
からMKPolygonRenderer
を作成して、renderer.path.contains
メソッドで判定できる。
// 対象の座標 let location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) // 四角形領域 var coordinates: [CLLocationCoordinate2D] = [coord1, coord2, coord3, coord4] let polygon = MKPolygon(coordinates: &coordinates, count: coordinates.count) let renderer = MKPolygonRenderer(polygon: polygon) let mapPoint = MKMapPoint(location) let rendererPoint = renderer.point(for: mapPoint) if renderer.path.contains(rendererPoint) { // 含まれる }
MKCircle、MKPolygon の Extension にする
extension MKCircle { func contains(_ coordinate: CLLocationCoordinate2D) -> Bool { let renderer = MKCircleRenderer(circle: self) let mapPoint = MKMapPoint(coordinate) let rendererPoint = renderer.point(for: mapPoint) return renderer.path.contains(rendererPoint) } } extension MKPolygon { func contains(_ coordinate: CLLocationCoordinate2D) -> Bool { let renderer = MKPolygonRenderer(polygon: self) let mapPoint = MKMapPoint(coordinate) let rendererPoint = renderer.point(for: mapPoint) return renderer.path.contains(rendererPoint) } }