определить, находится ли точка внутри оверлея MKPolygon

Я хочу быть в состоянии сказать, находится ли нажатие в пределах MKPolygon.

У меня есть МК Полигон:

<code>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];
</code>

это просто основной план штата Колорадо.

Я установил преобразование в долготу / долготу:

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

    CLLocationCoordinate2D tapPoint = [self.mapView convertPoint:point toCoordinateFromView:self.view];
}
</code>

но я не уверен, как технология, если моя точка касания находится в пределах MKPolygon. Кажется, нет способа сделать эту проверку, поэтому я предполагаю, что мне нужно преобразовать MKPolygon в CGRect и использовать CGRectContainsPoint.

У MKPolygon есть свойство .points, но я не могу их вернуть.

какие-либо предложения?

РЕДАКТИРОВАТЬ:

Оба решения ниже работают в iOS 6 или ниже, но ломаются в iOS 7. В iOS 7polygon.path собственность всегда возвращаетсяNULL, Г-жа Анна была достаточно любезна, чтобы предоставитьрешение в другом так вопрос здесь, Это включает в себя создание собственного пути из точек многоугольника, чтобы перейти вCGPathContainsPoint().

изображение моего многоугольника:

enter image description here

Ответы на вопрос(6)

року данных в массив точек и использую подходhttp://alienryderflex.com/polygon/

Меня устраивает....

-(BOOL)isPoint:(CLLocationCoordinate2D)findLocation inPloygon:(NSArray*)polygon{

    NSMutableArray *tempPolygon=[NSMutableArray arrayWithArray:polygon];
    int   i, j=(int)tempPolygon.count-1 ;
    bool  oddNodes=NO;
    double x=findLocation.latitude;
    double y=findLocation.longitude;

    for (i=0; i<tempPolygon.count; i++) {
        NSString*coordString=[tempPolygon objectAtIndex:i];
        NSArray*pointsOfCoordString=[coordString componentsSeparatedByString:@","];
        CLLocationCoordinate2D point=CLLocationCoordinate2DMake([[pointsOfCoordString objectAtIndex:1] doubleValue], [[pointsOfCoordString objectAtIndex:0] doubleValue]);
        NSString*nextCoordString=[tempPolygon objectAtIndex:j];
        NSArray*nextPointsOfCoordString=[nextCoordString componentsSeparatedByString:@","];
        CLLocationCoordinate2D nextPoint=CLLocationCoordinate2DMake([[nextPointsOfCoordString objectAtIndex:1] doubleValue], [[nextPointsOfCoordString objectAtIndex:0] doubleValue]);


        if ((point.longitude<y && nextPoint.longitude>=y)
            ||  (nextPoint.longitude<y && point.longitude>=y)) {
            if (point.latitude+(y-point.longitude)/(nextPoint.longitude-point.longitude)*(nextPoint.latitude-point.latitude)<x) {
                oddNodes=!oddNodes; }}
        j=i; }


    return oddNodes;

}

мои объекты многоугольника (NSArray) находятся в строке, например,@"-89.860021,44.944266,0"

 16 июн. 2015 г., 09:48
этот метод проверяет, что ваше заданное местоположение находится внутри многоугольника, созданного точками данных (точки данных - это массив географического местоположения). Для полного алгоритма, пожалуйста, пройдитеalienryderflex.com/polygon.
 16 июн. 2015 г., 09:23
Не могли бы вы более подробно изложить свой ответ, добавив немного больше описания предлагаемого вами решения?
 05 июл. 2017 г., 22:50
Отлично сработало для меня, но мне пришлось изменить порядок компонентов многоугольника: @ & quot; долгота, широта, 0 & quot; благодарю вас!
Решение Вопроса

если кто-то захочет ее использовать. Кажется, работает хорошо. Вы должны учитывать внутренние многоугольники (то есть отверстия в многоугольнике):

@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
 Padin21506 мар. 2013 г., 00:46
Я только что реализовал категорию и работает над моими простыми полигонами (без дырок). Вы говорите, нужно принять это во внимание? Означает ли это, что он не обнаружит, находится ли кран внутри отверстия?
 Padin21525 сент. 2013 г., 22:16
Хорошо, этот код ломается в iOS7. Что-то делать сCGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO) всегда возвращаетсяFALSE сейчас.

extension MKPolygon {

    func contains(coordinate: CLLocationCoordinate2D) -> Bool {

        let polygonRenderer = MKPolygonRenderer(polygon: self)
        let currentMapPoint: MKMapPoint = MKMapPointForCoordinate(coordinate)
        let polygonViewPoint: CGPoint = polygonRenderer.point(for: currentMapPoint)

        return  polygonRenderer.path.contains(polygonViewPoint)
    }
}

находится ли точка в произвольном многоугольнике, нетривиально, и неудивительно, что Apple не поставляет ее как часть MKPolygon. Вы можете получить доступ к точкам, что позволяет итерировать по краям.

Чтобы определить, находится ли точка p внутри многоугольника s, рассмотрим каждое ребро как направленный отрезок в s. Если луч из p в каком-либо фиксированном направлении (обычно параллельном оси X или Y) пересекает сегмент, принимает знак компонента Z перекрестного произведения луча с этим направленным сегментом линии. Если компонент Z является & gt; 0, добавьте 1 к счетчику. Если это & lt; 0, вычтите 1. Хитрость в реализации этого состоит в том, чтобы избежать проблем, когда ребро почти параллельно лучу или когда луч проходит через вершину (он должен считаться только один раз, а не один раз для каждого ребра).

Когда вы сделаете это для всех ребер в s, вы посчитаете, сколько раз ваш луч пересекает контур многоугольника, где, если ребро проходило слева направо, вы добавили, и если оно двигалось справа налево Вы вычитали. Если полученная сумма равна нулю, вы находитесь за пределами многоугольника. В противном случае вы внутри.

Возможны многочисленные оптимизации. Один из таких способов - выполнить быстрый ограничивающий тест перед более полным тестом. Другой - иметь структуру данных с границами по всем ребрам, чтобы тривиально отбрасывать ребра, не пересекающие луч.

Редактировать: Z-компонент A X B (перекрестное произведение A с B) определяется как:

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

так как все, что вас волнует, это знак, вы можете проверить

a.x * b.y > a.y * b.x
 11 апр. 2012 г., 22:07
добавлено определение, чтобы ответить.
 12 апр. 2012 г., 01:07
У Adrian Bowyer's Programmer's Geometry есть псевдокод для этого. Но вам не нужен общий случай: предположим, горизонтальный луч.
 Padin21511 апр. 2012 г., 21:27
что такое Z-компонент?
 Padin21511 апр. 2012 г., 22:52
ок, понял. работая над этим сейчас, просто пытаясь выяснить, как определить, пересекается ли луч с отрезком линии.

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;
        }
}
 12 февр. 2013 г., 11:38
@ Log139 Почему ты так говоришь?polygonView этоMKPolygonView, path это егоCGPathRefне ограничивающий его прямоугольник, аCGPathContainsPoint правильно ли проверяется путь / точка, нет? Что мне здесь не хватает? Я думаю, что если вы используете[polygonView pointInside:polygonViewPoint withEvent:nil], Возможно, ты прав. Но если вы получаетеpath и звонитCGPathContainsPointЯ думаю, ты в порядке.
 Padin21525 сент. 2013 г., 22:29
Хорошо, я убираю свой предыдущий комментарий, это работает. Ну, это работает в iOS6 или меньше, оно ломается в iOS7.
 Padin21510 дек. 2012 г., 18:13
Это хороший способ выполнить базовую проверку, чтобы увидеть, находится ли точка касания внутри прямоугольника многоугольника. не является точным для обнаружения отводов в пределах нарисованной области многоугольника.

extension MKPolygon {

    func isCoordinateInsidePolyon(coordinate: CLLocationCoordinate2D) -> Bool {

        var inside = false

        let polygonRenderer = MKPolygonRenderer(polygon: self)
        let currentMapPoint: MKMapPoint = MKMapPointForCoordinate(coordinate)
        let polygonViewPoint: CGPoint = polygonRenderer.pointForMapPoint(currentMapPoint)

        if CGPathContainsPoint(polygonRenderer.path, nil, polygonViewPoint, true) {
            inside = true
        }

        return inside
    }
}
 21 июл. 2017 г., 23:07
Это работает и имеет то преимущество, что не требует MKMapView, как подходы MKPolygonView, описанные в других ответах.

Ваш ответ на вопрос