1

I've been trying to get my MKMapView to detect whether or not a tap was on a tile with alpha > 0. I'm quite new at ObjC and Xcode as well so this functionality is a bit over my head. All help will me greatly appreciated! So far I've tried many different strategies but always come up short. We have custom classes to replace MKOverlay and MKOverlayView that implement each respectively so I've been trying to grab the tiles when they're created and save them to an array to later reference in the MKMapViewController when the map is touched.

- (NSArray *)tilesInMapRect:(MKMapRect)rect zoomScale:(MKZoomScale)scale
{
NSInteger z = zoomScaleToZoomLevel(scale);

// Number of tiles wide or high (but not wide * high)
NSInteger tilesAtZ = pow(2, z);

NSInteger minX = floor((MKMapRectGetMinX(rect) * scale) / TILE_SIZE);
NSInteger maxX = floor((MKMapRectGetMaxX(rect) * scale) / TILE_SIZE);
NSInteger minY = floor((MKMapRectGetMinY(rect) * scale) / TILE_SIZE);
NSInteger maxY = floor((MKMapRectGetMaxY(rect) * scale) / TILE_SIZE);

NSMutableArray *tiles = nil;

for (NSInteger x = minX; x <= maxX; x++) {
    for (NSInteger y = minY; y <= maxY; y++) {
        // As in initWithTilePath, need to flip y index to match the gdal2tiles.py convention.
        NSInteger flippedY = abs(y + 1 - tilesAtZ);

        NSString *tileKey = [[NSString alloc] initWithFormat:@"%d/%d/%d", z, x, flippedY];
        if ([tilePaths containsObject:tileKey]) {
            if (!tiles) {
                tiles = [NSMutableArray array];
            }

            MKMapRect frame = MKMapRectMake((double)(x * TILE_SIZE) / scale,
                                            (double)(y * TILE_SIZE) / scale,
                                            TILE_SIZE / scale,
                                            TILE_SIZE / scale);

            NSString *path = [[NSString alloc] initWithFormat:@"%@/%@.png", tileBase, tileKey];
            ImageTile *tile = [[ImageTile alloc] initWithFrame:frame path:path];
            [tiles addObject:tile];
            [myTiles addObject:tile];
            [path release];
            [tile release];
        }
        [tileKey release];
    }
}
return tiles;
}

That's where I populate the array which is a "class variable". If I comment out the [tiles addObject:tile]; I get the background of the map drawn but no buildings so I think adding specifically those tiles is correct. Then in the mapviewController gesture handler function I check if the touch is in the tile.frame which is is for 8 out of 32 (it can be 0 if you click far from the buildings and the total changes when you zoom around, but always gets bigger)which seems like an odd number. But pretending that that works correctly I check the alpha at that point using a modified version of this answerer's function: how to get the RGBA value of UIImage in the specific clicked point but I don't know if that works for mapView's like it would for imageViews. I think I might need to translate the context but I've never worked with contexts before...

Sorry for so much text! Maybe this isn't even possible? I'll add more code if clarification is needed. Any input would help!

Community
  • 1
  • 1
  • Are you trying to detect taps on arbitrary buildings anywhere in the world or is this some pre-defined list of a few buildings? If pre-defined, you might have an easier time defining polygons for the buildings and testing whether the tapped coordinate is inside the polygon (see http://stackoverflow.com/questions/19014926/detecting-a-point-in-a-mkpolygon-broke-with-ios7-cgpathcontainspoint/19018733#19018733). –  Nov 21 '13 at 02:40
  • Yeah, we have a finite set of buildings so that's probably our plan b, but this is what I was asked to do. I currently have rects implemented but didn't know about polygons so thank you! – user2909209 Nov 21 '13 at 19:40

0 Answers0