Search code examples
iosmkoverlay

Is CGPoint in MKPolygonView?


I'm trying to figure out a way to detect which MKOverlayView (actually MKPolygonView) was tapped and then change its color.

I got it running with this code:

- (void)mapTapped:(UITapGestureRecognizer *)recognizer {

    MKMapView *mapView = (MKMapView *)recognizer.view;
    MKPolygonView *tappedOverlay = nil;
    for (id<MKOverlay> overlay in mapView.overlays)
    {
        MKPolygonView *view = (MKPolygonView *)[mapView viewForOverlay:overlay];

        if (view){
            // Get view frame rect in the mapView's coordinate system
            CGRect viewFrameInMapView = [view.superview convertRect:view.frame toView:mapView];
            // Get touch point in the mapView's coordinate system
            CGPoint point = [recognizer locationInView:mapView];
            // Check if the touch is within the view bounds
            if (CGRectContainsPoint(viewFrameInMapView, point))
            {

                tappedOverlay = view;
                break;
            }
        }
    }

    if([[tappedOverlay fillColor] isEqual:[[UIColor cyanColor] colorWithAlphaComponent:0.2]]){
        [listOverlays addObject:tappedOverlay];
        tappedOverlay.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.2];
    }
    else{
        [listOverlays removeObject:tappedOverlay];
        tappedOverlay.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
    }
    //tappedOverlay.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];

}

Which works but sometimes, depending where I tap it gets wrong which MKPolygonView was tapped. I suppose because CGRectContainsPoint doesnt calculate properly the area, since it's not a rectangle it's a Polygon.

What other methods there are to do this? I tried CGPathContainsPoint but I get worse results.


Solution

  • Thanks to @Ana Karenina, that pointed out the right way, this is how you have to convert the gesture so that the method CGPathContainsPoint' works right.

    - (void)mapTapped:(UITapGestureRecognizer *)recognizer{
    
    MKMapView *mapView = (MKMapView *)recognizer.view;
    
    MKPolygonView *tappedOverlay = nil;
    int i = 0;
    for (id<MKOverlay> overlay in mapView.overlays)
    {
        MKPolygonView *view = (MKPolygonView *)[mapView viewForOverlay:overlay];
    
        if (view){
            CGPoint touchPoint = [recognizer locationInView:mapView];
            CLLocationCoordinate2D touchMapCoordinate =
            [mapView convertPoint:touchPoint toCoordinateFromView:mapView];
    
            MKMapPoint mapPoint = MKMapPointForCoordinate(touchMapCoordinate);
    
            CGPoint polygonViewPoint = [view pointForMapPoint:mapPoint];
            if(CGPathContainsPoint(view.path, NULL, polygonViewPoint, NO)){
                tappedOverlay = view;
                tappedOverlay.tag = i;
                break;
            }
        }
        i++;
    }
    
    if([[tappedOverlay fillColor] isEqual:[[UIColor cyanColor] colorWithAlphaComponent:0.2]]){
        [listOverlays addObject:tappedOverlay];
        tappedOverlay.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.2];
    }
    else{
        [listOverlays removeObject:tappedOverlay];
        tappedOverlay.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
    }
    //tappedOverlay.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
    
    }