18

タップが MKPolygon 内にあるかどうかを確認できるようにしたい。

私は MKPolygon を持っています:

CLLocationCoordinate2D  points[4];

points[0] = CLLocationCoordinate2DMake(41.000512, -109.050116);
points[1] = CLLocationCoordinate2DMake(41.002371, -102.052066);
points[2] = CLLocationCoordinate2DMake(36.993076, -102.041981);
points[3] = CLLocationCoordinate2DMake(36.99892, -109.045267);

MKPolygon* poly = [MKPolygon polygonWithCoordinates:points count:4];

[self.mapView addOverlay:poly];  

//create UIGestureRecognizer to detect a tap
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(foundTap:)];
tapRecognizer.numberOfTapsRequired = 1;
tapRecognizer.numberOfTouchesRequired = 1;
[self.mapView addGestureRecognizer:tapRecognizer];

コロラド州の基本的な概要です。

タップから緯度/経度への変換をセットアップしました。

-(IBAction)foundTap:(UITapGestureRecognizer *)recognizer
{
    CGPoint point = [recognizer locationInView:self.mapView];

    CLLocationCoordinate2D tapPoint = [self.mapView convertPoint:point toCoordinateFromView:self.view];
}

しかし、タップ ポイントが MKPolygon 内にある場合、どのようにテクノロジーを適用すればよいかわかりません。このチェックを行う方法はないようです。そのため、MKPolygon を CGRect に変換し、CGRectContainsPoint を使用する必要があると推測しています。

MKPolygon には .points プロパティがありますが、それらを取り戻すことができないようです。

助言がありますか?

編集:

以下のソリューションはどちらも iOS 6 以前では機能しますが、iOS 7 では動作しません。iOS 7 では、polygon.pathプロパティは常に を返しますNULL。アンナさんは、ここで別の SO の質問で解決策を提供してくれました。に渡すポリゴン ポイントから独自のパスを作成する必要がありますCGPathContainsPoint()

私のポリゴンの画像:

ここに画像の説明を入力

4

6 に答える 6

12

誰でも使いたい場合に備えて、この MKPolygon カテゴリを作成しました。うまくいくようです。内部ポリゴン (つまり、ポリゴンの穴) を考慮する必要があります。

@interface MKPolygon (PointInPolygon)
  -(BOOL) pointInPolygon:(CLLocationCoordinate2D) point mapView: (MKMapView*) mapView;
@end

@implementation MKPolygon (PointInPolygon)

-(BOOL) pointInPolygon:(CLLocationCoordinate2D) point mapView: (MKMapView*) mapView {
    MKMapPoint mapPoint = MKMapPointForCoordinate(point);
    MKPolygonView * polygonView = (MKPolygonView*)[mapView viewForOverlay:self];
    CGPoint polygonViewPoint = [polygonView pointForMapPoint:mapPoint];
    return CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO) && 
        ![self pointInInteriorPolygons:point mapView:mapView];
}

-(BOOL) pointInInteriorPolygons:(CLLocationCoordinate2D) point mapView: (MKMapView*) mapView {
    return [self pointInInteriorPolygonIndex:0 point:point mapView:mapView];
}

-(BOOL) pointInInteriorPolygonIndex:(int) index point:(CLLocationCoordinate2D) point mapView: (MKMapView*) mapView {
    if(index >= [self.interiorPolygons count])
        return NO;
    return [[self.interiorPolygons objectAtIndex:index] pointInPolygon:point mapView:mapView] || [self pointInInteriorPolygonIndex:(index+1) point:point mapView:mapView];
}

@end
于 2013-03-05T23:02:59.967 に答える
9

あなたのfoundTap方法:

-(IBAction)foundTap:(UITapGestureRecognizer *)recognizer
{
    CGPoint point = [recognizer locationInView:self.mapView];

    CLLocationCoordinate2D tapPoint = [self.mapView convertPoint:point toCoordinateFromView:self.view];

    [self pointInsideOverlay:tapPoint];

    if (isInside) 
     {
       ....
     }
}

ポイントがオーバーレイの内側にあるかどうかを確認するために前から呼び出すメソッドを次に示します。

-(void)pointInsideOverlay:(CLLocationCoordinate2D )tapPoint 
{
    isInside = FALSE; 

    MKPolygonView *polygonView = (MKPolygonView *)[mapView viewForOverlay:polygonOverlay];

    MKMapPoint mapPoint = MKMapPointForCoordinate(tapPoint);

    CGPoint polygonViewPoint = [polygonView pointForMapPoint:mapPoint];

    BOOL mapCoordinateIsInPolygon = CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO);

        if ( !mapCoordinateIsInPolygon )

            //we are finding points that are inside the overlay
        {
            isInside = TRUE;
        }
}
于 2012-04-19T15:44:38.593 に答える
5

ポイントが任意のポリゴン内にあるかどうかを判断することは自明ではなく、Apple が MKPolygon の一部としてそれを提供していないことは驚くべきことではありません。ポイントにアクセスできるため、エッジを反復処理できます。

点 p が多角形 s の内側にあるかどうかを判断するには、各エッジを s の有向線分と見なします。p からの任意の固定方向 (通常は X 軸または Y 軸に平行) の光線が線分と交差する場合、光線とその有向線分との外積の Z 成分の符号をとります。Z コンポーネントが > 0 の場合、カウンターに 1 を追加します。0 未満の場合、1 を減算します。これを実装する秘訣は、エッジが光線とほぼ平行である場合、または光線が頂点を通過する場合の問題を回避することです (エッジごとに 1 回ではなく、1 回だけカウントする必要があります)。 .

s のすべてのエッジに対してこれを行うと、レイがポリゴンのアウトラインと交差する回数がカウントされます。ここで、エッジが左から右に移動している場合、追加したエッジが右から左に移動している場合、差し引いた。結果の合計がゼロの場合、ポリゴンの外側にいます。そうでなければ、あなたはその中にいます。

多数の最適化が可能です。その 1 つは、より完全なテストの前に簡単なバウンディング ボックス テストを行うことです。もう 1 つは、光線と交差しないエッジを自明に破棄するために、すべてのエッジに境界を持つデータ構造を持つことです。

編集: AXB の Z コンポーネント ( A と B の外積) は、次の式で与えられます。

a.x * b.y - a.y * b.x

気になるのはサインだけなので、チェックできます

a.x * b.y > a.y * b.x
于 2012-04-11T18:32:44.497 に答える
5

これは #Swift 4.2 でうまくいきました:

extension MKPolygon {
    func isCoordinateInsidePolyon(coordinate: CLLocationCoordinate2D) -> Bool {
        let polygonRenderer = MKPolygonRenderer(polygon: self)
        let currentMapPoint: MKMapPoint = MKMapPoint(coor)
        let polygonViewPoint: CGPoint = polygonRenderer.point(for: currentMapPoint)
        if polygonRenderer.path == nil {
            return false
        }else{
            return polygonRenderer.path.contains(polygonViewPoint)
        }
    }
}
于 2016-09-25T19:15:52.767 に答える