非常に興味深い質問-ジェスチャレコグナイザーをマップオーバーレイに配置することすら考えたことはありませんでした。少し実験して、のタップを検出できることを確認しましたMKPolylineView
。ご覧のとおり、タップジェスチャはマップオーバーレイでは機能しません。その代わりに、タップジェスチャをではなくに配置MKMapView
しMKPolylineView
ます。次に、タップを処理します。
- (void)handleTapGesture:(UIGestureRecognizer*)gestureRecognizer
{
if (measureLine != nil)
{
UIView* hitView = [self.polylineView hitTest:[gestureRecognizer locationInView:self.polylineView] withEvent:nil];
}
}
hitView
タップがの外側にある場合はnilにMKPolylineView
なりself.polylineView
、タップが内側にある場合はnilになります。
ただし、これは希望どおりに動作しない場合があります。水平線と垂直線の場合、下にあるビューのサイズが線とほぼ同じサイズであるため、完全に機能します。ただし、45度の線の場合、下にあるビューは線よりもはるかに大きくする必要があります。これは、軸に位置合わせされたバウンディングボックス(AABB)であるためです。45度の線について考える場合、水平線と垂直線のみを使用してそれを囲むと、大きな領域になります。これは、タップを検出する場合よりもはるかに大きくなります。
例えば
--------
| / |
| / |
| / |
| / |
|/ |
--------
ただし、タップジェスチャまたはヒットテストを使用すると、常にこれらのAABB内のタップが認識されます。したがって、ジェスチャをどこにアタッチしよMKPolylineView
うとしても、たとえば、試したとおりに、またはに、MKMapView
偽の結果が得られます。長い線の場合、問題はさらに悪化します。マップビューの右上から左下に向かう線を想像すると、それを囲む必要があるAABBは、マップビューの領域全体をカバーします。つまり、左上または右下をタップすると、を押すと解釈されMKPolylineView
ます。
この問題を解決するには、次のアプローチをお勧めします。
- マップビューでタップジェスチャ認識機能を使用する
- タップを処理するメソッドでは、次のようになります。
- 画面のタップ位置を地図の座標に変換します
- 各ポリラインをループします(1つしかない場合を除く)
- ポリラインの各ポイントについて、そのポイントを次のポイントに接続する線分を取得し、この線からのマップ座標の距離を計算します。これを計算するには、三角法を使用します。
- 距離がこのセグメントに非常に近い場合は、残りのセグメントのチェックを停止し、表示したいコールアウトなどを処理します
- 距離が近くない場合は、次のポイントと、それを次の1つのポイントに接続する線分に移動します。
このアプローチは、ポリラインの長さやポリラインの角度に関係なく機能することが保証されています。AABBの懸念はありません。欠点は、これらの距離計算のすべてが計算コストがかかる可能性があることです。したがって、ポリラインが多数のポイントで構成されている場合、またはポリラインが多数ある場合は、これらの計算のすべてを実行できない可能性があります。 UIの応答をブロックせずに、つまり、UIをバックグラウンドスレッドに移動する必要があります。ポリラインがほんの一握りである場合、および/またはそれらが少数のポイントで構成されている場合は、問題ありません。